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