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