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