OSDN Git Service

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