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