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