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