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