]> 4ch.mooo.com Git - 16.git/blob - src/lib/16_ca.c
p16 is being worked on a bunch by me wwww [16_ca needs huge amounts of work and I...
[16.git] / src / lib / 16_ca.c
1 /* Catacomb Apocalypse Source Code\r
2  * Copyright (C) 1993-2014 Flat Rock Software\r
3  *\r
4  * This program is free software; you can redistribute it and/or modify\r
5  * it under the terms of the GNU General Public License as published by\r
6  * the Free Software Foundation; either version 2 of the License, or\r
7  * (at your option) any later version.\r
8  *\r
9  * This program is distributed in the hope that it will be useful,\r
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of\r
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r
12  * GNU General Public License for more details.\r
13  *\r
14  * You should have received a copy of the GNU General Public License along\r
15  * with this program; if not, write to the Free Software Foundation, Inc.,\r
16  * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.\r
17  */\r
18 \r
19 // ID_CA.C\r
20 \r
21 /*\r
22 =============================================================================\r
23 \r
24 Id Software Caching Manager\r
25 ---------------------------\r
26 \r
27 Must be started BEFORE the memory manager, because it needs to get the headers\r
28 loaded into the data segment\r
29 \r
30 =============================================================================\r
31 */\r
32 \r
33 #include "src/lib/16_ca.h"\r
34 #pragma hdrstop\r
35 \r
36 #pragma warn -pro\r
37 #pragma warn -use\r
38 \r
39 //#define THREEBYTEGRSTARTS\r
40 //https://github.com/open-watcom/open-watcom-v2/issues/279#issuecomment-244587566 for _seg\r
41 /*\r
42 =============================================================================\r
43 \r
44                                                  LOCAL CONSTANTS\r
45 \r
46 =============================================================================\r
47 */\r
48 \r
49 /*typedef struct\r
50 {\r
51   word bit0,bit1;       // 0-255 is a character, > is a pointer to a node\r
52 } huffnode;*/\r
53 \r
54 \r
55 /*typedef struct\r
56 {\r
57         unsigned        RLEWtag;\r
58         long            headeroffsets[100];\r
59         byte            tileinfo[];\r
60 } mapfiletype;*/\r
61 \r
62 \r
63 /*\r
64 =============================================================================\r
65 \r
66                                                  GLOBAL VARIABLES\r
67 \r
68 =============================================================================\r
69 */\r
70 \r
71 /*byte          _seg    *tinf;\r
72 int                     mapon;\r
73 \r
74 unsigned        _seg    *mapsegs[3];\r
75 maptype         _seg    *mapheaderseg[NUMMAPS];\r
76 byte            _seg    *audiosegs[NUMSNDCHUNKS];\r
77 void            _seg    *grsegs[NUMCHUNKS];\r
78 \r
79 byte            far     grneeded[NUMCHUNKS];*/\r
80 \r
81 void    (*drawcachebox)         (char *title, unsigned numcache);\r
82 void    (*updatecachebox)       (void);\r
83 void    (*finishcachebox)       (void);\r
84 \r
85 /*\r
86 =============================================================================\r
87 \r
88                                                  LOCAL VARIABLES\r
89 \r
90 =============================================================================\r
91 */\r
92 \r
93 /*extern        long    far     CGAhead;\r
94 extern  long    far     EGAhead;\r
95 extern  byte    CGAdict;\r
96 extern  byte    EGAdict;\r
97 extern  byte    far     maphead;\r
98 extern  byte    mapdict;\r
99 extern  byte    far     audiohead;\r
100 extern  byte    audiodict;\r
101 \r
102 \r
103 long            _seg *grstarts; // array of offsets in egagraph, -1 for sparse\r
104 long            _seg *audiostarts;      // array of offsets in audio / audiot\r
105 \r
106 #ifdef GRHEADERLINKED\r
107 huffnode        *grhuffman;\r
108 #else\r
109 huffnode        grhuffman[255];\r
110 #endif\r
111 \r
112 #ifdef AUDIOHEADERLINKED\r
113 huffnode        *audiohuffman;\r
114 #else\r
115 huffnode        audiohuffman[255];\r
116 #endif\r
117 \r
118 \r
119 int                     grhandle;               // handle to EGAGRAPH\r
120 int                     maphandle;              // handle to MAPTEMP / GAMEMAPS\r
121 int                     audiohandle;    // handle to AUDIOT / AUDIO\r
122 \r
123 long            chunkcomplen,chunkexplen;\r
124 \r
125 SDMode          oldsoundmode;\r
126 \r
127 \r
128 \r
129 void    CAL_DialogDraw (char *title,unsigned numcache);\r
130 void    CAL_DialogUpdate (void);\r
131 void    CAL_DialogFinish (void);*/\r
132 //void  CAL_CarmackExpand (unsigned far *source, unsigned far *dest,unsigned length);\r
133 \r
134 \r
135 #ifdef THREEBYTEGRSTARTS\r
136 #define FILEPOSSIZE     3\r
137 //#define       GRFILEPOS(c) (*(long far *)(((byte far *)grstarts)+(c)*3)&0xffffff)\r
138 long GRFILEPOS(int c, global_game_variables_t *gvar)\r
139 {\r
140         long value;\r
141         int     offset;\r
142 \r
143         offset = c*3;\r
144 \r
145         value = *(long far *)(((byte far *)gvar->ca.grstarts)+offset);\r
146 \r
147         value &= 0x00ffffffl;\r
148 \r
149         if (value == 0xffffffl)\r
150                 value = -1;\r
151 \r
152         return value;\r
153 };\r
154 #else\r
155 #define FILEPOSSIZE     4\r
156 #define GRFILEPOS(c) (gvar->ca.grstarts[c])\r
157 #endif\r
158 \r
159 /*\r
160 =============================================================================\r
161 \r
162                                            LOW LEVEL ROUTINES\r
163 \r
164 =============================================================================\r
165 */\r
166 \r
167 /*\r
168 ============================\r
169 =\r
170 = CA_OpenDebug / CA_CloseDebug\r
171 =\r
172 = Opens a binary file with the handle "debughandle"\r
173 =\r
174 ============================\r
175 */\r
176 void CA_OpenDebug(global_game_variables_t *gvar)\r
177 {\r
178 #ifdef __BORLANDC__\r
179         unlink("debug.16b");\r
180         gvar->handle.debughandle = open("debug.16b", O_CREAT | O_WRONLY | O_TEXT);\r
181 #endif\r
182 #ifdef __WATCOMC__\r
183         unlink("debug.16w");\r
184         gvar->handle.debughandle = open("debug.16w", O_CREAT | O_WRONLY | O_TEXT);\r
185 #endif\r
186 }\r
187 \r
188 void CA_CloseDebug(global_game_variables_t *gvar)\r
189 {\r
190         close(gvar->handle.debughandle);\r
191 }\r
192 \r
193 \r
194 \r
195 /*\r
196 ============================\r
197 =\r
198 = CAL_GetGrChunkLength\r
199 =\r
200 = Gets the length of an explicit length chunk (not tiles)\r
201 = The file pointer is positioned so the compressed data can be read in next.\r
202 =\r
203 ============================\r
204 */\r
205 /*++++\r
206 void CAL_GetGrChunkLength (int chunk)\r
207 {\r
208         lseek(grhandle,GRFILEPOS(chunk),SEEK_SET);\r
209         read(grhandle,&chunkexplen,sizeof(chunkexplen));\r
210         chunkcomplen = GRFILEPOS(chunk+1)-GRFILEPOS(chunk)-4;\r
211 }*/\r
212 \r
213 \r
214 /*\r
215 ==========================\r
216 =\r
217 = CA_FarRead\r
218 =\r
219 = Read from a file to a far pointer\r
220 =\r
221 ==========================\r
222 */\r
223 \r
224 boolean CA_FarRead(int handle, byte far *dest, dword length, global_game_variables_t *gvar)\r
225 {\r
226         boolean flag=0;\r
227         //dword fat=0;\r
228         //word segm=0;\r
229         if(gvar->pm.emm.EMSVer<0x40)\r
230         if(length>0xfffflu)\r
231         {\r
232                 printf("File is a fat bakapee\n");\r
233                 //segm=(length%0xfffflu)-1;\r
234                 //fat=segm*0xfffflu;\r
235                 //length-=fat;\r
236                 printf("CA_FarRead doesn't support 64K reads yet!\n");\r
237                 return 0;//TODO: EXPAND!!!\r
238         }\r
239 \r
240         //if(!fat&&!segm)\r
241         //{\r
242         __asm {\r
243                 push    ds\r
244                 mov     bx,[handle]\r
245                 mov     cx,[WORD PTR length]\r
246                 mov     dx,[WORD PTR dest]\r
247                 mov     ds,[WORD PTR dest+2]\r
248                 mov     ah,0x3f                         // READ w/handle\r
249                 int     21h\r
250                 pop     ds\r
251                 jnc     good\r
252                 mov     errno,ax\r
253                 mov     flag,0\r
254                 jmp End\r
255 #ifdef __BORLANDC__\r
256         }\r
257 #endif\r
258 good:\r
259 #ifdef __BORLANDC__\r
260         __asm {\r
261 #endif\r
262                 cmp     ax,[WORD PTR length]\r
263                 je      done\r
264 //              errno = EINVFMT;                        // user manager knows this is bad read\r
265                 mov     flag,0\r
266                 jmp End\r
267 #ifdef __BORLANDC__\r
268         }\r
269 #endif\r
270 done:\r
271 #ifdef __BORLANDC__\r
272         __asm {\r
273 #endif\r
274                 mov     flag,1\r
275 #ifdef __BORLANDC__\r
276         }\r
277 #endif\r
278 End:\r
279 #ifdef __WATCOMC__\r
280         }\r
281 #endif\r
282         return flag;\r
283 }\r
284 \r
285 \r
286 /*\r
287 ==========================\r
288 =\r
289 = CA_SegWrite\r
290 =\r
291 = Write from a file to a far pointer\r
292 =\r
293 ==========================\r
294 */\r
295 \r
296 boolean CA_FarWrite(int handle, byte far *source, dword length, global_game_variables_t *gvar)\r
297 {\r
298         boolean flag=0;\r
299         //dword fat=0;\r
300         //word segm=0;\r
301         if(gvar->pm.emm.EMSVer<0x40)\r
302         if(length>0xfffflu)\r
303         {\r
304                 printf("File is a fat bakapee\n");\r
305                 //segm=(length%0xfffflu)-1;\r
306                 //fat=segm*0xfffflu;\r
307                 //length-=fat;\r
308                 printf("CA_FarWrite doesn't support 64K reads yet!\n");\r
309                 return 0;\r
310         }\r
311 \r
312         //if(!fat&&!segm)\r
313         //{\r
314         __asm {\r
315                 push    ds\r
316                 mov     bx,[handle]\r
317                 mov     cx,[WORD PTR length]\r
318                 mov     dx,[WORD PTR source]\r
319                 mov     ds,[WORD PTR source+2]\r
320                 mov     ah,0x40                 // WRITE w/handle\r
321                 int     21h\r
322                 pop     ds\r
323                 jnc     good\r
324                 mov     errno,ax\r
325                 mov flag,0\r
326                 jmp End\r
327 #ifdef __BORLANDC__\r
328         }\r
329 #endif\r
330 good:\r
331 #ifdef __BORLANDC__\r
332         __asm {\r
333 #endif\r
334                 cmp     ax,[WORD PTR length]\r
335                 je      done\r
336 //              errno = ENOMEM;                         // user manager knows this is bad write\r
337                 mov     flag,0\r
338                 jmp End\r
339 #ifdef __BORLANDC__\r
340         }\r
341 #endif\r
342 done:\r
343 #ifdef __BORLANDC__\r
344         __asm {\r
345 #endif\r
346                 mov     flag,1\r
347 #ifdef __BORLANDC__\r
348         }\r
349 #endif\r
350 End:\r
351 #ifdef __WATCOMC__\r
352         }\r
353 #endif\r
354         return flag;\r
355 }\r
356 \r
357 \r
358 /*\r
359 ==========================\r
360 =\r
361 = CA_ReadFile\r
362 =\r
363 = Reads a file into an allready allocated buffer\r
364 =\r
365 ==========================\r
366 */\r
367 \r
368 boolean CA_ReadFile(char *filename, memptr *ptr, global_game_variables_t *gvar)\r
369 {\r
370         int handle;\r
371         sdword size;\r
372         //long size;\r
373 \r
374         if((handle = open(filename,O_RDONLY | O_BINARY, S_IREAD)) == -1)\r
375                 return false;\r
376 \r
377         size = filelength(handle);\r
378         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 ////++++ enable!\r
1026 /*void CAL_SetupGrFile (void)\r
1027 {\r
1028         int handle;\r
1029         memptr compseg;\r
1030 \r
1031 #ifdef GRHEADERLINKED\r
1032 \r
1033 #if GRMODE == EGAGR\r
1034         grhuffman = (huffnode *)&EGAdict;\r
1035         grstarts = (long _seg *)FP_SEG(&EGAhead);\r
1036 #endif\r
1037 #if GRMODE == CGAGR\r
1038         grhuffman = (huffnode *)&CGAdict;\r
1039         grstarts = (long _seg *)FP_SEG(&CGAhead);\r
1040 #endif\r
1041 \r
1042         CAL_OptimizeNodes (grhuffman);\r
1043 \r
1044 #else\r
1045 \r
1046 //\r
1047 // load ???dict.ext (huffman dictionary for graphics files)\r
1048 //\r
1049 \r
1050         if ((handle = open(GREXT"DICT."EXT,\r
1051                  O_RDONLY | O_BINARY, S_IREAD)) == -1)\r
1052                 Quit (gvar, "Can't open "GREXT"DICT."EXT"!");\r
1053 \r
1054         read(handle, &grhuffman, sizeof(grhuffman));\r
1055         close(handle);\r
1056         CAL_OptimizeNodes (grhuffman);\r
1057 //\r
1058 // load the data offsets from ???head.ext\r
1059 //\r
1060         MM_GetPtr (MEMPTR grstarts,(NUMCHUNKS+1)*FILEPOSSIZE);\r
1061 \r
1062         if ((handle = open(GREXT"HEAD."EXT,\r
1063                  O_RDONLY | O_BINARY, S_IREAD)) == -1)\r
1064                 Quit (gvar, "Can't open "GREXT"HEAD."EXT"!");\r
1065 \r
1066         CA_FarRead(handle, (memptr)grstarts, (NUMCHUNKS+1)*FILEPOSSIZE);\r
1067 \r
1068         close(handle);\r
1069 \r
1070 \r
1071 #endif\r
1072 \r
1073 //\r
1074 // Open the graphics file, leaving it open until the game is finished\r
1075 //\r
1076         grhandle = open(GREXT"GRAPH."EXT, O_RDONLY | O_BINARY);\r
1077         if (grhandle == -1)\r
1078                 Quit (gvar, "Cannot open "GREXT"GRAPH."EXT"!");\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(MEMPTR pictable,NUMPICS*sizeof(pictabletype));\r
1086         CAL_GetGrChunkLength(STRUCTPIC);                // position file pointer\r
1087         MM_GetPtr(&compseg,chunkcomplen);\r
1088         CA_FarRead (grhandle,compseg,chunkcomplen);\r
1089         CAL_HuffExpand (compseg, (byte far *)pictable,NUMPICS*sizeof(pictabletype),grhuffman);\r
1090         MM_FreePtr(&compseg);\r
1091 #endif\r
1092 \r
1093 #if NUMPICM>0\r
1094         MM_GetPtr(MEMPTR picmtable,NUMPICM*sizeof(pictabletype));\r
1095         CAL_GetGrChunkLength(STRUCTPICM);               // position file pointer\r
1096         MM_GetPtr(&compseg,chunkcomplen);\r
1097         CA_FarRead (grhandle,compseg,chunkcomplen);\r
1098         CAL_HuffExpand (compseg, (byte far *)picmtable,NUMPICS*sizeof(pictabletype),grhuffman);\r
1099         MM_FreePtr(&compseg);\r
1100 #endif\r
1101 \r
1102 #if NUMSPRITES>0\r
1103         MM_GetPtr(MEMPTR spritetable,NUMSPRITES*sizeof(spritetabletype));\r
1104         CAL_GetGrChunkLength(STRUCTSPRITE);     // position file pointer\r
1105         MM_GetPtr(&compseg,chunkcomplen);\r
1106         CA_FarRead (grhandle,compseg,chunkcomplen);\r
1107         CAL_HuffExpand (compseg, (byte far *)spritetable,NUMSPRITES*sizeof(spritetabletype),grhuffman);\r
1108         MM_FreePtr(&compseg);\r
1109 #endif\r
1110 \r
1111 }*/\r
1112 \r
1113 //==========================================================================\r
1114 \r
1115 \r
1116 /*\r
1117 ======================\r
1118 =\r
1119 = CAL_SetupMapFile\r
1120 =\r
1121 ======================\r
1122 */\r
1123 \r
1124 void CAL_SetupMapFile (global_game_variables_t *gvar)\r
1125 {\r
1126 #ifndef MAPHEADERLINKED\r
1127         int handle;\r
1128         long length;\r
1129 #endif\r
1130 \r
1131 //\r
1132 // load maphead.ext (offsets and tileinfo for map file)\r
1133 //\r
1134 #ifndef MAPHEADERLINKED\r
1135         if ((handle = open("maphead.mph",\r
1136                  O_RDONLY | O_BINARY, S_IREAD)) == -1)\r
1137                 Quit (gvar, "Can't open maphead.mph");\r
1138         length = filelength(handle);\r
1139         MM_GetPtr (MEMPTR gvar->ca.tinf,length,gvar);\r
1140         CA_FarRead(handle, gvar->ca.tinf, length,gvar);\r
1141         close(handle);\r
1142 //#else\r
1143 \r
1144         gvar->ca.tinf = (byte _seg *)FP_SEG(&maphead);\r
1145 \r
1146 #endif\r
1147 \r
1148 //\r
1149 // open the data file\r
1150 //\r
1151 //TODO: multiple files\r
1152         if ((gvar->ca.file.maphandle = open("data/test.map",\r
1153                  O_RDONLY | O_BINARY, S_IREAD)) == -1)\r
1154                 Quit (gvar, "Can't open data/test.map!");\r
1155 /*#ifdef MAPHEADERLINKED\r
1156         if ((maphandle = open("GAMEMAPS."EXTENSION,\r
1157                  O_RDONLY | O_BINARY, S_IREAD)) == -1)\r
1158                 Quit ("Can't open GAMEMAPS."EXTENSION"!");\r
1159 #else\r
1160         if ((maphandle = open("MAPTEMP."EXTENSION,\r
1161                  O_RDONLY | O_BINARY, S_IREAD)) == -1)\r
1162                 Quit ("Can't open MAPTEMP."EXTENSION"!");\r
1163 #endif*/\r
1164 }\r
1165 \r
1166 //==========================================================================\r
1167 \r
1168 \r
1169 /*\r
1170 ======================\r
1171 =\r
1172 = CAL_SetupAudioFile\r
1173 =\r
1174 ======================\r
1175 */\r
1176 \r
1177 /*void CAL_SetupAudioFile (void)\r
1178 {\r
1179         int handle;\r
1180         long length;\r
1181 \r
1182 //\r
1183 // load maphead.ext (offsets and tileinfo for map file)\r
1184 //\r
1185 #ifndef AUDIOHEADERLINKED\r
1186         if ((handle = open("AUDIOHED."EXT,\r
1187                  O_RDONLY | O_BINARY, S_IREAD)) == -1)\r
1188                 Quit (gvar, "Can't open AUDIOHED."EXT"!");\r
1189         length = filelength(handle);\r
1190         MM_GetPtr (MEMPTR audiostarts,length);\r
1191         CA_FarRead(handle, (byte far *)audiostarts, length);\r
1192         close(handle);\r
1193 #else\r
1194         audiohuffman = (huffnode *)&audiodict;\r
1195         CAL_OptimizeNodes (audiohuffman);\r
1196         audiostarts = (long _seg *)FP_SEG(&audiohead);\r
1197 #endif\r
1198 \r
1199 //\r
1200 // open the data file\r
1201 //\r
1202 #ifndef AUDIOHEADERLINKED\r
1203         if ((audiohandle = open("AUDIOT."EXT,\r
1204                  O_RDONLY | O_BINARY, S_IREAD)) == -1)\r
1205                 Quit (gvar, "Can't open AUDIOT."EXT"!");\r
1206 #else\r
1207         if ((audiohandle = open("AUDIO."EXT,\r
1208                  O_RDONLY | O_BINARY, S_IREAD)) == -1)\r
1209                 Quit (gvar, "Can't open AUDIO."EXT"!");\r
1210 #endif\r
1211 }*/\r
1212 \r
1213 //==========================================================================\r
1214 \r
1215 \r
1216 /*\r
1217 ======================\r
1218 =\r
1219 = CA_Startup\r
1220 =\r
1221 = Open all files and load in headers\r
1222 =\r
1223 ======================\r
1224 */\r
1225 \r
1226 void CA_Startup(global_game_variables_t *gvar)\r
1227 {\r
1228 #ifdef PROFILE\r
1229 #ifdef __BORLANDC__\r
1230         unlink("profile.16b");\r
1231         gvar->handle.profilehandle = open("profile.16b", O_CREAT | O_WRONLY | O_TEXT);\r
1232 #endif\r
1233 #ifdef __WATCOMC__\r
1234         unlink("profile.16w");\r
1235         gvar->handle.profilehandle = open("profile.16w", O_CREAT | O_WRONLY | O_TEXT);\r
1236 #endif\r
1237 #endif//profile\r
1238 \r
1239 #ifdef __BORLANDC__\r
1240         unlink("meminfo.16b");\r
1241         gvar->handle.showmemhandle = open("meminfo.16b", O_CREAT | O_WRONLY | O_TEXT);\r
1242 #endif\r
1243 #ifdef __WATCOMC__\r
1244         unlink("meminfo.16w");\r
1245         gvar->handle.showmemhandle = open("meminfo.16w", O_CREAT | O_WRONLY | O_TEXT);\r
1246 #endif\r
1247 \r
1248 \r
1249 #ifndef NOMAPS\r
1250         CAL_SetupMapFile (gvar);\r
1251 #endif\r
1252 #ifndef NOGRAPHICS\r
1253         CAL_SetupGrFile (gvar);\r
1254 #endif\r
1255 #ifndef NOAUDIO\r
1256         CAL_SetupMapFile (gvar);\r
1257 #endif\r
1258 \r
1259         gvar->ca.camap.mapon = -1;\r
1260         gvar->ca.ca_levelbit = 1;\r
1261         gvar->ca.ca_levelnum = 0;\r
1262 \r
1263 /*      drawcachebox    = CAL_DialogDraw;\r
1264         updatecachebox  = CAL_DialogUpdate;\r
1265         finishcachebox  = CAL_DialogFinish;*/\r
1266 }\r
1267 \r
1268 //==========================================================================\r
1269 \r
1270 \r
1271 /*\r
1272 ======================\r
1273 =\r
1274 = CA_Shutdown\r
1275 =\r
1276 = Closes all files\r
1277 =\r
1278 ======================\r
1279 */\r
1280 \r
1281 void CA_Shutdown(global_game_variables_t *gvar)\r
1282 {\r
1283 #ifdef PROFILE\r
1284         close(gvar->handle.profilehandle);\r
1285 #endif\r
1286         close(gvar->handle.showmemhandle);\r
1287 \r
1288         close(gvar->ca.file.maphandle);\r
1289         close(gvar->ca.file.grhandle);\r
1290         close(gvar->ca.file.audiohandle);\r
1291 }\r
1292 \r
1293 //===========================================================================\r
1294 \r
1295 /*\r
1296 ======================\r
1297 =\r
1298 = CA_CacheAudioChunk\r
1299 =\r
1300 ======================\r
1301 */\r
1302 /*++++\r
1303 void CA_CacheAudioChunk (int chunk)\r
1304 {\r
1305         long    pos,compressed;\r
1306 #ifdef AUDIOHEADERLINKED\r
1307         long    expanded;\r
1308         memptr  bigbufferseg;\r
1309         byte    far *source;\r
1310 #endif\r
1311 \r
1312         if (audiosegs[chunk])\r
1313         {\r
1314                 MM_SetPurge (MEMPTR audiosegs[chunk],0);\r
1315                 return;                                                 // allready in memory\r
1316         }\r
1317 \r
1318 // MDM begin - (GAMERS EDGE)\r
1319 //\r
1320         if (!FindFile("AUDIO."EXT,NULL,2))\r
1321                 Quit (gvar, "CA_CacheAudioChunk(): Can't find audio files.");\r
1322 //\r
1323 // MDM end\r
1324 \r
1325 //\r
1326 // load the chunk into a buffer, either the miscbuffer if it fits, or allocate\r
1327 // a larger buffer\r
1328 //\r
1329         pos = audiostarts[chunk];\r
1330         compressed = audiostarts[chunk+1]-pos;\r
1331 \r
1332         lseek(audiohandle,pos,SEEK_SET);\r
1333 \r
1334 #ifndef AUDIOHEADERLINKED\r
1335 \r
1336         MM_GetPtr (MEMPTR audiosegs[chunk],compressed);\r
1337         if (mmerror)\r
1338                 return;\r
1339 \r
1340         CA_FarRead(audiohandle,audiosegs[chunk],compressed);\r
1341 \r
1342 #else\r
1343 \r
1344         if (compressed<=BUFFERSIZE)\r
1345         {\r
1346                 CA_FarRead(audiohandle,bufferseg,compressed);\r
1347                 source = bufferseg;\r
1348         }\r
1349         else\r
1350         {\r
1351                 MM_GetPtr(&bigbufferseg,compressed);\r
1352                 if (mmerror)\r
1353                         return;\r
1354                 MM_SetLock (&bigbufferseg,true);\r
1355                 CA_FarRead(audiohandle,bigbufferseg,compressed);\r
1356                 source = bigbufferseg;\r
1357         }\r
1358 \r
1359         expanded = *(long far *)source;\r
1360         source += 4;                    // skip over length\r
1361         MM_GetPtr (MEMPTR audiosegs[chunk],expanded);\r
1362         if (mmerror)\r
1363                 goto done;\r
1364         CAL_HuffExpand (source,audiosegs[chunk],expanded,audiohuffman);\r
1365 \r
1366 done:\r
1367         if (compressed>BUFFERSIZE)\r
1368                 MM_FreePtr(&bigbufferseg);\r
1369 #endif\r
1370 }*/\r
1371 \r
1372 //===========================================================================\r
1373 \r
1374 /*\r
1375 ======================\r
1376 =\r
1377 = CA_LoadAllSounds\r
1378 =\r
1379 = Purges all sounds, then loads all new ones (mode switch)\r
1380 =\r
1381 ======================\r
1382 */\r
1383 /*++++\r
1384 void CA_LoadAllSounds (void)\r
1385 {\r
1386         unsigned        start,i;\r
1387 \r
1388         switch (oldsoundmode)\r
1389         {\r
1390         case sdm_Off:\r
1391                 goto cachein;\r
1392         case sdm_PC:\r
1393                 start = STARTPCSOUNDS;\r
1394                 break;\r
1395         case sdm_AdLib:\r
1396                 start = STARTADLIBSOUNDS;\r
1397                 break;\r
1398         }\r
1399 \r
1400         for (i=0;i<NUMSOUNDS;i++,start++)\r
1401                 if (audiosegs[start])\r
1402                         MM_SetPurge (MEMPTR audiosegs[start],3);                // make purgable\r
1403 \r
1404 cachein:\r
1405 \r
1406         switch (SoundMode)\r
1407         {\r
1408         case sdm_Off:\r
1409                 return;\r
1410         case sdm_PC:\r
1411                 start = STARTPCSOUNDS;\r
1412                 break;\r
1413         case sdm_AdLib:\r
1414                 start = STARTADLIBSOUNDS;\r
1415                 break;\r
1416         }\r
1417 \r
1418         for (i=0;i<NUMSOUNDS;i++,start++)\r
1419                 CA_CacheAudioChunk (start);\r
1420 \r
1421         oldsoundmode = SoundMode;\r
1422 }*/\r
1423 \r
1424 //===========================================================================\r
1425 \r
1426 //++++#if GRMODE == EGAGR\r
1427 \r
1428 /*\r
1429 ======================\r
1430 =\r
1431 = CAL_ShiftSprite\r
1432 =\r
1433 = Make a shifted (one byte wider) copy of a sprite into another area\r
1434 =\r
1435 ======================\r
1436 */\r
1437 /*++++\r
1438 unsigned        static  sheight,swidth;\r
1439 boolean static dothemask;\r
1440 \r
1441 void CAL_ShiftSprite (unsigned segment,unsigned source,unsigned dest,\r
1442         unsigned width, unsigned height, unsigned pixshift, boolean domask)\r
1443 {\r
1444 \r
1445         sheight = height;               // because we are going to reassign bp\r
1446         swidth = width;\r
1447         dothemask = domask;\r
1448 \r
1449 asm     mov     ax,[segment]\r
1450 asm     mov     ds,ax           // source and dest are in same segment, and all local\r
1451 \r
1452 asm     mov     bx,[source]\r
1453 asm     mov     di,[dest]\r
1454 \r
1455 asm     mov     bp,[pixshift]\r
1456 asm     shl     bp,1\r
1457 asm     mov     bp,WORD PTR [shifttabletable+bp]        // bp holds pointer to shift table\r
1458 \r
1459 asm     cmp     [ss:dothemask],0\r
1460 asm     je              skipmask\r
1461 \r
1462 //\r
1463 // table shift the mask\r
1464 //\r
1465 asm     mov     dx,[ss:sheight]\r
1466 \r
1467 domaskrow:\r
1468 \r
1469 asm     mov     BYTE PTR [di],255       // 0xff first byte\r
1470 asm     mov     cx,ss:[swidth]\r
1471 \r
1472 domaskbyte:\r
1473 \r
1474 asm     mov     al,[bx]                         // source\r
1475 asm     not     al\r
1476 asm     inc     bx                                      // next source byte\r
1477 asm     xor     ah,ah\r
1478 asm     shl     ax,1\r
1479 asm     mov     si,ax\r
1480 asm     mov     ax,[bp+si]                      // table shift into two bytes\r
1481 asm     not     ax\r
1482 asm     and     [di],al                         // and with first byte\r
1483 asm     inc     di\r
1484 asm     mov     [di],ah                         // replace next byte\r
1485 \r
1486 asm     loop    domaskbyte\r
1487 \r
1488 asm     inc     di                                      // the last shifted byte has 1s in it\r
1489 asm     dec     dx\r
1490 asm     jnz     domaskrow\r
1491 \r
1492 skipmask:\r
1493 \r
1494 //\r
1495 // table shift the data\r
1496 //\r
1497 asm     mov     dx,ss:[sheight]\r
1498 asm     shl     dx,1\r
1499 asm     shl     dx,1                            // four planes of data\r
1500 \r
1501 dodatarow:\r
1502 \r
1503 asm     mov     BYTE PTR [di],0         // 0 first byte\r
1504 asm     mov     cx,ss:[swidth]\r
1505 \r
1506 dodatabyte:\r
1507 \r
1508 asm     mov     al,[bx]                         // source\r
1509 asm     inc     bx                                      // next source byte\r
1510 asm     xor     ah,ah\r
1511 asm     shl     ax,1\r
1512 asm     mov     si,ax\r
1513 asm     mov     ax,[bp+si]                      // table shift into two bytes\r
1514 asm     or      [di],al                         // or with first byte\r
1515 asm     inc     di\r
1516 asm     mov     [di],ah                         // replace next byte\r
1517 \r
1518 asm     loop    dodatabyte\r
1519 \r
1520 asm     inc     di                                      // the last shifted byte has 0s in it\r
1521 asm     dec     dx\r
1522 asm     jnz     dodatarow\r
1523 \r
1524 //\r
1525 // done\r
1526 //\r
1527 \r
1528 asm     mov     ax,ss                           // restore data segment\r
1529 asm     mov     ds,ax\r
1530 \r
1531 }\r
1532 \r
1533 #endif\r
1534 */\r
1535 //===========================================================================\r
1536 \r
1537 /*\r
1538 ======================\r
1539 =\r
1540 = CAL_CacheSprite\r
1541 =\r
1542 = Generate shifts and set up sprite structure for a given sprite\r
1543 =\r
1544 ======================\r
1545 */\r
1546 /*++++\r
1547 void CAL_CacheSprite (int chunk, byte far *compressed)\r
1548 {\r
1549         int i;\r
1550         unsigned shiftstarts[5];\r
1551         unsigned smallplane,bigplane,expanded;\r
1552         spritetabletype far *spr;\r
1553         spritetype _seg *dest;\r
1554 \r
1555 #if GRMODE == CGAGR\r
1556 //\r
1557 // CGA has no pel panning, so shifts are never needed\r
1558 //\r
1559         spr = &spritetable[chunk-STARTSPRITES];\r
1560         smallplane = spr->width*spr->height;\r
1561         MM_GetPtr (&grsegs[chunk],smallplane*2+MAXSHIFTS*6);\r
1562         if (mmerror)\r
1563                 return;\r
1564         dest = (spritetype _seg *)grsegs[chunk];\r
1565         dest->sourceoffset[0] = MAXSHIFTS*6;    // start data after 3 unsigned tables\r
1566         dest->planesize[0] = smallplane;\r
1567         dest->width[0] = spr->width;\r
1568 \r
1569 //\r
1570 // expand the unshifted shape\r
1571 //\r
1572         CAL_HuffExpand (compressed, &dest->data[0],smallplane*2,grhuffman);\r
1573 \r
1574 #endif\r
1575 \r
1576 \r
1577 #if GRMODE == EGAGR\r
1578 \r
1579 //\r
1580 // calculate sizes\r
1581 //\r
1582         spr = &spritetable[chunk-STARTSPRITES];\r
1583         smallplane = spr->width*spr->height;\r
1584         bigplane = (spr->width+1)*spr->height;\r
1585 \r
1586         shiftstarts[0] = MAXSHIFTS*6;   // start data after 3 unsigned tables\r
1587         shiftstarts[1] = shiftstarts[0] + smallplane*5; // 5 planes in a sprite\r
1588         shiftstarts[2] = shiftstarts[1] + bigplane*5;\r
1589         shiftstarts[3] = shiftstarts[2] + bigplane*5;\r
1590         shiftstarts[4] = shiftstarts[3] + bigplane*5;   // nothing ever put here\r
1591 \r
1592         expanded = shiftstarts[spr->shifts];\r
1593         MM_GetPtr (&grsegs[chunk],expanded);\r
1594         if (mmerror)\r
1595                 return;\r
1596         dest = (spritetype _seg *)grsegs[chunk];\r
1597 \r
1598 //\r
1599 // expand the unshifted shape\r
1600 //\r
1601         CAL_HuffExpand (compressed, &dest->data[0],smallplane*5,grhuffman);\r
1602 \r
1603 //\r
1604 // make the shifts!\r
1605 //\r
1606         switch (spr->shifts)\r
1607         {\r
1608         case    1:\r
1609                 for (i=0;i<4;i++)\r
1610                 {\r
1611                         dest->sourceoffset[i] = shiftstarts[0];\r
1612                         dest->planesize[i] = smallplane;\r
1613                         dest->width[i] = spr->width;\r
1614                 }\r
1615                 break;\r
1616 \r
1617         case    2:\r
1618                 for (i=0;i<2;i++)\r
1619                 {\r
1620                         dest->sourceoffset[i] = shiftstarts[0];\r
1621                         dest->planesize[i] = smallplane;\r
1622                         dest->width[i] = spr->width;\r
1623                 }\r
1624                 for (i=2;i<4;i++)\r
1625                 {\r
1626                         dest->sourceoffset[i] = shiftstarts[1];\r
1627                         dest->planesize[i] = bigplane;\r
1628                         dest->width[i] = spr->width+1;\r
1629                 }\r
1630                 CAL_ShiftSprite ((unsigned)grsegs[chunk],dest->sourceoffset[0],\r
1631                         dest->sourceoffset[2],spr->width,spr->height,4,true);\r
1632                 break;\r
1633 \r
1634         case    4:\r
1635                 dest->sourceoffset[0] = shiftstarts[0];\r
1636                 dest->planesize[0] = smallplane;\r
1637                 dest->width[0] = spr->width;\r
1638 \r
1639                 dest->sourceoffset[1] = shiftstarts[1];\r
1640                 dest->planesize[1] = bigplane;\r
1641                 dest->width[1] = spr->width+1;\r
1642                 CAL_ShiftSprite ((unsigned)grsegs[chunk],dest->sourceoffset[0],\r
1643                         dest->sourceoffset[1],spr->width,spr->height,2,true);\r
1644 \r
1645                 dest->sourceoffset[2] = shiftstarts[2];\r
1646                 dest->planesize[2] = bigplane;\r
1647                 dest->width[2] = spr->width+1;\r
1648                 CAL_ShiftSprite ((unsigned)grsegs[chunk],dest->sourceoffset[0],\r
1649                         dest->sourceoffset[2],spr->width,spr->height,4,true);\r
1650 \r
1651                 dest->sourceoffset[3] = shiftstarts[3];\r
1652                 dest->planesize[3] = bigplane;\r
1653                 dest->width[3] = spr->width+1;\r
1654                 CAL_ShiftSprite ((unsigned)grsegs[chunk],dest->sourceoffset[0],\r
1655                         dest->sourceoffset[3],spr->width,spr->height,6,true);\r
1656 \r
1657                 break;\r
1658 \r
1659         default:\r
1660                 Quit (gvar, "CAL_CacheSprite: Bad shifts number!");\r
1661         }\r
1662 \r
1663 #endif\r
1664 }*/\r
1665 \r
1666 //===========================================================================\r
1667 \r
1668 \r
1669 /*\r
1670 ======================\r
1671 =\r
1672 = CAL_ExpandGrChunk\r
1673 =\r
1674 = Does whatever is needed with a pointer to a compressed chunk\r
1675 =\r
1676 ======================\r
1677 */\r
1678 /*++++\r
1679 void CAL_ExpandGrChunk (int chunk, byte far *source)\r
1680 {\r
1681         long    expanded;\r
1682 \r
1683 \r
1684         if (chunk >= STARTTILE8 && chunk < STARTEXTERNS)\r
1685         {\r
1686         //\r
1687         // expanded sizes of tile8/16/32 are implicit\r
1688         //\r
1689 \r
1690 #if GRMODE == EGAGR\r
1691 #define BLOCK           32\r
1692 #define MASKBLOCK       40\r
1693 #endif\r
1694 \r
1695 #if GRMODE == CGAGR\r
1696 #define BLOCK           16\r
1697 #define MASKBLOCK       32\r
1698 #endif\r
1699 \r
1700                 if (chunk<STARTTILE8M)                  // tile 8s are all in one chunk!\r
1701                         expanded = BLOCK*NUMTILE8;\r
1702                 else if (chunk<STARTTILE16)\r
1703                         expanded = MASKBLOCK*NUMTILE8M;\r
1704                 else if (chunk<STARTTILE16M)    // all other tiles are one/chunk\r
1705                         expanded = BLOCK*4;\r
1706                 else if (chunk<STARTTILE32)\r
1707                         expanded = MASKBLOCK*4;\r
1708                 else if (chunk<STARTTILE32M)\r
1709                         expanded = BLOCK*16;\r
1710                 else\r
1711                         expanded = MASKBLOCK*16;\r
1712         }\r
1713         else\r
1714         {\r
1715         //\r
1716         // everything else has an explicit size longword\r
1717         //\r
1718                 expanded = *(long far *)source;\r
1719                 source += 4;                    // skip over length\r
1720         }\r
1721 \r
1722 //\r
1723 // allocate final space, decompress it, and free bigbuffer\r
1724 // Sprites need to have shifts made and various other junk\r
1725 //\r
1726         if (chunk>=STARTSPRITES && chunk< STARTTILE8)\r
1727                 CAL_CacheSprite(chunk,source);\r
1728         else\r
1729         {\r
1730                 MM_GetPtr (&grsegs[chunk],expanded);\r
1731                 if (mmerror)\r
1732                         return;\r
1733                 CAL_HuffExpand (source,grsegs[chunk],expanded,grhuffman);\r
1734         }\r
1735 }\r
1736 */\r
1737 \r
1738 /*\r
1739 ======================\r
1740 =\r
1741 = CAL_ReadGrChunk\r
1742 =\r
1743 = Gets a chunk off disk, optimizing reads to general buffer\r
1744 =\r
1745 ======================\r
1746 */\r
1747 /*++++\r
1748 void CAL_ReadGrChunk (int chunk)\r
1749 {\r
1750         long    pos,compressed;\r
1751         memptr  bigbufferseg;\r
1752         byte    far *source;\r
1753         int             next;\r
1754 \r
1755 //\r
1756 // load the chunk into a buffer, either the miscbuffer if it fits, or allocate\r
1757 // a larger buffer\r
1758 //\r
1759         pos = GRFILEPOS(chunk);\r
1760         if (pos<0)                                                      // $FFFFFFFF start is a sparse tile\r
1761           return;\r
1762 \r
1763         next = chunk +1;\r
1764         while (GRFILEPOS(next) == -1)           // skip past any sparse tiles\r
1765                 next++;\r
1766 \r
1767         compressed = GRFILEPOS(next)-pos;\r
1768 \r
1769         lseek(grhandle,pos,SEEK_SET);\r
1770 \r
1771         if (compressed<=BUFFERSIZE)\r
1772         {\r
1773                 CA_FarRead(grhandle,bufferseg,compressed);\r
1774                 source = bufferseg;\r
1775         }\r
1776         else\r
1777         {\r
1778                 MM_GetPtr(&bigbufferseg,compressed);\r
1779                 if (mmerror)\r
1780                         return;\r
1781                 MM_SetLock (&bigbufferseg,true);\r
1782                 CA_FarRead(grhandle,bigbufferseg,compressed);\r
1783                 source = bigbufferseg;\r
1784         }\r
1785 \r
1786         CAL_ExpandGrChunk (chunk,source);\r
1787 \r
1788         if (compressed>BUFFERSIZE)\r
1789                 MM_FreePtr(&bigbufferseg);\r
1790 }\r
1791 */\r
1792 /*\r
1793 ======================\r
1794 =\r
1795 = CA_CacheGrChunk\r
1796 =\r
1797 = Makes sure a given chunk is in memory, loadiing it if needed\r
1798 =\r
1799 ======================\r
1800 */\r
1801 /*++++\r
1802 void CA_CacheGrChunk (int chunk)\r
1803 {\r
1804         long    pos,compressed;\r
1805         memptr  bigbufferseg;\r
1806         byte    far *source;\r
1807         int             next;\r
1808 \r
1809         gvar->ca.grneeded[chunk] |= ca_levelbit;                // make sure it doesn't get removed\r
1810         if (grsegs[chunk])\r
1811         {\r
1812                 MM_SetPurge (&grsegs[chunk],0);\r
1813                 return;                                                 // allready in memory\r
1814         }\r
1815 \r
1816 // MDM begin - (GAMERS EDGE)\r
1817 //\r
1818         if (!FindFile("EGAGRAPH."EXT,NULL,2))\r
1819                 Quit (gvar, "CA_CacheGrChunk(): Can't find graphics files.");\r
1820 //\r
1821 // MDM end\r
1822 \r
1823 //\r
1824 // load the chunk into a buffer, either the miscbuffer if it fits, or allocate\r
1825 // a larger buffer\r
1826 //\r
1827         pos = GRFILEPOS(chunk);\r
1828         if (pos<0)                                                      // $FFFFFFFF start is a sparse tile\r
1829           return;\r
1830 \r
1831         next = chunk +1;\r
1832         while (GRFILEPOS(next) == -1)           // skip past any sparse tiles\r
1833                 next++;\r
1834 \r
1835         compressed = GRFILEPOS(next)-pos;\r
1836 \r
1837         lseek(grhandle,pos,SEEK_SET);\r
1838 \r
1839         if (compressed<=BUFFERSIZE)\r
1840         {\r
1841                 CA_FarRead(grhandle,bufferseg,compressed);\r
1842                 source = bufferseg;\r
1843         }\r
1844         else\r
1845         {\r
1846                 MM_GetPtr(&bigbufferseg,compressed);\r
1847                 MM_SetLock (&bigbufferseg,true);\r
1848                 CA_FarRead(grhandle,bigbufferseg,compressed);\r
1849                 source = bigbufferseg;\r
1850         }\r
1851 \r
1852         CAL_ExpandGrChunk (chunk,source);\r
1853 \r
1854         if (compressed>BUFFERSIZE)\r
1855                 MM_FreePtr(&bigbufferseg);\r
1856 }\r
1857 */\r
1858 \r
1859 \r
1860 //==========================================================================\r
1861 \r
1862 /*\r
1863 ======================\r
1864 =\r
1865 = CA_CacheMap\r
1866 =\r
1867 ======================\r
1868 */\r
1869 /*++++ segments!\r
1870 void CA_CacheMap (global_game_variables_t *gvar)\r
1871 {\r
1872         long    pos,compressed;\r
1873         int             plane;\r
1874         memptr  *dest,bigbufferseg;\r
1875         unsigned        size;\r
1876         unsigned        far     *source;\r
1877 #ifdef MAPHEADERLINKED\r
1878         memptr  buffer2seg;\r
1879         long    expanded;\r
1880 #endif\r
1881 \r
1882 \r
1883 //\r
1884 // free up memory from last map\r
1885 //\r
1886         if (gvar->ca.camap.mapon>-1 && gvar->ca.camap.mapheaderseg[gvar->ca.camap.mapon])\r
1887                 MM_SetPurge (((memptr)gvar->ca.camap.mapheaderseg[(gvar->ca.camap.mapon)]), 3, gvar);\r
1888         for (plane=0;plane<MAPPLANES;plane++)\r
1889                 if (gvar->ca.camap.mapsegs[plane])\r
1890                         MM_FreePtr ((memptr)gvar->ca.camap.mapsegs[plane], gvar);\r
1891 \r
1892         gvar->ca.camap.mapon = gvar->ca.camap.mapnum;\r
1893 \r
1894 \r
1895 //\r
1896 // load map header\r
1897 // The header will be cached if it is still around\r
1898 //\r
1899 //      if (!gvar->ca.camap.mapheaderseg[gvar->ca.camap.mapnum])\r
1900 //      {\r
1901 //              //pos = ((mapfiletype   _seg *)tinf)->headeroffsets[mapnum];\r
1902 //              //pos = ((_seg *)gvar->ca.camap.tinf)->headeroffsets[gvar->ca.camap.mapnum];\r
1903 //              pos = ((memptr)gvar->ca.camap.tinf)->headeroffsets[gvar->ca.camap.mapnum];\r
1904 //              if (pos<0)                                              // $FFFFFFFF start is a sparse map\r
1905 //                printf("CA_CacheMap: Tried to load a non existent map!");\r
1906 \r
1907 //              MM_GetPtr(MEMPTR gvar->ca.camapheaderseg[mapnum],sizeof(maptype));\r
1908 //              lseek(maphandle,pos,SEEK_SET);\r
1909 //              CA_FarRead (maphandle,(memptr)mapheaderseg[mapnum],sizeof(maptype));\r
1910 //      }\r
1911 //      else\r
1912 //              MM_SetPurge (MEMPTR mapheaderseg[mapnum], 0, &(gvar->mm));\r
1913 \r
1914 //\r
1915 // load the planes in\r
1916 // If a plane's pointer still exists it will be overwritten (levels are\r
1917 // allways reloaded, never cached)\r
1918 //\r
1919 \r
1920         size = mapheaderseg[mapnum]->width * mapheaderseg[mapnum]->height * 2;\r
1921 \r
1922         for (plane = 0; plane<MAPPLANES; plane++)\r
1923         {\r
1924                 //pos = mapheaderseg[mapnum]->planestart[plane];\r
1925                 //compressed = mapheaderseg[mapnum]->planelength[plane];\r
1926 \r
1927                 if (!compressed)\r
1928                         continue;               // the plane is not used in this game\r
1929 \r
1930                 dest = MEMPTR mapsegs[plane];\r
1931                 MM_GetPtr(dest,size);\r
1932 \r
1933                 lseek(maphandle,pos,SEEK_SET);\r
1934                 if (compressed<=BUFFERSIZE)\r
1935                         source = bufferseg;\r
1936                 else\r
1937                 {\r
1938                         MM_GetPtr(&bigbufferseg,compressed);\r
1939                         MM_SetLock (&bigbufferseg,true);\r
1940                         source = bigbufferseg;\r
1941                 }\r
1942 \r
1943                 CA_FarRead(maphandle,(byte far *)source,compressed);\r
1944 #ifdef MAPHEADERLINKED\r
1945                 //\r
1946                 // unhuffman, then unRLEW\r
1947                 // The huffman'd chunk has a two byte expanded length first\r
1948                 // The resulting RLEW chunk also does, even though it's not really\r
1949                 // needed\r
1950                 //\r
1951                 expanded = *source;\r
1952                 source++;\r
1953                 MM_GetPtr (&buffer2seg,expanded);\r
1954                 CAL_CarmackExpand (source, (unsigned far *)buffer2seg,expanded);\r
1955                 CA_RLEWexpand (((unsigned far *)buffer2seg)+1,*dest,size,\r
1956                 ((mapfiletype _seg *)tinf)->RLEWtag);\r
1957                 MM_FreePtr (&buffer2seg);\r
1958 \r
1959 #else\r
1960                 //\r
1961                 // unRLEW, skipping expanded length\r
1962                 //\r
1963                 CA_RLEWexpand (source+1, *dest,size,\r
1964                 ((mapfiletype _seg *)tinf)->RLEWtag);\r
1965 #endif\r
1966 \r
1967                 if (compressed>BUFFERSIZE)\r
1968                         MM_FreePtr(&bigbufferseg);\r
1969         }\r
1970 }//*/\r
1971 \r
1972 //===========================================================================\r
1973 \r
1974 /*\r
1975 ======================\r
1976 =\r
1977 = CA_UpLevel\r
1978 =\r
1979 = Goes up a bit level in the needed lists and clears it out.\r
1980 = Everything is made purgable\r
1981 =\r
1982 ======================\r
1983 */\r
1984 \r
1985 void CA_UpLevel (global_game_variables_t *gvar)\r
1986 {\r
1987         if (gvar->ca.ca_levelnum==7)\r
1988                 printf("CA_UpLevel: Up past level 7!");\r
1989 \r
1990         gvar->ca.ca_levelbit<<=1;\r
1991         gvar->ca.ca_levelnum++;\r
1992 }\r
1993 \r
1994 //===========================================================================\r
1995 \r
1996 /*\r
1997 ======================\r
1998 =\r
1999 = CA_DownLevel\r
2000 =\r
2001 = Goes down a bit level in the needed lists and recaches\r
2002 = everything from the lower level\r
2003 =\r
2004 ======================\r
2005 */\r
2006 \r
2007 void CA_DownLevel (global_game_variables_t *gvar)\r
2008 {\r
2009         if (!gvar->ca.ca_levelnum)\r
2010                 printf("CA_DownLevel: Down past level 0!");\r
2011         gvar->ca.ca_levelbit>>=1;\r
2012         gvar->ca.ca_levelnum--;\r
2013         ////++++++++++++++++++++++++++++++++++++++++++CA_CacheMarks(NULL);\r
2014 }\r
2015 \r
2016 //===========================================================================\r
2017 \r
2018 /*\r
2019 ======================\r
2020 =\r
2021 = CA_ClearMarks\r
2022 =\r
2023 = Clears out all the marks at the current level\r
2024 =\r
2025 ======================\r
2026 */\r
2027 \r
2028 void CA_ClearMarks (global_game_variables_t *gvar)\r
2029 {\r
2030         int i;\r
2031 \r
2032         for (i=0;i<NUMCHUNKS;i++)\r
2033                 gvar->ca.grneeded[i]&=~gvar->ca.ca_levelbit;\r
2034 }\r
2035 \r
2036 //===========================================================================\r
2037 \r
2038 /*\r
2039 ======================\r
2040 =\r
2041 = CA_ClearAllMarks\r
2042 =\r
2043 = Clears out all the marks on all the levels\r
2044 =\r
2045 ======================\r
2046 */\r
2047 \r
2048 void CA_ClearAllMarks (global_game_variables_t *gvar)\r
2049 {\r
2050         _fmemset (gvar->ca.grneeded,0,sizeof(gvar->ca.grneeded));\r
2051         gvar->ca.ca_levelbit = 1;\r
2052         gvar->ca.ca_levelnum = 0;\r
2053 }\r
2054 \r
2055 //===========================================================================\r
2056 \r
2057 /*\r
2058 ======================\r
2059 =\r
2060 = CA_FreeGraphics\r
2061 =\r
2062 ======================\r
2063 */\r
2064 \r
2065 void CA_SetGrPurge (global_game_variables_t *gvar)\r
2066 {\r
2067         int i;\r
2068 \r
2069 //\r
2070 // free graphics\r
2071 //\r
2072         CA_ClearMarks (gvar);\r
2073 \r
2074         for (i=0;i<NUMCHUNKS;i++)\r
2075                 if (gvar->ca.grsegs[i])\r
2076                         MM_SetPurge (gvar->ca.grsegs[i],3, gvar);\r
2077 }\r
2078 \r
2079 \r
2080 /*\r
2081 ======================\r
2082 =\r
2083 = CA_SetAllPurge\r
2084 =\r
2085 = Make everything possible purgable\r
2086 =\r
2087 ======================\r
2088 */\r
2089 \r
2090 void CA_SetAllPurge (global_game_variables_t *gvar)\r
2091 {\r
2092         int i;\r
2093 \r
2094         CA_ClearMarks (gvar);\r
2095 \r
2096 //\r
2097 // free cursor sprite and background save\r
2098 //\r
2099         //____VW_FreeCursor ();\r
2100 \r
2101 //\r
2102 // free map headers and map planes\r
2103 //\r
2104 //      for (i=0;i<NUMMAPS;i++)\r
2105 //              if (gvar->ca.camap.mapheaderseg[i])\r
2106 //                      MM_SetPurge (gvar->ca.camap.mapheaderseg[i],3, gvar);\r
2107 \r
2108         for (i=0;i<3;i++)\r
2109                 if (gvar->ca.mapsegs[i])\r
2110                         MM_FreePtr ((memptr *)&gvar->ca.mapsegs[i], gvar);\r
2111 \r
2112 //\r
2113 // free sounds\r
2114 //\r
2115         for (i=0;i<NUMSNDCHUNKS;i++)\r
2116                 if (gvar->ca.audiosegs[i])\r
2117                         MM_SetPurge ((memptr *)&gvar->ca.audiosegs[i],3, gvar);\r
2118 \r
2119 //\r
2120 // free graphics\r
2121 //\r
2122         CA_SetGrPurge (gvar);\r
2123 }\r
2124 \r
2125 \r
2126 //===========================================================================\r
2127 \r
2128 \r
2129 /*\r
2130 ======================\r
2131 =\r
2132 = CAL_DialogDraw\r
2133 =\r
2134 ======================\r
2135 */\r
2136 /*\r
2137 #define NUMBARS (17l*8)\r
2138 #define BARSTEP 8\r
2139 \r
2140 unsigned        thx,thy,lastx;\r
2141 long            barx,barstep;\r
2142 \r
2143 void    CAL_DialogDraw (char *title,unsigned numcache)\r
2144 {\r
2145         unsigned        homex,homey,x;\r
2146 \r
2147         barstep = (NUMBARS<<16)/numcache;\r
2148 \r
2149 //\r
2150 // draw dialog window (masked tiles 12 - 20 are window borders)\r
2151 //\r
2152         US_CenterWindow (20,8);\r
2153         homex = PrintX;\r
2154         homey = PrintY;\r
2155 \r
2156         US_CPrint ("Loading");\r
2157         fontcolor = F_SECONDCOLOR;\r
2158         US_CPrint (title);\r
2159         fontcolor = F_BLACK;\r
2160 \r
2161 //\r
2162 // draw thermometer bar\r
2163 //\r
2164         thx = homex + 8;\r
2165         thy = homey + 32;\r
2166         VWB_DrawTile8(thx,thy,0);               // CAT3D numbers\r
2167         VWB_DrawTile8(thx,thy+8,3);\r
2168         VWB_DrawTile8(thx,thy+16,6);\r
2169         VWB_DrawTile8(thx+17*8,thy,2);\r
2170         VWB_DrawTile8(thx+17*8,thy+8,5);\r
2171         VWB_DrawTile8(thx+17*8,thy+16,8);\r
2172         for (x=thx+8;x<thx+17*8;x+=8)\r
2173         {\r
2174                 VWB_DrawTile8(x,thy,1);\r
2175                 VWB_DrawTile8(x,thy+8,4);\r
2176                 VWB_DrawTile8(x,thy+16,7);\r
2177         }\r
2178 \r
2179         thx += 4;               // first line location\r
2180         thy += 5;\r
2181         barx = (long)thx<<16;\r
2182         lastx = thx;\r
2183 \r
2184         VW_UpdateScreen();\r
2185 }\r
2186 */\r
2187 \r
2188 /*\r
2189 ======================\r
2190 =\r
2191 = CAL_DialogUpdate\r
2192 =\r
2193 ======================\r
2194 */\r
2195 /*\r
2196 void    CAL_DialogUpdate (void)\r
2197 {\r
2198         unsigned        x,xh;\r
2199 \r
2200         barx+=barstep;\r
2201         xh = barx>>16;\r
2202         if (xh - lastx > BARSTEP)\r
2203         {\r
2204                 for (x=lastx;x<=xh;x++)\r
2205 #if GRMODE == EGAGR\r
2206                         VWB_Vlin (thy,thy+13,x,14);\r
2207 #endif\r
2208 #if GRMODE == CGAGR\r
2209                         VWB_Vlin (thy,thy+13,x,SECONDCOLOR);\r
2210 #endif\r
2211                 lastx = xh;\r
2212                 VW_UpdateScreen();\r
2213         }\r
2214 }*/\r
2215 \r
2216 /*\r
2217 ======================\r
2218 =\r
2219 = CAL_DialogFinish\r
2220 =\r
2221 ======================\r
2222 */\r
2223 /*\r
2224 void    CAL_DialogFinish (void)\r
2225 {\r
2226         unsigned        x,xh;\r
2227 \r
2228         xh = thx + NUMBARS;\r
2229         for (x=lastx;x<=xh;x++)\r
2230 #if GRMODE == EGAGR\r
2231                 VWB_Vlin (thy,thy+13,x,14);\r
2232 #endif\r
2233 #if GRMODE == CGAGR\r
2234                 VWB_Vlin (thy,thy+13,x,SECONDCOLOR);\r
2235 #endif\r
2236         VW_UpdateScreen();\r
2237 \r
2238 }*/\r
2239 \r
2240 //===========================================================================\r
2241 \r
2242 /*\r
2243 ======================\r
2244 =\r
2245 = CA_CacheMarks\r
2246 =\r
2247 ======================\r
2248 *//*++++\r
2249 #define MAXEMPTYREAD    1024\r
2250 \r
2251 void CAL_CacheMarks (char *title, global_game_variables_t *gvar)\r
2252 {\r
2253         boolean dialog;\r
2254         int     i,next,numcache;\r
2255         long    pos,endpos,nextpos,nextendpos,compressed;\r
2256         long    bufferstart,bufferend;  // file position of general buffer\r
2257         byte    far *source;\r
2258         memptr  bigbufferseg;\r
2259 \r
2260         dialog = (title!=NULL);\r
2261 \r
2262         numcache = 0;\r
2263 //\r
2264 // go through and make everything not needed purgable\r
2265 //\r
2266         for (i=0;i<NUMCHUNKS;i++)\r
2267                 if (gvar->ca.grneeded[i]&(gvar->ca.ca_levelbit))//if (grneeded[i]&ca_levelbit)\r
2268                 {\r
2269                         if (gvar->ca.grsegs[i])                                 // its allready in memory, make\r
2270                                 MM_SetPurge(gvar->ca.grsegs[i],0,gvar); // sure it stays there!\r
2271                         else\r
2272                                 numcache++;\r
2273                 }\r
2274                 else\r
2275                 {\r
2276                         if (gvar->ca.grsegs[i])                                 // not needed, so make it purgeable\r
2277                                 MM_SetPurge(gvar->ca.grsegs[i],3,gvar);\r
2278                 }\r
2279 \r
2280         if (!numcache)                  // nothing to cache!\r
2281                 return;\r
2282 \r
2283 // MDM begin - (GAMERS EDGE)\r
2284 //\r
2285 //      if (!FindFile("EGAGRAPH."EXT,NULL,2))\r
2286 //              Quit (gvar, "CA_CacheMarks(): Can't find graphics files.");\r
2287 //\r
2288 // MDM end\r
2289 \r
2290         if (dialog)\r
2291         {\r
2292 #ifdef PROFILE\r
2293                 write(profilehandle,title,strlen(title));\r
2294                 write(profilehandle,"\n",1);\r
2295 #endif\r
2296                 if (drawcachebox)\r
2297                         drawcachebox(title,numcache);\r
2298         }\r
2299 \r
2300 //\r
2301 // go through and load in anything still needed\r
2302 //\r
2303         bufferstart = bufferend = 0;            // nothing good in buffer now\r
2304 \r
2305         for (i=0;i<NUMCHUNKS;i++)\r
2306                 if ( (gvar->ca.grneeded[i]&(gvar->ca.ca_levelbit)) && !gvar->ca.grsegs[i])\r
2307                 {\r
2308 //\r
2309 // update thermometer\r
2310 //\r
2311                         if (dialog && updatecachebox)\r
2312                                 updatecachebox ();\r
2313 \r
2314                         pos = GRFILEPOS(i);\r
2315                         if (pos<0)\r
2316                                 continue;\r
2317 \r
2318                         next = i +1;\r
2319                         while (GRFILEPOS(next) == -1)           // skip past any sparse tiles\r
2320                                 next++;\r
2321 \r
2322                         compressed = GRFILEPOS(next)-pos;\r
2323                         endpos = pos+compressed;\r
2324 \r
2325                         if (compressed<=BUFFERSIZE)\r
2326                         {\r
2327                                 if (bufferstart<=pos\r
2328                                 && bufferend>= endpos)\r
2329                                 {\r
2330                                 // data is allready in buffer\r
2331                                         source = (byte _seg *)bufferseg+(pos-bufferstart);\r
2332                                 }\r
2333                                 else\r
2334                                 {\r
2335                                 // load buffer with a new block from disk\r
2336                                 // try to get as many of the needed blocks in as possible\r
2337                                         while ( next < NUMCHUNKS )\r
2338                                         {\r
2339                                                 while (next < NUMCHUNKS &&\r
2340                                                 !(gvar->video.grneeded[next]&ca_levelbit && !grsegs[next]))\r
2341                                                         next++;\r
2342                                                 if (next == NUMCHUNKS)\r
2343                                                         continue;\r
2344 \r
2345                                                 nextpos = GRFILEPOS(next);\r
2346                                                 while (GRFILEPOS(++next) == -1) // skip past any sparse tiles\r
2347                                                         ;\r
2348                                                 nextendpos = GRFILEPOS(next);\r
2349                                                 if (nextpos - endpos <= MAXEMPTYREAD\r
2350                                                 && nextendpos-pos <= BUFFERSIZE)\r
2351                                                         endpos = nextendpos;\r
2352                                                 else\r
2353                                                         next = NUMCHUNKS;                       // read pos to posend\r
2354                                         }\r
2355 \r
2356                                         lseek(grhandle,pos,SEEK_SET);\r
2357                                         CA_FarRead(grhandle,(gvar->mm.bufferseg),endpos-pos,gvar);\r
2358                                         bufferstart = pos;\r
2359                                         bufferend = endpos;\r
2360                                         source = bufferseg;\r
2361                                 }\r
2362                         }\r
2363                         else\r
2364                         {\r
2365                         // big chunk, allocate temporary buffer\r
2366                                 MM_GetPtr(&bigbufferseg,compressed,gvar);\r
2367                                 if (mmerror)\r
2368                                         return;\r
2369                                 MM_SetLock (&bigbufferseg,true);\r
2370                                 lseek(grhandle,pos,SEEK_SET);\r
2371                                 CA_FarRead(grhandle,bigbufferseg,compressed,gvar);\r
2372                                 source = bigbufferseg;\r
2373                         }\r
2374 \r
2375                         CAL_ExpandGrChunk (i,source);\r
2376                         if (mmerror)\r
2377                                 return;\r
2378 \r
2379                         if (compressed>BUFFERSIZE)\r
2380                                 MM_FreePtr(&bigbufferseg);\r
2381 \r
2382                 }\r
2383 \r
2384 //\r
2385 // finish up any thermometer remnants\r
2386 //\r
2387                 if (dialog && finishcachebox)\r
2388                         finishcachebox();\r
2389 }*/\r