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