OSDN Git Service

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