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