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