]> 4ch.mooo.com Git - 16.git/blob - src/lib/16_ca.c
made 2 seperate debug files for the borland and watcom versions~ ^^; there is some...
[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         unlink("profile.16");\r
1092         gvar->handle.profilehandle = open("profile.16", O_CREAT | O_WRONLY | O_TEXT);\r
1093 #endif\r
1094 //      unlink("debug0.16");\r
1095 //      gvar->handle.showmemhandle = open("debug0.16", O_CREAT | O_WRONLY | O_TEXT);\r
1096 /*++++\r
1097 // MDM begin - (GAMERS EDGE)\r
1098 //\r
1099         if(!FindFile("AUDIO."EXT,NULL,2))\r
1100                 Quit("CA_Startup(): Can't find audio files.");\r
1101 //\r
1102 // MDM end\r
1103 \r
1104 #ifndef NOAUDIO\r
1105         CAL_SetupAudioFile();\r
1106 #endif\r
1107 \r
1108 // MDM begin - (GAMERS EDGE)\r
1109 //\r
1110         if (!FindFile("GAMEMAPS."EXT,NULL,1))\r
1111                 Quit("CA_Startup(): Can't find level files.");\r
1112 //\r
1113 // MDM end\r
1114 \r
1115 #ifndef NOMAPS\r
1116         CAL_SetupMapFile ();\r
1117 #endif\r
1118 \r
1119 // MDM begin - (GAMERS EDGE)\r
1120 //\r
1121         if (!FindFile("EGAGRAPH."EXT,NULL,2))\r
1122                 Quit("CA_Startup(): Can't find graphics files.");\r
1123 //\r
1124 // MDM end\r
1125 \r
1126 #ifndef NOGRAPHICS\r
1127         CAL_SetupGrFile ();\r
1128 #endif\r
1129 \r
1130         mapon = -1;\r
1131         ca_levelbit = 1;\r
1132         ca_levelnum = 0;\r
1133 \r
1134         drawcachebox    = CAL_DialogDraw;\r
1135         updatecachebox  = CAL_DialogUpdate;\r
1136         finishcachebox  = CAL_DialogFinish;*/\r
1137 }\r
1138 \r
1139 //==========================================================================\r
1140 \r
1141 \r
1142 /*\r
1143 ======================\r
1144 =\r
1145 = CA_Shutdown\r
1146 =\r
1147 = Closes all files\r
1148 =\r
1149 ======================\r
1150 */\r
1151 \r
1152 void CA_Shutdown(global_game_variables_t *gvar)\r
1153 {\r
1154 #ifdef PROFILE\r
1155         close(gvar->handle.profilehandle);\r
1156 #endif\r
1157 //      close(gvar->handle.showmemhandle);\r
1158 /*++++\r
1159         close(maphandle);\r
1160         close(grhandle);\r
1161         close(audiohandle);*/\r
1162 }\r
1163 \r
1164 //===========================================================================\r
1165 \r
1166 /*\r
1167 ======================\r
1168 =\r
1169 = CA_CacheAudioChunk\r
1170 =\r
1171 ======================\r
1172 */\r
1173 /*++++\r
1174 void CA_CacheAudioChunk (int chunk)\r
1175 {\r
1176         long    pos,compressed;\r
1177 #ifdef AUDIOHEADERLINKED\r
1178         long    expanded;\r
1179         memptr  bigbufferseg;\r
1180         byte    far *source;\r
1181 #endif\r
1182 \r
1183         if (audiosegs[chunk])\r
1184         {\r
1185                 MM_SetPurge (&(memptr)audiosegs[chunk],0);\r
1186                 return;                                                 // allready in memory\r
1187         }\r
1188 \r
1189 // MDM begin - (GAMERS EDGE)\r
1190 //\r
1191         if (!FindFile("AUDIO."EXT,NULL,2))\r
1192                 Quit("CA_CacheAudioChunk(): Can't find audio files.");\r
1193 //\r
1194 // MDM end\r
1195 \r
1196 //\r
1197 // load the chunk into a buffer, either the miscbuffer if it fits, or allocate\r
1198 // a larger buffer\r
1199 //\r
1200         pos = audiostarts[chunk];\r
1201         compressed = audiostarts[chunk+1]-pos;\r
1202 \r
1203         lseek(audiohandle,pos,SEEK_SET);\r
1204 \r
1205 #ifndef AUDIOHEADERLINKED\r
1206 \r
1207         MM_GetPtr (&(memptr)audiosegs[chunk],compressed);\r
1208         if (mmerror)\r
1209                 return;\r
1210 \r
1211         CA_FarRead(audiohandle,audiosegs[chunk],compressed);\r
1212 \r
1213 #else\r
1214 \r
1215         if (compressed<=BUFFERSIZE)\r
1216         {\r
1217                 CA_FarRead(audiohandle,bufferseg,compressed);\r
1218                 source = bufferseg;\r
1219         }\r
1220         else\r
1221         {\r
1222                 MM_GetPtr(&bigbufferseg,compressed);\r
1223                 if (mmerror)\r
1224                         return;\r
1225                 MM_SetLock (&bigbufferseg,true);\r
1226                 CA_FarRead(audiohandle,bigbufferseg,compressed);\r
1227                 source = bigbufferseg;\r
1228         }\r
1229 \r
1230         expanded = *(long far *)source;\r
1231         source += 4;                    // skip over length\r
1232         MM_GetPtr (&(memptr)audiosegs[chunk],expanded);\r
1233         if (mmerror)\r
1234                 goto done;\r
1235         CAL_HuffExpand (source,audiosegs[chunk],expanded,audiohuffman);\r
1236 \r
1237 done:\r
1238         if (compressed>BUFFERSIZE)\r
1239                 MM_FreePtr(&bigbufferseg);\r
1240 #endif\r
1241 }*/\r
1242 \r
1243 //===========================================================================\r
1244 \r
1245 /*\r
1246 ======================\r
1247 =\r
1248 = CA_LoadAllSounds\r
1249 =\r
1250 = Purges all sounds, then loads all new ones (mode switch)\r
1251 =\r
1252 ======================\r
1253 */\r
1254 /*++++\r
1255 void CA_LoadAllSounds (void)\r
1256 {\r
1257         unsigned        start,i;\r
1258 \r
1259         switch (oldsoundmode)\r
1260         {\r
1261         case sdm_Off:\r
1262                 goto cachein;\r
1263         case sdm_PC:\r
1264                 start = STARTPCSOUNDS;\r
1265                 break;\r
1266         case sdm_AdLib:\r
1267                 start = STARTADLIBSOUNDS;\r
1268                 break;\r
1269         }\r
1270 \r
1271         for (i=0;i<NUMSOUNDS;i++,start++)\r
1272                 if (audiosegs[start])\r
1273                         MM_SetPurge (&(memptr)audiosegs[start],3);              // make purgable\r
1274 \r
1275 cachein:\r
1276 \r
1277         switch (SoundMode)\r
1278         {\r
1279         case sdm_Off:\r
1280                 return;\r
1281         case sdm_PC:\r
1282                 start = STARTPCSOUNDS;\r
1283                 break;\r
1284         case sdm_AdLib:\r
1285                 start = STARTADLIBSOUNDS;\r
1286                 break;\r
1287         }\r
1288 \r
1289         for (i=0;i<NUMSOUNDS;i++,start++)\r
1290                 CA_CacheAudioChunk (start);\r
1291 \r
1292         oldsoundmode = SoundMode;\r
1293 }*/\r
1294 \r
1295 //===========================================================================\r
1296 \r
1297 //++++#if GRMODE == EGAGR\r
1298 \r
1299 /*\r
1300 ======================\r
1301 =\r
1302 = CAL_ShiftSprite\r
1303 =\r
1304 = Make a shifted (one byte wider) copy of a sprite into another area\r
1305 =\r
1306 ======================\r
1307 */\r
1308 /*++++\r
1309 unsigned        static  sheight,swidth;\r
1310 boolean static dothemask;\r
1311 \r
1312 void CAL_ShiftSprite (unsigned segment,unsigned source,unsigned dest,\r
1313         unsigned width, unsigned height, unsigned pixshift, boolean domask)\r
1314 {\r
1315 \r
1316         sheight = height;               // because we are going to reassign bp\r
1317         swidth = width;\r
1318         dothemask = domask;\r
1319 \r
1320 asm     mov     ax,[segment]\r
1321 asm     mov     ds,ax           // source and dest are in same segment, and all local\r
1322 \r
1323 asm     mov     bx,[source]\r
1324 asm     mov     di,[dest]\r
1325 \r
1326 asm     mov     bp,[pixshift]\r
1327 asm     shl     bp,1\r
1328 asm     mov     bp,WORD PTR [shifttabletable+bp]        // bp holds pointer to shift table\r
1329 \r
1330 asm     cmp     [ss:dothemask],0\r
1331 asm     je              skipmask\r
1332 \r
1333 //\r
1334 // table shift the mask\r
1335 //\r
1336 asm     mov     dx,[ss:sheight]\r
1337 \r
1338 domaskrow:\r
1339 \r
1340 asm     mov     BYTE PTR [di],255       // 0xff first byte\r
1341 asm     mov     cx,ss:[swidth]\r
1342 \r
1343 domaskbyte:\r
1344 \r
1345 asm     mov     al,[bx]                         // source\r
1346 asm     not     al\r
1347 asm     inc     bx                                      // next source byte\r
1348 asm     xor     ah,ah\r
1349 asm     shl     ax,1\r
1350 asm     mov     si,ax\r
1351 asm     mov     ax,[bp+si]                      // table shift into two bytes\r
1352 asm     not     ax\r
1353 asm     and     [di],al                         // and with first byte\r
1354 asm     inc     di\r
1355 asm     mov     [di],ah                         // replace next byte\r
1356 \r
1357 asm     loop    domaskbyte\r
1358 \r
1359 asm     inc     di                                      // the last shifted byte has 1s in it\r
1360 asm     dec     dx\r
1361 asm     jnz     domaskrow\r
1362 \r
1363 skipmask:\r
1364 \r
1365 //\r
1366 // table shift the data\r
1367 //\r
1368 asm     mov     dx,ss:[sheight]\r
1369 asm     shl     dx,1\r
1370 asm     shl     dx,1                            // four planes of data\r
1371 \r
1372 dodatarow:\r
1373 \r
1374 asm     mov     BYTE PTR [di],0         // 0 first byte\r
1375 asm     mov     cx,ss:[swidth]\r
1376 \r
1377 dodatabyte:\r
1378 \r
1379 asm     mov     al,[bx]                         // source\r
1380 asm     inc     bx                                      // next source byte\r
1381 asm     xor     ah,ah\r
1382 asm     shl     ax,1\r
1383 asm     mov     si,ax\r
1384 asm     mov     ax,[bp+si]                      // table shift into two bytes\r
1385 asm     or      [di],al                         // or with first byte\r
1386 asm     inc     di\r
1387 asm     mov     [di],ah                         // replace next byte\r
1388 \r
1389 asm     loop    dodatabyte\r
1390 \r
1391 asm     inc     di                                      // the last shifted byte has 0s in it\r
1392 asm     dec     dx\r
1393 asm     jnz     dodatarow\r
1394 \r
1395 //\r
1396 // done\r
1397 //\r
1398 \r
1399 asm     mov     ax,ss                           // restore data segment\r
1400 asm     mov     ds,ax\r
1401 \r
1402 }\r
1403 \r
1404 #endif\r
1405 */\r
1406 //===========================================================================\r
1407 \r
1408 /*\r
1409 ======================\r
1410 =\r
1411 = CAL_CacheSprite\r
1412 =\r
1413 = Generate shifts and set up sprite structure for a given sprite\r
1414 =\r
1415 ======================\r
1416 */\r
1417 /*++++\r
1418 void CAL_CacheSprite (int chunk, byte far *compressed)\r
1419 {\r
1420         int i;\r
1421         unsigned shiftstarts[5];\r
1422         unsigned smallplane,bigplane,expanded;\r
1423         spritetabletype far *spr;\r
1424         spritetype _seg *dest;\r
1425 \r
1426 #if GRMODE == CGAGR\r
1427 //\r
1428 // CGA has no pel panning, so shifts are never needed\r
1429 //\r
1430         spr = &spritetable[chunk-STARTSPRITES];\r
1431         smallplane = spr->width*spr->height;\r
1432         MM_GetPtr (&grsegs[chunk],smallplane*2+MAXSHIFTS*6);\r
1433         if (mmerror)\r
1434                 return;\r
1435         dest = (spritetype _seg *)grsegs[chunk];\r
1436         dest->sourceoffset[0] = MAXSHIFTS*6;    // start data after 3 unsigned tables\r
1437         dest->planesize[0] = smallplane;\r
1438         dest->width[0] = spr->width;\r
1439 \r
1440 //\r
1441 // expand the unshifted shape\r
1442 //\r
1443         CAL_HuffExpand (compressed, &dest->data[0],smallplane*2,grhuffman);\r
1444 \r
1445 #endif\r
1446 \r
1447 \r
1448 #if GRMODE == EGAGR\r
1449 \r
1450 //\r
1451 // calculate sizes\r
1452 //\r
1453         spr = &spritetable[chunk-STARTSPRITES];\r
1454         smallplane = spr->width*spr->height;\r
1455         bigplane = (spr->width+1)*spr->height;\r
1456 \r
1457         shiftstarts[0] = MAXSHIFTS*6;   // start data after 3 unsigned tables\r
1458         shiftstarts[1] = shiftstarts[0] + smallplane*5; // 5 planes in a sprite\r
1459         shiftstarts[2] = shiftstarts[1] + bigplane*5;\r
1460         shiftstarts[3] = shiftstarts[2] + bigplane*5;\r
1461         shiftstarts[4] = shiftstarts[3] + bigplane*5;   // nothing ever put here\r
1462 \r
1463         expanded = shiftstarts[spr->shifts];\r
1464         MM_GetPtr (&grsegs[chunk],expanded);\r
1465         if (mmerror)\r
1466                 return;\r
1467         dest = (spritetype _seg *)grsegs[chunk];\r
1468 \r
1469 //\r
1470 // expand the unshifted shape\r
1471 //\r
1472         CAL_HuffExpand (compressed, &dest->data[0],smallplane*5,grhuffman);\r
1473 \r
1474 //\r
1475 // make the shifts!\r
1476 //\r
1477         switch (spr->shifts)\r
1478         {\r
1479         case    1:\r
1480                 for (i=0;i<4;i++)\r
1481                 {\r
1482                         dest->sourceoffset[i] = shiftstarts[0];\r
1483                         dest->planesize[i] = smallplane;\r
1484                         dest->width[i] = spr->width;\r
1485                 }\r
1486                 break;\r
1487 \r
1488         case    2:\r
1489                 for (i=0;i<2;i++)\r
1490                 {\r
1491                         dest->sourceoffset[i] = shiftstarts[0];\r
1492                         dest->planesize[i] = smallplane;\r
1493                         dest->width[i] = spr->width;\r
1494                 }\r
1495                 for (i=2;i<4;i++)\r
1496                 {\r
1497                         dest->sourceoffset[i] = shiftstarts[1];\r
1498                         dest->planesize[i] = bigplane;\r
1499                         dest->width[i] = spr->width+1;\r
1500                 }\r
1501                 CAL_ShiftSprite ((unsigned)grsegs[chunk],dest->sourceoffset[0],\r
1502                         dest->sourceoffset[2],spr->width,spr->height,4,true);\r
1503                 break;\r
1504 \r
1505         case    4:\r
1506                 dest->sourceoffset[0] = shiftstarts[0];\r
1507                 dest->planesize[0] = smallplane;\r
1508                 dest->width[0] = spr->width;\r
1509 \r
1510                 dest->sourceoffset[1] = shiftstarts[1];\r
1511                 dest->planesize[1] = bigplane;\r
1512                 dest->width[1] = spr->width+1;\r
1513                 CAL_ShiftSprite ((unsigned)grsegs[chunk],dest->sourceoffset[0],\r
1514                         dest->sourceoffset[1],spr->width,spr->height,2,true);\r
1515 \r
1516                 dest->sourceoffset[2] = shiftstarts[2];\r
1517                 dest->planesize[2] = bigplane;\r
1518                 dest->width[2] = spr->width+1;\r
1519                 CAL_ShiftSprite ((unsigned)grsegs[chunk],dest->sourceoffset[0],\r
1520                         dest->sourceoffset[2],spr->width,spr->height,4,true);\r
1521 \r
1522                 dest->sourceoffset[3] = shiftstarts[3];\r
1523                 dest->planesize[3] = bigplane;\r
1524                 dest->width[3] = spr->width+1;\r
1525                 CAL_ShiftSprite ((unsigned)grsegs[chunk],dest->sourceoffset[0],\r
1526                         dest->sourceoffset[3],spr->width,spr->height,6,true);\r
1527 \r
1528                 break;\r
1529 \r
1530         default:\r
1531                 Quit ("CAL_CacheSprite: Bad shifts number!");\r
1532         }\r
1533 \r
1534 #endif\r
1535 }*/\r
1536 \r
1537 //===========================================================================\r
1538 \r
1539 \r
1540 /*\r
1541 ======================\r
1542 =\r
1543 = CAL_ExpandGrChunk\r
1544 =\r
1545 = Does whatever is needed with a pointer to a compressed chunk\r
1546 =\r
1547 ======================\r
1548 */\r
1549 /*++++\r
1550 void CAL_ExpandGrChunk (int chunk, byte far *source)\r
1551 {\r
1552         long    expanded;\r
1553 \r
1554 \r
1555         if (chunk >= STARTTILE8 && chunk < STARTEXTERNS)\r
1556         {\r
1557         //\r
1558         // expanded sizes of tile8/16/32 are implicit\r
1559         //\r
1560 \r
1561 #if GRMODE == EGAGR\r
1562 #define BLOCK           32\r
1563 #define MASKBLOCK       40\r
1564 #endif\r
1565 \r
1566 #if GRMODE == CGAGR\r
1567 #define BLOCK           16\r
1568 #define MASKBLOCK       32\r
1569 #endif\r
1570 \r
1571                 if (chunk<STARTTILE8M)                  // tile 8s are all in one chunk!\r
1572                         expanded = BLOCK*NUMTILE8;\r
1573                 else if (chunk<STARTTILE16)\r
1574                         expanded = MASKBLOCK*NUMTILE8M;\r
1575                 else if (chunk<STARTTILE16M)    // all other tiles are one/chunk\r
1576                         expanded = BLOCK*4;\r
1577                 else if (chunk<STARTTILE32)\r
1578                         expanded = MASKBLOCK*4;\r
1579                 else if (chunk<STARTTILE32M)\r
1580                         expanded = BLOCK*16;\r
1581                 else\r
1582                         expanded = MASKBLOCK*16;\r
1583         }\r
1584         else\r
1585         {\r
1586         //\r
1587         // everything else has an explicit size longword\r
1588         //\r
1589                 expanded = *(long far *)source;\r
1590                 source += 4;                    // skip over length\r
1591         }\r
1592 \r
1593 //\r
1594 // allocate final space, decompress it, and free bigbuffer\r
1595 // Sprites need to have shifts made and various other junk\r
1596 //\r
1597         if (chunk>=STARTSPRITES && chunk< STARTTILE8)\r
1598                 CAL_CacheSprite(chunk,source);\r
1599         else\r
1600         {\r
1601                 MM_GetPtr (&grsegs[chunk],expanded);\r
1602                 if (mmerror)\r
1603                         return;\r
1604                 CAL_HuffExpand (source,grsegs[chunk],expanded,grhuffman);\r
1605         }\r
1606 }\r
1607 */\r
1608 \r
1609 /*\r
1610 ======================\r
1611 =\r
1612 = CAL_ReadGrChunk\r
1613 =\r
1614 = Gets a chunk off disk, optimizing reads to general buffer\r
1615 =\r
1616 ======================\r
1617 */\r
1618 /*++++\r
1619 void CAL_ReadGrChunk (int chunk)\r
1620 {\r
1621         long    pos,compressed;\r
1622         memptr  bigbufferseg;\r
1623         byte    far *source;\r
1624         int             next;\r
1625 \r
1626 //\r
1627 // load the chunk into a buffer, either the miscbuffer if it fits, or allocate\r
1628 // a larger buffer\r
1629 //\r
1630         pos = GRFILEPOS(chunk);\r
1631         if (pos<0)                                                      // $FFFFFFFF start is a sparse tile\r
1632           return;\r
1633 \r
1634         next = chunk +1;\r
1635         while (GRFILEPOS(next) == -1)           // skip past any sparse tiles\r
1636                 next++;\r
1637 \r
1638         compressed = GRFILEPOS(next)-pos;\r
1639 \r
1640         lseek(grhandle,pos,SEEK_SET);\r
1641 \r
1642         if (compressed<=BUFFERSIZE)\r
1643         {\r
1644                 CA_FarRead(grhandle,bufferseg,compressed);\r
1645                 source = bufferseg;\r
1646         }\r
1647         else\r
1648         {\r
1649                 MM_GetPtr(&bigbufferseg,compressed);\r
1650                 if (mmerror)\r
1651                         return;\r
1652                 MM_SetLock (&bigbufferseg,true);\r
1653                 CA_FarRead(grhandle,bigbufferseg,compressed);\r
1654                 source = bigbufferseg;\r
1655         }\r
1656 \r
1657         CAL_ExpandGrChunk (chunk,source);\r
1658 \r
1659         if (compressed>BUFFERSIZE)\r
1660                 MM_FreePtr(&bigbufferseg);\r
1661 }\r
1662 */\r
1663 /*\r
1664 ======================\r
1665 =\r
1666 = CA_CacheGrChunk\r
1667 =\r
1668 = Makes sure a given chunk is in memory, loadiing it if needed\r
1669 =\r
1670 ======================\r
1671 */\r
1672 /*++++\r
1673 void CA_CacheGrChunk (int chunk)\r
1674 {\r
1675         long    pos,compressed;\r
1676         memptr  bigbufferseg;\r
1677         byte    far *source;\r
1678         int             next;\r
1679 \r
1680         grneeded[chunk] |= ca_levelbit;         // make sure it doesn't get removed\r
1681         if (grsegs[chunk])\r
1682         {\r
1683                 MM_SetPurge (&grsegs[chunk],0);\r
1684                 return;                                                 // allready in memory\r
1685         }\r
1686 \r
1687 // MDM begin - (GAMERS EDGE)\r
1688 //\r
1689         if (!FindFile("EGAGRAPH."EXT,NULL,2))\r
1690                 Quit("CA_CacheGrChunk(): Can't find graphics files.");\r
1691 //\r
1692 // MDM end\r
1693 \r
1694 //\r
1695 // load the chunk into a buffer, either the miscbuffer if it fits, or allocate\r
1696 // a larger buffer\r
1697 //\r
1698         pos = GRFILEPOS(chunk);\r
1699         if (pos<0)                                                      // $FFFFFFFF start is a sparse tile\r
1700           return;\r
1701 \r
1702         next = chunk +1;\r
1703         while (GRFILEPOS(next) == -1)           // skip past any sparse tiles\r
1704                 next++;\r
1705 \r
1706         compressed = GRFILEPOS(next)-pos;\r
1707 \r
1708         lseek(grhandle,pos,SEEK_SET);\r
1709 \r
1710         if (compressed<=BUFFERSIZE)\r
1711         {\r
1712                 CA_FarRead(grhandle,bufferseg,compressed);\r
1713                 source = bufferseg;\r
1714         }\r
1715         else\r
1716         {\r
1717                 MM_GetPtr(&bigbufferseg,compressed);\r
1718                 MM_SetLock (&bigbufferseg,true);\r
1719                 CA_FarRead(grhandle,bigbufferseg,compressed);\r
1720                 source = bigbufferseg;\r
1721         }\r
1722 \r
1723         CAL_ExpandGrChunk (chunk,source);\r
1724 \r
1725         if (compressed>BUFFERSIZE)\r
1726                 MM_FreePtr(&bigbufferseg);\r
1727 }\r
1728 */\r
1729 \r
1730 \r
1731 //==========================================================================\r
1732 \r
1733 /*\r
1734 ======================\r
1735 =\r
1736 = CA_CacheMap\r
1737 =\r
1738 ======================\r
1739 */\r
1740 /*++++\r
1741 void CA_CacheMap (int mapnum)\r
1742 {\r
1743         long    pos,compressed;\r
1744         int             plane;\r
1745         memptr  *dest,bigbufferseg;\r
1746         unsigned        size;\r
1747         unsigned        far     *source;\r
1748 #ifdef MAPHEADERLINKED\r
1749         memptr  buffer2seg;\r
1750         long    expanded;\r
1751 #endif\r
1752 \r
1753 \r
1754 // MDM begin - (GAMERS EDGE)\r
1755 //\r
1756         if (!FindFile("GAMEMAPS."EXT,NULL,1))\r
1757                 Quit("CA_CacheMap(): Can't find level files.");\r
1758 //\r
1759 // MDM end\r
1760 \r
1761 \r
1762 //\r
1763 // free up memory from last map\r
1764 //\r
1765         if (mapon>-1 && mapheaderseg[mapon])\r
1766                 MM_SetPurge (&(memptr)mapheaderseg[mapon],3);\r
1767         for (plane=0;plane<MAPPLANES;plane++)\r
1768                 if (mapsegs[plane])\r
1769                         MM_FreePtr (&(memptr)mapsegs[plane]);\r
1770 \r
1771         mapon = mapnum;\r
1772 \r
1773 \r
1774 //\r
1775 // load map header\r
1776 // The header will be cached if it is still around\r
1777 //\r
1778         if (!mapheaderseg[mapnum])\r
1779         {\r
1780                 pos = ((mapfiletype     _seg *)tinf)->headeroffsets[mapnum];\r
1781                 if (pos<0)                                              // $FFFFFFFF start is a sparse map\r
1782                   Quit ("CA_CacheMap: Tried to load a non existent map!");\r
1783 \r
1784                 MM_GetPtr(&(memptr)mapheaderseg[mapnum],sizeof(maptype));\r
1785                 lseek(maphandle,pos,SEEK_SET);\r
1786                 CA_FarRead (maphandle,(memptr)mapheaderseg[mapnum],sizeof(maptype));\r
1787         }\r
1788         else\r
1789                 MM_SetPurge (&(memptr)mapheaderseg[mapnum],0);\r
1790 \r
1791 //\r
1792 // load the planes in\r
1793 // If a plane's pointer still exists it will be overwritten (levels are\r
1794 // allways reloaded, never cached)\r
1795 //\r
1796 \r
1797         size = mapheaderseg[mapnum]->width * mapheaderseg[mapnum]->height * 2;\r
1798 \r
1799         for (plane = 0; plane<MAPPLANES; plane++)\r
1800         {\r
1801                 pos = mapheaderseg[mapnum]->planestart[plane];\r
1802                 compressed = mapheaderseg[mapnum]->planelength[plane];\r
1803 \r
1804                 if (!compressed)\r
1805                         continue;               // the plane is not used in this game\r
1806 \r
1807                 dest = &(memptr)mapsegs[plane];\r
1808                 MM_GetPtr(dest,size);\r
1809 \r
1810                 lseek(maphandle,pos,SEEK_SET);\r
1811                 if (compressed<=BUFFERSIZE)\r
1812                         source = bufferseg;\r
1813                 else\r
1814                 {\r
1815                         MM_GetPtr(&bigbufferseg,compressed);\r
1816                         MM_SetLock (&bigbufferseg,true);\r
1817                         source = bigbufferseg;\r
1818                 }\r
1819 \r
1820                 CA_FarRead(maphandle,(byte far *)source,compressed);\r
1821 #ifdef MAPHEADERLINKED\r
1822                 //\r
1823                 // unhuffman, then unRLEW\r
1824                 // The huffman'd chunk has a two byte expanded length first\r
1825                 // The resulting RLEW chunk also does, even though it's not really\r
1826                 // needed\r
1827                 //\r
1828                 expanded = *source;\r
1829                 source++;\r
1830                 MM_GetPtr (&buffer2seg,expanded);\r
1831                 CAL_CarmackExpand (source, (unsigned far *)buffer2seg,expanded);\r
1832                 CA_RLEWexpand (((unsigned far *)buffer2seg)+1,*dest,size,\r
1833                 ((mapfiletype _seg *)tinf)->RLEWtag);\r
1834                 MM_FreePtr (&buffer2seg);\r
1835 \r
1836 #else\r
1837                 //\r
1838                 // unRLEW, skipping expanded length\r
1839                 //\r
1840                 CA_RLEWexpand (source+1, *dest,size,\r
1841                 ((mapfiletype _seg *)tinf)->RLEWtag);\r
1842 #endif\r
1843 \r
1844                 if (compressed>BUFFERSIZE)\r
1845                         MM_FreePtr(&bigbufferseg);\r
1846         }\r
1847 }*/\r
1848 \r
1849 //===========================================================================\r
1850 \r
1851 /*\r
1852 ======================\r
1853 =\r
1854 = CA_UpLevel\r
1855 =\r
1856 = Goes up a bit level in the needed lists and clears it out.\r
1857 = Everything is made purgable\r
1858 =\r
1859 ======================\r
1860 */\r
1861 /*++++\r
1862 void CA_UpLevel (void)\r
1863 {\r
1864         if (ca_levelnum==7)\r
1865                 Quit ("CA_UpLevel: Up past level 7!");\r
1866 \r
1867         ca_levelbit<<=1;\r
1868         ca_levelnum++;\r
1869 }*/\r
1870 \r
1871 //===========================================================================\r
1872 \r
1873 /*\r
1874 ======================\r
1875 =\r
1876 = CA_DownLevel\r
1877 =\r
1878 = Goes down a bit level in the needed lists and recaches\r
1879 = everything from the lower level\r
1880 =\r
1881 ======================\r
1882 */\r
1883 /*++\r
1884 void CA_DownLevel (void)\r
1885 {\r
1886         if (!ca_levelnum)\r
1887                 Quit ("CA_DownLevel: Down past level 0!");\r
1888         ca_levelbit>>=1;\r
1889         ca_levelnum--;\r
1890         CA_CacheMarks(NULL);\r
1891 }*/\r
1892 \r
1893 //===========================================================================\r
1894 \r
1895 /*\r
1896 ======================\r
1897 =\r
1898 = CA_ClearMarks\r
1899 =\r
1900 = Clears out all the marks at the current level\r
1901 =\r
1902 ======================\r
1903 */\r
1904 /*\r
1905 void CA_ClearMarks (void)\r
1906 {\r
1907         int i;\r
1908 \r
1909         for (i=0;i<NUMCHUNKS;i++)\r
1910                 grneeded[i]&=~ca_levelbit;\r
1911 }\r
1912 */\r
1913 \r
1914 //===========================================================================\r
1915 \r
1916 /*\r
1917 ======================\r
1918 =\r
1919 = CA_ClearAllMarks\r
1920 =\r
1921 = Clears out all the marks on all the levels\r
1922 =\r
1923 ======================\r
1924 */\r
1925 /*\r
1926 void CA_ClearAllMarks (void)\r
1927 {\r
1928         _fmemset (grneeded,0,sizeof(grneeded));\r
1929         ca_levelbit = 1;\r
1930         ca_levelnum = 0;\r
1931 }\r
1932 */\r
1933 \r
1934 //===========================================================================\r
1935 \r
1936 /*\r
1937 ======================\r
1938 =\r
1939 = CA_FreeGraphics\r
1940 =\r
1941 ======================\r
1942 */\r
1943 /*++++\r
1944 void CA_FreeGraphics (void)\r
1945 {\r
1946         int     i;\r
1947 \r
1948         for (i=0;i<NUMCHUNKS;i++)\r
1949                 if (grsegs[i])\r
1950                         MM_SetPurge (&(memptr)grsegs[i],3);\r
1951 }\r
1952 */\r
1953 \r
1954 /*\r
1955 ======================\r
1956 =\r
1957 = CA_SetAllPurge\r
1958 =\r
1959 = Make everything possible purgable\r
1960 =\r
1961 ======================\r
1962 */\r
1963 /*++++++++\r
1964 void CA_SetAllPurge (void)\r
1965 {\r
1966         int i;\r
1967 \r
1968         CA_ClearMarks ();\r
1969 \r
1970 //\r
1971 // free cursor sprite and background save\r
1972 //\r
1973         VW_FreeCursor ();\r
1974 \r
1975 //\r
1976 // free map headers and map planes\r
1977 //\r
1978         for (i=0;i<NUMMAPS;i++)\r
1979                 if (mapheaderseg[i])\r
1980                         MM_SetPurge (&(memptr)mapheaderseg[i],3);\r
1981 \r
1982         for (i=0;i<3;i++)\r
1983                 if (mapsegs[i])\r
1984                         MM_FreePtr (&(memptr)mapsegs[i]);\r
1985 \r
1986 //\r
1987 // free sounds\r
1988 //\r
1989         for (i=0;i<NUMSNDCHUNKS;i++)\r
1990                 if (audiosegs[i])\r
1991                         MM_SetPurge (&(memptr)audiosegs[i],3);\r
1992 \r
1993 //\r
1994 // free graphics\r
1995 //\r
1996         CA_FreeGraphics ();\r
1997 }\r
1998 \r
1999 \r
2000 void CA_SetGrPurge (void)\r
2001 {\r
2002         int i;\r
2003 \r
2004 //\r
2005 // free graphics\r
2006 //\r
2007         for (i=0;i<NUMCHUNKS;i++)\r
2008                 if (grsegs[i])\r
2009                         MM_SetPurge (&(memptr)grsegs[i],3);\r
2010 }*/\r
2011 \r
2012 \r
2013 //===========================================================================\r
2014 \r
2015 \r
2016 /*\r
2017 ======================\r
2018 =\r
2019 = CAL_DialogDraw\r
2020 =\r
2021 ======================\r
2022 */\r
2023 /*\r
2024 #define NUMBARS (17l*8)\r
2025 #define BARSTEP 8\r
2026 \r
2027 unsigned        thx,thy,lastx;\r
2028 long            barx,barstep;\r
2029 \r
2030 void    CAL_DialogDraw (char *title,unsigned numcache)\r
2031 {\r
2032         unsigned        homex,homey,x;\r
2033 \r
2034         barstep = (NUMBARS<<16)/numcache;\r
2035 \r
2036 //\r
2037 // draw dialog window (masked tiles 12 - 20 are window borders)\r
2038 //\r
2039         US_CenterWindow (20,8);\r
2040         homex = PrintX;\r
2041         homey = PrintY;\r
2042 \r
2043         US_CPrint ("Loading");\r
2044         fontcolor = F_SECONDCOLOR;\r
2045         US_CPrint (title);\r
2046         fontcolor = F_BLACK;\r
2047 \r
2048 //\r
2049 // draw thermometer bar\r
2050 //\r
2051         thx = homex + 8;\r
2052         thy = homey + 32;\r
2053         VWB_DrawTile8(thx,thy,0);               // CAT3D numbers\r
2054         VWB_DrawTile8(thx,thy+8,3);\r
2055         VWB_DrawTile8(thx,thy+16,6);\r
2056         VWB_DrawTile8(thx+17*8,thy,2);\r
2057         VWB_DrawTile8(thx+17*8,thy+8,5);\r
2058         VWB_DrawTile8(thx+17*8,thy+16,8);\r
2059         for (x=thx+8;x<thx+17*8;x+=8)\r
2060         {\r
2061                 VWB_DrawTile8(x,thy,1);\r
2062                 VWB_DrawTile8(x,thy+8,4);\r
2063                 VWB_DrawTile8(x,thy+16,7);\r
2064         }\r
2065 \r
2066         thx += 4;               // first line location\r
2067         thy += 5;\r
2068         barx = (long)thx<<16;\r
2069         lastx = thx;\r
2070 \r
2071         VW_UpdateScreen();\r
2072 }\r
2073 */\r
2074 \r
2075 /*\r
2076 ======================\r
2077 =\r
2078 = CAL_DialogUpdate\r
2079 =\r
2080 ======================\r
2081 */\r
2082 /*\r
2083 void    CAL_DialogUpdate (void)\r
2084 {\r
2085         unsigned        x,xh;\r
2086 \r
2087         barx+=barstep;\r
2088         xh = barx>>16;\r
2089         if (xh - lastx > BARSTEP)\r
2090         {\r
2091                 for (x=lastx;x<=xh;x++)\r
2092 #if GRMODE == EGAGR\r
2093                         VWB_Vlin (thy,thy+13,x,14);\r
2094 #endif\r
2095 #if GRMODE == CGAGR\r
2096                         VWB_Vlin (thy,thy+13,x,SECONDCOLOR);\r
2097 #endif\r
2098                 lastx = xh;\r
2099                 VW_UpdateScreen();\r
2100         }\r
2101 }*/\r
2102 \r
2103 /*\r
2104 ======================\r
2105 =\r
2106 = CAL_DialogFinish\r
2107 =\r
2108 ======================\r
2109 */\r
2110 /*\r
2111 void    CAL_DialogFinish (void)\r
2112 {\r
2113         unsigned        x,xh;\r
2114 \r
2115         xh = thx + NUMBARS;\r
2116         for (x=lastx;x<=xh;x++)\r
2117 #if GRMODE == EGAGR\r
2118                 VWB_Vlin (thy,thy+13,x,14);\r
2119 #endif\r
2120 #if GRMODE == CGAGR\r
2121                 VWB_Vlin (thy,thy+13,x,SECONDCOLOR);\r
2122 #endif\r
2123         VW_UpdateScreen();\r
2124 \r
2125 }*/\r
2126 \r
2127 //===========================================================================\r
2128 \r
2129 /*\r
2130 ======================\r
2131 =\r
2132 = CA_CacheMarks\r
2133 =\r
2134 ======================\r
2135 *//*\r
2136 #define MAXEMPTYREAD    1024\r
2137 \r
2138 void CA_CacheMarks (char *title)\r
2139 {\r
2140         boolean dialog;\r
2141         int     i,next,numcache;\r
2142         long    pos,endpos,nextpos,nextendpos,compressed;\r
2143         long    bufferstart,bufferend;  // file position of general buffer\r
2144         byte    far *source;\r
2145         memptr  bigbufferseg;\r
2146 \r
2147         dialog = (title!=NULL);\r
2148 \r
2149         numcache = 0;\r
2150 //\r
2151 // go through and make everything not needed purgable\r
2152 //\r
2153         for (i=0;i<NUMCHUNKS;i++)\r
2154                 if (grneeded[i]&ca_levelbit)\r
2155                 {\r
2156                         if (grsegs[i])                                  // its allready in memory, make\r
2157                                 MM_SetPurge(&grsegs[i],0);      // sure it stays there!\r
2158                         else\r
2159                                 numcache++;\r
2160                 }\r
2161                 else\r
2162                 {\r
2163                         if (grsegs[i])                                  // not needed, so make it purgeable\r
2164                                 MM_SetPurge(&grsegs[i],3);\r
2165                 }\r
2166 \r
2167         if (!numcache)                  // nothing to cache!\r
2168                 return;\r
2169 \r
2170 // MDM begin - (GAMERS EDGE)\r
2171 //\r
2172         if (!FindFile("EGAGRAPH."EXT,NULL,2))\r
2173                 Quit("CA_CacheMarks(): Can't find graphics files.");\r
2174 //\r
2175 // MDM end\r
2176 \r
2177         if (dialog)\r
2178         {\r
2179 #ifdef PROFILE\r
2180                 write(profilehandle,title,strlen(title));\r
2181                 write(profilehandle,"\n",1);\r
2182 #endif\r
2183                 if (drawcachebox)\r
2184                         drawcachebox(title,numcache);\r
2185         }\r
2186 \r
2187 //\r
2188 // go through and load in anything still needed\r
2189 //\r
2190         bufferstart = bufferend = 0;            // nothing good in buffer now\r
2191 \r
2192         for (i=0;i<NUMCHUNKS;i++)\r
2193                 if ( (grneeded[i]&ca_levelbit) && !grsegs[i])\r
2194                 {\r
2195 //\r
2196 // update thermometer\r
2197 //\r
2198                         if (dialog && updatecachebox)\r
2199                                 updatecachebox ();\r
2200 \r
2201                         pos = GRFILEPOS(i);\r
2202                         if (pos<0)\r
2203                                 continue;\r
2204 \r
2205                         next = i +1;\r
2206                         while (GRFILEPOS(next) == -1)           // skip past any sparse tiles\r
2207                                 next++;\r
2208 \r
2209                         compressed = GRFILEPOS(next)-pos;\r
2210                         endpos = pos+compressed;\r
2211 \r
2212                         if (compressed<=BUFFERSIZE)\r
2213                         {\r
2214                                 if (bufferstart<=pos\r
2215                                 && bufferend>= endpos)\r
2216                                 {\r
2217                                 // data is allready in buffer\r
2218                                         source = (byte _seg *)bufferseg+(pos-bufferstart);\r
2219                                 }\r
2220                                 else\r
2221                                 {\r
2222                                 // load buffer with a new block from disk\r
2223                                 // try to get as many of the needed blocks in as possible\r
2224                                         while ( next < NUMCHUNKS )\r
2225                                         {\r
2226                                                 while (next < NUMCHUNKS &&\r
2227                                                 !(grneeded[next]&ca_levelbit && !grsegs[next]))\r
2228                                                         next++;\r
2229                                                 if (next == NUMCHUNKS)\r
2230                                                         continue;\r
2231 \r
2232                                                 nextpos = GRFILEPOS(next);\r
2233                                                 while (GRFILEPOS(++next) == -1) // skip past any sparse tiles\r
2234                                                         ;\r
2235                                                 nextendpos = GRFILEPOS(next);\r
2236                                                 if (nextpos - endpos <= MAXEMPTYREAD\r
2237                                                 && nextendpos-pos <= BUFFERSIZE)\r
2238                                                         endpos = nextendpos;\r
2239                                                 else\r
2240                                                         next = NUMCHUNKS;                       // read pos to posend\r
2241                                         }\r
2242 \r
2243                                         lseek(grhandle,pos,SEEK_SET);\r
2244                                         CA_FarRead(grhandle,bufferseg,endpos-pos);\r
2245                                         bufferstart = pos;\r
2246                                         bufferend = endpos;\r
2247                                         source = bufferseg;\r
2248                                 }\r
2249                         }\r
2250                         else\r
2251                         {\r
2252                         // big chunk, allocate temporary buffer\r
2253                                 MM_GetPtr(&bigbufferseg,compressed);\r
2254                                 if (mmerror)\r
2255                                         return;\r
2256                                 MM_SetLock (&bigbufferseg,true);\r
2257                                 lseek(grhandle,pos,SEEK_SET);\r
2258                                 CA_FarRead(grhandle,bigbufferseg,compressed);\r
2259                                 source = bigbufferseg;\r
2260                         }\r
2261 \r
2262                         CAL_ExpandGrChunk (i,source);\r
2263                         if (mmerror)\r
2264                                 return;\r
2265 \r
2266                         if (compressed>BUFFERSIZE)\r
2267                                 MM_FreePtr(&bigbufferseg);\r
2268 \r
2269                 }\r
2270 \r
2271 //\r
2272 // finish up any thermometer remnants\r
2273 //\r
2274                 if (dialog && finishcachebox)\r
2275                         finishcachebox();\r
2276 }*/\r