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