OSDN Git Service

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