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