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