]> 4ch.mooo.com Git - 16.git/blob - src/lib/16_ca.c
16_ca needs huge amounts of work and I should remember what needs to be done soon...
[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 #if NUMPICS>0\r
1049         memptr compseg;\r
1050 #endif\r
1051 \r
1052 #ifdef GRHEADERLINKED\r
1053 \r
1054         gvar->ca.grhuffman = (huffnode *)&VGAdict;\r
1055         grstarts = (long _seg *)FP_SEG(&VGAhead);\r
1056 \r
1057         CAL_OptimizeNodes (gvar->ca.grhuffman);\r
1058 \r
1059 #else\r
1060 \r
1061 //\r
1062 // load ???dict.ext (huffman dictionary for graphics files)\r
1063 //\r
1064 \r
1065         strcpy(fname,GDICTNAME);\r
1066         strcat(fname,EXTENSION);\r
1067 \r
1068         if ((handle = open(fname,\r
1069                  O_RDONLY | O_BINARY, S_IREAD)) == -1)\r
1070                 CA_CannotOpen(fname,gvar);\r
1071 \r
1072         read(handle, &gvar->ca.grhuffman, sizeof(gvar->ca.grhuffman));\r
1073         close(handle);\r
1074         CAL_OptimizeNodes (gvar->ca.grhuffman);\r
1075 //\r
1076 // load the data offsets from ???head.ext\r
1077 //\r
1078         MM_GetPtr (MEMPTRCONV gvar->ca.grstarts,(NUMCHUNKS+1)*FILEPOSSIZE, gvar);\r
1079 \r
1080         strcpy(fname,GHEADNAME);\r
1081         strcat(fname,EXTENSION);\r
1082 \r
1083         if ((handle = open(fname,\r
1084                  O_RDONLY | O_BINARY, S_IREAD)) == -1)\r
1085                 CA_CannotOpen(fname,gvar);\r
1086 \r
1087         CA_FarRead(handle, (memptr)gvar->ca.grstarts, (NUMCHUNKS+1)*FILEPOSSIZE, gvar);\r
1088 \r
1089         close(handle);\r
1090 \r
1091 \r
1092 #endif\r
1093 \r
1094 //\r
1095 // Open the graphics file, leaving it open until the game is finished\r
1096 //\r
1097         strcpy(fname,GFILENAME);\r
1098         strcat(fname,EXTENSION);\r
1099 \r
1100         gvar->ca.file.grhandle = open(fname, O_RDONLY | O_BINARY);\r
1101         if (gvar->ca.file.grhandle == -1)\r
1102                 CA_CannotOpen(fname,gvar);\r
1103 \r
1104 \r
1105 //\r
1106 // load the pic and sprite headers into the arrays in the data segment\r
1107 //\r
1108 #if NUMPICS>0\r
1109         MM_GetPtr(MEMPTRCONV gvar->video.pictable,NUMPICS*sizeof(pictabletype),gvar);\r
1110         CAL_GetGrChunkLength(STRUCTPIC,gvar);           // position file pointer\r
1111         printf("CAL_SetupGrFile:\n");\r
1112         printf("        gvar->ca.chunkcomplen size is %lu\n", gvar->ca.chunkcomplen);\r
1113         MM_GetPtr(&compseg,gvar->ca.chunkcomplen,gvar);\r
1114         IN_Ack(gvar);\r
1115         CA_FarRead (gvar->ca.file.grhandle,compseg,gvar->ca.chunkcomplen,gvar);\r
1116         CAL_HuffExpand (compseg, (byte far *)gvar->video.pictable,NUMPICS*sizeof(pictabletype),gvar->ca.grhuffman);\r
1117         MM_FreePtr(&compseg,gvar);\r
1118 #endif\r
1119 \r
1120 #if NUMPICM>0\r
1121         MM_GetPtr(MEMPTRCONV picmtable,NUMPICM*sizeof(pictabletype));\r
1122         CAL_GetGrChunkLength(STRUCTPICM);               // position file pointer\r
1123         MM_GetPtr(&compseg,gvar->ca.chunkcomplen);\r
1124         CA_FarRead (gvar->ca.file.grhandle,compseg,gvar->ca.chunkcomplen);\r
1125         CAL_HuffExpand (compseg, (byte far *)picmtable,NUMPICS*sizeof(pictabletype),gvar->ca.grhuffman);\r
1126         MM_FreePtr(&compseg);\r
1127 #endif\r
1128 \r
1129 #if NUMSPRITES>0\r
1130         MM_GetPtr(MEMPTRCONV spritetable,NUMSPRITES*sizeof(spritetabletype));\r
1131         CAL_GetGrChunkLength(STRUCTSPRITE);     // position file pointer\r
1132         MM_GetPtr(&compseg,gvar->ca.chunkcomplen);\r
1133         CA_FarRead (gvar->ca.file.grhandle,compseg,gvar->ca.chunkcomplen);\r
1134         CAL_HuffExpand (compseg, (byte far *)spritetable,NUMSPRITES*sizeof(spritetabletype),gvar->ca.grhuffman);\r
1135         MM_FreePtr(&compseg);\r
1136 #endif\r
1137 \r
1138 }\r
1139 \r
1140 //==========================================================================\r
1141 \r
1142 \r
1143 /*\r
1144 ======================\r
1145 =\r
1146 = CAL_SetupMapFile\r
1147 =\r
1148 ======================\r
1149 */\r
1150 \r
1151 void CAL_SetupMapFile (global_game_variables_t *gvar)\r
1152 {\r
1153 #ifndef MAPHEADERLINKED\r
1154         int handle;\r
1155         long length;\r
1156 #endif\r
1157 \r
1158 //\r
1159 // load maphead.ext (offsets and tileinfo for map file)\r
1160 //\r
1161 #ifndef MAPHEADERLINKED\r
1162         if ((handle = open("maphead.mph",\r
1163                  O_RDONLY | O_BINARY, S_IREAD)) == -1)\r
1164                 Quit (gvar, "Can't open maphead.mph");\r
1165         length = filelength(handle);\r
1166         MM_GetPtr (MEMPTRCONV gvar->ca.tinf,length,gvar);\r
1167         CA_FarRead(handle, gvar->ca.tinf, length,gvar);\r
1168         close(handle);\r
1169 //#else\r
1170 \r
1171         gvar->ca.tinf = (byte _seg *)FP_SEG(&maphead);\r
1172 \r
1173 #endif\r
1174 \r
1175 //\r
1176 // open the data file\r
1177 //\r
1178 //TODO: multiple files\r
1179         if ((gvar->ca.file.maphandle = open("data/test.map",\r
1180                  O_RDONLY | O_BINARY, S_IREAD)) == -1)\r
1181                 Quit (gvar, "Can't open data/test.map!");\r
1182 /*#ifdef MAPHEADERLINKED\r
1183         if ((maphandle = open("GAMEMAPS.16"ENSION,\r
1184                  O_RDONLY | O_BINARY, S_IREAD)) == -1)\r
1185                 Quit (gvar, "Can't open GAMEMAPS.16"ENSION"!");\r
1186 #else\r
1187         if ((maphandle = open("MAPTEMP.16"ENSION,\r
1188                  O_RDONLY | O_BINARY, S_IREAD)) == -1)\r
1189                 Quit (gvar, "Can't open MAPTEMP.16"ENSION"!");\r
1190 #endif*/\r
1191 }\r
1192 \r
1193 //==========================================================================\r
1194 \r
1195 \r
1196 /*\r
1197 ======================\r
1198 =\r
1199 = CAL_SetupAudioFile\r
1200 =\r
1201 ======================\r
1202 */\r
1203 \r
1204 /*void CAL_SetupAudioFile (void)\r
1205 {\r
1206         int handle;\r
1207         long length;\r
1208 \r
1209 //\r
1210 // load maphead.ext (offsets and tileinfo for map file)\r
1211 //\r
1212 #ifndef AUDIOHEADERLINKED\r
1213         if ((handle = open("AUDIOHED.16",\r
1214                  O_RDONLY | O_BINARY, S_IREAD)) == -1)\r
1215                 Quit (gvar, "Can't open AUDIOHED.16""!");\r
1216         length = filelength(handle);\r
1217         MM_GetPtr (MEMPTRCONV audiostarts,length);\r
1218         CA_FarRead(handle, (byte far *)audiostarts, length);\r
1219         close(handle);\r
1220 #else\r
1221         audiohuffman = (huffnode *)&audiodict;\r
1222         CAL_OptimizeNodes (audiohuffman);\r
1223         audiostarts = (long _seg *)FP_SEG(&audiohead);\r
1224 #endif\r
1225 \r
1226 //\r
1227 // open the data file\r
1228 //\r
1229 #ifndef AUDIOHEADERLINKED\r
1230         if ((audiohandle = open("AUDIOT.16",\r
1231                  O_RDONLY | O_BINARY, S_IREAD)) == -1)\r
1232                 Quit (gvar, "Can't open AUDIOT.16""!");\r
1233 #else\r
1234         if ((audiohandle = open("AUDIO.16",\r
1235                  O_RDONLY | O_BINARY, S_IREAD)) == -1)\r
1236                 Quit (gvar, "Can't open AUDIO.16""!");\r
1237 #endif\r
1238 }*/\r
1239 \r
1240 //==========================================================================\r
1241 \r
1242 \r
1243 /*\r
1244 ======================\r
1245 =\r
1246 = CA_Startup\r
1247 =\r
1248 = Open all files and load in headers\r
1249 =\r
1250 ======================\r
1251 */\r
1252 \r
1253 void CA_Startup(global_game_variables_t *gvar)\r
1254 {\r
1255 #ifdef PROFILE\r
1256 #ifdef __BORLANDC__\r
1257         unlink("profile.16b");\r
1258         gvar->handle.profilehandle = open("profile.16b", O_CREAT | O_WRONLY | O_TEXT);\r
1259 #endif\r
1260 #ifdef __WATCOMC__\r
1261         unlink("profile.16w");\r
1262         gvar->handle.profilehandle = open("profile.16w", O_CREAT | O_WRONLY | O_TEXT);\r
1263 #endif\r
1264 #endif//profile\r
1265 \r
1266 #ifdef __BORLANDC__\r
1267         unlink("meminfo.16b");\r
1268         gvar->handle.showmemhandle = open("meminfo.16b", O_CREAT | O_WRONLY | O_TEXT);\r
1269 #endif\r
1270 #ifdef __WATCOMC__\r
1271         unlink("meminfo.16w");\r
1272         gvar->handle.showmemhandle = open("meminfo.16w", O_CREAT | O_WRONLY | O_TEXT);\r
1273 #endif\r
1274 \r
1275 \r
1276 #ifndef NOMAPS\r
1277         CAL_SetupMapFile (gvar);\r
1278 #endif\r
1279 #ifndef NOGRAPHICS\r
1280         CAL_SetupGrFile (gvar);\r
1281 #endif\r
1282 #ifndef NOAUDIO\r
1283         CAL_SetupMapFile (gvar);\r
1284 #endif\r
1285 \r
1286         gvar->ca.camap.mapon = -1;\r
1287         gvar->ca.ca_levelbit = 1;\r
1288         gvar->ca.ca_levelnum = 0;\r
1289 \r
1290 /*      drawcachebox    = CAL_DialogDraw;\r
1291         updatecachebox  = CAL_DialogUpdate;\r
1292         finishcachebox  = CAL_DialogFinish;*/\r
1293 }\r
1294 \r
1295 //==========================================================================\r
1296 \r
1297 \r
1298 /*\r
1299 ======================\r
1300 =\r
1301 = CA_Shutdown\r
1302 =\r
1303 = Closes all files\r
1304 =\r
1305 ======================\r
1306 */\r
1307 \r
1308 void CA_Shutdown(global_game_variables_t *gvar)\r
1309 {\r
1310 #ifdef PROFILE\r
1311         close(gvar->handle.profilehandle);\r
1312 #endif\r
1313         close(gvar->handle.showmemhandle);\r
1314 \r
1315         close(gvar->ca.file.maphandle);\r
1316         close(gvar->ca.file.grhandle);\r
1317         close(gvar->ca.file.audiohandle);\r
1318 }\r
1319 \r
1320 //===========================================================================\r
1321 \r
1322 /*\r
1323 ======================\r
1324 =\r
1325 = CA_CacheAudioChunk\r
1326 =\r
1327 ======================\r
1328 */\r
1329 /*++++\r
1330 void CA_CacheAudioChunk (int chunk)\r
1331 {\r
1332         long    pos,compressed;\r
1333 #ifdef AUDIOHEADERLINKED\r
1334         long    expanded;\r
1335         memptr  bigbufferseg;\r
1336         byte    far *source;\r
1337 #endif\r
1338 \r
1339         if (audiosegs[chunk])\r
1340         {\r
1341                 MM_SetPurge (MEMPTRCONV audiosegs[chunk],0);\r
1342                 return;                                                 // allready in memory\r
1343         }\r
1344 \r
1345 // MDM begin - (GAMERS EDGE)\r
1346 //\r
1347         if (!FindFile("AUDIO.16",NULL,2))\r
1348                 Quit (gvar, "CA_CacheAudioChunk(): Can't find audio files.");\r
1349 //\r
1350 // MDM end\r
1351 \r
1352 //\r
1353 // load the chunk into a buffer, either the miscbuffer if it fits, or allocate\r
1354 // a larger buffer\r
1355 //\r
1356         pos = audiostarts[chunk];\r
1357         compressed = audiostarts[chunk+1]-pos;\r
1358 \r
1359         lseek(audiohandle,pos,SEEK_SET);\r
1360 \r
1361 #ifndef AUDIOHEADERLINKED\r
1362 \r
1363         MM_GetPtr (MEMPTRCONV audiosegs[chunk],compressed);\r
1364         if (mmerror)\r
1365                 return;\r
1366 \r
1367         CA_FarRead(audiohandle,audiosegs[chunk],compressed);\r
1368 \r
1369 #else\r
1370 \r
1371         if (compressed<=BUFFERSIZE)\r
1372         {\r
1373                 CA_FarRead(audiohandle,bufferseg,compressed);\r
1374                 source = bufferseg;\r
1375         }\r
1376         else\r
1377         {\r
1378                 MM_GetPtr(&bigbufferseg,compressed);\r
1379                 if (mmerror)\r
1380                         return;\r
1381                 MM_SetLock (&bigbufferseg,true);\r
1382                 CA_FarRead(audiohandle,bigbufferseg,compressed);\r
1383                 source = bigbufferseg;\r
1384         }\r
1385 \r
1386         expanded = *(long far *)source;\r
1387         source += 4;                    // skip over length\r
1388         MM_GetPtr (MEMPTRCONV audiosegs[chunk],expanded);\r
1389         if (mmerror)\r
1390                 goto done;\r
1391         CAL_HuffExpand (source,audiosegs[chunk],expanded,audiohuffman);\r
1392 \r
1393 done:\r
1394         if (compressed>BUFFERSIZE)\r
1395                 MM_FreePtr(&bigbufferseg);\r
1396 #endif\r
1397 }*/\r
1398 \r
1399 //===========================================================================\r
1400 \r
1401 /*\r
1402 ======================\r
1403 =\r
1404 = CA_LoadAllSounds\r
1405 =\r
1406 = Purges all sounds, then loads all new ones (mode switch)\r
1407 =\r
1408 ======================\r
1409 */\r
1410 /*++++\r
1411 void CA_LoadAllSounds (void)\r
1412 {\r
1413         unsigned        start,i;\r
1414 \r
1415         switch (oldsoundmode)\r
1416         {\r
1417         case sdm_Off:\r
1418                 goto cachein;\r
1419         case sdm_PC:\r
1420                 start = STARTPCSOUNDS;\r
1421                 break;\r
1422         case sdm_AdLib:\r
1423                 start = STARTADLIBSOUNDS;\r
1424                 break;\r
1425         }\r
1426 \r
1427         for (i=0;i<NUMSOUNDS;i++,start++)\r
1428                 if (audiosegs[start])\r
1429                         MM_SetPurge (MEMPTRCONV audiosegs[start],3);            // make purgable\r
1430 \r
1431 cachein:\r
1432 \r
1433         switch (SoundMode)\r
1434         {\r
1435         case sdm_Off:\r
1436                 return;\r
1437         case sdm_PC:\r
1438                 start = STARTPCSOUNDS;\r
1439                 break;\r
1440         case sdm_AdLib:\r
1441                 start = STARTADLIBSOUNDS;\r
1442                 break;\r
1443         }\r
1444 \r
1445         for (i=0;i<NUMSOUNDS;i++,start++)\r
1446                 CA_CacheAudioChunk (start);\r
1447 \r
1448         oldsoundmode = SoundMode;\r
1449 }*/\r
1450 \r
1451 //===========================================================================\r
1452 \r
1453 //????#if GRMODE == EGAGR\r
1454 #if 1\r
1455 \r
1456 /*\r
1457 ======================\r
1458 =\r
1459 = CAL_ShiftSprite\r
1460 =\r
1461 = Make a shifted (one byte wider) copy of a sprite into another area\r
1462 =\r
1463 ======================\r
1464 */\r
1465 \r
1466 unsigned        static  sheight,swidth;\r
1467 boolean static dothemask;\r
1468 unsigned        *shifttabletable[8];\r
1469 \r
1470 void CAL_ShiftSprite (unsigned segment,unsigned source,unsigned dest,\r
1471         unsigned width, unsigned height, unsigned pixshift, boolean domask, global_game_variables_t *gvar)\r
1472 {\r
1473 \r
1474         sheight = height;               // because we are going to reassign bp\r
1475         swidth = width;\r
1476         dothemask = domask;\r
1477 \r
1478         __asm {\r
1479                 mov     ax,[segment]\r
1480                 mov     ds,ax           // source and dest are in same segment, and all local\r
1481 \r
1482                 mov     bx,[source]\r
1483                 mov     di,[dest]\r
1484 \r
1485                 mov     bp,[pixshift]\r
1486                 shl     bp,1\r
1487                 mov     bp,WORD PTR [shifttabletable+bp]        // bp holds pointer to shift table\r
1488 //              mov     bp,WORD PTR [gvar->video.shifttabletable+bp]    // bp holds pointer to shift table\r
1489 \r
1490                 cmp     [ss:dothemask],0\r
1491                 je              skipmask\r
1492 \r
1493 //\r
1494 // table shift the mask\r
1495 //\r
1496                 mov     dx,[ss:sheight]\r
1497 #ifdef __BORLANDC__\r
1498         }\r
1499 #endif\r
1500 domaskrow:\r
1501 #ifdef __BORLANDC__\r
1502         __asm {\r
1503 #endif\r
1504                 mov     BYTE PTR [di],255       // 0xff first byte\r
1505                 mov     cx,ss:[swidth]\r
1506 #ifdef __BORLANDC__\r
1507         }\r
1508 #endif\r
1509 domaskbyte:\r
1510 #ifdef __BORLANDC__\r
1511         __asm {\r
1512 #endif\r
1513                 mov     al,[bx]                         // source\r
1514                 not     al\r
1515                 inc     bx                                      // next source byte\r
1516                 xor     ah,ah\r
1517                 shl     ax,1\r
1518                 mov     si,ax\r
1519                 mov     ax,[bp+si]                      // table shift into two bytes\r
1520                 not     ax\r
1521                 and     [di],al                         // and with first byte\r
1522                 inc     di\r
1523                 mov     [di],ah                         // replace next byte\r
1524 \r
1525                 loop    domaskbyte\r
1526 \r
1527                 inc     di                                      // the last shifted byte has 1s in it\r
1528                 dec     dx\r
1529                 jnz     domaskrow\r
1530 #ifdef __BORLANDC__\r
1531         }\r
1532 #endif\r
1533 skipmask:\r
1534 #ifdef __BORLANDC__\r
1535         __asm {\r
1536 #endif\r
1537 //\r
1538 // table shift the data\r
1539 //\r
1540                 mov     dx,ss:[sheight]\r
1541                 shl     dx,1\r
1542                 shl     dx,1                            // four planes of data\r
1543 #ifdef __BORLANDC__\r
1544         }\r
1545 #endif\r
1546 dodatarow:\r
1547 #ifdef __BORLANDC__\r
1548         __asm {\r
1549 #endif\r
1550                 mov     BYTE PTR [di],0         // 0 first byte\r
1551                 mov     cx,ss:[swidth]\r
1552 #ifdef __BORLANDC__\r
1553         }\r
1554 #endif\r
1555 dodatabyte:\r
1556 #ifdef __BORLANDC__\r
1557         __asm {\r
1558 #endif\r
1559                 mov     al,[bx]                         // source\r
1560                 inc     bx                                      // next source byte\r
1561                 xor     ah,ah\r
1562                 shl     ax,1\r
1563                 mov     si,ax\r
1564                 mov     ax,[bp+si]                      // table shift into two bytes\r
1565                 or      [di],al                         // or with first byte\r
1566                 inc     di\r
1567                 mov     [di],ah                         // replace next byte\r
1568 \r
1569                 loop    dodatabyte\r
1570 \r
1571                 inc     di                                      // the last shifted byte has 0s in it\r
1572                 dec     dx\r
1573                 jnz     dodatarow\r
1574 \r
1575 //\r
1576 // done\r
1577 //\r
1578 \r
1579                 mov     ax,ss                           // restore data segment\r
1580                 mov     ds,ax\r
1581         }\r
1582 \r
1583 }\r
1584 \r
1585 #endif\r
1586 \r
1587 //===========================================================================\r
1588 \r
1589 /*\r
1590 ======================\r
1591 =\r
1592 = CAL_CacheSprite\r
1593 =\r
1594 = Generate shifts and set up sprite structure for a given sprite\r
1595 =\r
1596 ======================\r
1597 */\r
1598 \r
1599 void CAL_CacheSprite (int chunk, byte far *compressed, global_game_variables_t *gvar)\r
1600 {\r
1601         int i;\r
1602         unsigned shiftstarts[5];\r
1603         unsigned smallplane,bigplane,expanded;\r
1604         spritetabletype far *spr;\r
1605         spritetype _seg *dest;\r
1606 \r
1607 #if 0\r
1608 //GRMODE == CGAGR\r
1609 //\r
1610 // CGA has no pel panning, so shifts are never needed\r
1611 //\r
1612         spr = &gvar->video.spritetable[chunk-STARTSPRITES];\r
1613         smallplane = spr->width*spr->height;\r
1614         MM_GetPtr (&grsegs[chunk],smallplane*2+MAXSHIFTS*6);\r
1615         if (mmerror)\r
1616                 return;\r
1617         dest = (spritetype _seg *)grsegs[chunk];\r
1618         dest->sourceoffset[0] = MAXSHIFTS*6;    // start data after 3 unsigned tables\r
1619         dest->planesize[0] = smallplane;\r
1620         dest->width[0] = spr->width;\r
1621 \r
1622 //\r
1623 // expand the unshifted shape\r
1624 //\r
1625         CAL_HuffExpand (compressed, &dest->data[0],smallplane*2,gvar->ca.grhuffman);\r
1626 \r
1627 #endif\r
1628 \r
1629 \r
1630 //#if GRMODE == EGAGR\r
1631 \r
1632 //\r
1633 // calculate sizes\r
1634 //\r
1635         spr = &gvar->video.spritetable[chunk-STARTSPRITES];\r
1636         smallplane = spr->width*spr->height;\r
1637         bigplane = (spr->width+1)*spr->height;\r
1638 \r
1639         shiftstarts[0] = MAXSHIFTS*6;   // start data after 3 unsigned tables\r
1640         shiftstarts[1] = shiftstarts[0] + smallplane*5; // 5 planes in a sprite\r
1641         shiftstarts[2] = shiftstarts[1] + bigplane*5;\r
1642         shiftstarts[3] = shiftstarts[2] + bigplane*5;\r
1643         shiftstarts[4] = shiftstarts[3] + bigplane*5;   // nothing ever put here\r
1644 \r
1645         expanded = shiftstarts[spr->shifts];\r
1646         MM_GetPtr (MEMPTRCONV gvar->ca.grsegs[chunk],expanded, gvar);\r
1647         if (gvar->mm.mmerror)\r
1648                 return;\r
1649         dest = (spritetype _seg *)gvar->ca.grsegs[chunk];\r
1650 \r
1651 //\r
1652 // expand the unshifted shape\r
1653 //\r
1654         CAL_HuffExpand (compressed, &dest->data[0],smallplane*5,gvar->ca.grhuffman);\r
1655 \r
1656 //\r
1657 // make the shifts!\r
1658 //\r
1659         switch (spr->shifts)\r
1660         {\r
1661         case    1:\r
1662                 for (i=0;i<4;i++)\r
1663                 {\r
1664                         dest->sourceoffset[i] = shiftstarts[0];\r
1665                         dest->planesize[i] = smallplane;\r
1666                         dest->width[i] = spr->width;\r
1667                 }\r
1668                 break;\r
1669 \r
1670         case    2:\r
1671                 for (i=0;i<2;i++)\r
1672                 {\r
1673                         dest->sourceoffset[i] = shiftstarts[0];\r
1674                         dest->planesize[i] = smallplane;\r
1675                         dest->width[i] = spr->width;\r
1676                 }\r
1677                 for (i=2;i<4;i++)\r
1678                 {\r
1679                         dest->sourceoffset[i] = shiftstarts[1];\r
1680                         dest->planesize[i] = bigplane;\r
1681                         dest->width[i] = spr->width+1;\r
1682                 }\r
1683                 CAL_ShiftSprite ((unsigned)gvar->ca.grsegs[chunk],dest->sourceoffset[0],\r
1684                         dest->sourceoffset[2],spr->width,spr->height,4,true,gvar);\r
1685                 break;\r
1686 \r
1687         case    4:\r
1688                 dest->sourceoffset[0] = shiftstarts[0];\r
1689                 dest->planesize[0] = smallplane;\r
1690                 dest->width[0] = spr->width;\r
1691 \r
1692                 dest->sourceoffset[1] = shiftstarts[1];\r
1693                 dest->planesize[1] = bigplane;\r
1694                 dest->width[1] = spr->width+1;\r
1695                 CAL_ShiftSprite ((unsigned)gvar->ca.grsegs[chunk],dest->sourceoffset[0],\r
1696                         dest->sourceoffset[1],spr->width,spr->height,2,true,gvar);\r
1697 \r
1698                 dest->sourceoffset[2] = shiftstarts[2];\r
1699                 dest->planesize[2] = bigplane;\r
1700                 dest->width[2] = spr->width+1;\r
1701                 CAL_ShiftSprite ((unsigned)gvar->ca.grsegs[chunk],dest->sourceoffset[0],\r
1702                         dest->sourceoffset[2],spr->width,spr->height,4,true,gvar);\r
1703 \r
1704                 dest->sourceoffset[3] = shiftstarts[3];\r
1705                 dest->planesize[3] = bigplane;\r
1706                 dest->width[3] = spr->width+1;\r
1707                 CAL_ShiftSprite ((unsigned)gvar->ca.grsegs[chunk],dest->sourceoffset[0],\r
1708                         dest->sourceoffset[3],spr->width,spr->height,6,true,gvar);\r
1709 \r
1710                 break;\r
1711 \r
1712         default:\r
1713                 Quit (gvar, "CAL_CacheSprite: Bad shifts number!");\r
1714         }\r
1715 \r
1716 //#endif\r
1717 }\r
1718 \r
1719 //===========================================================================\r
1720 \r
1721 \r
1722 /*\r
1723 ======================\r
1724 =\r
1725 = CAL_ExpandGrChunk\r
1726 =\r
1727 = Does whatever is needed with a pointer to a compressed chunk\r
1728 =\r
1729 ======================\r
1730 */\r
1731 /*++++\r
1732 void CAL_ExpandGrChunk (int chunk, byte far *source)\r
1733 {\r
1734         long    expanded;\r
1735 \r
1736 \r
1737         if (chunk >= STARTTILE8 && chunk < STARTEXTERNS)\r
1738         {\r
1739         //\r
1740         // expanded sizes of tile8/16/32 are implicit\r
1741         //\r
1742 \r
1743 #if GRMODE == EGAGR\r
1744 #define BLOCK           32\r
1745 #define MASKBLOCK       40\r
1746 #endif\r
1747 \r
1748 #if GRMODE == CGAGR\r
1749 #define BLOCK           16\r
1750 #define MASKBLOCK       32\r
1751 #endif\r
1752 \r
1753                 if (chunk<STARTTILE8M)                  // tile 8s are all in one chunk!\r
1754                         expanded = BLOCK*NUMTILE8;\r
1755                 else if (chunk<STARTTILE16)\r
1756                         expanded = MASKBLOCK*NUMTILE8M;\r
1757                 else if (chunk<STARTTILE16M)    // all other tiles are one/chunk\r
1758                         expanded = BLOCK*4;\r
1759                 else if (chunk<STARTTILE32)\r
1760                         expanded = MASKBLOCK*4;\r
1761                 else if (chunk<STARTTILE32M)\r
1762                         expanded = BLOCK*16;\r
1763                 else\r
1764                         expanded = MASKBLOCK*16;\r
1765         }\r
1766         else\r
1767         {\r
1768         //\r
1769         // everything else has an explicit size longword\r
1770         //\r
1771                 expanded = *(long far *)source;\r
1772                 source += 4;                    // skip over length\r
1773         }\r
1774 \r
1775 //\r
1776 // allocate final space, decompress it, and free bigbuffer\r
1777 // Sprites need to have shifts made and various other junk\r
1778 //\r
1779         if (chunk>=STARTSPRITES && chunk< STARTTILE8)\r
1780                 CAL_CacheSprite(chunk,source);\r
1781         else\r
1782         {\r
1783                 MM_GetPtr (&grsegs[chunk],expanded);\r
1784                 if (mmerror)\r
1785                         return;\r
1786                 CAL_HuffExpand (source,grsegs[chunk],expanded,gvar->ca.grhuffman);\r
1787         }\r
1788 }\r
1789 */\r
1790 \r
1791 /*\r
1792 ======================\r
1793 =\r
1794 = CAL_ReadGrChunk\r
1795 =\r
1796 = Gets a chunk off disk, optimizing reads to general buffer\r
1797 =\r
1798 ======================\r
1799 */\r
1800 /*++++\r
1801 void CAL_ReadGrChunk (int chunk)\r
1802 {\r
1803         long    pos,compressed;\r
1804         memptr  bigbufferseg;\r
1805         byte    far *source;\r
1806         int             next;\r
1807 \r
1808 //\r
1809 // load the chunk into a buffer, either the miscbuffer if it fits, or allocate\r
1810 // a larger buffer\r
1811 //\r
1812         pos = GRFILEPOS(chunk,gvar);\r
1813         if (pos<0)                                                      // $FFFFFFFF start is a sparse tile\r
1814           return;\r
1815 \r
1816         next = chunk +1;\r
1817         while (GRFILEPOS(next,gvar) == -1)              // skip past any sparse tiles\r
1818                 next++;\r
1819 \r
1820         compressed = GRFILEPOS(next,gvar)-pos;\r
1821 \r
1822         lseek(gvar->ca.file.grhandle,pos,SEEK_SET);\r
1823 \r
1824         if (compressed<=BUFFERSIZE)\r
1825         {\r
1826                 CA_FarRead(gvar->ca.file.grhandle,bufferseg,compressed);\r
1827                 source = bufferseg;\r
1828         }\r
1829         else\r
1830         {\r
1831                 MM_GetPtr(&bigbufferseg,compressed);\r
1832                 if (mmerror)\r
1833                         return;\r
1834                 MM_SetLock (&bigbufferseg,true);\r
1835                 CA_FarRead(gvar->ca.file.grhandle,bigbufferseg,compressed);\r
1836                 source = bigbufferseg;\r
1837         }\r
1838 \r
1839         CAL_ExpandGrChunk (chunk,source);\r
1840 \r
1841         if (compressed>BUFFERSIZE)\r
1842                 MM_FreePtr(&bigbufferseg);\r
1843 }\r
1844 */\r
1845 /*\r
1846 ======================\r
1847 =\r
1848 = CA_CacheGrChunk\r
1849 =\r
1850 = Makes sure a given chunk is in memory, loadiing it if needed\r
1851 =\r
1852 ======================\r
1853 */\r
1854 /*++++\r
1855 void CA_CacheGrChunk (int chunk)\r
1856 {\r
1857         long    pos,compressed;\r
1858         memptr  bigbufferseg;\r
1859         byte    far *source;\r
1860         int             next;\r
1861 \r
1862         gvar->ca.grneeded[chunk] |= ca_levelbit;                // make sure it doesn't get removed\r
1863         if (grsegs[chunk])\r
1864         {\r
1865                 MM_SetPurge (&grsegs[chunk],0);\r
1866                 return;                                                 // allready in memory\r
1867         }\r
1868 \r
1869 // MDM begin - (GAMERS EDGE)\r
1870 //\r
1871         if (!FindFile("EGAGRAPH.16",NULL,2))\r
1872                 Quit (gvar, "CA_CacheGrChunk(): Can't find graphics files.");\r
1873 //\r
1874 // MDM end\r
1875 \r
1876 //\r
1877 // load the chunk into a buffer, either the miscbuffer if it fits, or allocate\r
1878 // a larger buffer\r
1879 //\r
1880         pos = GRFILEPOS(chunk,gvar);\r
1881         if (pos<0)                                                      // $FFFFFFFF start is a sparse tile\r
1882           return;\r
1883 \r
1884         next = chunk +1;\r
1885         while (GRFILEPOS(next) == -1)           // skip past any sparse tiles\r
1886                 next++;\r
1887 \r
1888         compressed = GRFILEPOS(next,gvar)-pos;\r
1889 \r
1890         lseek(gvar->ca.file.grhandle,pos,SEEK_SET);\r
1891 \r
1892         if (compressed<=BUFFERSIZE)\r
1893         {\r
1894                 CA_FarRead(gvar->ca.file.grhandle,bufferseg,compressed);\r
1895                 source = bufferseg;\r
1896         }\r
1897         else\r
1898         {\r
1899                 MM_GetPtr(&bigbufferseg,compressed);\r
1900                 MM_SetLock (&bigbufferseg,true);\r
1901                 CA_FarRead(gvar->ca.file.grhandle,bigbufferseg,compressed);\r
1902                 source = bigbufferseg;\r
1903         }\r
1904 \r
1905         CAL_ExpandGrChunk (chunk,source);\r
1906 \r
1907         if (compressed>BUFFERSIZE)\r
1908                 MM_FreePtr(&bigbufferseg);\r
1909 }\r
1910 */\r
1911 \r
1912 \r
1913 //==========================================================================\r
1914 \r
1915 /*\r
1916 ======================\r
1917 =\r
1918 = CA_CacheMap\r
1919 =\r
1920 ======================\r
1921 */\r
1922 /*++++ segments!\r
1923 void CA_CacheMap (global_game_variables_t *gvar)\r
1924 {\r
1925         long    pos,compressed;\r
1926         int             plane;\r
1927         memptr  *dest,bigbufferseg;\r
1928         unsigned        size;\r
1929         unsigned        far     *source;\r
1930 #ifdef MAPHEADERLINKED\r
1931         memptr  buffer2seg;\r
1932         long    expanded;\r
1933 #endif\r
1934 \r
1935 \r
1936 //\r
1937 // free up memory from last map\r
1938 //\r
1939         if (gvar->ca.camap.mapon>-1 && gvar->ca.camap.mapheaderseg[gvar->ca.camap.mapon])\r
1940                 MM_SetPurge (((memptr)gvar->ca.camap.mapheaderseg[(gvar->ca.camap.mapon)]), 3, gvar);\r
1941         for (plane=0;plane<MAPPLANES;plane++)\r
1942                 if (gvar->ca.camap.mapsegs[plane])\r
1943                         MM_FreePtr ((memptr)gvar->ca.camap.mapsegs[plane], gvar);\r
1944 \r
1945         gvar->ca.camap.mapon = gvar->ca.camap.mapnum;\r
1946 \r
1947 \r
1948 //\r
1949 // load map header\r
1950 // The header will be cached if it is still around\r
1951 //\r
1952 //      if (!gvar->ca.camap.mapheaderseg[gvar->ca.camap.mapnum])\r
1953 //      {\r
1954 //              //pos = ((mapfiletype   _seg *)tinf)->headeroffsets[mapnum];\r
1955 //              //pos = ((_seg *)gvar->ca.camap.tinf)->headeroffsets[gvar->ca.camap.mapnum];\r
1956 //              pos = ((memptr)gvar->ca.camap.tinf)->headeroffsets[gvar->ca.camap.mapnum];\r
1957 //              if (pos<0)                                              // $FFFFFFFF start is a sparse map\r
1958 //                printf("CA_CacheMap: Tried to load a non existent map!");\r
1959 \r
1960 //              MM_GetPtr(MEMPTRCONV gvar->ca.camapheaderseg[mapnum],sizeof(maptype));\r
1961 //              lseek(maphandle,pos,SEEK_SET);\r
1962 //              CA_FarRead (maphandle,(memptr)mapheaderseg[mapnum],sizeof(maptype));\r
1963 //      }\r
1964 //      else\r
1965 //              MM_SetPurge (MEMPTRCONV mapheaderseg[mapnum], 0, &(gvar->mm));\r
1966 \r
1967 //\r
1968 // load the planes in\r
1969 // If a plane's pointer still exists it will be overwritten (levels are\r
1970 // allways reloaded, never cached)\r
1971 //\r
1972 \r
1973         size = mapheaderseg[mapnum]->width * mapheaderseg[mapnum]->height * 2;\r
1974 \r
1975         for (plane = 0; plane<MAPPLANES; plane++)\r
1976         {\r
1977                 //pos = mapheaderseg[mapnum]->planestart[plane];\r
1978                 //compressed = mapheaderseg[mapnum]->planelength[plane];\r
1979 \r
1980                 if (!compressed)\r
1981                         continue;               // the plane is not used in this game\r
1982 \r
1983                 dest = MEMPTRCONV mapsegs[plane];\r
1984                 MM_GetPtr(dest,size);\r
1985 \r
1986                 lseek(maphandle,pos,SEEK_SET);\r
1987                 if (compressed<=BUFFERSIZE)\r
1988                         source = bufferseg;\r
1989                 else\r
1990                 {\r
1991                         MM_GetPtr(&bigbufferseg,compressed);\r
1992                         MM_SetLock (&bigbufferseg,true);\r
1993                         source = bigbufferseg;\r
1994                 }\r
1995 \r
1996                 CA_FarRead(maphandle,(byte far *)source,compressed);\r
1997 #ifdef MAPHEADERLINKED\r
1998                 //\r
1999                 // unhuffman, then unRLEW\r
2000                 // The huffman'd chunk has a two byte expanded length first\r
2001                 // The resulting RLEW chunk also does, even though it's not really\r
2002                 // needed\r
2003                 //\r
2004                 expanded = *source;\r
2005                 source++;\r
2006                 MM_GetPtr (&buffer2seg,expanded);\r
2007                 CAL_CarmackExpand (source, (unsigned far *)buffer2seg,expanded);\r
2008                 CA_RLEWexpand (((unsigned far *)buffer2seg)+1,*dest,size,\r
2009                 ((mapfiletype _seg *)tinf)->RLEWtag);\r
2010                 MM_FreePtr (&buffer2seg);\r
2011 \r
2012 #else\r
2013                 //\r
2014                 // unRLEW, skipping expanded length\r
2015                 //\r
2016                 CA_RLEWexpand (source+1, *dest,size,\r
2017                 ((mapfiletype _seg *)tinf)->RLEWtag);\r
2018 #endif\r
2019 \r
2020                 if (compressed>BUFFERSIZE)\r
2021                         MM_FreePtr(&bigbufferseg);\r
2022         }\r
2023 }//*/\r
2024 \r
2025 //===========================================================================\r
2026 \r
2027 /*\r
2028 ======================\r
2029 =\r
2030 = CA_UpLevel\r
2031 =\r
2032 = Goes up a bit level in the needed lists and clears it out.\r
2033 = Everything is made purgable\r
2034 =\r
2035 ======================\r
2036 */\r
2037 \r
2038 void CA_UpLevel (global_game_variables_t *gvar)\r
2039 {\r
2040         if (gvar->ca.ca_levelnum==7)\r
2041                 printf("CA_UpLevel: Up past level 7!");\r
2042 \r
2043         gvar->ca.ca_levelbit<<=1;\r
2044         gvar->ca.ca_levelnum++;\r
2045 }\r
2046 \r
2047 //===========================================================================\r
2048 \r
2049 /*\r
2050 ======================\r
2051 =\r
2052 = CA_DownLevel\r
2053 =\r
2054 = Goes down a bit level in the needed lists and recaches\r
2055 = everything from the lower level\r
2056 =\r
2057 ======================\r
2058 */\r
2059 \r
2060 void CA_DownLevel (global_game_variables_t *gvar)\r
2061 {\r
2062         if (!gvar->ca.ca_levelnum)\r
2063                 printf("CA_DownLevel: Down past level 0!");\r
2064         gvar->ca.ca_levelbit>>=1;\r
2065         gvar->ca.ca_levelnum--;\r
2066         ////++++++++++++++++++++++++++++++++++++++++++CA_CacheMarks(NULL);\r
2067 }\r
2068 \r
2069 //===========================================================================\r
2070 \r
2071 /*\r
2072 ======================\r
2073 =\r
2074 = CA_ClearMarks\r
2075 =\r
2076 = Clears out all the marks at the current level\r
2077 =\r
2078 ======================\r
2079 */\r
2080 \r
2081 void CA_ClearMarks (global_game_variables_t *gvar)\r
2082 {\r
2083         int i;\r
2084 \r
2085         for (i=0;i<NUMCHUNKS;i++)\r
2086                 gvar->ca.grneeded[i]&=~gvar->ca.ca_levelbit;\r
2087 }\r
2088 \r
2089 //===========================================================================\r
2090 \r
2091 /*\r
2092 ======================\r
2093 =\r
2094 = CA_ClearAllMarks\r
2095 =\r
2096 = Clears out all the marks on all the levels\r
2097 =\r
2098 ======================\r
2099 */\r
2100 \r
2101 void CA_ClearAllMarks (global_game_variables_t *gvar)\r
2102 {\r
2103         _fmemset (gvar->ca.grneeded,0,sizeof(gvar->ca.grneeded));\r
2104         gvar->ca.ca_levelbit = 1;\r
2105         gvar->ca.ca_levelnum = 0;\r
2106 }\r
2107 \r
2108 //===========================================================================\r
2109 \r
2110 /*\r
2111 ======================\r
2112 =\r
2113 = CA_FreeGraphics\r
2114 =\r
2115 ======================\r
2116 */\r
2117 \r
2118 void CA_SetGrPurge (global_game_variables_t *gvar)\r
2119 {\r
2120         int i;\r
2121 \r
2122 //\r
2123 // free graphics\r
2124 //\r
2125         CA_ClearMarks (gvar);\r
2126 \r
2127         for (i=0;i<NUMCHUNKS;i++)\r
2128                 if (gvar->ca.grsegs[i])\r
2129                         MM_SetPurge (gvar->ca.grsegs[i],3, gvar);\r
2130 }\r
2131 \r
2132 \r
2133 /*\r
2134 ======================\r
2135 =\r
2136 = CA_SetAllPurge\r
2137 =\r
2138 = Make everything possible purgable\r
2139 =\r
2140 ======================\r
2141 */\r
2142 \r
2143 void CA_SetAllPurge (global_game_variables_t *gvar)\r
2144 {\r
2145         int i;\r
2146 \r
2147         CA_ClearMarks (gvar);\r
2148 \r
2149 //\r
2150 // free cursor sprite and background save\r
2151 //\r
2152         //____VW_FreeCursor ();\r
2153 \r
2154 //\r
2155 // free map headers and map planes\r
2156 //\r
2157 //      for (i=0;i<NUMMAPS;i++)\r
2158 //              if (gvar->ca.camap.mapheaderseg[i])\r
2159 //                      MM_SetPurge (gvar->ca.camap.mapheaderseg[i],3, gvar);\r
2160 \r
2161         for (i=0;i<3;i++)\r
2162                 if (gvar->ca.mapsegs[i])\r
2163                         MM_FreePtr ((memptr *)&gvar->ca.mapsegs[i], gvar);\r
2164 \r
2165 //\r
2166 // free sounds\r
2167 //\r
2168         for (i=0;i<NUMSNDCHUNKS;i++)\r
2169                 if (gvar->ca.audiosegs[i])\r
2170                         MM_SetPurge ((memptr *)&gvar->ca.audiosegs[i],3, gvar);\r
2171 \r
2172 //\r
2173 // free graphics\r
2174 //\r
2175         CA_SetGrPurge (gvar);\r
2176 }\r
2177 \r
2178 \r
2179 //===========================================================================\r
2180 \r
2181 \r
2182 /*\r
2183 ======================\r
2184 =\r
2185 = CAL_DialogDraw\r
2186 =\r
2187 ======================\r
2188 */\r
2189 /*\r
2190 #define NUMBARS (17l*8)\r
2191 #define BARSTEP 8\r
2192 \r
2193 unsigned        thx,thy,lastx;\r
2194 long            barx,barstep;\r
2195 \r
2196 void    CAL_DialogDraw (char *title,unsigned numcache)\r
2197 {\r
2198         unsigned        homex,homey,x;\r
2199 \r
2200         barstep = (NUMBARS<<16)/numcache;\r
2201 \r
2202 //\r
2203 // draw dialog window (masked tiles 12 - 20 are window borders)\r
2204 //\r
2205         US_CenterWindow (20,8);\r
2206         homex = PrintX;\r
2207         homey = PrintY;\r
2208 \r
2209         US_CPrint ("Loading");\r
2210         fontcolor = F_SECONDCOLOR;\r
2211         US_CPrint (title);\r
2212         fontcolor = F_BLACK;\r
2213 \r
2214 //\r
2215 // draw thermometer bar\r
2216 //\r
2217         thx = homex + 8;\r
2218         thy = homey + 32;\r
2219         VWB_DrawTile8(thx,thy,0);               // CAT3D numbers\r
2220         VWB_DrawTile8(thx,thy+8,3);\r
2221         VWB_DrawTile8(thx,thy+16,6);\r
2222         VWB_DrawTile8(thx+17*8,thy,2);\r
2223         VWB_DrawTile8(thx+17*8,thy+8,5);\r
2224         VWB_DrawTile8(thx+17*8,thy+16,8);\r
2225         for (x=thx+8;x<thx+17*8;x+=8)\r
2226         {\r
2227                 VWB_DrawTile8(x,thy,1);\r
2228                 VWB_DrawTile8(x,thy+8,4);\r
2229                 VWB_DrawTile8(x,thy+16,7);\r
2230         }\r
2231 \r
2232         thx += 4;               // first line location\r
2233         thy += 5;\r
2234         barx = (long)thx<<16;\r
2235         lastx = thx;\r
2236 \r
2237         VW_UpdateScreen();\r
2238 }\r
2239 */\r
2240 \r
2241 /*\r
2242 ======================\r
2243 =\r
2244 = CAL_DialogUpdate\r
2245 =\r
2246 ======================\r
2247 */\r
2248 /*\r
2249 void    CAL_DialogUpdate (void)\r
2250 {\r
2251         unsigned        x,xh;\r
2252 \r
2253         barx+=barstep;\r
2254         xh = barx>>16;\r
2255         if (xh - lastx > BARSTEP)\r
2256         {\r
2257                 for (x=lastx;x<=xh;x++)\r
2258 #if GRMODE == EGAGR\r
2259                         VWB_Vlin (thy,thy+13,x,14);\r
2260 #endif\r
2261 #if GRMODE == CGAGR\r
2262                         VWB_Vlin (thy,thy+13,x,SECONDCOLOR);\r
2263 #endif\r
2264                 lastx = xh;\r
2265                 VW_UpdateScreen();\r
2266         }\r
2267 }*/\r
2268 \r
2269 /*\r
2270 ======================\r
2271 =\r
2272 = CAL_DialogFinish\r
2273 =\r
2274 ======================\r
2275 */\r
2276 /*\r
2277 void    CAL_DialogFinish (void)\r
2278 {\r
2279         unsigned        x,xh;\r
2280 \r
2281         xh = thx + NUMBARS;\r
2282         for (x=lastx;x<=xh;x++)\r
2283 #if GRMODE == EGAGR\r
2284                 VWB_Vlin (thy,thy+13,x,14);\r
2285 #endif\r
2286 #if GRMODE == CGAGR\r
2287                 VWB_Vlin (thy,thy+13,x,SECONDCOLOR);\r
2288 #endif\r
2289         VW_UpdateScreen();\r
2290 \r
2291 }*/\r
2292 \r
2293 //===========================================================================\r
2294 \r
2295 /*\r
2296 ======================\r
2297 =\r
2298 = CA_CacheMarks\r
2299 =\r
2300 ======================\r
2301 *//*++++\r
2302 #define MAXEMPTYREAD    1024\r
2303 \r
2304 void CAL_CacheMarks (char *title, global_game_variables_t *gvar)\r
2305 {\r
2306         boolean dialog;\r
2307         int     i,next,numcache;\r
2308         long    pos,endpos,nextpos,nextendpos,compressed;\r
2309         long    bufferstart,bufferend;  // file position of general buffer\r
2310         byte    far *source;\r
2311         memptr  bigbufferseg;\r
2312 \r
2313         dialog = (title!=NULL);\r
2314 \r
2315         numcache = 0;\r
2316 //\r
2317 // go through and make everything not needed purgable\r
2318 //\r
2319         for (i=0;i<NUMCHUNKS;i++)\r
2320                 if (gvar->ca.grneeded[i]&(gvar->ca.ca_levelbit))//if (grneeded[i]&ca_levelbit)\r
2321                 {\r
2322                         if (gvar->ca.grsegs[i])                                 // its allready in memory, make\r
2323                                 MM_SetPurge(gvar->ca.grsegs[i],0,gvar); // sure it stays there!\r
2324                         else\r
2325                                 numcache++;\r
2326                 }\r
2327                 else\r
2328                 {\r
2329                         if (gvar->ca.grsegs[i])                                 // not needed, so make it purgeable\r
2330                                 MM_SetPurge(gvar->ca.grsegs[i],3,gvar);\r
2331                 }\r
2332 \r
2333         if (!numcache)                  // nothing to cache!\r
2334                 return;\r
2335 \r
2336 // MDM begin - (GAMERS EDGE)\r
2337 //\r
2338 //      if (!FindFile("EGAGRAPH.16",NULL,2))\r
2339 //              Quit (gvar, "CA_CacheMarks(): Can't find graphics files.");\r
2340 //\r
2341 // MDM end\r
2342 \r
2343         if (dialog)\r
2344         {\r
2345 #ifdef PROFILE\r
2346                 write(profilehandle,title,strlen(title));\r
2347                 write(profilehandle,"\n",1);\r
2348 #endif\r
2349                 if (drawcachebox)\r
2350                         drawcachebox(title,numcache);\r
2351         }\r
2352 \r
2353 //\r
2354 // go through and load in anything still needed\r
2355 //\r
2356         bufferstart = bufferend = 0;            // nothing good in buffer now\r
2357 \r
2358         for (i=0;i<NUMCHUNKS;i++)\r
2359                 if ( (gvar->ca.grneeded[i]&(gvar->ca.ca_levelbit)) && !gvar->ca.grsegs[i])\r
2360                 {\r
2361 //\r
2362 // update thermometer\r
2363 //\r
2364                         if (dialog && updatecachebox)\r
2365                                 updatecachebox ();\r
2366 \r
2367                         pos = GRFILEPOS(i,gvar);\r
2368                         if (pos<0)\r
2369                                 continue;\r
2370 \r
2371                         next = i +1;\r
2372                         while (GRFILEPOS(next) == -1)           // skip past any sparse tiles\r
2373                                 next++;\r
2374 \r
2375                         compressed = GRFILEPOS(next,gvar)-pos;\r
2376                         endpos = pos+compressed;\r
2377 \r
2378                         if (compressed<=BUFFERSIZE)\r
2379                         {\r
2380                                 if (bufferstart<=pos\r
2381                                 && bufferend>= endpos)\r
2382                                 {\r
2383                                 // data is allready in buffer\r
2384                                         source = (byte _seg *)bufferseg+(pos-bufferstart);\r
2385                                 }\r
2386                                 else\r
2387                                 {\r
2388                                 // load buffer with a new block from disk\r
2389                                 // try to get as many of the needed blocks in as possible\r
2390                                         while ( next < NUMCHUNKS )\r
2391                                         {\r
2392                                                 while (next < NUMCHUNKS &&\r
2393                                                 !(gvar->video.grneeded[next]&ca_levelbit && !grsegs[next]))\r
2394                                                         next++;\r
2395                                                 if (next == NUMCHUNKS)\r
2396                                                         continue;\r
2397 \r
2398                                                 nextpos = GRFILEPOS(next,gvar);\r
2399                                                 while (GRFILEPOS(++next,gvar) == -1)    // skip past any sparse tiles\r
2400                                                         ;\r
2401                                                 nextendpos = GRFILEPOS(next,gvar);\r
2402                                                 if (nextpos - endpos <= MAXEMPTYREAD\r
2403                                                 && nextendpos-pos <= BUFFERSIZE)\r
2404                                                         endpos = nextendpos;\r
2405                                                 else\r
2406                                                         next = NUMCHUNKS;                       // read pos to posend\r
2407                                         }\r
2408 \r
2409                                         lseek(gvar->ca.file.grhandle,pos,SEEK_SET);\r
2410                                         CA_FarRead(gvar->ca.file.grhandle,(gvar->mm.bufferseg),endpos-pos,gvar);\r
2411                                         bufferstart = pos;\r
2412                                         bufferend = endpos;\r
2413                                         source = bufferseg;\r
2414                                 }\r
2415                         }\r
2416                         else\r
2417                         {\r
2418                         // big chunk, allocate temporary buffer\r
2419                                 MM_GetPtr(&bigbufferseg,compressed,gvar);\r
2420                                 if (mmerror)\r
2421                                         return;\r
2422                                 MM_SetLock (&bigbufferseg,true);\r
2423                                 lseek(gvar->ca.file.grhandle,pos,SEEK_SET);\r
2424                                 CA_FarRead(gvar->ca.file.grhandle,bigbufferseg,compressed,gvar);\r
2425                                 source = bigbufferseg;\r
2426                         }\r
2427 \r
2428                         CAL_ExpandGrChunk (i,source);\r
2429                         if (mmerror)\r
2430                                 return;\r
2431 \r
2432                         if (compressed>BUFFERSIZE)\r
2433                                 MM_FreePtr(&bigbufferseg);\r
2434 \r
2435                 }\r
2436 \r
2437 //\r
2438 // finish up any thermometer remnants\r
2439 //\r
2440                 if (dialog && finishcachebox)\r
2441                         finishcachebox();\r
2442 }*/\r
2443 \r
2444 void CA_CannotOpen(char *string, global_game_variables_t *gvar)\r
2445 {\r
2446  char str[30];\r
2447 \r
2448  strcpy(str,"Can't open ");\r
2449  strcat(str,string);\r
2450  strcat(str,"!\n");\r
2451  Quit (gvar, str);\r
2452 }\r