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