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