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