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