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