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