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