+++ /dev/null
-/* Reconstructed Commander Keen 4-6 Source Code\r
- * Copyright (C) 2021 K1n9_Duk3\r
- *\r
- * This file is primarily based on:\r
- * Catacomb 3-D Source Code\r
- * Copyright (C) 1993-2014 Flat Rock Software\r
- *\r
- * This program is free software; you can redistribute it and/or modify\r
- * it under the terms of the GNU General Public License as published by\r
- * the Free Software Foundation; either version 2 of the License, or\r
- * (at your option) any later version.\r
- *\r
- * This program is distributed in the hope that it will be useful,\r
- * but WITHOUT ANY WARRANTY; without even the implied warranty of\r
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\r
- * GNU General Public License for more details.\r
- *\r
- * You should have received a copy of the GNU General Public License along\r
- * with this program; if not, write to the Free Software Foundation, Inc.,\r
- * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.\r
- */\r
-\r
-// ID_CA.C\r
-\r
-/*\r
-=============================================================================\r
-\r
-Id Software Caching Manager\r
----------------------------\r
-\r
-Must be started BEFORE the memory manager, because it needs to get the headers\r
-loaded into the data segment\r
-\r
-=============================================================================\r
-*/\r
-\r
-#include "ID_HEADS.H"\r
-#pragma hdrstop\r
-\r
-#pragma warn -pro\r
-#pragma warn -use\r
-\r
-#define THREEBYTEGRSTARTS\r
-\r
-/*\r
-=============================================================================\r
-\r
- LOCAL CONSTANTS\r
-\r
-=============================================================================\r
-*/\r
-\r
-typedef struct\r
-{\r
- unsigned bit0,bit1; // 0-255 is a character, > is a pointer to a node\r
-} huffnode;\r
-\r
-\r
-typedef struct\r
-{\r
- unsigned RLEWtag;\r
- long headeroffsets[100];\r
- byte tileinfo[];\r
-} mapfiletype;\r
-\r
-\r
-/*\r
-=============================================================================\r
-\r
- GLOBAL VARIABLES\r
-\r
-=============================================================================\r
-*/\r
-\r
-byte _seg *tinf;\r
-int mapon;\r
-\r
-unsigned _seg *mapsegs[3];\r
-maptype _seg *mapheaderseg[NUMMAPS];\r
-byte _seg *audiosegs[NUMSNDCHUNKS];\r
-void _seg *grsegs[NUMCHUNKS];\r
-\r
-byte far grneeded[NUMCHUNKS];\r
-byte ca_levelbit,ca_levelnum;\r
-\r
-int profilehandle,debughandle;\r
-\r
-void (*drawcachebox) (char *title, unsigned numcache);\r
-void (*updatecachebox) (void);\r
-void (*finishcachebox) (void);\r
-\r
-/*\r
-=============================================================================\r
-\r
- LOCAL VARIABLES\r
-\r
-=============================================================================\r
-*/\r
-\r
-extern long far CGAhead;\r
-extern long far EGAhead;\r
-extern byte CGAdict;\r
-extern byte EGAdict;\r
-extern byte far maphead;\r
-extern byte mapdict;\r
-extern byte far audiohead;\r
-extern byte audiodict;\r
-\r
-\r
-long _seg *grstarts; // array of offsets in egagraph, -1 for sparse\r
-long _seg *audiostarts; // array of offsets in audio / audiot\r
-\r
-#ifdef GRHEADERLINKED\r
-huffnode *grhuffman;\r
-#else\r
-huffnode grhuffman[255];\r
-#endif\r
-\r
-#ifdef AUDIOHEADERLINKED\r
-huffnode *audiohuffman;\r
-#else\r
-huffnode audiohuffman[255];\r
-#endif\r
-\r
-\r
-int grhandle; // handle to EGAGRAPH\r
-int maphandle; // handle to MAPTEMP / GAMEMAPS\r
-int audiohandle; // handle to AUDIOT / AUDIO\r
-\r
-long chunkcomplen,chunkexplen;\r
-\r
-SDMode oldsoundmode;\r
-\r
-\r
-\r
-void CAL_DialogDraw (char *title,unsigned numcache);\r
-void CAL_DialogUpdate (void);\r
-void CAL_DialogFinish (void);\r
-void CAL_CarmackExpand (unsigned far *source, unsigned far *dest,\r
- unsigned length);\r
-\r
-\r
-#ifdef THREEBYTEGRSTARTS\r
-#define FILEPOSSIZE 3\r
-//#define GRFILEPOS(c) (*(long far *)(((byte far *)grstarts)+(c)*3)&0xffffff)\r
-long GRFILEPOS(int c)\r
-{\r
- long value;\r
- int offset;\r
-\r
- offset = c*3;\r
-\r
- value = *(long far *)(((byte far *)grstarts)+offset);\r
-\r
- value &= 0x00ffffffl;\r
-\r
- if (value == 0xffffffl)\r
- value = -1;\r
-\r
- return value;\r
-};\r
-#else\r
-#define FILEPOSSIZE 4\r
-#define GRFILEPOS(c) (grstarts[c])\r
-#endif\r
-\r
-/*\r
-=============================================================================\r
-\r
- LOW LEVEL ROUTINES\r
-\r
-=============================================================================\r
-*/\r
-\r
-/*\r
-============================\r
-=\r
-= CA_OpenDebug / CA_CloseDebug\r
-=\r
-= Opens a binary file with the handle "debughandle"\r
-=\r
-============================\r
-*/\r
-\r
-void CA_OpenDebug (void)\r
-{\r
- unlink ("DEBUG.TXT");\r
- debughandle = open("DEBUG.TXT", O_CREAT | O_WRONLY | O_TEXT);\r
-}\r
-\r
-void CA_CloseDebug (void)\r
-{\r
- close (debughandle);\r
-}\r
-\r
-\r
-\r
-/*\r
-============================\r
-=\r
-= CAL_GetGrChunkLength\r
-=\r
-= Gets the length of an explicit length chunk (not tiles)\r
-= The file pointer is positioned so the compressed data can be read in next.\r
-=\r
-============================\r
-*/\r
-\r
-void CAL_GetGrChunkLength (int chunk)\r
-{\r
- lseek(grhandle,GRFILEPOS(chunk),SEEK_SET);\r
- read(grhandle,&chunkexplen,sizeof(chunkexplen));\r
- chunkcomplen = GRFILEPOS(chunk+1)-GRFILEPOS(chunk)-4;\r
-}\r
-\r
-\r
-/*\r
-==========================\r
-=\r
-= CA_FarRead\r
-=\r
-= Read from a file to a far pointer\r
-=\r
-==========================\r
-*/\r
-\r
-boolean CA_FarRead (int handle, byte far *dest, long length)\r
-{\r
- if (length>0xffffl)\r
- Quit ("CA_FarRead doesn't support 64K reads yet!");\r
-\r
-asm push ds\r
-asm mov bx,[handle]\r
-asm mov cx,[WORD PTR length]\r
-asm mov dx,[WORD PTR dest]\r
-asm mov ds,[WORD PTR dest+2]\r
-asm mov ah,0x3f // READ w/handle\r
-asm int 21h\r
-asm pop ds\r
-asm jnc good\r
- errno = _AX;\r
- return false;\r
-good:\r
-asm cmp ax,[WORD PTR length]\r
-asm je done\r
- errno = EINVFMT; // user manager knows this is bad read\r
- return false;\r
-done:\r
- return true;\r
-}\r
-\r
-\r
-/*\r
-==========================\r
-=\r
-= CA_SegWrite\r
-=\r
-= Write from a file to a far pointer\r
-=\r
-==========================\r
-*/\r
-\r
-boolean CA_FarWrite (int handle, byte far *source, long length)\r
-{\r
- if (length>0xffffl)\r
- Quit ("CA_FarWrite doesn't support 64K reads yet!");\r
-\r
-asm push ds\r
-asm mov bx,[handle]\r
-asm mov cx,[WORD PTR length]\r
-asm mov dx,[WORD PTR source]\r
-asm mov ds,[WORD PTR source+2]\r
-asm mov ah,0x40 // WRITE w/handle\r
-asm int 21h\r
-asm pop ds\r
-asm jnc good\r
- errno = _AX;\r
- return false;\r
-good:\r
-asm cmp ax,[WORD PTR length]\r
-asm je done\r
- errno = ENOMEM; // user manager knows this is bad write\r
- return false;\r
-\r
-done:\r
- return true;\r
-}\r
-\r
-\r
-/*\r
-==========================\r
-=\r
-= CA_ReadFile\r
-=\r
-= Reads a file into an allready allocated buffer\r
-=\r
-==========================\r
-*/\r
-\r
-boolean CA_ReadFile (char *filename, memptr *ptr)\r
-{\r
- int handle;\r
- long size;\r
-\r
- if ((handle = open(filename,O_RDONLY | O_BINARY, S_IREAD)) == -1)\r
- return false;\r
-\r
- size = filelength (handle);\r
- if (!CA_FarRead (handle,*ptr,size))\r
- {\r
- close (handle);\r
- return false;\r
- }\r
- close (handle);\r
- return true;\r
-}\r
-\r
-\r
-\r
-/*\r
-==========================\r
-=\r
-= CA_LoadFile\r
-=\r
-= Allocate space for and load a file\r
-=\r
-==========================\r
-*/\r
-\r
-boolean CA_LoadFile (char *filename, memptr *ptr)\r
-{\r
- int handle;\r
- long size;\r
-\r
- if ((handle = open(filename,O_RDONLY | O_BINARY, S_IREAD)) == -1)\r
- return false;\r
-\r
- size = filelength (handle);\r
- MM_GetPtr (ptr,size);\r
- if (!CA_FarRead (handle,*ptr,size))\r
- {\r
- close (handle);\r
- return false;\r
- }\r
- close (handle);\r
- return true;\r
-}\r
-\r
-/*\r
-============================================================================\r
-\r
- COMPRESSION routines, see JHUFF.C for more\r
-\r
-============================================================================\r
-*/\r
-\r
-\r
-\r
-/*\r
-===============\r
-=\r
-= CAL_OptimizeNodes\r
-=\r
-= Goes through a huffman table and changes the 256-511 node numbers to the\r
-= actular address of the node. Must be called before CAL_HuffExpand\r
-=\r
-===============\r
-*/\r
-\r
-void CAL_OptimizeNodes (huffnode *table)\r
-{\r
- huffnode *node;\r
- int i;\r
-\r
- node = table;\r
-\r
- for (i=0;i<255;i++)\r
- {\r
- if (node->bit0 >= 256)\r
- node->bit0 = (unsigned)(table+(node->bit0-256));\r
- if (node->bit1 >= 256)\r
- node->bit1 = (unsigned)(table+(node->bit1-256));\r
- node++;\r
- }\r
-}\r
-\r
-\r
-\r
-/*\r
-======================\r
-=\r
-= CAL_HuffExpand\r
-=\r
-= Length is the length of the EXPANDED data\r
-=\r
-======================\r
-*/\r
-\r
-void CAL_HuffExpand (byte huge *source, byte huge *dest,\r
- long length,huffnode *hufftable)\r
-{\r
-// unsigned bit,byte,node,code;\r
- unsigned sourceseg,sourceoff,destseg,destoff,endoff;\r
- huffnode *headptr;\r
-// huffnode *nodeon;\r
-\r
- headptr = hufftable+254; // head node is allways node 254\r
-\r
- source++; // normalize\r
- source--;\r
- dest++;\r
- dest--;\r
-\r
- sourceseg = FP_SEG(source);\r
- sourceoff = FP_OFF(source);\r
- destseg = FP_SEG(dest);\r
- destoff = FP_OFF(dest);\r
- endoff = destoff+length;\r
-\r
-//\r
-// ds:si source\r
-// es:di dest\r
-// ss:bx node pointer\r
-//\r
-\r
- if (length <0xfff0)\r
- {\r
-\r
-//--------------------------\r
-// expand less than 64k of data\r
-//--------------------------\r
-\r
-asm mov bx,[headptr]\r
-\r
-asm mov si,[sourceoff]\r
-asm mov di,[destoff]\r
-asm mov es,[destseg]\r
-asm mov ds,[sourceseg]\r
-asm mov ax,[endoff]\r
-\r
-asm mov ch,[si] // load first byte\r
-asm inc si\r
-asm mov cl,1\r
-\r
-expandshort:\r
-asm test ch,cl // bit set?\r
-asm jnz bit1short\r
-asm mov dx,[ss:bx] // take bit0 path from node\r
-asm shl cl,1 // advance to next bit position\r
-asm jc newbyteshort\r
-asm jnc sourceupshort\r
-\r
-bit1short:\r
-asm mov dx,[ss:bx+2] // take bit1 path\r
-asm shl cl,1 // advance to next bit position\r
-asm jnc sourceupshort\r
-\r
-newbyteshort:\r
-asm mov ch,[si] // load next byte\r
-asm inc si\r
-asm mov cl,1 // back to first bit\r
-\r
-sourceupshort:\r
-asm or dh,dh // if dx<256 its a byte, else move node\r
-asm jz storebyteshort\r
-asm mov bx,dx // next node = (huffnode *)code\r
-asm jmp expandshort\r
-\r
-storebyteshort:\r
-asm mov [es:di],dl\r
-asm inc di // write a decopmpressed byte out\r
-asm mov bx,[headptr] // back to the head node for next bit\r
-\r
-asm cmp di,ax // done?\r
-asm jne expandshort\r
- }\r
- else\r
- {\r
-\r
-//--------------------------\r
-// expand more than 64k of data\r
-//--------------------------\r
-\r
- length--;\r
-\r
-asm mov bx,[headptr]\r
-asm mov cl,1\r
-\r
-asm mov si,[sourceoff]\r
-asm mov di,[destoff]\r
-asm mov es,[destseg]\r
-asm mov ds,[sourceseg]\r
-\r
-asm lodsb // load first byte\r
-\r
-expand:\r
-asm test al,cl // bit set?\r
-asm jnz bit1\r
-asm mov dx,[ss:bx] // take bit0 path from node\r
-asm jmp gotcode\r
-bit1:\r
-asm mov dx,[ss:bx+2] // take bit1 path\r
-\r
-gotcode:\r
-asm shl cl,1 // advance to next bit position\r
-asm jnc sourceup\r
-asm lodsb\r
-asm cmp si,0x10 // normalize ds:si\r
-asm jb sinorm\r
-asm mov cx,ds\r
-asm inc cx\r
-asm mov ds,cx\r
-asm xor si,si\r
-sinorm:\r
-asm mov cl,1 // back to first bit\r
-\r
-sourceup:\r
-asm or dh,dh // if dx<256 its a byte, else move node\r
-asm jz storebyte\r
-asm mov bx,dx // next node = (huffnode *)code\r
-asm jmp expand\r
-\r
-storebyte:\r
-asm mov [es:di],dl\r
-asm inc di // write a decopmpressed byte out\r
-asm mov bx,[headptr] // back to the head node for next bit\r
-\r
-asm cmp di,0x10 // normalize es:di\r
-asm jb dinorm\r
-asm mov dx,es\r
-asm inc dx\r
-asm mov es,dx\r
-asm xor di,di\r
-dinorm:\r
-\r
-asm sub [WORD PTR ss:length],1\r
-asm jnc expand\r
-asm dec [WORD PTR ss:length+2]\r
-asm jns expand // when length = ffff ffff, done\r
-\r
- }\r
-\r
-asm mov ax,ss\r
-asm mov ds,ax\r
-\r
-}\r
-\r
-\r
-/*\r
-======================\r
-=\r
-= CAL_CarmackExpand\r
-=\r
-= Length is the length of the EXPANDED data\r
-=\r
-======================\r
-*/\r
-\r
-#define NEARTAG 0xa7\r
-#define FARTAG 0xa8\r
-\r
-void CAL_CarmackExpand (unsigned far *source, unsigned far *dest, unsigned length)\r
-{\r
- unsigned ch,chhigh,count,offset;\r
- unsigned far *copyptr, far *inptr, far *outptr;\r
-\r
- length/=2;\r
-\r
- inptr = source;\r
- outptr = dest;\r
-\r
- while (length)\r
- {\r
- ch = *inptr++;\r
- chhigh = ch>>8;\r
- if (chhigh == NEARTAG)\r
- {\r
- count = ch&0xff;\r
- if (!count)\r
- { // have to insert a word containing the tag byte\r
- ch |= *((unsigned char far *)inptr)++;\r
- *outptr++ = ch;\r
- length--;\r
- }\r
- else\r
- {\r
- offset = *((unsigned char far *)inptr)++;\r
- copyptr = outptr - offset;\r
- length -= count;\r
- while (count--)\r
- *outptr++ = *copyptr++;\r
- }\r
- }\r
- else if (chhigh == FARTAG)\r
- {\r
- count = ch&0xff;\r
- if (!count)\r
- { // have to insert a word containing the tag byte\r
- ch |= *((unsigned char far *)inptr)++;\r
- *outptr++ = ch;\r
- length --;\r
- }\r
- else\r
- {\r
- offset = *inptr++;\r
- copyptr = dest + offset;\r
- length -= count;\r
- while (count--)\r
- *outptr++ = *copyptr++;\r
- }\r
- }\r
- else\r
- {\r
- *outptr++ = ch;\r
- length --;\r
- }\r
- }\r
-}\r
-\r
-\r
-\r
-/*\r
-======================\r
-=\r
-= CA_RLEWcompress\r
-=\r
-======================\r
-*/\r
-\r
-long CA_RLEWCompress (unsigned huge *source, long length, unsigned huge *dest,\r
- unsigned rlewtag)\r
-{\r
- long complength;\r
- unsigned value,count,i;\r
- unsigned huge *start,huge *end;\r
-\r
- start = dest;\r
-\r
- end = source + (length+1)/2;\r
-\r
-//\r
-// compress it\r
-//\r
- do\r
- {\r
- count = 1;\r
- value = *source++;\r
- while (*source == value && source<end)\r
- {\r
- count++;\r
- source++;\r
- }\r
- if (count>3 || value == rlewtag)\r
- {\r
- //\r
- // send a tag / count / value string\r
- //\r
- *dest++ = rlewtag;\r
- *dest++ = count;\r
- *dest++ = value;\r
- }\r
- else\r
- {\r
- //\r
- // send word without compressing\r
- //\r
- for (i=1;i<=count;i++)\r
- *dest++ = value;\r
- }\r
-\r
- } while (source<end);\r
-\r
- complength = 2*(dest-start);\r
- return complength;\r
-}\r
-\r
-\r
-/*\r
-======================\r
-=\r
-= CA_RLEWexpand\r
-= length is EXPANDED length\r
-=\r
-======================\r
-*/\r
-\r
-void CA_RLEWexpand (unsigned huge *source, unsigned huge *dest,long length,\r
- unsigned rlewtag)\r
-{\r
-// unsigned value,count,i;\r
- unsigned huge *end;\r
- unsigned sourceseg,sourceoff,destseg,destoff,endseg,endoff;\r
-\r
-\r
-//\r
-// expand it\r
-//\r
-#if 0\r
- do\r
- {\r
- value = *source++;\r
- if (value != rlewtag)\r
- //\r
- // uncompressed\r
- //\r
- *dest++=value;\r
- else\r
- {\r
- //\r
- // compressed string\r
- //\r
- count = *source++;\r
- value = *source++;\r
- for (i=1;i<=count;i++)\r
- *dest++ = value;\r
- }\r
- } while (dest<end);\r
-#endif\r
-\r
- end = dest + (length)/2;\r
- sourceseg = FP_SEG(source);\r
- sourceoff = FP_OFF(source);\r
- destseg = FP_SEG(dest);\r
- destoff = FP_OFF(dest);\r
- endseg = FP_SEG(end);\r
- endoff = FP_OFF(end);\r
-\r
-\r
-//\r
-// ax = source value\r
-// bx = tag value\r
-// cx = repeat counts\r
-// dx = scratch\r
-//\r
-// NOTE: A repeat count that produces 0xfff0 bytes can blow this!\r
-//\r
-\r
-asm mov bx,rlewtag\r
-asm mov si,sourceoff\r
-asm mov di,destoff\r
-asm mov es,destseg\r
-asm mov ds,sourceseg\r
-\r
-expand:\r
-asm lodsw\r
-asm cmp ax,bx\r
-asm je repeat\r
-asm stosw\r
-asm jmp next\r
-\r
-repeat:\r
-asm lodsw\r
-asm mov cx,ax // repeat count\r
-asm lodsw // repeat value\r
-asm rep stosw\r
-\r
-next:\r
-\r
-asm cmp si,0x10 // normalize ds:si\r
-asm jb sinorm\r
-asm mov ax,si\r
-asm shr ax,1\r
-asm shr ax,1\r
-asm shr ax,1\r
-asm shr ax,1\r
-asm mov dx,ds\r
-asm add dx,ax\r
-asm mov ds,dx\r
-asm and si,0xf\r
-sinorm:\r
-asm cmp di,0x10 // normalize es:di\r
-asm jb dinorm\r
-asm mov ax,di\r
-asm shr ax,1\r
-asm shr ax,1\r
-asm shr ax,1\r
-asm shr ax,1\r
-asm mov dx,es\r
-asm add dx,ax\r
-asm mov es,dx\r
-asm and di,0xf\r
-dinorm:\r
-\r
-asm cmp di,ss:endoff\r
-asm jne expand\r
-asm mov ax,es\r
-asm cmp ax,ss:endseg\r
-asm jb expand\r
-\r
-asm mov ax,ss\r
-asm mov ds,ax\r
-\r
-}\r
-\r
-\r
-\r
-/*\r
-=============================================================================\r
-\r
- CACHE MANAGER ROUTINES\r
-\r
-=============================================================================\r
-*/\r
-\r
-\r
-/*\r
-======================\r
-=\r
-= CAL_SetupGrFile\r
-=\r
-======================\r
-*/\r
-\r
-void CAL_SetupGrFile (void)\r
-{\r
- int handle;\r
- memptr compseg;\r
-\r
-#ifdef GRHEADERLINKED\r
-\r
-#if GRMODE == EGAGR\r
- grhuffman = (huffnode *)&EGAdict;\r
- grstarts = (long _seg *)FP_SEG(&EGAhead);\r
-#endif\r
-#if GRMODE == CGAGR\r
- grhuffman = (huffnode *)&CGAdict;\r
- grstarts = (long _seg *)FP_SEG(&CGAhead);\r
-#endif\r
-\r
- CAL_OptimizeNodes (grhuffman);\r
-\r
-#else\r
-\r
-//\r
-// load ???dict.ext (huffman dictionary for graphics files)\r
-//\r
-\r
- if ((handle = open(GREXT"DICT."EXTENSION,\r
- O_RDONLY | O_BINARY, S_IREAD)) == -1)\r
- Quit ("Can't open "GREXT"DICT."EXTENSION"!");\r
-\r
- read(handle, &grhuffman, sizeof(grhuffman));\r
- close(handle);\r
- CAL_OptimizeNodes (grhuffman);\r
-//\r
-// load the data offsets from ???head.ext\r
-//\r
- MM_GetPtr (&(memptr)grstarts,(NUMCHUNKS+1)*FILEPOSSIZE);\r
-\r
- if ((handle = open(GREXT"HEAD."EXTENSION,\r
- O_RDONLY | O_BINARY, S_IREAD)) == -1)\r
- Quit ("Can't open "GREXT"HEAD."EXTENSION"!");\r
-\r
- CA_FarRead(handle, (memptr)grstarts, (NUMCHUNKS+1)*FILEPOSSIZE);\r
-\r
- close(handle);\r
-\r
-\r
-#endif\r
-\r
-//\r
-// Open the graphics file, leaving it open until the game is finished\r
-//\r
- grhandle = open(GREXT"GRAPH."EXTENSION, O_RDONLY | O_BINARY);\r
- if (grhandle == -1)\r
- Quit ("Cannot open "GREXT"GRAPH."EXTENSION"!");\r
-\r
-\r
-//\r
-// load the pic and sprite headers into the arrays in the data segment\r
-//\r
-#if NUMPICS>0\r
- MM_GetPtr(&(memptr)pictable,NUMPICS*sizeof(pictabletype));\r
- CAL_GetGrChunkLength(STRUCTPIC); // position file pointer\r
- MM_GetPtr(&compseg,chunkcomplen);\r
- CA_FarRead (grhandle,compseg,chunkcomplen);\r
- CAL_HuffExpand (compseg, (byte huge *)pictable,NUMPICS*sizeof(pictabletype),grhuffman);\r
- MM_FreePtr(&compseg);\r
-#endif\r
-\r
-#if NUMPICM>0\r
- MM_GetPtr(&(memptr)picmtable,NUMPICM*sizeof(pictabletype));\r
- CAL_GetGrChunkLength(STRUCTPICM); // position file pointer\r
- MM_GetPtr(&compseg,chunkcomplen);\r
- CA_FarRead (grhandle,compseg,chunkcomplen);\r
- CAL_HuffExpand (compseg, (byte huge *)picmtable,NUMPICS*sizeof(pictabletype),grhuffman);\r
- MM_FreePtr(&compseg);\r
-#endif\r
-\r
-#if NUMSPRITES>0\r
- MM_GetPtr(&(memptr)spritetable,NUMSPRITES*sizeof(spritetabletype));\r
- CAL_GetGrChunkLength(STRUCTSPRITE); // position file pointer\r
- MM_GetPtr(&compseg,chunkcomplen);\r
- CA_FarRead (grhandle,compseg,chunkcomplen);\r
- CAL_HuffExpand (compseg, (byte huge *)spritetable,NUMSPRITES*sizeof(spritetabletype),grhuffman);\r
- MM_FreePtr(&compseg);\r
-#endif\r
-\r
-}\r
-\r
-//==========================================================================\r
-\r
-\r
-/*\r
-======================\r
-=\r
-= CAL_SetupMapFile\r
-=\r
-======================\r
-*/\r
-\r
-void CAL_SetupMapFile (void)\r
-{\r
- int handle;\r
- long length;\r
-\r
-//\r
-// load maphead.ext (offsets and tileinfo for map file)\r
-//\r
-#ifndef MAPHEADERLINKED\r
- if ((handle = open("MAPHEAD."EXTENSION,\r
- O_RDONLY | O_BINARY, S_IREAD)) == -1)\r
- Quit ("Can't open MAPHEAD."EXTENSION"!");\r
- length = filelength(handle);\r
- MM_GetPtr (&(memptr)tinf,length);\r
- CA_FarRead(handle, tinf, length);\r
- close(handle);\r
-#else\r
-\r
- tinf = (byte _seg *)FP_SEG(&maphead);\r
-\r
-#endif\r
-\r
-//\r
-// open the data file\r
-//\r
-#ifdef MAPHEADERLINKED\r
- if ((maphandle = open("GAMEMAPS."EXTENSION,\r
- O_RDONLY | O_BINARY, S_IREAD)) == -1)\r
- Quit ("Can't open GAMEMAPS."EXTENSION"!");\r
-#else\r
- if ((maphandle = open("MAPTEMP."EXTENSION,\r
- O_RDONLY | O_BINARY, S_IREAD)) == -1)\r
- Quit ("Can't open MAPTEMP."EXTENSION"!");\r
-#endif\r
-}\r
-\r
-//==========================================================================\r
-\r
-\r
-/*\r
-======================\r
-=\r
-= CAL_SetupAudioFile\r
-=\r
-======================\r
-*/\r
-\r
-void CAL_SetupAudioFile (void)\r
-{\r
- int handle;\r
- long length;\r
-\r
-//\r
-// load maphead.ext (offsets and tileinfo for map file)\r
-//\r
-#ifndef AUDIOHEADERLINKED\r
- if ((handle = open("AUDIOHED."EXTENSION,\r
- O_RDONLY | O_BINARY, S_IREAD)) == -1)\r
- Quit ("Can't open AUDIOHED."EXTENSION"!");\r
- length = filelength(handle);\r
- MM_GetPtr (&(memptr)audiostarts,length);\r
- CA_FarRead(handle, (byte far *)audiostarts, length);\r
- close(handle);\r
-#else\r
- audiohuffman = (huffnode *)&audiodict;\r
- CAL_OptimizeNodes (audiohuffman);\r
- audiostarts = (long _seg *)FP_SEG(&audiohead);\r
-#endif\r
-\r
-//\r
-// open the data file\r
-//\r
-#ifndef AUDIOHEADERLINKED\r
- if ((audiohandle = open("AUDIOT."EXTENSION,\r
- O_RDONLY | O_BINARY, S_IREAD)) == -1)\r
- Quit ("Can't open AUDIOT."EXTENSION"!");\r
-#else\r
- if ((audiohandle = open("AUDIO."EXTENSION,\r
- O_RDONLY | O_BINARY, S_IREAD)) == -1)\r
- Quit ("Can't open AUDIO."EXTENSION"!");\r
-#endif\r
-}\r
-\r
-//==========================================================================\r
-\r
-\r
-/*\r
-======================\r
-=\r
-= CA_Startup\r
-=\r
-= Open all files and load in headers\r
-=\r
-======================\r
-*/\r
-\r
-void CA_Startup (void)\r
-{\r
-#ifdef PROFILE\r
- unlink ("PROFILE.TXT");\r
- profilehandle = open("PROFILE.TXT", O_CREAT | O_WRONLY | O_TEXT);\r
-#endif\r
-\r
-#ifndef NOMAPS\r
- CAL_SetupMapFile ();\r
-#endif\r
-#ifndef NOGRAPHICS\r
- CAL_SetupGrFile ();\r
-#endif\r
-#ifndef NOAUDIO\r
- CAL_SetupAudioFile ();\r
-#endif\r
-\r
- mapon = -1;\r
- ca_levelbit = 1;\r
- ca_levelnum = 0;\r
-\r
- drawcachebox = CAL_DialogDraw;\r
- updatecachebox = CAL_DialogUpdate;\r
- finishcachebox = CAL_DialogFinish;\r
-}\r
-\r
-//==========================================================================\r
-\r
-\r
-/*\r
-======================\r
-=\r
-= CA_Shutdown\r
-=\r
-= Closes all files\r
-=\r
-======================\r
-*/\r
-\r
-void CA_Shutdown (void)\r
-{\r
-#ifdef PROFILE\r
- close (profilehandle);\r
-#endif\r
-\r
- close (maphandle);\r
- close (grhandle);\r
- close (audiohandle);\r
-}\r
-\r
-//===========================================================================\r
-\r
-/*\r
-======================\r
-=\r
-= CA_CacheAudioChunk\r
-=\r
-======================\r
-*/\r
-\r
-void CA_CacheAudioChunk (int chunk)\r
-{\r
- long pos,compressed;\r
-#ifdef AUDIOHEADERLINKED\r
- long expanded;\r
- memptr bigbufferseg;\r
- byte far *source;\r
-#endif\r
-\r
- if (audiosegs[chunk])\r
- {\r
- MM_SetPurge (&(memptr)audiosegs[chunk],0);\r
- return; // allready in memory\r
- }\r
-\r
-//\r
-// load the chunk into a buffer, either the miscbuffer if it fits, or allocate\r
-// a larger buffer\r
-//\r
- pos = audiostarts[chunk];\r
- compressed = audiostarts[chunk+1]-pos;\r
-\r
- lseek(audiohandle,pos,SEEK_SET);\r
-\r
-#ifndef AUDIOHEADERLINKED\r
-\r
- MM_GetPtr (&(memptr)audiosegs[chunk],compressed);\r
- if (mmerror)\r
- return;\r
-\r
- CA_FarRead(audiohandle,audiosegs[chunk],compressed);\r
-\r
-#else\r
-\r
- if (compressed<=BUFFERSIZE)\r
- {\r
- CA_FarRead(audiohandle,bufferseg,compressed);\r
- source = bufferseg;\r
- }\r
- else\r
- {\r
- MM_GetPtr(&bigbufferseg,compressed);\r
- if (mmerror)\r
- return;\r
- MM_SetLock (&bigbufferseg,true);\r
- CA_FarRead(audiohandle,bigbufferseg,compressed);\r
- source = bigbufferseg;\r
- }\r
-\r
- expanded = *(long far *)source;\r
- source += 4; // skip over length\r
- MM_GetPtr (&(memptr)audiosegs[chunk],expanded);\r
- if (mmerror)\r
- goto done;\r
- CAL_HuffExpand (source,audiosegs[chunk],expanded,audiohuffman);\r
-\r
-done:\r
- if (compressed>BUFFERSIZE)\r
- MM_FreePtr(&bigbufferseg);\r
-#endif\r
-}\r
-\r
-//===========================================================================\r
-\r
-/*\r
-======================\r
-=\r
-= CA_LoadAllSounds\r
-=\r
-= Purges all sounds, then loads all new ones (mode switch)\r
-=\r
-======================\r
-*/\r
-\r
-void CA_LoadAllSounds (void)\r
-{\r
- unsigned start,i;\r
-\r
- switch (oldsoundmode)\r
- {\r
- case sdm_Off:\r
- goto cachein;\r
- case sdm_PC:\r
- start = STARTPCSOUNDS;\r
- break;\r
- case sdm_AdLib:\r
- start = STARTADLIBSOUNDS;\r
- break;\r
- }\r
-\r
- for (i=0;i<NUMSOUNDS;i++,start++)\r
- if (audiosegs[start])\r
- MM_SetPurge (&(memptr)audiosegs[start],3); // make purgable\r
-\r
-cachein:\r
-\r
- switch (SoundMode)\r
- {\r
- case sdm_Off:\r
- return;\r
- case sdm_PC:\r
- start = STARTPCSOUNDS;\r
- break;\r
- case sdm_AdLib:\r
- start = STARTADLIBSOUNDS;\r
- break;\r
- }\r
-\r
- for (i=0;i<NUMSOUNDS;i++,start++)\r
- CA_CacheAudioChunk (start);\r
-\r
- oldsoundmode = SoundMode;\r
-}\r
-\r
-//===========================================================================\r
-\r
-#if GRMODE == EGAGR\r
-\r
-/*\r
-======================\r
-=\r
-= CAL_ShiftSprite\r
-=\r
-= Make a shifted (one byte wider) copy of a sprite into another area\r
-=\r
-======================\r
-*/\r
-\r
-unsigned static sheight,swidth;\r
-\r
-void CAL_ShiftSprite (unsigned segment,unsigned source,unsigned dest,\r
- unsigned width, unsigned height, unsigned pixshift)\r
-{\r
-\r
- sheight = height; // because we are going to reassign bp\r
- swidth = width;\r
-\r
-asm mov ax,[segment]\r
-asm mov ds,ax // source and dest are in same segment, and all local\r
-\r
-asm mov bx,[source]\r
-asm mov di,[dest]\r
-\r
-asm mov bp,[pixshift]\r
-asm shl bp,1\r
-asm mov bp,WORD PTR [shifttabletable+bp] // bp holds pointer to shift table\r
-\r
-//\r
-// table shift the mask\r
-//\r
-asm mov dx,[ss:sheight]\r
-\r
-domaskrow:\r
-\r
-asm mov BYTE PTR [di],255 // 0xff first byte\r
-asm mov cx,ss:[swidth]\r
-\r
-domaskbyte:\r
-\r
-asm mov al,[bx] // source\r
-asm not al\r
-asm inc bx // next source byte\r
-asm xor ah,ah\r
-asm shl ax,1\r
-asm mov si,ax\r
-asm mov ax,[bp+si] // table shift into two bytes\r
-asm not ax\r
-asm and [di],al // and with first byte\r
-asm inc di\r
-asm mov [di],ah // replace next byte\r
-\r
-asm loop domaskbyte\r
-\r
-asm inc di // the last shifted byte has 1s in it\r
-asm dec dx\r
-asm jnz domaskrow\r
-\r
-//\r
-// table shift the data\r
-//\r
-asm mov dx,ss:[sheight]\r
-asm shl dx,1\r
-asm shl dx,1 // four planes of data\r
-\r
-dodatarow:\r
-\r
-asm mov BYTE PTR [di],0 // 0 first byte\r
-asm mov cx,ss:[swidth]\r
-\r
-dodatabyte:\r
-\r
-asm mov al,[bx] // source\r
-asm inc bx // next source byte\r
-asm xor ah,ah\r
-asm shl ax,1\r
-asm mov si,ax\r
-asm mov ax,[bp+si] // table shift into two bytes\r
-asm or [di],al // or with first byte\r
-asm inc di\r
-asm mov [di],ah // replace next byte\r
-\r
-asm loop dodatabyte\r
-\r
-asm inc di // the last shifted byte has 0s in it\r
-asm dec dx\r
-asm jnz dodatarow\r
-\r
-//\r
-// done\r
-//\r
-\r
-asm mov ax,ss // restore data segment\r
-asm mov ds,ax\r
-\r
-}\r
-\r
-#endif\r
-\r
-//===========================================================================\r
-\r
-/*\r
-======================\r
-=\r
-= CAL_CacheSprite\r
-=\r
-= Generate shifts and set up sprite structure for a given sprite\r
-=\r
-======================\r
-*/\r
-\r
-void CAL_CacheSprite (int chunk, byte far *compressed)\r
-{\r
- int i;\r
- unsigned shiftstarts[5];\r
- unsigned smallplane,bigplane,expanded;\r
- spritetabletype far *spr;\r
- spritetype _seg *dest;\r
-\r
-#if GRMODE == CGAGR\r
-//\r
-// CGA has no pel panning, so shifts are never needed\r
-//\r
- spr = &spritetable[chunk-STARTSPRITES];\r
- smallplane = spr->width*spr->height;\r
- MM_GetPtr (&grsegs[chunk],smallplane*2+MAXSHIFTS*6);\r
- if (mmerror)\r
- return;\r
- dest = (spritetype _seg *)grsegs[chunk];\r
- dest->sourceoffset[0] = MAXSHIFTS*6; // start data after 3 unsigned tables\r
- dest->planesize[0] = smallplane;\r
- dest->width[0] = spr->width;\r
-\r
-//\r
-// expand the unshifted shape\r
-//\r
- CAL_HuffExpand (compressed, &dest->data[0],smallplane*2,grhuffman);\r
-\r
-#endif\r
-\r
-\r
-#if GRMODE == EGAGR\r
-\r
-//\r
-// calculate sizes\r
-//\r
- spr = &spritetable[chunk-STARTSPRITES];\r
- smallplane = spr->width*spr->height;\r
- bigplane = (spr->width+1)*spr->height;\r
-\r
- shiftstarts[0] = MAXSHIFTS*6; // start data after 3 unsigned tables\r
- shiftstarts[1] = shiftstarts[0] + smallplane*5; // 5 planes in a sprite\r
- shiftstarts[2] = shiftstarts[1] + bigplane*5;\r
- shiftstarts[3] = shiftstarts[2] + bigplane*5;\r
- shiftstarts[4] = shiftstarts[3] + bigplane*5; // nothing ever put here\r
-\r
- expanded = shiftstarts[spr->shifts];\r
- MM_GetPtr (&grsegs[chunk],expanded);\r
- if (mmerror)\r
- return;\r
- dest = (spritetype _seg *)grsegs[chunk];\r
-\r
-//\r
-// expand the unshifted shape\r
-//\r
- CAL_HuffExpand (compressed, &dest->data[0],smallplane*5,grhuffman);\r
-\r
-//\r
-// make the shifts!\r
-//\r
- switch (spr->shifts)\r
- {\r
- case 1:\r
- for (i=0;i<4;i++)\r
- {\r
- dest->sourceoffset[i] = shiftstarts[0];\r
- dest->planesize[i] = smallplane;\r
- dest->width[i] = spr->width;\r
- }\r
- break;\r
-\r
- case 2:\r
- for (i=0;i<2;i++)\r
- {\r
- dest->sourceoffset[i] = shiftstarts[0];\r
- dest->planesize[i] = smallplane;\r
- dest->width[i] = spr->width;\r
- }\r
- for (i=2;i<4;i++)\r
- {\r
- dest->sourceoffset[i] = shiftstarts[1];\r
- dest->planesize[i] = bigplane;\r
- dest->width[i] = spr->width+1;\r
- }\r
- CAL_ShiftSprite ((unsigned)grsegs[chunk],dest->sourceoffset[0],\r
- dest->sourceoffset[2],spr->width,spr->height,4);\r
- break;\r
-\r
- case 4:\r
- dest->sourceoffset[0] = shiftstarts[0];\r
- dest->planesize[0] = smallplane;\r
- dest->width[0] = spr->width;\r
-\r
- dest->sourceoffset[1] = shiftstarts[1];\r
- dest->planesize[1] = bigplane;\r
- dest->width[1] = spr->width+1;\r
- CAL_ShiftSprite ((unsigned)grsegs[chunk],dest->sourceoffset[0],\r
- dest->sourceoffset[1],spr->width,spr->height,2);\r
-\r
- dest->sourceoffset[2] = shiftstarts[2];\r
- dest->planesize[2] = bigplane;\r
- dest->width[2] = spr->width+1;\r
- CAL_ShiftSprite ((unsigned)grsegs[chunk],dest->sourceoffset[0],\r
- dest->sourceoffset[2],spr->width,spr->height,4);\r
-\r
- dest->sourceoffset[3] = shiftstarts[3];\r
- dest->planesize[3] = bigplane;\r
- dest->width[3] = spr->width+1;\r
- CAL_ShiftSprite ((unsigned)grsegs[chunk],dest->sourceoffset[0],\r
- dest->sourceoffset[3],spr->width,spr->height,6);\r
-\r
- break;\r
-\r
- default:\r
- Quit ("CAL_CacheSprite: Bad shifts number!");\r
- }\r
-\r
-#endif\r
-}\r
-\r
-//===========================================================================\r
-\r
-\r
-/*\r
-======================\r
-=\r
-= CAL_ExpandGrChunk\r
-=\r
-= Does whatever is needed with a pointer to a compressed chunk\r
-=\r
-======================\r
-*/\r
-\r
-void CAL_ExpandGrChunk (int chunk, byte far *source)\r
-{\r
- long expanded;\r
-\r
-\r
- if (chunk >= STARTTILE8 && chunk < STARTEXTERNS)\r
- {\r
- //\r
- // expanded sizes of tile8/16/32 are implicit\r
- //\r
-\r
-#if GRMODE == EGAGR\r
-#define BLOCK 32\r
-#define MASKBLOCK 40\r
-#endif\r
-\r
-#if GRMODE == CGAGR\r
-#define BLOCK 16\r
-#define MASKBLOCK 32\r
-#endif\r
-\r
- if (chunk<STARTTILE8M) // tile 8s are all in one chunk!\r
- expanded = BLOCK*NUMTILE8;\r
- else if (chunk<STARTTILE16)\r
- expanded = MASKBLOCK*NUMTILE8M;\r
- else if (chunk<STARTTILE16M) // all other tiles are one/chunk\r
- expanded = BLOCK*4;\r
- else if (chunk<STARTTILE32)\r
- expanded = MASKBLOCK*4;\r
- else if (chunk<STARTTILE32M)\r
- expanded = BLOCK*16;\r
- else\r
- expanded = MASKBLOCK*16;\r
- }\r
- else\r
- {\r
- //\r
- // everything else has an explicit size longword\r
- //\r
- expanded = *(long far *)source;\r
- source += 4; // skip over length\r
- }\r
-\r
-//\r
-// allocate final space, decompress it, and free bigbuffer\r
-// Sprites need to have shifts made and various other junk\r
-//\r
- if (chunk>=STARTSPRITES && chunk< STARTTILE8)\r
- CAL_CacheSprite(chunk,source);\r
- else\r
- {\r
- MM_GetPtr (&grsegs[chunk],expanded);\r
- if (mmerror)\r
- return;\r
- CAL_HuffExpand (source,grsegs[chunk],expanded,grhuffman);\r
- }\r
-}\r
-\r
-\r
-/*\r
-======================\r
-=\r
-= CAL_ReadGrChunk\r
-=\r
-= Gets a chunk off disk, optimizing reads to general buffer\r
-=\r
-======================\r
-*/\r
-\r
-void CAL_ReadGrChunk (int chunk)\r
-{\r
- long pos,compressed;\r
- memptr bigbufferseg;\r
- byte far *source;\r
- int next;\r
-\r
-//\r
-// load the chunk into a buffer, either the miscbuffer if it fits, or allocate\r
-// a larger buffer\r
-//\r
- pos = GRFILEPOS(chunk);\r
- if (pos<0) // $FFFFFFFF start is a sparse tile\r
- return;\r
-\r
- next = chunk +1;\r
- while (GRFILEPOS(next) == -1) // skip past any sparse tiles\r
- next++;\r
-\r
- compressed = GRFILEPOS(next)-pos;\r
-\r
- lseek(grhandle,pos,SEEK_SET);\r
-\r
- if (compressed<=BUFFERSIZE)\r
- {\r
- CA_FarRead(grhandle,bufferseg,compressed);\r
- source = bufferseg;\r
- }\r
- else\r
- {\r
- MM_GetPtr(&bigbufferseg,compressed);\r
- if (mmerror)\r
- return;\r
- MM_SetLock (&bigbufferseg,true);\r
- CA_FarRead(grhandle,bigbufferseg,compressed);\r
- source = bigbufferseg;\r
- }\r
-\r
- CAL_ExpandGrChunk (chunk,source);\r
-\r
- if (compressed>BUFFERSIZE)\r
- MM_FreePtr(&bigbufferseg);\r
-}\r
-\r
-\r
-/*\r
-======================\r
-=\r
-= CA_CacheGrChunk\r
-=\r
-= Makes sure a given chunk is in memory, loadiing it if needed\r
-=\r
-======================\r
-*/\r
-\r
-void CA_CacheGrChunk (int chunk)\r
-{\r
- long pos,compressed;\r
- memptr bigbufferseg;\r
- byte far *source;\r
- int next;\r
-\r
- grneeded[chunk] |= ca_levelbit; // make sure it doesn't get removed\r
- if (grsegs[chunk])\r
- {\r
- MM_SetPurge (&grsegs[chunk],0);\r
- return; // allready in memory\r
- }\r
-\r
-//\r
-// load the chunk into a buffer, either the miscbuffer if it fits, or allocate\r
-// a larger buffer\r
-//\r
- pos = GRFILEPOS(chunk);\r
- if (pos<0) // $FFFFFFFF start is a sparse tile\r
- return;\r
-\r
- next = chunk +1;\r
- while (GRFILEPOS(next) == -1) // skip past any sparse tiles\r
- next++;\r
-\r
- compressed = GRFILEPOS(next)-pos;\r
-\r
- lseek(grhandle,pos,SEEK_SET);\r
-\r
- if (compressed<=BUFFERSIZE)\r
- {\r
- CA_FarRead(grhandle,bufferseg,compressed);\r
- source = bufferseg;\r
- }\r
- else\r
- {\r
- MM_GetPtr(&bigbufferseg,compressed);\r
- MM_SetLock (&bigbufferseg,true);\r
- CA_FarRead(grhandle,bigbufferseg,compressed);\r
- source = bigbufferseg;\r
- }\r
-\r
- CAL_ExpandGrChunk (chunk,source);\r
-\r
- if (compressed>BUFFERSIZE)\r
- MM_FreePtr(&bigbufferseg);\r
-}\r
-\r
-\r
-\r
-//==========================================================================\r
-\r
-/*\r
-======================\r
-=\r
-= CA_CacheMap\r
-=\r
-======================\r
-*/\r
-\r
-void CA_CacheMap (int mapnum)\r
-{\r
- long pos,compressed;\r
- int plane;\r
- memptr *dest,bigbufferseg;\r
- unsigned size;\r
- unsigned far *source;\r
-#ifdef MAPHEADERLINKED\r
- memptr buffer2seg;\r
- long expanded;\r
-#endif\r
-\r
-\r
-//\r
-// free up memory from last map\r
-//\r
- if (mapon>-1 && mapheaderseg[mapon])\r
- MM_SetPurge (&(memptr)mapheaderseg[mapon],3);\r
- for (plane=0;plane<MAPPLANES;plane++)\r
- if (mapsegs[plane])\r
- MM_FreePtr (&(memptr)mapsegs[plane]);\r
-\r
- mapon = mapnum;\r
-\r
-\r
-//\r
-// load map header\r
-// The header will be cached if it is still around\r
-//\r
- if (!mapheaderseg[mapnum])\r
- {\r
- pos = ((mapfiletype _seg *)tinf)->headeroffsets[mapnum];\r
- if (pos<0) // $FFFFFFFF start is a sparse map\r
- Quit ("CA_CacheMap: Tried to load a non existent map!");\r
-\r
- MM_GetPtr(&(memptr)mapheaderseg[mapnum],sizeof(maptype));\r
- lseek(maphandle,pos,SEEK_SET);\r
- CA_FarRead (maphandle,(memptr)mapheaderseg[mapnum],sizeof(maptype));\r
- }\r
- else\r
- MM_SetPurge (&(memptr)mapheaderseg[mapnum],0);\r
-\r
-//\r
-// load the planes in\r
-// If a plane's pointer still exists it will be overwritten (levels are\r
-// allways reloaded, never cached)\r
-//\r
-\r
- size = mapheaderseg[mapnum]->width * mapheaderseg[mapnum]->height * 2;\r
-\r
- for (plane = 0; plane<MAPPLANES; plane++)\r
- {\r
- pos = mapheaderseg[mapnum]->planestart[plane];\r
- compressed = mapheaderseg[mapnum]->planelength[plane];\r
-\r
- if (!compressed)\r
- continue; // the plane is not used in this game\r
-\r
- dest = &(memptr)mapsegs[plane];\r
- MM_GetPtr(dest,size);\r
-\r
- lseek(maphandle,pos,SEEK_SET);\r
- if (compressed<=BUFFERSIZE)\r
- source = bufferseg;\r
- else\r
- {\r
- MM_GetPtr(&bigbufferseg,compressed);\r
- MM_SetLock (&bigbufferseg,true);\r
- source = bigbufferseg;\r
- }\r
-\r
- CA_FarRead(maphandle,(byte far *)source,compressed);\r
-#ifdef MAPHEADERLINKED\r
- //\r
- // unhuffman, then unRLEW\r
- // The huffman'd chunk has a two byte expanded length first\r
- // The resulting RLEW chunk also does, even though it's not really\r
- // needed\r
- //\r
- expanded = *source;\r
- source++;\r
- MM_GetPtr (&buffer2seg,expanded);\r
- CAL_CarmackExpand (source, (unsigned far *)buffer2seg,expanded);\r
- CA_RLEWexpand (((unsigned far *)buffer2seg)+1,*dest,size,\r
- ((mapfiletype _seg *)tinf)->RLEWtag);\r
- MM_FreePtr (&buffer2seg);\r
-\r
-#else\r
- //\r
- // unRLEW, skipping expanded length\r
- //\r
- CA_RLEWexpand (source+1, *dest,size,\r
- ((mapfiletype _seg *)tinf)->RLEWtag);\r
-#endif\r
-\r
- if (compressed>BUFFERSIZE)\r
- MM_FreePtr(&bigbufferseg);\r
- }\r
-}\r
-\r
-//===========================================================================\r
-\r
-/*\r
-======================\r
-=\r
-= CA_UpLevel\r
-=\r
-= Goes up a bit level in the needed lists and clears it out.\r
-= Everything is made purgable\r
-=\r
-======================\r
-*/\r
-\r
-void CA_UpLevel (void)\r
-{\r
- if (ca_levelnum==7)\r
- Quit ("CA_UpLevel: Up past level 7!");\r
-\r
- ca_levelbit<<=1;\r
- ca_levelnum++;\r
-}\r
-\r
-//===========================================================================\r
-\r
-/*\r
-======================\r
-=\r
-= CA_DownLevel\r
-=\r
-= Goes down a bit level in the needed lists and recaches\r
-= everything from the lower level\r
-=\r
-======================\r
-*/\r
-\r
-void CA_DownLevel (void)\r
-{\r
- if (!ca_levelnum)\r
- Quit ("CA_DownLevel: Down past level 0!");\r
- ca_levelbit>>=1;\r
- ca_levelnum--;\r
- CA_CacheMarks(NULL);\r
-}\r
-\r
-//===========================================================================\r
-\r
-/*\r
-======================\r
-=\r
-= CA_ClearMarks\r
-=\r
-= Clears out all the marks at the current level\r
-=\r
-======================\r
-*/\r
-\r
-void CA_ClearMarks (void)\r
-{\r
- int i;\r
-\r
- for (i=0;i<NUMCHUNKS;i++)\r
- grneeded[i]&=~ca_levelbit;\r
-}\r
-\r
-\r
-//===========================================================================\r
-\r
-/*\r
-======================\r
-=\r
-= CA_ClearAllMarks\r
-=\r
-= Clears out all the marks on all the levels\r
-=\r
-======================\r
-*/\r
-\r
-void CA_ClearAllMarks (void)\r
-{\r
- _fmemset (grneeded,0,sizeof(grneeded));\r
- ca_levelbit = 1;\r
- ca_levelnum = 0;\r
-}\r
-\r
-\r
-//===========================================================================\r
-\r
-/*\r
-======================\r
-=\r
-= CA_FreeGraphics\r
-=\r
-======================\r
-*/\r
-\r
-void CA_FreeGraphics (void)\r
-{\r
- int i;\r
-\r
- for (i=0;i<NUMCHUNKS;i++)\r
- if (grsegs[i])\r
- MM_SetPurge (&(memptr)grsegs[i],3);\r
-}\r
-\r
-\r
-/*\r
-======================\r
-=\r
-= CA_SetAllPurge\r
-=\r
-= Make everything possible purgable\r
-=\r
-======================\r
-*/\r
-\r
-void CA_SetAllPurge (void)\r
-{\r
- int i;\r
-\r
- CA_ClearMarks ();\r
-\r
-//\r
-// free cursor sprite and background save\r
-//\r
- VW_FreeCursor ();\r
-\r
-//\r
-// free map headers and map planes\r
-//\r
- for (i=0;i<NUMMAPS;i++)\r
- if (mapheaderseg[i])\r
- MM_SetPurge (&(memptr)mapheaderseg[i],3);\r
-\r
- for (i=0;i<3;i++)\r
- if (mapsegs[i])\r
- MM_FreePtr (&(memptr)mapsegs[i]);\r
-\r
-//\r
-// free sounds\r
-//\r
- for (i=0;i<NUMSNDCHUNKS;i++)\r
- if (audiosegs[i])\r
- MM_SetPurge (&(memptr)audiosegs[i],3);\r
-\r
-//\r
-// free graphics\r
-//\r
- CA_FreeGraphics ();\r
-}\r
-\r
-\r
-void CA_SetGrPurge (void)\r
-{\r
- int i;\r
-\r
-//\r
-// free graphics\r
-//\r
- for (i=0;i<NUMCHUNKS;i++)\r
- if (grsegs[i])\r
- MM_SetPurge (&(memptr)grsegs[i],3);\r
-}\r
-\r
-\r
-//===========================================================================\r
-\r
-\r
-/*\r
-======================\r
-=\r
-= CAL_DialogDraw\r
-=\r
-======================\r
-*/\r
-\r
-#define NUMBARS (17l*8)\r
-#define BARSTEP 8\r
-\r
-unsigned thx,thy,lastx;\r
-long barx,barstep;\r
-\r
-void CAL_DialogDraw (char *title,unsigned numcache)\r
-{\r
- unsigned homex,homey,x;\r
-\r
- barstep = (NUMBARS<<16)/numcache;\r
-\r
-//\r
-// draw dialog window (masked tiles 12 - 20 are window borders)\r
-//\r
- US_CenterWindow (20,8);\r
- homex = PrintX;\r
- homey = PrintY;\r
-\r
- US_CPrint ("Loading");\r
- fontcolor = F_SECONDCOLOR;\r
- US_CPrint (title);\r
- fontcolor = F_BLACK;\r
-\r
-//\r
-// draw thermometer bar\r
-//\r
- thx = homex + 8;\r
- thy = homey + 32;\r
-#ifdef CAT3D\r
- VWB_DrawTile8(thx,thy,0); // CAT3D numbers\r
- VWB_DrawTile8(thx,thy+8,3);\r
- VWB_DrawTile8(thx,thy+16,6);\r
- VWB_DrawTile8(thx+17*8,thy,2);\r
- VWB_DrawTile8(thx+17*8,thy+8,5);\r
- VWB_DrawTile8(thx+17*8,thy+16,8);\r
- for (x=thx+8;x<thx+17*8;x+=8)\r
- {\r
- VWB_DrawTile8(x,thy,1);\r
- VWB_DrawTile8(x,thy+8,4);\r
- VWB_DrawTile8(x,thy+16,7);\r
- }\r
-#else\r
- VWB_DrawTile8(thx,thy,11); // KEEN numbers\r
- VWB_DrawTile8(thx,thy+8,14);\r
- VWB_DrawTile8(thx,thy+16,17);\r
- VWB_DrawTile8(thx+17*8,thy,13);\r
- VWB_DrawTile8(thx+17*8,thy+8,16);\r
- VWB_DrawTile8(thx+17*8,thy+16,19);\r
- for (x=thx+8;x<thx+17*8;x+=8)\r
- {\r
- VWB_DrawTile8(x,thy,12);\r
- VWB_DrawTile8(x,thy+8,15);\r
- VWB_DrawTile8(x,thy+16,18);\r
- }\r
-#endif\r
-\r
- thx += 4; // first line location\r
- thy += 5;\r
- barx = (long)thx<<16;\r
- lastx = thx;\r
-\r
- VW_UpdateScreen();\r
-}\r
-\r
-\r
-/*\r
-======================\r
-=\r
-= CAL_DialogUpdate\r
-=\r
-======================\r
-*/\r
-\r
-void CAL_DialogUpdate (void)\r
-{\r
- unsigned x,xh;\r
-\r
- barx+=barstep;\r
- xh = barx>>16;\r
- if (xh - lastx > BARSTEP)\r
- {\r
- for (x=lastx;x<=xh;x++)\r
-#if GRMODE == EGAGR\r
- VWB_Vlin (thy,thy+13,x,14);\r
-#endif\r
-#if GRMODE == CGAGR\r
- VWB_Vlin (thy,thy+13,x,SECONDCOLOR);\r
-#endif\r
- lastx = xh;\r
- VW_UpdateScreen();\r
- }\r
-}\r
-\r
-/*\r
-======================\r
-=\r
-= CAL_DialogFinish\r
-=\r
-======================\r
-*/\r
-\r
-void CAL_DialogFinish (void)\r
-{\r
- unsigned x,xh;\r
-\r
- xh = thx + NUMBARS;\r
- for (x=lastx;x<=xh;x++)\r
-#if GRMODE == EGAGR\r
- VWB_Vlin (thy,thy+13,x,14);\r
-#endif\r
-#if GRMODE == CGAGR\r
- VWB_Vlin (thy,thy+13,x,SECONDCOLOR);\r
-#endif\r
- VW_UpdateScreen();\r
-\r
-}\r
-\r
-//===========================================================================\r
-\r
-/*\r
-======================\r
-=\r
-= CA_CacheMarks\r
-=\r
-======================\r
-*/\r
-#define MAXEMPTYREAD 1024\r
-\r
-void CA_CacheMarks (char *title)\r
-{\r
- boolean dialog;\r
- int i,next,numcache;\r
- long pos,endpos,nextpos,nextendpos,compressed;\r
- long bufferstart,bufferend; // file position of general buffer\r
- byte far *source;\r
- memptr bigbufferseg;\r
-\r
- dialog = (title!=NULL);\r
-\r
- numcache = 0;\r
-//\r
-// go through and make everything not needed purgable\r
-//\r
- for (i=0;i<NUMCHUNKS;i++)\r
- if (grneeded[i]&ca_levelbit)\r
- {\r
- if (grsegs[i]) // its allready in memory, make\r
- MM_SetPurge(&grsegs[i],0); // sure it stays there!\r
- else\r
- numcache++;\r
- }\r
- else\r
- {\r
- if (grsegs[i]) // not needed, so make it purgeable\r
- MM_SetPurge(&grsegs[i],3);\r
- }\r
-\r
- if (!numcache) // nothing to cache!\r
- return;\r
-\r
- if (dialog)\r
- {\r
-#ifdef PROFILE\r
- write(profilehandle,title,strlen(title));\r
- write(profilehandle,"\n",1);\r
-#endif\r
- if (drawcachebox)\r
- drawcachebox(title,numcache);\r
- }\r
-\r
-//\r
-// go through and load in anything still needed\r
-//\r
- bufferstart = bufferend = 0; // nothing good in buffer now\r
-\r
- for (i=0;i<NUMCHUNKS;i++)\r
- if ( (grneeded[i]&ca_levelbit) && !grsegs[i])\r
- {\r
-//\r
-// update thermometer\r
-//\r
- if (dialog && updatecachebox)\r
- updatecachebox ();\r
-\r
- pos = GRFILEPOS(i);\r
- if (pos<0)\r
- continue;\r
-\r
- next = i +1;\r
- while (GRFILEPOS(next) == -1) // skip past any sparse tiles\r
- next++;\r
-\r
- compressed = GRFILEPOS(next)-pos;\r
- endpos = pos+compressed;\r
-\r
- if (compressed<=BUFFERSIZE)\r
- {\r
- if (bufferstart<=pos\r
- && bufferend>= endpos)\r
- {\r
- // data is allready in buffer\r
- source = (byte _seg *)bufferseg+(pos-bufferstart);\r
- }\r
- else\r
- {\r
- // load buffer with a new block from disk\r
- // try to get as many of the needed blocks in as possible\r
- while ( next < NUMCHUNKS )\r
- {\r
- while (next < NUMCHUNKS &&\r
- !(grneeded[next]&ca_levelbit && !grsegs[next]))\r
- next++;\r
- if (next == NUMCHUNKS)\r
- continue;\r
-\r
- nextpos = GRFILEPOS(next);\r
- while (GRFILEPOS(++next) == -1) // skip past any sparse tiles\r
- ;\r
- nextendpos = GRFILEPOS(next);\r
- if (nextpos - endpos <= MAXEMPTYREAD\r
- && nextendpos-pos <= BUFFERSIZE)\r
- endpos = nextendpos;\r
- else\r
- next = NUMCHUNKS; // read pos to posend\r
- }\r
-\r
- lseek(grhandle,pos,SEEK_SET);\r
- CA_FarRead(grhandle,bufferseg,endpos-pos);\r
- bufferstart = pos;\r
- bufferend = endpos;\r
- source = bufferseg;\r
- }\r
- }\r
- else\r
- {\r
- // big chunk, allocate temporary buffer\r
- MM_GetPtr(&bigbufferseg,compressed);\r
- if (mmerror)\r
- return;\r
- MM_SetLock (&bigbufferseg,true);\r
- lseek(grhandle,pos,SEEK_SET);\r
- CA_FarRead(grhandle,bigbufferseg,compressed);\r
- source = bigbufferseg;\r
- }\r
-\r
- CAL_ExpandGrChunk (i,source);\r
- if (mmerror)\r
- return;\r
-\r
- if (compressed>BUFFERSIZE)\r
- MM_FreePtr(&bigbufferseg);\r
-\r
- }\r
-\r
-//\r
-// finish up any thermometer remnants\r
-//\r
- if (dialog && finishcachebox)\r
- finishcachebox();\r
-}\r
-\r