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