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