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