]> 4ch.mooo.com Git - 16.git/blob - src/lib/16_ca.c
reverted part 2
[16.git] / src / lib / 16_ca.c
1 /* Project 16 Source Code~\r
2  * Copyright (C) 2012-2017 sparky4 & pngwen & andrius4669 & joncampbell123 & yakui-lover\r
3  *\r
4  * This file is part of Project 16.\r
5  *\r
6  * Project 16 is free software; you can redistribute it and/or modify\r
7  * it under the terms of the GNU General Public License as published by\r
8  * the Free Software Foundation; either version 3 of the License, or\r
9  * (at your option) any later version.\r
10  *\r
11  * Project 16 is distributed in the hope that it will be useful,\r
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of\r
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r
14  * GNU General Public License for more details.\r
15  *\r
16  * You should have received a copy of the GNU General Public License\r
17  * along with this program.  If not, see <http://www.gnu.org/licenses/>, or\r
18  * write to the Free Software Foundation, Inc., 51 Franklin Street,\r
19  * Fifth Floor, Boston, MA 02110-1301 USA.\r
20  *\r
21  */\r
22 \r
23 // ID_CA.C\r
24 \r
25 /*\r
26 =============================================================================\r
27 \r
28 Id Software Caching Manager\r
29 ---------------------------\r
30 \r
31 Must be started BEFORE the memory manager, because it needs to get the headers\r
32 loaded into the data segment\r
33 \r
34 =============================================================================\r
35 */\r
36 \r
37 #include "src/lib/16_ca.h"\r
38 #pragma hdrstop\r
39 \r
40 #pragma warn -pro\r
41 #pragma warn -use\r
42 \r
43 #define THREEBYTEGRSTARTS\r
44 //https://github.com/open-watcom/open-watcom-v2/issues/279#issuecomment-244587566 for _seg\r
45 //http://www.shikadi.net/moddingwiki/GameMaps_Format for info on the code\r
46 /*\r
47 =============================================================================\r
48 \r
49                                                  LOCAL CONSTANTS\r
50 \r
51 =============================================================================\r
52 */\r
53 \r
54 /*typedef struct\r
55 {\r
56   word bit0,bit1;       // 0-255 is a character, > is a pointer to a node\r
57 } huffnode;*/\r
58 \r
59 \r
60 /*typedef struct\r
61 {\r
62         unsigned        RLEWtag;\r
63         long            headeroffsets[100];\r
64         byte            tileinfo[];\r
65 } mapfiletype;*/\r
66 \r
67 \r
68 /*\r
69 =============================================================================\r
70 \r
71                                                  GLOBAL VARIABLES\r
72 \r
73 =============================================================================\r
74 */\r
75 \r
76 /*byte          _seg    *tinf;\r
77 int                     mapon;\r
78 \r
79 unsigned        _seg    *mapsegs[3];\r
80 maptype         _seg    *mapheaderseg[NUMMAPS];\r
81 byte            _seg    *audiosegs[NUMSNDCHUNKS];\r
82 void            _seg    *grsegs[NUMCHUNKS];\r
83 \r
84 byte            far     grneeded[NUMCHUNKS];*/\r
85 \r
86 void    (*drawcachebox)         (char *title, unsigned numcache);\r
87 void    (*updatecachebox)       (void);\r
88 void    (*finishcachebox)       (void);\r
89 \r
90 /*\r
91 =============================================================================\r
92 \r
93                                                  LOCAL VARIABLES\r
94 \r
95 =============================================================================\r
96 */\r
97 \r
98 /*extern        long    far     CGAhead;\r
99 extern  long    far     EGAhead;\r
100 extern  byte    CGAdict;\r
101 extern  byte    EGAdict;\r
102 extern  byte    far     maphead;\r
103 extern  byte    mapdict;\r
104 extern  byte    far     audiohead;\r
105 extern  byte    audiodict;*/\r
106 \r
107 void CA_CannotOpen(char *string, global_game_variables_t *gvar);\r
108 \r
109 /*long          _seg *grstarts; // array of offsets in egagraph, -1 for sparse\r
110 long            _seg *audiostarts;      // array of offsets in audio / audiot\r
111 \r
112 #ifdef GRHEADERLINKED\r
113 huffnode        *gvar->ca.grhuffman;\r
114 #else\r
115 huffnode        gvar->ca.grhuffman[255];\r
116 #endif\r
117 \r
118 #ifdef AUDIOHEADERLINKED\r
119 huffnode        *audiohuffman;\r
120 #else\r
121 huffnode        audiohuffman[255];\r
122 #endif\r
123 \r
124 \r
125 int                     grhandle;               // handle to EGAGRAPH\r
126 int                     maphandle;              // handle to MAPTEMP / GAMEMAPS\r
127 int                     audiohandle;    // handle to AUDIOT / AUDIO\r
128 */\r
129 long            chunkcomplen,chunkexplen;\r
130 /*\r
131 SDMode          oldsoundmode;\r
132 \r
133 \r
134 \r
135 void    CAL_DialogDraw (char *title,unsigned numcache);\r
136 void    CAL_DialogUpdate (void);\r
137 void    CAL_DialogFinish (void);*/\r
138 void    CAL_CarmackExpand (unsigned far *source, unsigned far *dest,\r
139                 unsigned length);\r
140 \r
141 \r
142 #ifdef THREEBYTEGRSTARTS\r
143 #define FILEPOSSIZE     3\r
144 //#define       GRFILEPOS(c) (*(long far *)(((byte far *)grstarts)+(c)*3)&0xffffff)\r
145 CASVT GRFILEPOS(int c, global_game_variables_t *gvar)\r
146 {\r
147         CASVT value;\r
148         int     offset;\r
149 \r
150         offset = c*3;\r
151 \r
152         value = *(CASVT far *)(((byte far *)gvar->ca.grstarts)+offset);\r
153 \r
154         value &= 0x00ffffffl;\r
155 \r
156         if (value == 0xffffffl)\r
157                 value = -1;\r
158 \r
159         return value;\r
160 };\r
161 #else\r
162 #define FILEPOSSIZE     4\r
163 //#define       GRFILEPOS(c) (gvar->ca.grstarts[c])\r
164 CASVT GRFILEPOS(int c, global_game_variables_t *gvar)\r
165 {\r
166         return gvar->ca.grstarts[c];\r
167 }\r
168 #endif\r
169 \r
170 /*\r
171 =============================================================================\r
172 \r
173                                            LOW LEVEL ROUTINES\r
174 \r
175 =============================================================================\r
176 */\r
177 \r
178 /*\r
179 ============================\r
180 =\r
181 = CA_OpenDebug / CA_CloseDebug\r
182 =\r
183 = Opens a binary file with the handle "debughandle"\r
184 =\r
185 ============================\r
186 */\r
187 void CA_OpenDebug(global_game_variables_t *gvar)\r
188 {\r
189 #ifdef __BORLANDC__\r
190         unlink("debug.16b");\r
191         gvar->handle.debughandle = open("debug.16b", O_CREAT | O_WRONLY | O_TEXT);\r
192 #endif\r
193 #ifdef __WATCOMC__\r
194         unlink("debug.16w");\r
195         gvar->handle.debughandle = open("debug.16w", O_CREAT | O_WRONLY | O_TEXT);\r
196 #endif\r
197 }\r
198 \r
199 void CA_CloseDebug(global_game_variables_t *gvar)\r
200 {\r
201         close(gvar->handle.debughandle);\r
202 }\r
203 \r
204 \r
205 \r
206 /*\r
207 ============================\r
208 =\r
209 = CAL_GetGrChunkLength\r
210 =\r
211 = Gets the length of an explicit length chunk (not tiles)\r
212 = The file pointer is positioned so the compressed data can be read in next.\r
213 =\r
214 ============================\r
215 */\r
216 \r
217 void CAL_GetGrChunkLength (int chunk,global_game_variables_t *gvar)\r
218 {\r
219         lseek(gvar->ca.file.grhandle,GRFILEPOS(chunk,gvar),SEEK_SET);\r
220         read(gvar->ca.file.grhandle,&gvar->ca.chunkexplen,sizeof(gvar->ca.chunkexplen));\r
221         gvar->ca.chunkcomplen = GRFILEPOS(chunk+1,gvar)-GRFILEPOS(chunk,gvar)-4;\r
222 }\r
223 \r
224 \r
225 /*\r
226 ==========================\r
227 =\r
228 = CA_FarRead\r
229 =\r
230 = Read from a file to a far pointer\r
231 =\r
232 ==========================\r
233 */\r
234 \r
235 boolean CA_FarRead(int handle, byte far *dest, dword length, global_game_variables_t *gvar)\r
236 {\r
237         boolean flag=0;\r
238         //dword fat=0;\r
239         //word segm=0;\r
240         if(gvar->pm.emm.EMSVer<0x40)\r
241         if(length>0xfffflu)\r
242         {\r
243                 printf("File is a fat bakapee\n");\r
244                 //segm=(length%0xfffflu)-1;\r
245                 //fat=segm*0xfffflu;\r
246                 //length-=fat;\r
247                 printf("CA_FarRead doesn't support 64K reads yet!\n");\r
248                 return 0;//TODO: EXPAND!!!\r
249         }\r
250 \r
251         //if(!fat&&!segm)\r
252         //{\r
253         __asm {\r
254                 push    ds\r
255                 mov     bx,[handle]\r
256                 mov     cx,[WORD PTR length]\r
257                 mov     dx,[WORD PTR dest]\r
258                 mov     ds,[WORD PTR dest+2]\r
259                 mov     ah,0x3f                         // READ w/handle\r
260                 int     21h\r
261                 pop     ds\r
262                 jnc     good\r
263                 mov     errno,ax\r
264                 mov     flag,0\r
265                 jmp End\r
266 #ifdef __BORLANDC__\r
267         }\r
268 #endif\r
269 good:\r
270 #ifdef __BORLANDC__\r
271         __asm {\r
272 #endif\r
273                 cmp     ax,[WORD PTR length]\r
274                 je      done\r
275 //              errno = EINVFMT;                        // user manager knows this is bad read\r
276                 mov     flag,0\r
277                 jmp End\r
278 #ifdef __BORLANDC__\r
279         }\r
280 #endif\r
281 done:\r
282 #ifdef __BORLANDC__\r
283         __asm {\r
284 #endif\r
285                 mov     flag,1\r
286 #ifdef __BORLANDC__\r
287         }\r
288 #endif\r
289 End:\r
290 #ifdef __WATCOMC__\r
291         }\r
292 #endif\r
293         return flag;\r
294 }\r
295 \r
296 \r
297 /*\r
298 ==========================\r
299 =\r
300 = CA_SegWrite\r
301 =\r
302 = Write from a file to a far pointer\r
303 =\r
304 ==========================\r
305 */\r
306 \r
307 boolean CA_FarWrite(int handle, byte far *source, dword length, global_game_variables_t *gvar)\r
308 {\r
309         boolean flag=0;\r
310         //dword fat=0;\r
311         //word segm=0;\r
312         if(gvar->pm.emm.EMSVer<0x40)\r
313         if(length>0xfffflu)\r
314         {\r
315                 printf("File is a fat bakapee\n");\r
316                 //segm=(length%0xfffflu)-1;\r
317                 //fat=segm*0xfffflu;\r
318                 //length-=fat;\r
319                 printf("CA_FarWrite doesn't support 64K reads yet!\n");\r
320                 return 0;\r
321         }\r
322 \r
323         //if(!fat&&!segm)\r
324         //{\r
325         __asm {\r
326                 push    ds\r
327                 mov     bx,[handle]\r
328                 mov     cx,[WORD PTR length]\r
329                 mov     dx,[WORD PTR source]\r
330                 mov     ds,[WORD PTR source+2]\r
331                 mov     ah,0x40                 // WRITE w/handle\r
332                 int     21h\r
333                 pop     ds\r
334                 jnc     good\r
335                 mov     errno,ax\r
336                 mov flag,0\r
337                 jmp End\r
338 #ifdef __BORLANDC__\r
339         }\r
340 #endif\r
341 good:\r
342 #ifdef __BORLANDC__\r
343         __asm {\r
344 #endif\r
345                 cmp     ax,[WORD PTR length]\r
346                 je      done\r
347 //              errno = ENOMEM;                         // user manager knows this is bad write\r
348                 mov     flag,0\r
349                 jmp End\r
350 #ifdef __BORLANDC__\r
351         }\r
352 #endif\r
353 done:\r
354 #ifdef __BORLANDC__\r
355         __asm {\r
356 #endif\r
357                 mov     flag,1\r
358 #ifdef __BORLANDC__\r
359         }\r
360 #endif\r
361 End:\r
362 #ifdef __WATCOMC__\r
363         }\r
364 #endif\r
365         return flag;\r
366 }\r
367 \r
368 \r
369 /*\r
370 ==========================\r
371 =\r
372 = CA_ReadFile\r
373 =\r
374 = Reads a file into an allready allocated buffer\r
375 =\r
376 ==========================\r
377 */\r
378 \r
379 boolean CA_ReadFile(char *filename, memptr *ptr, global_game_variables_t *gvar)\r
380 {\r
381         int handle;\r
382         sdword size;\r
383         //long size;\r
384 \r
385         if((handle = open(filename,O_RDONLY | O_BINARY, S_IREAD)) == -1)\r
386                 return false;\r
387 \r
388         size = filelength(handle);\r
389 #ifdef __DEBUG_CA__\r
390         if(dbg_debugca>0){\r
391                 printf("===============================================================================\n");\r
392                 printf("                CA_ReadFile\n");\r
393                 printf("===============================================================================\n");\r
394                 //%04x\r
395                 printf("        ptr=%Fp\n", ptr);\r
396                 printf("        *ptr=%Fp\n", *ptr);\r
397                 printf("        &ptr=%Fp\n", &ptr);\r
398         }\r
399 #endif\r
400         if(!CA_FarRead(handle,*ptr,size, gvar))\r
401         {\r
402                 close(handle);\r
403                 return false;\r
404         }\r
405         close(handle);\r
406         return true;\r
407 }\r
408 \r
409 \r
410 /*\r
411 ==========================\r
412 =\r
413 = CA_WriteFile\r
414 =\r
415 = Writes a file from a memory buffer\r
416 =\r
417 ==========================\r
418 */\r
419 \r
420 boolean CA_WriteFile (char *filename, void far *ptr, long length, global_game_variables_t *gvar)\r
421 {\r
422         int handle;\r
423         //sdword size;\r
424         //long size;\r
425 \r
426         handle = open(filename,O_CREAT | O_BINARY | O_WRONLY,\r
427                                 S_IREAD | S_IWRITE | S_IFREG);\r
428 \r
429         if (handle == -1)\r
430                 return false;\r
431 \r
432         if (!CA_FarWrite (handle,ptr,length, gvar))\r
433         {\r
434                 close(handle);\r
435                 return false;\r
436         }\r
437         close(handle);\r
438         return true;\r
439 }\r
440 \r
441 \r
442 \r
443 /*\r
444 ==========================\r
445 =\r
446 = CA_LoadFile\r
447 =\r
448 = Allocate space for and load a file\r
449 =\r
450 ==========================\r
451 */\r
452 \r
453 boolean CA_LoadFile(char *filename, memptr *ptr, global_game_variables_t *gvar)\r
454 {\r
455         int handle;\r
456         sdword size;\r
457         //long size;\r
458 \r
459         if((handle = open(filename,O_RDONLY | O_BINARY, S_IREAD)) == -1)\r
460                 return false;\r
461 \r
462         size = filelength(handle);\r
463 #ifdef __DEBUG_CA__\r
464         if(dbg_debugca>0){\r
465                 printf("===============================================================================\n");\r
466                 printf("                CA_LoadFile\n");\r
467                 printf("===============================================================================\n");\r
468                 //%04x\r
469                 printf("        ptr=%Fp\n", ptr);\r
470                 printf("        *ptr=%Fp\n", *ptr);\r
471                 printf("        &ptr=%Fp\n", &ptr);\r
472         }\r
473 #endif\r
474         MM_GetPtr(ptr,size, gvar);\r
475 #ifdef __DEBUG_CA__\r
476         if(dbg_debugca>0){\r
477                 //%04x\r
478                 printf("---------------------------------------\n");\r
479                 printf("        ptr=%Fp\n", ptr);\r
480                 printf("        *ptr=%Fp\n", *ptr);\r
481                 printf("        &ptr=%Fp\n", &ptr);\r
482                 printf("-------------------------------------------------------------------------------\n");\r
483         }\r
484 #endif\r
485         if(!CA_FarRead(handle,*ptr,size, gvar))\r
486         {\r
487                 close(handle);\r
488                 return false;\r
489         }\r
490         close(handle);\r
491         return true;\r
492 }\r
493 \r
494 /*\r
495 ============================================================================\r
496 \r
497                 COMPRESSION routines, see JHUFF.C for more\r
498 \r
499 ============================================================================\r
500 */\r
501 \r
502 \r
503 \r
504 /*\r
505 ===============\r
506 =\r
507 = CAL_OptimizeNodes\r
508 =\r
509 = Goes through a huffman table and changes the 256-511 node numbers to the\r
510 = actular address of the node.  Must be called before CAL_HuffExpand\r
511 =\r
512 ===============\r
513 */\r
514 \r
515 void CAL_OptimizeNodes(huffnode *table)\r
516 {\r
517   huffnode *node;\r
518   int i;\r
519 \r
520   node = table;\r
521 \r
522   for (i=0;i<255;i++)\r
523   {\r
524         if (node->bit0 >= 256)\r
525           node->bit0 = (unsigned)(table+(node->bit0-256));\r
526         if (node->bit1 >= 256)\r
527           node->bit1 = (unsigned)(table+(node->bit1-256));\r
528         node++;\r
529   }\r
530 }\r
531 \r
532 \r
533 \r
534 /*\r
535 ======================\r
536 =\r
537 = CAL_HuffExpand\r
538 =\r
539 = Length is the length of the EXPANDED data\r
540 =\r
541 ======================\r
542 */\r
543 \r
544 void CAL_HuffExpand (byte far *source, byte far *dest,\r
545   long length,huffnode *hufftable)\r
546 {\r
547 //  unsigned bit,byte,node,code;\r
548   unsigned sourceseg,sourceoff,destseg,destoff,endoff;\r
549         huffnode *headptr;\r
550 //  huffnode *nodeon;\r
551 \r
552         headptr = hufftable+254;        // head node is allways node 254\r
553 \r
554   source++;     // normalize\r
555   source--;\r
556   dest++;\r
557   dest--;\r
558 \r
559   sourceseg = FP_SEG(source);\r
560   sourceoff = FP_OFF(source);\r
561   destseg = FP_SEG(dest);\r
562   destoff = FP_OFF(dest);\r
563   endoff = destoff+length;\r
564 \r
565 //\r
566 // ds:si source\r
567 // es:di dest\r
568 // ss:bx node pointer\r
569 //\r
570 \r
571         if (length <0xfff0)\r
572         {\r
573 \r
574 //--------------------------\r
575 // expand less than 64k of data\r
576 //--------------------------\r
577 \r
578         __asm {\r
579                 mov     bx,[word ptr headptr]\r
580 \r
581                 mov     si,[sourceoff]\r
582                 mov     di,[destoff]\r
583                 mov     es,[destseg]\r
584                 mov     ds,[sourceseg]\r
585                 mov     ax,[endoff]\r
586 \r
587                 mov     ch,[si]                         // load first byte\r
588                 inc     si\r
589                 mov     cl,1\r
590 #ifdef __BORLANDC__\r
591         }\r
592 #endif\r
593 expandshort:\r
594 #ifdef __BORLANDC__\r
595         __asm {\r
596 #endif\r
597                 test    ch,cl                   // bit set?\r
598                 jnz     bit1short\r
599                 mov     dx,[ss:bx]                      // take bit0 path from node\r
600                 shl     cl,1                            // advance to next bit position\r
601                 jc      newbyteshort\r
602                 jnc     sourceupshort\r
603 #ifdef __BORLANDC__\r
604         }\r
605 #endif\r
606 bit1short:\r
607 #ifdef __BORLANDC__\r
608         __asm {\r
609 #endif\r
610                 mov     dx,[ss:bx+2]            // take bit1 path\r
611                 shl     cl,1                            // advance to next bit position\r
612                 jnc     sourceupshort\r
613 #ifdef __BORLANDC__\r
614         }\r
615 #endif\r
616 newbyteshort:\r
617 #ifdef __BORLANDC__\r
618         __asm {\r
619 #endif\r
620                 mov     ch,[si]                         // load next byte\r
621                 inc     si\r
622                 mov     cl,1                            // back to first bit\r
623 #ifdef __BORLANDC__\r
624         }\r
625 #endif\r
626 sourceupshort:\r
627 #ifdef __BORLANDC__\r
628         __asm {\r
629 #endif\r
630                 or      dh,dh                           // if dx<256 its a byte, else move node\r
631                 jz      storebyteshort\r
632                 mov     bx,dx                           // next node = (huffnode *)code\r
633                 jmp     expandshort\r
634 #ifdef __BORLANDC__\r
635         }\r
636 #endif\r
637 storebyteshort:\r
638 #ifdef __BORLANDC__\r
639         __asm {\r
640 #endif\r
641                 mov     [es:di],dl\r
642                 inc     di                                      // write a decopmpressed byte out\r
643                 mov     bx,[word ptr headptr]           // back to the head node for next bit\r
644 \r
645                 cmp     di,ax                           // done?\r
646                 jne     expandshort\r
647         }\r
648         }\r
649         else\r
650         {\r
651 \r
652 //--------------------------\r
653 // expand more than 64k of data\r
654 //--------------------------\r
655 \r
656   length--;\r
657 \r
658         __asm {\r
659                 mov     bx,[word ptr headptr]\r
660                 mov     cl,1\r
661 \r
662                 mov     si,[sourceoff]\r
663                 mov     di,[destoff]\r
664                 mov     es,[destseg]\r
665                 mov     ds,[sourceseg]\r
666 \r
667                 lodsb                   // load first byte\r
668 #ifdef __BORLANDC__\r
669         }\r
670 #endif\r
671 expand:\r
672 #ifdef __BORLANDC__\r
673         __asm {\r
674 #endif\r
675                 test    al,cl           // bit set?\r
676                 jnz     bit1\r
677                 mov     dx,[ss:bx]      // take bit0 path from node\r
678                 jmp     gotcode\r
679 #ifdef __BORLANDC__\r
680         }\r
681 #endif\r
682 bit1:\r
683 #ifdef __BORLANDC__\r
684         __asm {\r
685 #endif\r
686                 mov     dx,[ss:bx+2]    // take bit1 path\r
687 #ifdef __BORLANDC__\r
688         }\r
689 #endif\r
690 gotcode:\r
691 #ifdef __BORLANDC__\r
692         __asm {\r
693 #endif\r
694                 shl     cl,1            // advance to next bit position\r
695                 jnc     sourceup\r
696                 lodsb\r
697                 cmp     si,0x10         // normalize ds:si\r
698                 jb      sinorm\r
699                 mov     cx,ds\r
700                 inc     cx\r
701                 mov     ds,cx\r
702                 xor     si,si\r
703 #ifdef __BORLANDC__\r
704         }\r
705 #endif\r
706 sinorm:\r
707 #ifdef __BORLANDC__\r
708         __asm {\r
709 #endif\r
710                 mov     cl,1            // back to first bit\r
711 #ifdef __BORLANDC__\r
712         }\r
713 #endif\r
714 sourceup:\r
715 #ifdef __BORLANDC__\r
716         __asm {\r
717 #endif\r
718                 or      dh,dh           // if dx<256 its a byte, else move node\r
719                 jz      storebyte\r
720                 mov     bx,dx           // next node = (huffnode *)code\r
721                 jmp     expand\r
722 #ifdef __BORLANDC__\r
723         }\r
724 #endif\r
725 storebyte:\r
726 #ifdef __BORLANDC__\r
727         __asm {\r
728 #endif\r
729                 mov     [es:di],dl\r
730                 inc     di              // write a decopmpressed byte out\r
731                 mov     bx,[word ptr headptr]   // back to the head node for next bit\r
732 \r
733                 cmp     di,0x10         // normalize es:di\r
734                 jb      dinorm\r
735                 mov     dx,es\r
736                 inc     dx\r
737                 mov     es,dx\r
738                 xor     di,di\r
739 #ifdef __BORLANDC__\r
740         }\r
741 #endif\r
742 dinorm:\r
743 #ifdef __BORLANDC__\r
744         __asm {\r
745 #endif\r
746                 sub     [WORD PTR ss:length],1\r
747                 jnc     expand\r
748                 dec     [WORD PTR ss:length+2]\r
749                 jns     expand          // when length = ffff ffff, done\r
750         }\r
751         }\r
752 \r
753         __asm {\r
754                 mov     ax,ss\r
755                 mov     ds,ax\r
756         }\r
757 \r
758 }\r
759 \r
760 \r
761 /*\r
762 ======================\r
763 =\r
764 = CAL_CarmackExpand\r
765 =\r
766 = Length is the length of the EXPANDED data\r
767 =\r
768 ======================\r
769 */\r
770 \r
771 #define NEARTAG 0xa7\r
772 #define FARTAG  0xa8\r
773 \r
774 void CAL_CarmackExpand (unsigned far *source, unsigned far *dest, unsigned length)\r
775 {\r
776         unsigned        ch,chhigh,count,offset;\r
777         unsigned        far *copyptr, far *inptr, far *outptr;\r
778 \r
779         length/=2;\r
780 \r
781         inptr = source;\r
782         outptr = dest;\r
783 \r
784         while (length)\r
785         {\r
786                 ch = *inptr++;\r
787                 chhigh = ch>>8;\r
788                 if (chhigh == NEARTAG)\r
789                 {\r
790                         count = ch&0xff;\r
791                         if (!count)\r
792                         {                               // have to insert a word containing the tag byte\r
793                                 ch |= *(/*(unsigned char far *)*/inptr)++;\r
794                                 *outptr++ = ch;\r
795                                 length--;\r
796                         }\r
797                         else\r
798                         {\r
799                                 offset = *(/*(unsigned char far *)*/inptr)++;\r
800                                 copyptr = outptr - offset;\r
801                                 length -= count;\r
802                                 while (count--)\r
803                                         *outptr++ = *copyptr++;\r
804                         }\r
805                 }\r
806                 else if (chhigh == FARTAG)\r
807                 {\r
808                         count = ch&0xff;\r
809                         if (!count)\r
810                         {                               // have to insert a word containing the tag byte\r
811                                 ch |= *(/*(unsigned char far *)*/inptr)++;\r
812                                 *outptr++ = ch;\r
813                                 length --;\r
814                         }\r
815                         else\r
816                         {\r
817                                 offset = *inptr++;\r
818                                 copyptr = dest + offset;\r
819                                 length -= count;\r
820                                 while (count--)\r
821                                         *outptr++ = *copyptr++;\r
822                         }\r
823                 }\r
824                 else\r
825                 {\r
826                         *outptr++ = ch;\r
827                         length --;\r
828                 }\r
829         }\r
830 }\r
831 \r
832 \r
833 /*\r
834 ======================\r
835 =\r
836 = CA_RLEWcompress\r
837 =\r
838 ======================\r
839 */\r
840 \r
841 long CA_RLEWCompress (unsigned far *source, long length, unsigned far *dest,\r
842   unsigned rlewtag)\r
843 {\r
844   long complength;\r
845   unsigned value,count,i;\r
846   unsigned far *start,far *end;\r
847 \r
848   start = dest;\r
849 \r
850   end = source + (length+1)/2;\r
851 \r
852 //\r
853 // compress it\r
854 //\r
855   do\r
856   {\r
857         count = 1;\r
858         value = *source++;\r
859         while (*source == value && source<end)\r
860         {\r
861           count++;\r
862           source++;\r
863         }\r
864         if (count>3 || value == rlewtag)\r
865         {\r
866     //\r
867     // send a tag / count / value string\r
868     //\r
869       *dest++ = rlewtag;\r
870       *dest++ = count;\r
871       *dest++ = value;\r
872     }\r
873     else\r
874     {\r
875     //\r
876     // send word without compressing\r
877     //\r
878       for (i=1;i<=count;i++)\r
879         *dest++ = value;\r
880         }\r
881 \r
882   } while (source<end);\r
883 \r
884   complength = 2*(dest-start);\r
885   return complength;\r
886 }\r
887 \r
888 \r
889 /*\r
890 ======================\r
891 =\r
892 = CA_RLEWexpand\r
893 = length is EXPANDED length\r
894 =\r
895 ======================\r
896 */\r
897 \r
898 void CA_RLEWexpand (unsigned far *source, unsigned far *dest,long length,\r
899   unsigned rlewtag)\r
900 {\r
901 //  unsigned value,count,i;\r
902   unsigned far *end;\r
903   unsigned sourceseg,sourceoff,destseg,destoff,endseg,endoff;\r
904 \r
905 \r
906 //\r
907 // expand it\r
908 //\r
909 #if 0\r
910   do\r
911   {\r
912         value = *source++;\r
913         if (value != rlewtag)\r
914         //\r
915         // uncompressed\r
916         //\r
917           *dest++=value;\r
918         else\r
919         {\r
920         //\r
921         // compressed string\r
922         //\r
923           count = *source++;\r
924           value = *source++;\r
925           for (i=1;i<=count;i++)\r
926         *dest++ = value;\r
927         }\r
928   } while (dest<end);\r
929 #endif\r
930 \r
931   end = dest + (length)/2;\r
932   sourceseg = FP_SEG(source);\r
933   sourceoff = FP_OFF(source);\r
934   destseg = FP_SEG(dest);\r
935   destoff = FP_OFF(dest);\r
936   endseg = FP_SEG(end);\r
937   endoff = FP_OFF(end);\r
938 \r
939 \r
940 //\r
941 // ax = source value\r
942 // bx = tag value\r
943 // cx = repeat counts\r
944 // dx = scratch\r
945 //\r
946 // NOTE: A repeat count that produces 0xfff0 bytes can blow this!\r
947 //\r
948         __asm {\r
949                 mov     bx,rlewtag\r
950                 mov     si,sourceoff\r
951                 mov     di,destoff\r
952                 mov     es,destseg\r
953                 mov     ds,sourceseg\r
954 #ifdef __BORLANDC__\r
955         }\r
956 #endif\r
957 expand:\r
958 #ifdef __BORLANDC__\r
959         __asm {\r
960 #endif\r
961                 lodsw\r
962                 cmp     ax,bx\r
963                 je      repeat\r
964                 stosw\r
965                 jmp     next\r
966 #ifdef __BORLANDC__\r
967         }\r
968 #endif\r
969 repeat:\r
970 #ifdef __BORLANDC__\r
971         __asm {\r
972 #endif\r
973                 lodsw\r
974                 mov     cx,ax           // repeat count\r
975                 lodsw                   // repeat value\r
976                 rep stosw\r
977 #ifdef __BORLANDC__\r
978         }\r
979 #endif\r
980 next:\r
981 #ifdef __BORLANDC__\r
982         __asm {\r
983 #endif\r
984                 cmp     si,0x10         // normalize ds:si\r
985                 jb      sinorm\r
986                 mov     ax,si\r
987                 shr     ax,1\r
988                 shr     ax,1\r
989                 shr     ax,1\r
990                 shr     ax,1\r
991                 mov     dx,ds\r
992                 add     dx,ax\r
993                 mov     ds,dx\r
994                 and     si,0xf\r
995 #ifdef __BORLANDC__\r
996         }\r
997 #endif\r
998 sinorm:\r
999 #ifdef __BORLANDC__\r
1000         __asm {\r
1001 #endif\r
1002                 cmp     di,0x10         // normalize es:di\r
1003                 jb      dinorm\r
1004                 mov     ax,di\r
1005                 shr     ax,1\r
1006                 shr     ax,1\r
1007                 shr     ax,1\r
1008                 shr     ax,1\r
1009                 mov     dx,es\r
1010                 add     dx,ax\r
1011                 mov     es,dx\r
1012                 and     di,0xf\r
1013 #ifdef __BORLANDC__\r
1014         }\r
1015 #endif\r
1016 dinorm:\r
1017 #ifdef __BORLANDC__\r
1018         __asm {\r
1019 #endif\r
1020                 cmp     di,ss:endoff\r
1021                 jne     expand\r
1022                 mov     ax,es\r
1023                 cmp     ax,ss:endseg\r
1024                 jb      expand\r
1025 \r
1026                 mov     ax,ss\r
1027                 mov     ds,ax\r
1028         }\r
1029 }\r
1030 \r
1031 \r
1032 /*\r
1033 =============================================================================\r
1034 \r
1035                                          CACHE MANAGER ROUTINES\r
1036 \r
1037 =============================================================================\r
1038 */\r
1039 \r
1040 /*\r
1041 ======================\r
1042 =\r
1043 = CAL_SetupGrFile\r
1044 =\r
1045 ======================\r
1046 */\r
1047 \r
1048 void CAL_SetupGrFile (global_game_variables_t *gvar)\r
1049 {\r
1050         char fname[13];\r
1051         int handle;\r
1052         memptr compseg;\r
1053 \r
1054 #ifdef GRHEADERLINKED\r
1055 \r
1056         gvar->ca.grhuffman = (huffnode *)&VGAdict;\r
1057         grstarts = (long _seg *)FP_SEG(&VGAhead);\r
1058 \r
1059         CAL_OptimizeNodes (gvar->ca.grhuffman);\r
1060 \r
1061 #else\r
1062 \r
1063 //\r
1064 // load ???dict.ext (huffman dictionary for graphics files)\r
1065 //\r
1066 \r
1067         strcpy(fname,GDICTNAME);\r
1068         strcat(fname,EXTENSION);\r
1069 \r
1070         if ((handle = open(fname,\r
1071                  O_RDONLY | O_BINARY, S_IREAD)) == -1)\r
1072                 CA_CannotOpen(fname,gvar);\r
1073 \r
1074         read(handle, &gvar->ca.grhuffman, sizeof(gvar->ca.grhuffman));\r
1075         close(handle);\r
1076         CAL_OptimizeNodes (gvar->ca.grhuffman);\r
1077 //\r
1078 // load the data offsets from ???head.ext\r
1079 //\r
1080         MM_GetPtr (MEMPTRCONV gvar->ca.grstarts,(NUMCHUNKS+1)*FILEPOSSIZE, gvar);\r
1081 \r
1082         strcpy(fname,GHEADNAME);\r
1083         strcat(fname,EXTENSION);\r
1084 \r
1085         if ((handle = open(fname,\r
1086                  O_RDONLY | O_BINARY, S_IREAD)) == -1)\r
1087                 CA_CannotOpen(fname,gvar);\r
1088 \r
1089         CA_FarRead(handle, (memptr)gvar->ca.grstarts, (NUMCHUNKS+1)*FILEPOSSIZE, gvar);\r
1090 \r
1091         close(handle);\r
1092 \r
1093 \r
1094 #endif\r
1095 \r
1096 //\r
1097 // Open the graphics file, leaving it open until the game is finished\r
1098 //\r
1099         strcpy(fname,GFILENAME);\r
1100         strcat(fname,EXTENSION);\r
1101 \r
1102         gvar->ca.file.grhandle = open(fname, O_RDONLY | O_BINARY);\r
1103         if (gvar->ca.file.grhandle == -1)\r
1104                 CA_CannotOpen(fname,gvar);\r
1105 \r
1106 \r
1107 //\r
1108 // load the pic and sprite headers into the arrays in the data segment\r
1109 //\r
1110 #if NUMPICS>0\r
1111         MM_GetPtr(MEMPTRCONV gvar->video.pictable,NUMPICS*sizeof(pictabletype),gvar);\r
1112         CAL_GetGrChunkLength(STRUCTPIC,gvar);           // position file pointer\r
1113         printf("CAL_SetupGrFile:\n");\r
1114         printf("        gvar->ca.chunkcomplen size is %lu\n", gvar->ca.chunkcomplen);\r
1115         MM_GetPtr(&compseg,gvar->ca.chunkcomplen,gvar);\r
1116         IN_Ack(gvar);\r
1117         CA_FarRead (gvar->ca.file.grhandle,compseg,gvar->ca.chunkcomplen,gvar);\r
1118         CAL_HuffExpand (compseg, (byte far *)gvar->video.pictable,NUMPICS*sizeof(pictabletype),gvar->ca.grhuffman);\r
1119         MM_FreePtr(&compseg,gvar);\r
1120 #endif\r
1121 \r
1122 #if NUMPICM>0\r
1123         MM_GetPtr(MEMPTRCONV picmtable,NUMPICM*sizeof(pictabletype));\r
1124         CAL_GetGrChunkLength(STRUCTPICM);               // position file pointer\r
1125         MM_GetPtr(&compseg,gvar->ca.chunkcomplen);\r
1126         CA_FarRead (gvar->ca.file.grhandle,compseg,gvar->ca.chunkcomplen);\r
1127         CAL_HuffExpand (compseg, (byte far *)picmtable,NUMPICS*sizeof(pictabletype),gvar->ca.grhuffman);\r
1128         MM_FreePtr(&compseg);\r
1129 #endif\r
1130 \r
1131 #if NUMSPRITES>0\r
1132         MM_GetPtr(MEMPTRCONV spritetable,NUMSPRITES*sizeof(spritetabletype));\r
1133         CAL_GetGrChunkLength(STRUCTSPRITE);     // position file pointer\r
1134         MM_GetPtr(&compseg,gvar->ca.chunkcomplen);\r
1135         CA_FarRead (gvar->ca.file.grhandle,compseg,gvar->ca.chunkcomplen);\r
1136         CAL_HuffExpand (compseg, (byte far *)spritetable,NUMSPRITES*sizeof(spritetabletype),gvar->ca.grhuffman);\r
1137         MM_FreePtr(&compseg);\r
1138 #endif\r
1139 \r
1140 }\r
1141 \r
1142 //==========================================================================\r
1143 \r
1144 \r
1145 /*\r
1146 ======================\r
1147 =\r
1148 = CAL_SetupMapFile\r
1149 =\r
1150 ======================\r
1151 */\r
1152 \r
1153 void CAL_SetupMapFile (global_game_variables_t *gvar)\r
1154 {\r
1155 #ifndef MAPHEADERLINKED\r
1156         int handle;\r
1157         long length;\r
1158 #endif\r
1159 \r
1160 //\r
1161 // load maphead.ext (offsets and tileinfo for map file)\r
1162 //\r
1163 #ifndef MAPHEADERLINKED\r
1164         if ((handle = open("maphead.mph",\r
1165                  O_RDONLY | O_BINARY, S_IREAD)) == -1)\r
1166                 Quit (gvar, "Can't open maphead.mph");\r
1167         length = filelength(handle);\r
1168         MM_GetPtr (MEMPTRCONV gvar->ca.tinf,length,gvar);\r
1169         CA_FarRead(handle, gvar->ca.tinf, length,gvar);\r
1170         close(handle);\r
1171 //#else\r
1172 \r
1173         gvar->ca.tinf = (byte _seg *)FP_SEG(&maphead);\r
1174 \r
1175 #endif\r
1176 \r
1177 //\r
1178 // open the data file\r
1179 //\r
1180 //TODO: multiple files\r
1181         if ((gvar->ca.file.maphandle = open("data/test.map",\r
1182                  O_RDONLY | O_BINARY, S_IREAD)) == -1)\r
1183                 Quit (gvar, "Can't open data/test.map!");\r
1184 /*#ifdef MAPHEADERLINKED\r
1185         if ((maphandle = open("GAMEMAPS.16"ENSION,\r
1186                  O_RDONLY | O_BINARY, S_IREAD)) == -1)\r
1187                 Quit ("Can't open GAMEMAPS.16"ENSION"!");\r
1188 #else\r
1189         if ((maphandle = open("MAPTEMP.16"ENSION,\r
1190                  O_RDONLY | O_BINARY, S_IREAD)) == -1)\r
1191                 Quit ("Can't open MAPTEMP.16"ENSION"!");\r
1192 #endif*/\r
1193 }\r
1194 \r
1195 //==========================================================================\r
1196 \r
1197 \r
1198 /*\r
1199 ======================\r
1200 =\r
1201 = CAL_SetupAudioFile\r
1202 =\r
1203 ======================\r
1204 */\r
1205 \r
1206 /*void CAL_SetupAudioFile (void)\r
1207 {\r
1208         int handle;\r
1209         long length;\r
1210 \r
1211 //\r
1212 // load maphead.ext (offsets and tileinfo for map file)\r
1213 //\r
1214 #ifndef AUDIOHEADERLINKED\r
1215         if ((handle = open("AUDIOHED.16",\r
1216                  O_RDONLY | O_BINARY, S_IREAD)) == -1)\r
1217                 Quit (gvar, "Can't open AUDIOHED.16""!");\r
1218         length = filelength(handle);\r
1219         MM_GetPtr (MEMPTRCONV audiostarts,length);\r
1220         CA_FarRead(handle, (byte far *)audiostarts, length);\r
1221         close(handle);\r
1222 #else\r
1223         audiohuffman = (huffnode *)&audiodict;\r
1224         CAL_OptimizeNodes (audiohuffman);\r
1225         audiostarts = (long _seg *)FP_SEG(&audiohead);\r
1226 #endif\r
1227 \r
1228 //\r
1229 // open the data file\r
1230 //\r
1231 #ifndef AUDIOHEADERLINKED\r
1232         if ((audiohandle = open("AUDIOT.16",\r
1233                  O_RDONLY | O_BINARY, S_IREAD)) == -1)\r
1234                 Quit (gvar, "Can't open AUDIOT.16""!");\r
1235 #else\r
1236         if ((audiohandle = open("AUDIO.16",\r
1237                  O_RDONLY | O_BINARY, S_IREAD)) == -1)\r
1238                 Quit (gvar, "Can't open AUDIO.16""!");\r
1239 #endif\r
1240 }*/\r
1241 \r
1242 //==========================================================================\r
1243 \r
1244 \r
1245 /*\r
1246 ======================\r
1247 =\r
1248 = CA_Startup\r
1249 =\r
1250 = Open all files and load in headers\r
1251 =\r
1252 ======================\r
1253 */\r
1254 \r
1255 void CA_Startup(global_game_variables_t *gvar)\r
1256 {\r
1257 #ifdef PROFILE\r
1258 #ifdef __BORLANDC__\r
1259         unlink("profile.16b");\r
1260         gvar->handle.profilehandle = open("profile.16b", O_CREAT | O_WRONLY | O_TEXT);\r
1261 #endif\r
1262 #ifdef __WATCOMC__\r
1263         unlink("profile.16w");\r
1264         gvar->handle.profilehandle = open("profile.16w", O_CREAT | O_WRONLY | O_TEXT);\r
1265 #endif\r
1266 #endif//profile\r
1267 \r
1268 #ifdef __BORLANDC__\r
1269         unlink("meminfo.16b");\r
1270         gvar->handle.showmemhandle = open("meminfo.16b", O_CREAT | O_WRONLY | O_TEXT);\r
1271 #endif\r
1272 #ifdef __WATCOMC__\r
1273         unlink("meminfo.16w");\r
1274         gvar->handle.showmemhandle = open("meminfo.16w", O_CREAT | O_WRONLY | O_TEXT);\r
1275 #endif\r
1276 \r
1277 \r
1278 #ifndef NOMAPS\r
1279         CAL_SetupMapFile (gvar);\r
1280 #endif\r
1281 #ifndef NOGRAPHICS\r
1282         CAL_SetupGrFile (gvar);\r
1283 #endif\r
1284 #ifndef NOAUDIO\r
1285         CAL_SetupMapFile (gvar);\r
1286 #endif\r
1287 \r
1288         gvar->ca.camap.mapon = -1;\r
1289         gvar->ca.ca_levelbit = 1;\r
1290         gvar->ca.ca_levelnum = 0;\r
1291 \r
1292 /*      drawcachebox    = CAL_DialogDraw;\r
1293         updatecachebox  = CAL_DialogUpdate;\r
1294         finishcachebox  = CAL_DialogFinish;*/\r
1295 }\r
1296 \r
1297 //==========================================================================\r
1298 \r
1299 \r
1300 /*\r
1301 ======================\r
1302 =\r
1303 = CA_Shutdown\r
1304 =\r
1305 = Closes all files\r
1306 =\r
1307 ======================\r
1308 */\r
1309 \r
1310 void CA_Shutdown(global_game_variables_t *gvar)\r
1311 {\r
1312 #ifdef PROFILE\r
1313         close(gvar->handle.profilehandle);\r
1314 #endif\r
1315         close(gvar->handle.showmemhandle);\r
1316 \r
1317         close(gvar->ca.file.maphandle);\r
1318         close(gvar->ca.file.grhandle);\r
1319         close(gvar->ca.file.audiohandle);\r
1320 }\r
1321 \r
1322 //===========================================================================\r
1323 \r
1324 /*\r
1325 ======================\r
1326 =\r
1327 = CA_CacheAudioChunk\r
1328 =\r
1329 ======================\r
1330 */\r
1331 /*++++\r
1332 void CA_CacheAudioChunk (int chunk)\r
1333 {\r
1334         long    pos,compressed;\r
1335 #ifdef AUDIOHEADERLINKED\r
1336         long    expanded;\r
1337         memptr  bigbufferseg;\r
1338         byte    far *source;\r
1339 #endif\r
1340 \r
1341         if (audiosegs[chunk])\r
1342         {\r
1343                 MM_SetPurge (MEMPTRCONV audiosegs[chunk],0);\r
1344                 return;                                                 // allready in memory\r
1345         }\r
1346 \r
1347 // MDM begin - (GAMERS EDGE)\r
1348 //\r
1349         if (!FindFile("AUDIO.16",NULL,2))\r
1350                 Quit (gvar, "CA_CacheAudioChunk(): Can't find audio files.");\r
1351 //\r
1352 // MDM end\r
1353 \r
1354 //\r
1355 // load the chunk into a buffer, either the miscbuffer if it fits, or allocate\r
1356 // a larger buffer\r
1357 //\r
1358         pos = audiostarts[chunk];\r
1359         compressed = audiostarts[chunk+1]-pos;\r
1360 \r
1361         lseek(audiohandle,pos,SEEK_SET);\r
1362 \r
1363 #ifndef AUDIOHEADERLINKED\r
1364 \r
1365         MM_GetPtr (MEMPTRCONV audiosegs[chunk],compressed);\r
1366         if (mmerror)\r
1367                 return;\r
1368 \r
1369         CA_FarRead(audiohandle,audiosegs[chunk],compressed);\r
1370 \r
1371 #else\r
1372 \r
1373         if (compressed<=BUFFERSIZE)\r
1374         {\r
1375                 CA_FarRead(audiohandle,bufferseg,compressed);\r
1376                 source = bufferseg;\r
1377         }\r
1378         else\r
1379         {\r
1380                 MM_GetPtr(&bigbufferseg,compressed);\r
1381                 if (mmerror)\r
1382                         return;\r
1383                 MM_SetLock (&bigbufferseg,true);\r
1384                 CA_FarRead(audiohandle,bigbufferseg,compressed);\r
1385                 source = bigbufferseg;\r
1386         }\r
1387 \r
1388         expanded = *(long far *)source;\r
1389         source += 4;                    // skip over length\r
1390         MM_GetPtr (MEMPTRCONV audiosegs[chunk],expanded);\r
1391         if (mmerror)\r
1392                 goto done;\r
1393         CAL_HuffExpand (source,audiosegs[chunk],expanded,audiohuffman);\r
1394 \r
1395 done:\r
1396         if (compressed>BUFFERSIZE)\r
1397                 MM_FreePtr(&bigbufferseg);\r
1398 #endif\r
1399 }*/\r
1400 \r
1401 //===========================================================================\r
1402 \r
1403 /*\r
1404 ======================\r
1405 =\r
1406 = CA_LoadAllSounds\r
1407 =\r
1408 = Purges all sounds, then loads all new ones (mode switch)\r
1409 =\r
1410 ======================\r
1411 */\r
1412 /*++++\r
1413 void CA_LoadAllSounds (void)\r
1414 {\r
1415         unsigned        start,i;\r
1416 \r
1417         switch (oldsoundmode)\r
1418         {\r
1419         case sdm_Off:\r
1420                 goto cachein;\r
1421         case sdm_PC:\r
1422                 start = STARTPCSOUNDS;\r
1423                 break;\r
1424         case sdm_AdLib:\r
1425                 start = STARTADLIBSOUNDS;\r
1426                 break;\r
1427         }\r
1428 \r
1429         for (i=0;i<NUMSOUNDS;i++,start++)\r
1430                 if (audiosegs[start])\r
1431                         MM_SetPurge (MEMPTRCONV audiosegs[start],3);            // make purgable\r
1432 \r
1433 cachein:\r
1434 \r
1435         switch (SoundMode)\r
1436         {\r
1437         case sdm_Off:\r
1438                 return;\r
1439         case sdm_PC:\r
1440                 start = STARTPCSOUNDS;\r
1441                 break;\r
1442         case sdm_AdLib:\r
1443                 start = STARTADLIBSOUNDS;\r
1444                 break;\r
1445         }\r
1446 \r
1447         for (i=0;i<NUMSOUNDS;i++,start++)\r
1448                 CA_CacheAudioChunk (start);\r
1449 \r
1450         oldsoundmode = SoundMode;\r
1451 }*/\r
1452 \r
1453 //===========================================================================\r
1454 \r
1455 //????#if GRMODE == EGAGR\r
1456 #if 0\r
1457 \r
1458 /*\r
1459 ======================\r
1460 =\r
1461 = CAL_ShiftSprite\r
1462 =\r
1463 = Make a shifted (one byte wider) copy of a sprite into another area\r
1464 =\r
1465 ======================\r
1466 */\r
1467 \r
1468 unsigned        static  sheight,swidth;\r
1469 boolean static dothemask;\r
1470 \r
1471 void CAL_ShiftSprite (unsigned segment,unsigned source,unsigned dest,\r
1472         unsigned width, unsigned height, unsigned pixshift, boolean domask)\r
1473 {\r
1474 \r
1475         sheight = height;               // because we are going to reassign bp\r
1476         swidth = width;\r
1477         dothemask = domask;\r
1478 \r
1479         __asm {\r
1480                 mov     ax,[segment]\r
1481                 mov     ds,ax           // source and dest are in same segment, and all local\r
1482 \r
1483                 mov     bx,[source]\r
1484                 mov     di,[dest]\r
1485 \r
1486                 mov     bp,[pixshift]\r
1487                 shl     bp,1\r
1488                 mov     bp,WORD PTR [shifttabletable+bp]        // bp holds pointer to shift table\r
1489 \r
1490                 cmp     [ss:dothemask],0\r
1491                 je              skipmask\r
1492 \r
1493 //\r
1494 // table shift the mask\r
1495 //\r
1496                 mov     dx,[ss:sheight]\r
1497 #ifdef __BORLANDC__\r
1498         }\r
1499 #endif\r
1500 domaskrow:\r
1501 #ifdef __BORLANDC__\r
1502         __asm {\r
1503 #endif\r
1504                 mov     BYTE PTR [di],255       // 0xff first byte\r
1505                 mov     cx,ss:[swidth]\r
1506 #ifdef __BORLANDC__\r
1507         }\r
1508 #endif\r
1509 domaskbyte:\r
1510 #ifdef __BORLANDC__\r
1511         __asm {\r
1512 #endif\r
1513                 mov     al,[bx]                         // source\r
1514                 not     al\r
1515                 inc     bx                                      // next source byte\r
1516                 xor     ah,ah\r
1517                 shl     ax,1\r
1518                 mov     si,ax\r
1519                 mov     ax,[bp+si]                      // table shift into two bytes\r
1520                 not     ax\r
1521                 and     [di],al                         // and with first byte\r
1522                 inc     di\r
1523                 mov     [di],ah                         // replace next byte\r
1524 \r
1525                 loop    domaskbyte\r
1526 \r
1527                 inc     di                                      // the last shifted byte has 1s in it\r
1528                 dec     dx\r
1529                 jnz     domaskrow\r
1530 #ifdef __BORLANDC__\r
1531         }\r
1532 #endif\r
1533 skipmask:\r
1534 #ifdef __BORLANDC__\r
1535         __asm {\r
1536 #endif\r
1537 //\r
1538 // table shift the data\r
1539 //\r
1540                 mov     dx,ss:[sheight]\r
1541                 shl     dx,1\r
1542                 shl     dx,1                            // four planes of data\r
1543 #ifdef __BORLANDC__\r
1544         }\r
1545 #endif\r
1546 dodatarow:\r
1547 #ifdef __BORLANDC__\r
1548         __asm {\r
1549 #endif\r
1550                 mov     BYTE PTR [di],0         // 0 first byte\r
1551                 mov     cx,ss:[swidth]\r
1552 #ifdef __BORLANDC__\r
1553         }\r
1554 #endif\r
1555 dodatabyte:\r
1556 #ifdef __BORLANDC__\r
1557         __asm {\r
1558 #endif\r
1559                 mov     al,[bx]                         // source\r
1560                 inc     bx                                      // next source byte\r
1561                 xor     ah,ah\r
1562                 shl     ax,1\r
1563                 mov     si,ax\r
1564                 mov     ax,[bp+si]                      // table shift into two bytes\r
1565                 or      [di],al                         // or with first byte\r
1566                 inc     di\r
1567                 mov     [di],ah                         // replace next byte\r
1568 \r
1569                 loop    dodatabyte\r
1570 \r
1571                 inc     di                                      // the last shifted byte has 0s in it\r
1572                 dec     dx\r
1573                 jnz     dodatarow\r
1574 \r
1575 //\r
1576 // done\r
1577 //\r
1578 \r
1579                 mov     ax,ss                           // restore data segment\r
1580                 mov     ds,ax\r
1581         }\r
1582 \r
1583 }\r
1584 \r
1585 #endif\r
1586 \r
1587 //===========================================================================\r
1588 \r
1589 /*\r
1590 ======================\r
1591 =\r
1592 = CAL_CacheSprite\r
1593 =\r
1594 = Generate shifts and set up sprite structure for a given sprite\r
1595 =\r
1596 ======================\r
1597 */\r
1598 /*++++\r
1599 void CAL_CacheSprite (int chunk, byte far *compressed)\r
1600 {\r
1601         int i;\r
1602         unsigned shiftstarts[5];\r
1603         unsigned smallplane,bigplane,expanded;\r
1604         spritetabletype far *spr;\r
1605         spritetype _seg *dest;\r
1606 \r
1607 #if GRMODE == CGAGR\r
1608 //\r
1609 // CGA has no pel panning, so shifts are never needed\r
1610 //\r
1611         spr = &spritetable[chunk-STARTSPRITES];\r
1612         smallplane = spr->width*spr->height;\r
1613         MM_GetPtr (&grsegs[chunk],smallplane*2+MAXSHIFTS*6);\r
1614         if (mmerror)\r
1615                 return;\r
1616         dest = (spritetype _seg *)grsegs[chunk];\r
1617         dest->sourceoffset[0] = MAXSHIFTS*6;    // start data after 3 unsigned tables\r
1618         dest->planesize[0] = smallplane;\r
1619         dest->width[0] = spr->width;\r
1620 \r
1621 //\r
1622 // expand the unshifted shape\r
1623 //\r
1624         CAL_HuffExpand (compressed, &dest->data[0],smallplane*2,gvar->ca.grhuffman);\r
1625 \r
1626 #endif\r
1627 \r
1628 \r
1629 #if GRMODE == EGAGR\r
1630 \r
1631 //\r
1632 // calculate sizes\r
1633 //\r
1634         spr = &spritetable[chunk-STARTSPRITES];\r
1635         smallplane = spr->width*spr->height;\r
1636         bigplane = (spr->width+1)*spr->height;\r
1637 \r
1638         shiftstarts[0] = MAXSHIFTS*6;   // start data after 3 unsigned tables\r
1639         shiftstarts[1] = shiftstarts[0] + smallplane*5; // 5 planes in a sprite\r
1640         shiftstarts[2] = shiftstarts[1] + bigplane*5;\r
1641         shiftstarts[3] = shiftstarts[2] + bigplane*5;\r
1642         shiftstarts[4] = shiftstarts[3] + bigplane*5;   // nothing ever put here\r
1643 \r
1644         expanded = shiftstarts[spr->shifts];\r
1645         MM_GetPtr (&grsegs[chunk],expanded);\r
1646         if (mmerror)\r
1647                 return;\r
1648         dest = (spritetype _seg *)grsegs[chunk];\r
1649 \r
1650 //\r
1651 // expand the unshifted shape\r
1652 //\r
1653         CAL_HuffExpand (compressed, &dest->data[0],smallplane*5,gvar->ca.grhuffman);\r
1654 \r
1655 //\r
1656 // make the shifts!\r
1657 //\r
1658         switch (spr->shifts)\r
1659         {\r
1660         case    1:\r
1661                 for (i=0;i<4;i++)\r
1662                 {\r
1663                         dest->sourceoffset[i] = shiftstarts[0];\r
1664                         dest->planesize[i] = smallplane;\r
1665                         dest->width[i] = spr->width;\r
1666                 }\r
1667                 break;\r
1668 \r
1669         case    2:\r
1670                 for (i=0;i<2;i++)\r
1671                 {\r
1672                         dest->sourceoffset[i] = shiftstarts[0];\r
1673                         dest->planesize[i] = smallplane;\r
1674                         dest->width[i] = spr->width;\r
1675                 }\r
1676                 for (i=2;i<4;i++)\r
1677                 {\r
1678                         dest->sourceoffset[i] = shiftstarts[1];\r
1679                         dest->planesize[i] = bigplane;\r
1680                         dest->width[i] = spr->width+1;\r
1681                 }\r
1682                 CAL_ShiftSprite ((unsigned)grsegs[chunk],dest->sourceoffset[0],\r
1683                         dest->sourceoffset[2],spr->width,spr->height,4,true);\r
1684                 break;\r
1685 \r
1686         case    4:\r
1687                 dest->sourceoffset[0] = shiftstarts[0];\r
1688                 dest->planesize[0] = smallplane;\r
1689                 dest->width[0] = spr->width;\r
1690 \r
1691                 dest->sourceoffset[1] = shiftstarts[1];\r
1692                 dest->planesize[1] = bigplane;\r
1693                 dest->width[1] = spr->width+1;\r
1694                 CAL_ShiftSprite ((unsigned)grsegs[chunk],dest->sourceoffset[0],\r
1695                         dest->sourceoffset[1],spr->width,spr->height,2,true);\r
1696 \r
1697                 dest->sourceoffset[2] = shiftstarts[2];\r
1698                 dest->planesize[2] = bigplane;\r
1699                 dest->width[2] = spr->width+1;\r
1700                 CAL_ShiftSprite ((unsigned)grsegs[chunk],dest->sourceoffset[0],\r
1701                         dest->sourceoffset[2],spr->width,spr->height,4,true);\r
1702 \r
1703                 dest->sourceoffset[3] = shiftstarts[3];\r
1704                 dest->planesize[3] = bigplane;\r
1705                 dest->width[3] = spr->width+1;\r
1706                 CAL_ShiftSprite ((unsigned)grsegs[chunk],dest->sourceoffset[0],\r
1707                         dest->sourceoffset[3],spr->width,spr->height,6,true);\r
1708 \r
1709                 break;\r
1710 \r
1711         default:\r
1712                 Quit (gvar, "CAL_CacheSprite: Bad shifts number!");\r
1713         }\r
1714 \r
1715 #endif\r
1716 }*/\r
1717 \r
1718 //===========================================================================\r
1719 \r
1720 \r
1721 /*\r
1722 ======================\r
1723 =\r
1724 = CAL_ExpandGrChunk\r
1725 =\r
1726 = Does whatever is needed with a pointer to a compressed chunk\r
1727 =\r
1728 ======================\r
1729 */\r
1730 /*++++\r
1731 void CAL_ExpandGrChunk (int chunk, byte far *source)\r
1732 {\r
1733         long    expanded;\r
1734 \r
1735 \r
1736         if (chunk >= STARTTILE8 && chunk < STARTEXTERNS)\r
1737         {\r
1738         //\r
1739         // expanded sizes of tile8/16/32 are implicit\r
1740         //\r
1741 \r
1742 #if GRMODE == EGAGR\r
1743 #define BLOCK           32\r
1744 #define MASKBLOCK       40\r
1745 #endif\r
1746 \r
1747 #if GRMODE == CGAGR\r
1748 #define BLOCK           16\r
1749 #define MASKBLOCK       32\r
1750 #endif\r
1751 \r
1752                 if (chunk<STARTTILE8M)                  // tile 8s are all in one chunk!\r
1753                         expanded = BLOCK*NUMTILE8;\r
1754                 else if (chunk<STARTTILE16)\r
1755                         expanded = MASKBLOCK*NUMTILE8M;\r
1756                 else if (chunk<STARTTILE16M)    // all other tiles are one/chunk\r
1757                         expanded = BLOCK*4;\r
1758                 else if (chunk<STARTTILE32)\r
1759                         expanded = MASKBLOCK*4;\r
1760                 else if (chunk<STARTTILE32M)\r
1761                         expanded = BLOCK*16;\r
1762                 else\r
1763                         expanded = MASKBLOCK*16;\r
1764         }\r
1765         else\r
1766         {\r
1767         //\r
1768         // everything else has an explicit size longword\r
1769         //\r
1770                 expanded = *(long far *)source;\r
1771                 source += 4;                    // skip over length\r
1772         }\r
1773 \r
1774 //\r
1775 // allocate final space, decompress it, and free bigbuffer\r
1776 // Sprites need to have shifts made and various other junk\r
1777 //\r
1778         if (chunk>=STARTSPRITES && chunk< STARTTILE8)\r
1779                 CAL_CacheSprite(chunk,source);\r
1780         else\r
1781         {\r
1782                 MM_GetPtr (&grsegs[chunk],expanded);\r
1783                 if (mmerror)\r
1784                         return;\r
1785                 CAL_HuffExpand (source,grsegs[chunk],expanded,gvar->ca.grhuffman);\r
1786         }\r
1787 }\r
1788 */\r
1789 \r
1790 /*\r
1791 ======================\r
1792 =\r
1793 = CAL_ReadGrChunk\r
1794 =\r
1795 = Gets a chunk off disk, optimizing reads to general buffer\r
1796 =\r
1797 ======================\r
1798 */\r
1799 /*++++\r
1800 void CAL_ReadGrChunk (int chunk)\r
1801 {\r
1802         long    pos,compressed;\r
1803         memptr  bigbufferseg;\r
1804         byte    far *source;\r
1805         int             next;\r
1806 \r
1807 //\r
1808 // load the chunk into a buffer, either the miscbuffer if it fits, or allocate\r
1809 // a larger buffer\r
1810 //\r
1811         pos = GRFILEPOS(chunk,gvar);\r
1812         if (pos<0)                                                      // $FFFFFFFF start is a sparse tile\r
1813           return;\r
1814 \r
1815         next = chunk +1;\r
1816         while (GRFILEPOS(next,gvar) == -1)              // skip past any sparse tiles\r
1817                 next++;\r
1818 \r
1819         compressed = GRFILEPOS(next,gvar)-pos;\r
1820 \r
1821         lseek(gvar->ca.file.grhandle,pos,SEEK_SET);\r
1822 \r
1823         if (compressed<=BUFFERSIZE)\r
1824         {\r
1825                 CA_FarRead(gvar->ca.file.grhandle,bufferseg,compressed);\r
1826                 source = bufferseg;\r
1827         }\r
1828         else\r
1829         {\r
1830                 MM_GetPtr(&bigbufferseg,compressed);\r
1831                 if (mmerror)\r
1832                         return;\r
1833                 MM_SetLock (&bigbufferseg,true);\r
1834                 CA_FarRead(gvar->ca.file.grhandle,bigbufferseg,compressed);\r
1835                 source = bigbufferseg;\r
1836         }\r
1837 \r
1838         CAL_ExpandGrChunk (chunk,source);\r
1839 \r
1840         if (compressed>BUFFERSIZE)\r
1841                 MM_FreePtr(&bigbufferseg);\r
1842 }\r
1843 */\r
1844 /*\r
1845 ======================\r
1846 =\r
1847 = CA_CacheGrChunk\r
1848 =\r
1849 = Makes sure a given chunk is in memory, loadiing it if needed\r
1850 =\r
1851 ======================\r
1852 */\r
1853 /*++++\r
1854 void CA_CacheGrChunk (int chunk)\r
1855 {\r
1856         long    pos,compressed;\r
1857         memptr  bigbufferseg;\r
1858         byte    far *source;\r
1859         int             next;\r
1860 \r
1861         gvar->ca.grneeded[chunk] |= ca_levelbit;                // make sure it doesn't get removed\r
1862         if (grsegs[chunk])\r
1863         {\r
1864                 MM_SetPurge (&grsegs[chunk],0);\r
1865                 return;                                                 // allready in memory\r
1866         }\r
1867 \r
1868 // MDM begin - (GAMERS EDGE)\r
1869 //\r
1870         if (!FindFile("EGAGRAPH.16",NULL,2))\r
1871                 Quit (gvar, "CA_CacheGrChunk(): Can't find graphics files.");\r
1872 //\r
1873 // MDM end\r
1874 \r
1875 //\r
1876 // load the chunk into a buffer, either the miscbuffer if it fits, or allocate\r
1877 // a larger buffer\r
1878 //\r
1879         pos = GRFILEPOS(chunk,gvar);\r
1880         if (pos<0)                                                      // $FFFFFFFF start is a sparse tile\r
1881           return;\r
1882 \r
1883         next = chunk +1;\r
1884         while (GRFILEPOS(next) == -1)           // skip past any sparse tiles\r
1885                 next++;\r
1886 \r
1887         compressed = GRFILEPOS(next,gvar)-pos;\r
1888 \r
1889         lseek(gvar->ca.file.grhandle,pos,SEEK_SET);\r
1890 \r
1891         if (compressed<=BUFFERSIZE)\r
1892         {\r
1893                 CA_FarRead(gvar->ca.file.grhandle,bufferseg,compressed);\r
1894                 source = bufferseg;\r
1895         }\r
1896         else\r
1897         {\r
1898                 MM_GetPtr(&bigbufferseg,compressed);\r
1899                 MM_SetLock (&bigbufferseg,true);\r
1900                 CA_FarRead(gvar->ca.file.grhandle,bigbufferseg,compressed);\r
1901                 source = bigbufferseg;\r
1902         }\r
1903 \r
1904         CAL_ExpandGrChunk (chunk,source);\r
1905 \r
1906         if (compressed>BUFFERSIZE)\r
1907                 MM_FreePtr(&bigbufferseg);\r
1908 }\r
1909 */\r
1910 \r
1911 \r
1912 //==========================================================================\r
1913 \r
1914 /*\r
1915 ======================\r
1916 =\r
1917 = CA_CacheMap\r
1918 =\r
1919 ======================\r
1920 */\r
1921 /*++++ segments!\r
1922 void CA_CacheMap (global_game_variables_t *gvar)\r
1923 {\r
1924         long    pos,compressed;\r
1925         int             plane;\r
1926         memptr  *dest,bigbufferseg;\r
1927         unsigned        size;\r
1928         unsigned        far     *source;\r
1929 #ifdef MAPHEADERLINKED\r
1930         memptr  buffer2seg;\r
1931         long    expanded;\r
1932 #endif\r
1933 \r
1934 \r
1935 //\r
1936 // free up memory from last map\r
1937 //\r
1938         if (gvar->ca.camap.mapon>-1 && gvar->ca.camap.mapheaderseg[gvar->ca.camap.mapon])\r
1939                 MM_SetPurge (((memptr)gvar->ca.camap.mapheaderseg[(gvar->ca.camap.mapon)]), 3, gvar);\r
1940         for (plane=0;plane<MAPPLANES;plane++)\r
1941                 if (gvar->ca.camap.mapsegs[plane])\r
1942                         MM_FreePtr ((memptr)gvar->ca.camap.mapsegs[plane], gvar);\r
1943 \r
1944         gvar->ca.camap.mapon = gvar->ca.camap.mapnum;\r
1945 \r
1946 \r
1947 //\r
1948 // load map header\r
1949 // The header will be cached if it is still around\r
1950 //\r
1951 //      if (!gvar->ca.camap.mapheaderseg[gvar->ca.camap.mapnum])\r
1952 //      {\r
1953 //              //pos = ((mapfiletype   _seg *)tinf)->headeroffsets[mapnum];\r
1954 //              //pos = ((_seg *)gvar->ca.camap.tinf)->headeroffsets[gvar->ca.camap.mapnum];\r
1955 //              pos = ((memptr)gvar->ca.camap.tinf)->headeroffsets[gvar->ca.camap.mapnum];\r
1956 //              if (pos<0)                                              // $FFFFFFFF start is a sparse map\r
1957 //                printf("CA_CacheMap: Tried to load a non existent map!");\r
1958 \r
1959 //              MM_GetPtr(MEMPTRCONV gvar->ca.camapheaderseg[mapnum],sizeof(maptype));\r
1960 //              lseek(maphandle,pos,SEEK_SET);\r
1961 //              CA_FarRead (maphandle,(memptr)mapheaderseg[mapnum],sizeof(maptype));\r
1962 //      }\r
1963 //      else\r
1964 //              MM_SetPurge (MEMPTRCONV mapheaderseg[mapnum], 0, &(gvar->mm));\r
1965 \r
1966 //\r
1967 // load the planes in\r
1968 // If a plane's pointer still exists it will be overwritten (levels are\r
1969 // allways reloaded, never cached)\r
1970 //\r
1971 \r
1972         size = mapheaderseg[mapnum]->width * mapheaderseg[mapnum]->height * 2;\r
1973 \r
1974         for (plane = 0; plane<MAPPLANES; plane++)\r
1975         {\r
1976                 //pos = mapheaderseg[mapnum]->planestart[plane];\r
1977                 //compressed = mapheaderseg[mapnum]->planelength[plane];\r
1978 \r
1979                 if (!compressed)\r
1980                         continue;               // the plane is not used in this game\r
1981 \r
1982                 dest = MEMPTRCONV mapsegs[plane];\r
1983                 MM_GetPtr(dest,size);\r
1984 \r
1985                 lseek(maphandle,pos,SEEK_SET);\r
1986                 if (compressed<=BUFFERSIZE)\r
1987                         source = bufferseg;\r
1988                 else\r
1989                 {\r
1990                         MM_GetPtr(&bigbufferseg,compressed);\r
1991                         MM_SetLock (&bigbufferseg,true);\r
1992                         source = bigbufferseg;\r
1993                 }\r
1994 \r
1995                 CA_FarRead(maphandle,(byte far *)source,compressed);\r
1996 #ifdef MAPHEADERLINKED\r
1997                 //\r
1998                 // unhuffman, then unRLEW\r
1999                 // The huffman'd chunk has a two byte expanded length first\r
2000                 // The resulting RLEW chunk also does, even though it's not really\r
2001                 // needed\r
2002                 //\r
2003                 expanded = *source;\r
2004                 source++;\r
2005                 MM_GetPtr (&buffer2seg,expanded);\r
2006                 CAL_CarmackExpand (source, (unsigned far *)buffer2seg,expanded);\r
2007                 CA_RLEWexpand (((unsigned far *)buffer2seg)+1,*dest,size,\r
2008                 ((mapfiletype _seg *)tinf)->RLEWtag);\r
2009                 MM_FreePtr (&buffer2seg);\r
2010 \r
2011 #else\r
2012                 //\r
2013                 // unRLEW, skipping expanded length\r
2014                 //\r
2015                 CA_RLEWexpand (source+1, *dest,size,\r
2016                 ((mapfiletype _seg *)tinf)->RLEWtag);\r
2017 #endif\r
2018 \r
2019                 if (compressed>BUFFERSIZE)\r
2020                         MM_FreePtr(&bigbufferseg);\r
2021         }\r
2022 }//*/\r
2023 \r
2024 //===========================================================================\r
2025 \r
2026 /*\r
2027 ======================\r
2028 =\r
2029 = CA_UpLevel\r
2030 =\r
2031 = Goes up a bit level in the needed lists and clears it out.\r
2032 = Everything is made purgable\r
2033 =\r
2034 ======================\r
2035 */\r
2036 \r
2037 void CA_UpLevel (global_game_variables_t *gvar)\r
2038 {\r
2039         if (gvar->ca.ca_levelnum==7)\r
2040                 printf("CA_UpLevel: Up past level 7!");\r
2041 \r
2042         gvar->ca.ca_levelbit<<=1;\r
2043         gvar->ca.ca_levelnum++;\r
2044 }\r
2045 \r
2046 //===========================================================================\r
2047 \r
2048 /*\r
2049 ======================\r
2050 =\r
2051 = CA_DownLevel\r
2052 =\r
2053 = Goes down a bit level in the needed lists and recaches\r
2054 = everything from the lower level\r
2055 =\r
2056 ======================\r
2057 */\r
2058 \r
2059 void CA_DownLevel (global_game_variables_t *gvar)\r
2060 {\r
2061         if (!gvar->ca.ca_levelnum)\r
2062                 printf("CA_DownLevel: Down past level 0!");\r
2063         gvar->ca.ca_levelbit>>=1;\r
2064         gvar->ca.ca_levelnum--;\r
2065         ////++++++++++++++++++++++++++++++++++++++++++CA_CacheMarks(NULL);\r
2066 }\r
2067 \r
2068 //===========================================================================\r
2069 \r
2070 /*\r
2071 ======================\r
2072 =\r
2073 = CA_ClearMarks\r
2074 =\r
2075 = Clears out all the marks at the current level\r
2076 =\r
2077 ======================\r
2078 */\r
2079 \r
2080 void CA_ClearMarks (global_game_variables_t *gvar)\r
2081 {\r
2082         int i;\r
2083 \r
2084         for (i=0;i<NUMCHUNKS;i++)\r
2085                 gvar->ca.grneeded[i]&=~gvar->ca.ca_levelbit;\r
2086 }\r
2087 \r
2088 //===========================================================================\r
2089 \r
2090 /*\r
2091 ======================\r
2092 =\r
2093 = CA_ClearAllMarks\r
2094 =\r
2095 = Clears out all the marks on all the levels\r
2096 =\r
2097 ======================\r
2098 */\r
2099 \r
2100 void CA_ClearAllMarks (global_game_variables_t *gvar)\r
2101 {\r
2102         _fmemset (gvar->ca.grneeded,0,sizeof(gvar->ca.grneeded));\r
2103         gvar->ca.ca_levelbit = 1;\r
2104         gvar->ca.ca_levelnum = 0;\r
2105 }\r
2106 \r
2107 //===========================================================================\r
2108 \r
2109 /*\r
2110 ======================\r
2111 =\r
2112 = CA_FreeGraphics\r
2113 =\r
2114 ======================\r
2115 */\r
2116 \r
2117 void CA_SetGrPurge (global_game_variables_t *gvar)\r
2118 {\r
2119         int i;\r
2120 \r
2121 //\r
2122 // free graphics\r
2123 //\r
2124         CA_ClearMarks (gvar);\r
2125 \r
2126         for (i=0;i<NUMCHUNKS;i++)\r
2127                 if (gvar->ca.grsegs[i])\r
2128                         MM_SetPurge (gvar->ca.grsegs[i],3, gvar);\r
2129 }\r
2130 \r
2131 \r
2132 /*\r
2133 ======================\r
2134 =\r
2135 = CA_SetAllPurge\r
2136 =\r
2137 = Make everything possible purgable\r
2138 =\r
2139 ======================\r
2140 */\r
2141 \r
2142 void CA_SetAllPurge (global_game_variables_t *gvar)\r
2143 {\r
2144         int i;\r
2145 \r
2146         CA_ClearMarks (gvar);\r
2147 \r
2148 //\r
2149 // free cursor sprite and background save\r
2150 //\r
2151         //____VW_FreeCursor ();\r
2152 \r
2153 //\r
2154 // free map headers and map planes\r
2155 //\r
2156 //      for (i=0;i<NUMMAPS;i++)\r
2157 //              if (gvar->ca.camap.mapheaderseg[i])\r
2158 //                      MM_SetPurge (gvar->ca.camap.mapheaderseg[i],3, gvar);\r
2159 \r
2160         for (i=0;i<3;i++)\r
2161                 if (gvar->ca.mapsegs[i])\r
2162                         MM_FreePtr ((memptr *)&gvar->ca.mapsegs[i], gvar);\r
2163 \r
2164 //\r
2165 // free sounds\r
2166 //\r
2167         for (i=0;i<NUMSNDCHUNKS;i++)\r
2168                 if (gvar->ca.audiosegs[i])\r
2169                         MM_SetPurge ((memptr *)&gvar->ca.audiosegs[i],3, gvar);\r
2170 \r
2171 //\r
2172 // free graphics\r
2173 //\r
2174         CA_SetGrPurge (gvar);\r
2175 }\r
2176 \r
2177 \r
2178 //===========================================================================\r
2179 \r
2180 \r
2181 /*\r
2182 ======================\r
2183 =\r
2184 = CAL_DialogDraw\r
2185 =\r
2186 ======================\r
2187 */\r
2188 /*\r
2189 #define NUMBARS (17l*8)\r
2190 #define BARSTEP 8\r
2191 \r
2192 unsigned        thx,thy,lastx;\r
2193 long            barx,barstep;\r
2194 \r
2195 void    CAL_DialogDraw (char *title,unsigned numcache)\r
2196 {\r
2197         unsigned        homex,homey,x;\r
2198 \r
2199         barstep = (NUMBARS<<16)/numcache;\r
2200 \r
2201 //\r
2202 // draw dialog window (masked tiles 12 - 20 are window borders)\r
2203 //\r
2204         US_CenterWindow (20,8);\r
2205         homex = PrintX;\r
2206         homey = PrintY;\r
2207 \r
2208         US_CPrint ("Loading");\r
2209         fontcolor = F_SECONDCOLOR;\r
2210         US_CPrint (title);\r
2211         fontcolor = F_BLACK;\r
2212 \r
2213 //\r
2214 // draw thermometer bar\r
2215 //\r
2216         thx = homex + 8;\r
2217         thy = homey + 32;\r
2218         VWB_DrawTile8(thx,thy,0);               // CAT3D numbers\r
2219         VWB_DrawTile8(thx,thy+8,3);\r
2220         VWB_DrawTile8(thx,thy+16,6);\r
2221         VWB_DrawTile8(thx+17*8,thy,2);\r
2222         VWB_DrawTile8(thx+17*8,thy+8,5);\r
2223         VWB_DrawTile8(thx+17*8,thy+16,8);\r
2224         for (x=thx+8;x<thx+17*8;x+=8)\r
2225         {\r
2226                 VWB_DrawTile8(x,thy,1);\r
2227                 VWB_DrawTile8(x,thy+8,4);\r
2228                 VWB_DrawTile8(x,thy+16,7);\r
2229         }\r
2230 \r
2231         thx += 4;               // first line location\r
2232         thy += 5;\r
2233         barx = (long)thx<<16;\r
2234         lastx = thx;\r
2235 \r
2236         VW_UpdateScreen();\r
2237 }\r
2238 */\r
2239 \r
2240 /*\r
2241 ======================\r
2242 =\r
2243 = CAL_DialogUpdate\r
2244 =\r
2245 ======================\r
2246 */\r
2247 /*\r
2248 void    CAL_DialogUpdate (void)\r
2249 {\r
2250         unsigned        x,xh;\r
2251 \r
2252         barx+=barstep;\r
2253         xh = barx>>16;\r
2254         if (xh - lastx > BARSTEP)\r
2255         {\r
2256                 for (x=lastx;x<=xh;x++)\r
2257 #if GRMODE == EGAGR\r
2258                         VWB_Vlin (thy,thy+13,x,14);\r
2259 #endif\r
2260 #if GRMODE == CGAGR\r
2261                         VWB_Vlin (thy,thy+13,x,SECONDCOLOR);\r
2262 #endif\r
2263                 lastx = xh;\r
2264                 VW_UpdateScreen();\r
2265         }\r
2266 }*/\r
2267 \r
2268 /*\r
2269 ======================\r
2270 =\r
2271 = CAL_DialogFinish\r
2272 =\r
2273 ======================\r
2274 */\r
2275 /*\r
2276 void    CAL_DialogFinish (void)\r
2277 {\r
2278         unsigned        x,xh;\r
2279 \r
2280         xh = thx + NUMBARS;\r
2281         for (x=lastx;x<=xh;x++)\r
2282 #if GRMODE == EGAGR\r
2283                 VWB_Vlin (thy,thy+13,x,14);\r
2284 #endif\r
2285 #if GRMODE == CGAGR\r
2286                 VWB_Vlin (thy,thy+13,x,SECONDCOLOR);\r
2287 #endif\r
2288         VW_UpdateScreen();\r
2289 \r
2290 }*/\r
2291 \r
2292 //===========================================================================\r
2293 \r
2294 /*\r
2295 ======================\r
2296 =\r
2297 = CA_CacheMarks\r
2298 =\r
2299 ======================\r
2300 *//*++++\r
2301 #define MAXEMPTYREAD    1024\r
2302 \r
2303 void CAL_CacheMarks (char *title, global_game_variables_t *gvar)\r
2304 {\r
2305         boolean dialog;\r
2306         int     i,next,numcache;\r
2307         long    pos,endpos,nextpos,nextendpos,compressed;\r
2308         long    bufferstart,bufferend;  // file position of general buffer\r
2309         byte    far *source;\r
2310         memptr  bigbufferseg;\r
2311 \r
2312         dialog = (title!=NULL);\r
2313 \r
2314         numcache = 0;\r
2315 //\r
2316 // go through and make everything not needed purgable\r
2317 //\r
2318         for (i=0;i<NUMCHUNKS;i++)\r
2319                 if (gvar->ca.grneeded[i]&(gvar->ca.ca_levelbit))//if (grneeded[i]&ca_levelbit)\r
2320                 {\r
2321                         if (gvar->ca.grsegs[i])                                 // its allready in memory, make\r
2322                                 MM_SetPurge(gvar->ca.grsegs[i],0,gvar); // sure it stays there!\r
2323                         else\r
2324                                 numcache++;\r
2325                 }\r
2326                 else\r
2327                 {\r
2328                         if (gvar->ca.grsegs[i])                                 // not needed, so make it purgeable\r
2329                                 MM_SetPurge(gvar->ca.grsegs[i],3,gvar);\r
2330                 }\r
2331 \r
2332         if (!numcache)                  // nothing to cache!\r
2333                 return;\r
2334 \r
2335 // MDM begin - (GAMERS EDGE)\r
2336 //\r
2337 //      if (!FindFile("EGAGRAPH.16",NULL,2))\r
2338 //              Quit (gvar, "CA_CacheMarks(): Can't find graphics files.");\r
2339 //\r
2340 // MDM end\r
2341 \r
2342         if (dialog)\r
2343         {\r
2344 #ifdef PROFILE\r
2345                 write(profilehandle,title,strlen(title));\r
2346                 write(profilehandle,"\n",1);\r
2347 #endif\r
2348                 if (drawcachebox)\r
2349                         drawcachebox(title,numcache);\r
2350         }\r
2351 \r
2352 //\r
2353 // go through and load in anything still needed\r
2354 //\r
2355         bufferstart = bufferend = 0;            // nothing good in buffer now\r
2356 \r
2357         for (i=0;i<NUMCHUNKS;i++)\r
2358                 if ( (gvar->ca.grneeded[i]&(gvar->ca.ca_levelbit)) && !gvar->ca.grsegs[i])\r
2359                 {\r
2360 //\r
2361 // update thermometer\r
2362 //\r
2363                         if (dialog && updatecachebox)\r
2364                                 updatecachebox ();\r
2365 \r
2366                         pos = GRFILEPOS(i,gvar);\r
2367                         if (pos<0)\r
2368                                 continue;\r
2369 \r
2370                         next = i +1;\r
2371                         while (GRFILEPOS(next) == -1)           // skip past any sparse tiles\r
2372                                 next++;\r
2373 \r
2374                         compressed = GRFILEPOS(next,gvar)-pos;\r
2375                         endpos = pos+compressed;\r
2376 \r
2377                         if (compressed<=BUFFERSIZE)\r
2378                         {\r
2379                                 if (bufferstart<=pos\r
2380                                 && bufferend>= endpos)\r
2381                                 {\r
2382                                 // data is allready in buffer\r
2383                                         source = (byte _seg *)bufferseg+(pos-bufferstart);\r
2384                                 }\r
2385                                 else\r
2386                                 {\r
2387                                 // load buffer with a new block from disk\r
2388                                 // try to get as many of the needed blocks in as possible\r
2389                                         while ( next < NUMCHUNKS )\r
2390                                         {\r
2391                                                 while (next < NUMCHUNKS &&\r
2392                                                 !(gvar->video.grneeded[next]&ca_levelbit && !grsegs[next]))\r
2393                                                         next++;\r
2394                                                 if (next == NUMCHUNKS)\r
2395                                                         continue;\r
2396 \r
2397                                                 nextpos = GRFILEPOS(next,gvar);\r
2398                                                 while (GRFILEPOS(++next,gvar) == -1)    // skip past any sparse tiles\r
2399                                                         ;\r
2400                                                 nextendpos = GRFILEPOS(next,gvar);\r
2401                                                 if (nextpos - endpos <= MAXEMPTYREAD\r
2402                                                 && nextendpos-pos <= BUFFERSIZE)\r
2403                                                         endpos = nextendpos;\r
2404                                                 else\r
2405                                                         next = NUMCHUNKS;                       // read pos to posend\r
2406                                         }\r
2407 \r
2408                                         lseek(gvar->ca.file.grhandle,pos,SEEK_SET);\r
2409                                         CA_FarRead(gvar->ca.file.grhandle,(gvar->mm.bufferseg),endpos-pos,gvar);\r
2410                                         bufferstart = pos;\r
2411                                         bufferend = endpos;\r
2412                                         source = bufferseg;\r
2413                                 }\r
2414                         }\r
2415                         else\r
2416                         {\r
2417                         // big chunk, allocate temporary buffer\r
2418                                 MM_GetPtr(&bigbufferseg,compressed,gvar);\r
2419                                 if (mmerror)\r
2420                                         return;\r
2421                                 MM_SetLock (&bigbufferseg,true);\r
2422                                 lseek(gvar->ca.file.grhandle,pos,SEEK_SET);\r
2423                                 CA_FarRead(gvar->ca.file.grhandle,bigbufferseg,compressed,gvar);\r
2424                                 source = bigbufferseg;\r
2425                         }\r
2426 \r
2427                         CAL_ExpandGrChunk (i,source);\r
2428                         if (mmerror)\r
2429                                 return;\r
2430 \r
2431                         if (compressed>BUFFERSIZE)\r
2432                                 MM_FreePtr(&bigbufferseg);\r
2433 \r
2434                 }\r
2435 \r
2436 //\r
2437 // finish up any thermometer remnants\r
2438 //\r
2439                 if (dialog && finishcachebox)\r
2440                         finishcachebox();\r
2441 }*/\r
2442 \r
2443 void CA_CannotOpen(char *string, global_game_variables_t *gvar)\r
2444 {\r
2445  char str[30];\r
2446 \r
2447  strcpy(str,"Can't open ");\r
2448  strcat(str,string);\r
2449  strcat(str,"!\n");\r
2450  Quit (gvar, str);\r
2451 }\r