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