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