+++ /dev/null
-/* Catacomb Apocalypse 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 "16_ca.h"\r
-//#include "ID_STRS.H"\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,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
-void CA_OpenDebug(void)\r
-{\r
- unlink("debug.16");\r
- debughandle = open("debug.16", 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 huge *dest, dword length, mminfo_t *mm)\r
-{\r
- boolean flag;\r
- /*dword fat=0;
- word segm=0;
- //if(mm->EMSVer<0x40)\r
- if(length>0xfffflu)
- {
- printf("File is a fat bakapee\n");
- segm=(length%0xfffflu)-1;
- fat=segm*0xfffflu;
- length-=fat;\r
-// printf("CA_FarRead doesn't support 64K reads yet!\n");\r
- }
-
- if(!fat&&!segm)
- {*/\r
- __asm {\r
- push ds\r
- mov bx,[handle]\r
- mov cx,[WORD PTR length]\r
- mov dx,[WORD PTR dest]\r
- mov ds,[WORD PTR dest+2]\r
- mov ah,0x3f // READ w/handle\r
- int 21h\r
- pop ds\r
- jnc good\r
- mov errno,ax\r
- mov flag,0\r
- jmp End
- }\r
-good:
- __asm {\r
- cmp ax,[WORD PTR length]\r
- je done\r
-// errno = EINVFMT; // user manager knows this is bad read\r
- mov flag,0\r
- jmp End
- }\r
-done:
- __asm {\r
- mov flag,1
- }\r
-End:\r
- return flag;
- //}else return 0;//todo: EXPAND!!!\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 huge *source, dword length, mminfo_t *mm)\r
-{\r
- boolean flag;\r
- /*dword fat=0;
- word segm=0;
- //if(mm->EMSVer<0x40)\r
- if(length>0xfffflu)
- {
- printf("File is a fat bakapee\n");
- segm=(length%0xfffflu)-1;
- fat=segm*0xfffflu;
- length-=fat;\r
-// printf("CA_FarRead doesn't support 64K reads yet!\n");\r
- }\r
-
- if(!fat&&!segm)
- {*/\r
- __asm {\r
- push ds\r
- mov bx,[handle]\r
- mov cx,[WORD PTR length]\r
- mov dx,[WORD PTR source]\r
- mov ds,[WORD PTR source+2]\r
- mov ah,0x40 // WRITE w/handle\r
- int 21h\r
- pop ds\r
- jnc good\r
- mov errno,ax\r
- mov flag,0\r
- jmp End
- }\r
-good:
- __asm {\r
- cmp ax,[WORD PTR length]\r
- je done\r
- //errno = ENOMEM; // user manager knows this is bad write\r
- mov flag,0\r
- jmp End
- }\r
-done:
- __asm {\r
- mov flag,1
- }\r
-End:\r
- return flag;
- //}else return 0;\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, mminfo_t *mm)\r
-{\r
- int handle;\r
- dword size;
- //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, mm))\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, mminfo_t *mm, mminfotype *mmi)\r
-{\r
- int handle;\r
- dword size;
- //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, mm, mmi);\r
- if(!CA_FarRead(handle,*ptr,size, mm))\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\r
- {\r
- mov bx,[headptr]\r
-\r
- mov si,[sourceoff]\r
- mov di,[destoff]\r
- mov es,[destseg]\r
- mov ds,[sourceseg]\r
- mov ax,[endoff]\r
-\r
- mov ch,[si] // load first byte\r
- inc si\r
- mov cl,1\r
-\r
-expandshort:\r
- test ch,cl // bit set?\r
- jnz bit1short\r
- mov dx,[ss:bx] // take bit0 path from node\r
- shl cl,1 // advance to next bit position\r
- jc newbyteshort\r
- 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
- }\r
- else\r
- {\r
-\r
-//--------------------------\r
-// expand more than 64k of data\r
-//--------------------------\r
-\r
- length--;\r
-\r
- __asm\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\r
- {\r
- mov ax,ss\r
- mov ds,ax\r
- }\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
-= 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."EXT,\r
- O_RDONLY | O_BINARY, S_IREAD)) == -1)\r
- Quit ("Can't open "GREXT"DICT."EXT"!");\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."EXT,\r
- O_RDONLY | O_BINARY, S_IREAD)) == -1)\r
- Quit ("Can't open "GREXT"HEAD."EXT"!");\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."EXT, O_RDONLY | O_BINARY);\r
- if (grhandle == -1)\r
- Quit ("Cannot open "GREXT"GRAPH."EXT"!");\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."EXT,\r
- O_RDONLY | O_BINARY, S_IREAD)) == -1)\r
- Quit ("Can't open MAPHEAD."EXT"!");\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."EXT,\r
- O_RDONLY | O_BINARY, S_IREAD)) == -1)\r
- Quit ("Can't open GAMEMAPS."EXT"!");\r
-#else\r
- if ((maphandle = open("MAPTEMP."EXT,\r
- O_RDONLY | O_BINARY, S_IREAD)) == -1)\r
- Quit ("Can't open MAPTEMP."EXT"!");\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."EXT,\r
- O_RDONLY | O_BINARY, S_IREAD)) == -1)\r
- Quit ("Can't open AUDIOHED."EXT"!");\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."EXT,\r
- O_RDONLY | O_BINARY, S_IREAD)) == -1)\r
- Quit ("Can't open AUDIOT."EXT"!");\r
-#else\r
- if ((audiohandle = open("AUDIO."EXT,\r
- O_RDONLY | O_BINARY, S_IREAD)) == -1)\r
- Quit ("Can't open AUDIO."EXT"!");\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.16");\r
- profilehandle = open("profile.16", O_CREAT | O_WRONLY | O_TEXT);\r
-#endif\r
-/*++++\r
-// MDM begin - (GAMERS EDGE)\r
-//\r
- if(!FindFile("AUDIO."EXT,NULL,2))\r
- Quit("CA_Startup(): Can't find audio files.");\r
-//\r
-// MDM end\r
-\r
-#ifndef NOAUDIO\r
- CAL_SetupAudioFile();\r
-#endif\r
-\r
-// MDM begin - (GAMERS EDGE)\r
-//\r
- if (!FindFile("GAMEMAPS."EXT,NULL,1))\r
- Quit("CA_Startup(): Can't find level files.");\r
-//\r
-// MDM end\r
-\r
-#ifndef NOMAPS\r
- CAL_SetupMapFile ();\r
-#endif\r
-\r
-// MDM begin - (GAMERS EDGE)\r
-//\r
- if (!FindFile("EGAGRAPH."EXT,NULL,2))\r
- Quit("CA_Startup(): Can't find graphics files.");\r
-//\r
-// MDM end\r
-\r
-#ifndef NOGRAPHICS\r
- CAL_SetupGrFile ();\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
-// MDM begin - (GAMERS EDGE)\r
-//\r
- if (!FindFile("AUDIO."EXT,NULL,2))\r
- Quit("CA_CacheAudioChunk(): Can't find audio files.");\r
-//\r
-// MDM end\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
-boolean static dothemask;\r
-\r
-void CAL_ShiftSprite (unsigned segment,unsigned source,unsigned dest,\r
- unsigned width, unsigned height, unsigned pixshift, boolean domask)\r
-{\r
-\r
- sheight = height; // because we are going to reassign bp\r
- swidth = width;\r
- dothemask = domask;\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
-asm cmp [ss:dothemask],0\r
-asm je skipmask\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
-skipmask:\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,true);\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,true);\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,true);\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,true);\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
-= 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
-// MDM begin - (GAMERS EDGE)\r
-//\r
- if (!FindFile("EGAGRAPH."EXT,NULL,2))\r
- Quit("CA_CacheGrChunk(): Can't find graphics files.");\r
-//\r
-// MDM end\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
-// MDM begin - (GAMERS EDGE)\r
-//\r
- if (!FindFile("GAMEMAPS."EXT,NULL,1))\r
- Quit("CA_CacheMap(): Can't find level files.");\r
-//\r
-// MDM end\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
- 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
-\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
-// MDM begin - (GAMERS EDGE)\r
-//\r
- if (!FindFile("EGAGRAPH."EXT,NULL,2))\r
- Quit("CA_CacheMarks(): Can't find graphics files.");\r
-//\r
-// MDM end\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
+++ /dev/null
-/* Catacomb Apocalypse 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.H\r
-#ifndef __16_CA__\r
-#define __16_CA__\r
-\r
-#ifndef __16_MM__\r
-#include "16_head.h"\r
-#include "16_mm.h"\r
-#endif\r
-\r
-//===========================================================================\r
-\r
-//#define NOMAPS\r
-//#define NOGRAPHICS\r
-//#define NOAUDIO\r
-\r
-//#define MAPHEADERLINKED\r
-//#define GRHEADERLINKED\r
-//#define AUDIOHEADERLINKED\r
-\r
-//#define NUMMAPS 39\r
-//#define MAPPLANES 3
-#define PROFILE\r
-\r
-//===========================================================================\r
-\r
-/*typedef struct\r
-{\r
- long planestart[3];\r
- unsigned planelength[3];\r
- unsigned width,height;\r
- char name[16];\r
-} maptype;*/\r
-\r
-//===========================================================================\r
-\r
-/*extern byte _seg *tinf;\r
-extern int mapon;\r
-\r
-extern unsigned _seg *mapsegs[3];\r
-extern maptype _seg *mapheaderseg[NUMMAPS];\r
-extern byte _seg *audiosegs[NUMSNDCHUNKS];\r
-extern void _seg *grsegs[NUMCHUNKS];\r
-\r
-extern byte far grneeded[NUMCHUNKS];\r
-extern byte ca_levelbit,ca_levelnum;\r
-\r
-extern char *titleptr[8];*/\r
-\r
-extern int profilehandle,debughandle;\r
-\r
-//\r
-// hooks for custom cache dialogs\r
-//\r
-extern void (*drawcachebox) (char *title, unsigned numcache);\r
-extern void (*updatecachebox) (void);\r
-extern void (*finishcachebox) (void);\r
-\r
-//===========================================================================\r
-\r
-// just for the score box reshifting\r
-\r
-//void CAL_ShiftSprite (unsigned segment,unsigned source,unsigned dest,unsigned width, unsigned height, unsigned pixshift, boolean domask);\r
-\r
-//===========================================================================\r
-
-void CA_OpenDebug (void);\r
-void CA_CloseDebug (void);
-boolean CA_FarRead (int handle, byte huge *dest, dword length, mminfo_t *mm);\r
-boolean CA_FarWrite (int handle, byte huge *source, dword length, mminfo_t *mm);
-\r
-boolean CA_ReadFile (char *filename, memptr *ptr, mminfo_t *mm);\r
-boolean CA_LoadFile (char *filename, memptr *ptr, mminfo_t *mm, mminfotype *mmi);
-\r
-//long CA_RLEWCompress (unsigned huge *source, long length, unsigned huge *dest,unsigned rlewtag);\r
-\r
-//void CA_RLEWexpand (unsigned huge *source, unsigned huge *dest,long length,unsigned rlewtag);\r
-\r
-void CA_Startup (void);\r
-void CA_Shutdown (void);\r
-\r
-//void CA_CacheAudioChunk (int chunk);\r
-//void CA_LoadAllSounds (void);\r
-\r
-/*void CA_UpLevel (void);\r
-void CA_DownLevel (void);\r
-\r
-void CA_SetAllPurge (void);\r
-\r
-void CA_ClearMarks (void);\r
-void CA_ClearAllMarks (void);\r
-\r
-#define CA_MarkGrChunk(chunk) grneeded[chunk]|=ca_levelbit\r
-\r
-void CA_CacheGrChunk (int chunk);\r
-void CA_CacheMap (int mapnum);\r
-\r
-void CA_CacheMarks (char *title);*/\r
-#endif\r
+++ /dev/null
-/* Project 16 Source Code~
- * Copyright (C) 2012-2015 sparky4 & pngwen & andrius4669
- *
- * This file is part of Project 16.
- *
- * Project 16 is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 3 of the License, or
- * (at your option) any later version.
- *
- * Project 16 is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>, or
- * write to the Free Software Foundation, Inc., 51 Franklin Street,
- * Fifth Floor, Boston, MA 02110-1301 USA.
- *
- */
-
-#include "16_head.h"
-
-/* Function: Wait **********************************************************\r
-*\r
-* Parameters: wait - time in microseconds\r
-*\r
-* Description: pauses for a specified number of microseconds.\r
-*\r
-*/\r
-void wait(clock_t wait){\r
- clock_t goal;\r
-\r
- if(!wait) return;\r
-\r
- goal = wait + clock();\r
- while((goal > clock()) && !kbhit()) ;\r
-} /* End of wait */
-
-void* AllocateLargestFreeBlock(size_t* Size)
-{
- size_t s0, s1;
- void* p;
-
- s0 = ~(size_t)0 ^ (~(size_t)0 >> 1);
-
- while (s0 && (p = malloc(s0)) == NULL)
- s0 >>= 1;
-
- if (p)
- free(p);
-
- s1 = s0 >> 1;
-
- while (s1)
- {
- if ((p = malloc(s0 + s1)) != NULL)
- {
- s0 += s1;
- free(p);
- }
- s1 >>= 1;
- }
-
- while (s0 && (p = malloc(s0)) == NULL)
- s0 ^= s0 & -s0;
-
- *Size = s0;
- return p;
-}
-
-size_t GetFreeSize(void)
-{
- size_t total = 0;
- void* pFirst = NULL;
- void* pLast = NULL;
-
- for (;;)
- {
- size_t largest;
- void* p = AllocateLargestFreeBlock(&largest);
-
- if (largest < sizeof(void*))
- {
- if (p != NULL)
- free(p);
- break;
- }
-
- *(void**)p = NULL;
-
- total += largest;
-
- if (pFirst == NULL)
- pFirst = p;
-
- if (pLast != NULL)
- *(void**)pLast = p;
-
- pLast = p;
- }
-
- while (pFirst != NULL)
- {
- void* p = *(void**)pFirst;
- free(pFirst);
- pFirst = p;
- }
-
- return total;
-}
-
-void far* AllocateLargestFarFreeBlock(size_t* Size)
-{
- size_t s0, s1;
- void far* p;
-
- s0 = ~(size_t)0 ^ (~(size_t)0 >> 1);
- while (s0 && (p = _fmalloc(s0)) == NULL)
- s0 >>= 1;
-
- if (p)
- _ffree(p);
-
- s1 = s0 >> 1;
- while (s1)
- {
- if ((p = _fmalloc(s0 + s1)) != NULL)
- {
- s0 += s1;
- _ffree(p);
- }
- s1 >>= 1;
- }
- while (s0 && (p = _fmalloc(s0)) == NULL)
- s0 ^= s0 & -s0;
-
- *Size = s0;
- return p;
-}
-
-size_t GetFarFreeSize(void)
-{
- size_t total = 0;
- void far* pFirst = NULL;
- void far* pLast = NULL;
- for(;;)
- {
- size_t largest;
- void far* p = AllocateLargestFarFreeBlock(&largest);
- if (largest < sizeof(void far*))
- {
- if (p != NULL)
- _ffree(p);
- break;
- }
- *(void far* far*)p = NULL;
- total += largest;
- if (pFirst == NULL)
- pFirst = p;
-
- if (pLast != NULL)
- *(void far* far*)pLast = p;
- pLast = p;
- }
-
- while (pFirst != NULL)
- {
- void far* p = *(void far* far*)pFirst;
- _ffree(pFirst);
- pFirst = p;
- }
- return total;
-}
-
-long int
-filesize(FILE *fp)\r
-{\r
- long int save_pos, size_of_file;\r
-\r
- save_pos = ftell(fp);\r
- fseek(fp, 0L, SEEK_END);\r
- size_of_file = ftell(fp);\r
- fseek(fp, save_pos, SEEK_SET);\r
- return(size_of_file);\r
-}
-
-///////////////////////////////////////////////////////////////////////////\r
-//\r
-// US_CheckParm() - checks to see if a string matches one of a set of\r
-// strings. The check is case insensitive. The routine returns the\r
-// index of the string that matched, or -1 if no matches were found\r
-//\r
-///////////////////////////////////////////////////////////////////////////\r
-int\r
-US_CheckParm(char *parm,char **strings)\r
-{\r
- char cp,cs,\r
- *p,*s;\r
- int i;\r
-\r
- while (!isalpha(*parm)) // Skip non-alphas\r
- parm++;\r
-\r
- for (i = 0;*strings && **strings;i++)\r
- {\r
- for (s = *strings++,p = parm,cs = cp = 0;cs == cp;)\r
- {\r
- cs = *s++;\r
- if (!cs)\r
- return(i);\r
- cp = *p++;\r
-\r
- if (isupper(cs))\r
- cs = tolower(cs);\r
- if (isupper(cp))\r
- cp = tolower(cp);\r
- }\r
- }\r
- return(-1);\r
-}
-
-/*\r
-==========================\r
-=\r
-= Quit\r
-=\r
-==========================\r
-*/\r
-\r
-/*void Quit(char *error, ...)\r
-{\r
- short exit_code=0;\r
- unsigned finscreen;\r
-\r
- va_list ap;\r
-\r
- va_start(ap,error);\r
-\r
-#ifndef CATALOG\r
- if (!error)\r
- {\r
- CA_SetAllPurge ();\r
- CA_CacheGrChunk (PIRACY);\r
- finscreen = (unsigned)grsegs[PIRACY];\r
- }\r
-#endif\r
-\r
- //ShutdownId ();\r
-\r
- if (error && *error)\r
- {\r
- vprintf(error,ap);\r
- exit_code = 1;\r
- }\r
-#ifndef CATALOG\r
- else\r
- if (!NoWait)\r
- {\r
- movedata (finscreen,0,0xb800,0,4000);\r
- bioskey (0);\r
- }\r
-#endif\r
-\r
- va_end(ap);\r
-\r
-#ifndef CATALOG\r
- if (!error)\r
- {\r
- _argc = 2;\r
- _argv[1] = "LAST.SHL";\r
- _argv[2] = "ENDSCN.SCN";\r
- _argv[3] = NULL;\r
- if (execv("LOADSCN.EXE", _argv) == -1)\r
- {\r
- clrscr();\r
- puts("Couldn't find executable LOADSCN.EXE.\n");\r
- exit(1);\r
- }\r
- }\r
-#endif\r
-\r
- exit(exit_code);\r
-}*/
+++ /dev/null
-/* Project 16 Source Code~
- * Copyright (C) 2012-2015 sparky4 & pngwen & andrius4669
- *
- * This file is part of Project 16.
- *
- * Project 16 is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 3 of the License, or
- * (at your option) any later version.
- *
- * Project 16 is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>, or
- * write to the Free Software Foundation, Inc., 51 Franklin Street,
- * Fifth Floor, Boston, MA 02110-1301 USA.
- *
- */
-
-/*
-#if !defined(__LARGE__) && !defined(__COMPACT__) && !defined(__HUGE__)
-#error Invalid memory model for compiling project 16
-#endif
-*/
-
-#if !defined(__i86__) && defined(__i386__)
-#error i8088 only
-#endif
-
-#ifndef _LIBHEAD_H_
-#define _LIBHEAD_H_
-#include <io.h>
-#include <dos.h>
-#include <stdio.h>
-#include <conio.h> // just for wait
-#include <time.h> // just for wait
-#include <stdlib.h>
-#include <malloc.h>
-#include <ctype.h>
-//#include <unistd.h>
-#include <fcntl.h>\r
-#include <sys/stat.h>
-#include <mem.h>
-#include "../../src/lib/types.h"
-
-/* Control codes for all keys on the keyboard */
-//here temperarly
-/*
-#define KEY_A (0x1E)
-#define KEY_B (0x30)
-#define KEY_C (0x2E)
-#define KEY_D (0x20)
-#define KEY_E (0x12)
-#define KEY_F (0x21)
-#define KEY_G (0x22)
-#define KEY_H (0x23)
-#define KEY_I (0x17)
-#define KEY_J (0x24)
-#define KEY_K (0x25)
-#define KEY_L (0x26)
-#define KEY_M (0x32)
-#define KEY_N (0x31)
-#define KEY_O (0x18)
-#define KEY_P (0x19)
-#define KEY_Q (0x10)
-#define KEY_R (0x13)
-#define KEY_S (0x1F)
-#define KEY_T (0x14)
-#define KEY_U (0x16)
-#define KEY_V (0x2F)
-#define KEY_W (0x11)
-#define KEY_X (0x2D)
-#define KEY_Y (0x15)
-#define KEY_Z (0x2C)
-#define KEY_1 (0x02)
-#define KEY_2 (0x03)
-#define KEY_3 (0x04)
-#define KEY_4 (0x05)
-#define KEY_5 (0x06)
-#define KEY_6 (0x07)
-#define KEY_7 (0x08)
-#define KEY_8 (0x09)
-#define KEY_9 (0x0A)
-#define KEY_0 (0x0B)
-#define KEY_DASH (0x0C) // -_
-#define KEY_EQUAL (0x0D) // =+
-#define KEY_LBRACKET (0x1A) // [{
-#define KEY_RBRACKET (0x1B) // ]}
-#define KEY_SEMICOLON (0x27) // ;:
-#define KEY_RQUOTE (0x28) // '"
-#define KEY_LQUOTE (0x29) // `~
-#define KEY_PERIOD (0x33) // .>
-#define KEY_COMMA (0x34) // ,<
-#define KEY_SLASH (0x35) // /?
-#define KEY_BACKSLASH (0x2B) // \|
-#define KEY_F1 (0x3B)
-#define KEY_F2 (0x3C)
-#define KEY_F3 (0x3D)
-#define KEY_F4 (0x3E)
-#define KEY_F5 (0x3F)
-#define KEY_F6 (0x40)
-#define KEY_F7 (0x41)
-#define KEY_F8 (0x42)
-#define KEY_F9 (0x43)
-#define KEY_F10 (0x44)
-#define KEY_ESC (0x01)
-#define KEY_BACKSPACE (0x0E)
-#define KEY_TAB (0x0F)
-#define KEY_ENTER (0x1C)
-#define KEY_CONTROL (0x1D)
-#define KEY_LSHIFT (0x2A)
-#define KEY_RSHIFT (0x36)
-#define KEY_PRTSC (0x37)
-#define KEY_ALT (0x38)
-#define KEY_SPACE (0x39)
-#define KEY_CAPSLOCK (0x3A)
-#define KEY_NUMLOCK (0x45)
-#define KEY_SCROLLLOCK (0x46)
-#define KEY_HOME (0x47)
-#define KEY_UP (0x48)
-#define KEY_PGUP (0x49)
-#define KEY_MINUS (0x4A)
-#define KEY_LEFT (0x4B)
-#define KEY_CENTER (0x4C)
-#define KEY_RIGHT (0x4D)
-#define KEY_PLUS (0x4E)
-#define KEY_END (0x4F)
-#define KEY_DOWN (0x50)
-#define KEY_PGDOWN (0x51)
-#define KEY_INS (0x52)
-#define KEY_DEL (0x53)
-
-#define KEY_LWIN (0x73)
-#define KEY_RWIN (0x74)
-#define KEY_MENU (0x75)
-*/
-
-static dword far* clockdw= (dword far*) 0x046C; /* 18.2hz clock */
-//static dword clockdw=0;
-extern int profilehandle,debughandle; //make it into game global
-
-#define nil ((void *)0)
-
-#define __DEBUG__
-
-//#define peekb(segm,ofs) (*(byte far*)MK_FP((segm),(ofs)))\r
-//#define peekw(segm,ofs) (*(word far*)MK_FP((segm),(ofs)))\r
-//#define pokeb(segm,ofs,value) (peekb((segm),(ofs)) = (byte)(value))\r
-//#define pokew(segm,ofs,value) (peekw((segm),(ofs)) = (word)(value))\r
-
-//typedef union REGPACK regs_t;
-typedef enum {false,true} boolean;
-//I hope this is correct!
-//__self
-typedef void _seg * memptr;
-//typedef void __based(__self) * memptr;
-//typedef __segment * memptr;
-typedef struct
-{\r
- int old_mode; //old video mode before game!
-} global_game_variables_t;
-
-/* local function */\r
-void wait(clock_t wait);
-void* AllocateLargestFreeBlock(size_t* Size);
-size_t GetFreeSize(void);
-void far *AllocateLargestFarFreeBlock(size_t* Size);
-size_t GetFarFreeSize(void);
-long int filesize(FILE *fp);
-int US_CheckParm(char *parm,char **strings);
-
-extern void CA_OpenDebug (void);\r
-extern void CA_CloseDebug (void);
-
-#endif/*_LIBHEAD_H_*/
+++ /dev/null
-/* Catacomb Apocalypse Source Code
- * Copyright (C) 1993-2014 Flat Rock Software
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along
- * with this program; if not, write to the Free Software Foundation, Inc.,
- * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
- */
-
-// NEWMM.C
-
-/*
-=============================================================================
-
- ID software memory manager
- --------------------------
-
-Primary coder: John Carmack
-
-RELIES ON
----------
-Quit (char *error) function
-
-
-WORK TO DO
-----------
-MM_SizePtr to change the size of a given pointer
-
-Multiple purge levels utilized
-
-EMS / XMS unmanaged routines
-
-=============================================================================
-*/
-/*
-
-Open Watcom port by sparky4
-
-*/
-#include "16_mm.h"
-#pragma hdrstop
-
-#pragma warn -pro
-#pragma warn -use
-
-/*#define GETNEWBLOCK {if(!(mmnew=mmfree))Quit("MM_GETNEWBLOCK: No free blocks!")\\r
- ;mmfree=mmfree->next;}\r
-\r
-//#define GETNEWBLOCK {if(!mmfree)MML_ClearBlock();mmnew=mmfree;mmfree=mmfree->next;}\r
-\r
-#define FREEBLOCK(x) {*x->useptr=NULL;x->next=mmfree;mmfree=x;}*/
-
-/*
-=============================================================================
-
- GLOBAL VARIABLES
-
-=============================================================================
-*/
-
-void (* beforesort) (void);
-void (* aftersort) (void);
-void (* XMSaddr) (void); // far pointer to XMS driver
-
-/*
-=============================================================================
-
- LOCAL VARIABLES
-
-=============================================================================
-*/
-
-static char *ParmStringsexmm[] = {"noems","noxms",""};
-
-/*
-======================
-=
-= MML_CheckForEMS
-=
-= Routine from p36 of Extending DOS
-=
-=======================
-*/
-
-boolean MML_CheckForEMS(void)
-{
- boolean emmcfems;
- static char emmname[] = "EMMXXXX0"; //fix by andrius4669
-// mov dx,OFFSET emmname
- __asm {
- //LEA DX, emmname //fix by andrius4669
- mov dx,OFFSET emmname //fix by andrius4669
- mov ax,0x3d00
- int 0x21 // try to open EMMXXXX0 device
- jc error
-
- mov bx,ax
- mov ax,0x4400
-
- int 0x21 // get device info
- jc error
-
- and dx,0x80
- jz error
-
- mov ax,0x4407
-
- int 0x21 // get status
- jc error
- or al,al
- jz error
-
- mov ah,0x3e
- int 0x21 // close handle
- jc error
- //
- // EMS is good
- //
- mov emmcfems,1
- jmp End
- }
- error:
- __asm {
- //
- // EMS is bad
- //
- mov emmcfems,0
- }
- End:
- return(emmcfems);
-}
-
-
-/*
-======================
-=
-= MML_SetupEMS
-=
-=======================
-*/
-
-byte MML_SetupEMS(mminfo_t *mm)
-{
- byte str[160];
- byte err;
- boolean errorflag=false;
-
- unsigned int EMSVer = 0;
- //byte EMS_status;
- unsigned totalEMSpages,freeEMSpages,EMSpageframe,EMSpagesmapped,EMShandle;
- totalEMSpages = freeEMSpages = EMSpageframe = EMSpagesmapped = 0;
-
- __asm {
- mov ah,EMS_STATUS
- int EMS_INT // make sure EMS hardware is present
- or ah,ah
- //mov [EMS_status],ah
- jnz error
-
- mov ah,EMS_VERSION
- int EMS_INT
- or ah,ah
- jnz error
- mov [EMSVer],ax // set EMSVer
- cmp al,0x32 // only work on ems 3.2 or greater
- jb error
-
- mov ah,EMS_GETFRAME
- int EMS_INT // find the page frame address
- or ah,ah
- jnz error
- mov [EMSpageframe],bx
-
- mov ah,EMS_GETPAGES
- int EMS_INT // find out how much EMS is there
- or ah,ah
- jnz error
- mov [totalEMSpages],dx
- mov [freeEMSpages],bx
- or bx,bx
- jz noEMS // no EMS at all to allocate
- //EXPAND DONG!!!!
- cmp [EMSVer],0x40
- jb low
- cmp bx,[freeEMSpages]
- jle getpages
- mov bx,[freeEMSpages]
- jmp getpages
- }
-
-low:
- __asm {
- cmp bx,4
- jle getpages // there is only 1,2,3,or 4 pages
- mov bx,4 // we can't use more than 4 pages
- }
-
-getpages:
- __asm {
- mov [EMSpagesmapped],bx
- mov ah,EMS_ALLOCPAGES // allocate up to 64k of EMS
- int EMS_INT
- or ah,ah
- jnz error
- mov [EMShandle],dx
- jmp End
- }
-error:
- __asm {
- mov err,ah
- mov errorflag,1
- jmp End
- }
-noEMS:
-End:
- if(errorflag==true)
- {
- //err = CPURegs.h.ah;
- strcpy(str,"MM_SetupEMS: EMS error ");
- //itoa(err,str2,16);
- MM_EMSerr(str, err);
- printf("%s\n",str);
- return err;
- }
- mm->totalEMSpages=totalEMSpages;
- mm->freeEMSpages=freeEMSpages;
- mm->EMSpageframe=EMSpageframe;
- mm->EMSpagesmapped=EMSpagesmapped;
- mm->EMShandle=EMShandle;
- mm->EMSVer=EMSVer;
- return 0;
-}
-
-
-/*
-======================
-=
-= MML_ShutdownEMS
-=
-=======================
-*/
-
-void MML_ShutdownEMS(mminfo_t *mm)
-{
- boolean errorflag=false;
- unsigned EMShandle=mm->EMShandle;
-
- if(!EMShandle)
- return;
- __asm {
- mov ah,EMS_FREEPAGES
- mov dx,[EMShandle]
- int EMS_INT
- or ah,ah
- jz ok
- mov errorflag,1
- }
- ok:
- if(errorflag==true) printf("MML_ShutdownEMS: Error freeing EMS!\n"); //++++ add something
-}
-
-/*
-====================
-=
-= MM_MapEMS
-=
-= Maps the 64k of EMS used by memory manager into the page frame
-= for general use. This only needs to be called if you are keeping
-= other things in EMS.
-=
-====================
-*/
-
-byte MM_MapEMS(mminfo_t *mm, mminfotype *mmi)
-{
- byte str[160];
- unsigned EMShandle;
- byte err;
- boolean errorflag=false;
- int i;
- EMShandle=mm->EMShandle;
-
- for (i=0;i<4/*MAPPAGES*/;i++)
- {
- __asm {
- mov ah,EMS_MAPPAGE
- mov bx,[i] // logical page
- mov al,bl // physical page
- mov dx,[EMShandle] // handle
- int EMS_INT
- or ah,ah
- jnz error
- jmp End
- }
- error:
- __asm {
- mov err,ah
- mov errorflag,1
- }
- End:
- if(errorflag==true)
- {
- //err = CPURegs.h.ah;
- strcpy(str,"MM_MapEMS: EMS error ");
- //itoa(err,str2,16);
- MM_EMSerr(str, err);
- printf("%s\n",str);
- //printf("FACK! %x\n", err);
- return err;
- }
- }
- mmi->EMSmem = (i)*0x4000lu;
- return 0;
-}
-
-byte MM_MapXEMS(mminfo_t *mm, mminfotype *mmi)
-{
-//SUB EMS.MapXPages (PhysicalStart, LogicalStart, NumPages, Handle)
-
- //Maps up to 4 logical EMS pages to physical pages in the page frame, where:
- //PhysicalStart = Physical page first logical page is mapped to
- //LogicalStart = First logical page to map
- //NumPages = Number of pages to map (1 to 4)
- //Handle = EMS handle logical pages are allocated to
-
- /*//Create a buffer containing the page information
-// FOR x = 0 TO NumPages - 1
-// MapInfo$ = MapInfo$ + MKI$(LogicalStart + x) + MKI$(PhysicalStart + x)
-// NEXT*/
-
-// Regs.ax = 0x5000 //Map the pages in the buffer
-// Regs.cx = NumPages //to the pageframe
-// Regs.dx = Handle
-// Regs.ds = VARSEG(MapInfo$)
-// Regs.si = SADD(MapInfo$)
-// InterruptX 0x67, Regs, Regs
-// EMS.Error = (Regs.ax AND 0xFF00&) \ 0x100 //Store the status code
-
-//END SUB
- byte str[160];
- byte err;
- word EMShandle;
- boolean errorflag=false;
- int i;
- EMShandle=mm->EMShandle;
-
- if(mm->EMSVer<0x40)
- return 5;
-
- for (i=0;i<MAPPAGES;i++)
- {
- __asm {
- mov ah,EMS_MAPXPAGE
- mov cx,[i] // logical page
- mov al,bl // physical page
- mov dx,[EMShandle] // handle
- int EMS_INT
- or ah,ah
- jnz error
- jmp End
- }
- error:
- __asm {
- mov err,ah
- mov errorflag,1
- }
- End:
- if(errorflag==true)
- {
- //err = CPURegs.h.ah;
- //strcpy(str,"MM_MapXEMS: EMS error 0x");
- strcpy(str,"MM_MapXEMS: EMS error ");
- //itoa(err,str2,16);
- MM_EMSerr(str, err);
- printf("%s\n",str);
- //printf("%s%x\n",str, err);
- //printf("FACK! %x\n", err);
- return err;
- }
- }
- mmi->EMSmem = (i)*0x4000lu;
- return 0;
-}
-
-//==========================================================================
-
-/*
-======================
-=
-= MML_CheckForXMS
-=
-= Check for XMM driver
-=
-=======================
-*/
-
-boolean MML_CheckForXMS(mminfo_t *mm)
-{
- boolean errorflag=false;
- mm->numUMBs = 0;
-
- __asm {
- mov ax,0x4300
- int 0x2f // query status of installed diver
- cmp al,0x80
- je good
- mov errorflag,1
- }
- good:
- if(errorflag==true) return false;
- else return true;
-}
-
-
-/*
-======================
-=
-= MML_SetupXMS
-=
-= Try to allocate all upper memory block
-=
-=======================
-*/
-
-void MML_SetupXMS(mminfo_t *mm, mminfotype *mmi)
-{
- unsigned base,size;
-
-getmemory:
- __asm {
- mov ax,0x4310
- int 0x2f
- mov [WORD PTR XMSaddr],bx
- mov [WORD PTR XMSaddr+2],es // function pointer to XMS driver
-
- mov ah,XMS_ALLOCUMB
- mov dx,0xffff // try for largest block possible
- //mov ax,dx // Set available Kbytes.
- call [DWORD PTR XMSaddr]
- or ax,ax
- jnz gotone
-
- cmp bl,0xb0 // error: smaller UMB is available
- jne done;
-
- mov ah,XMS_ALLOCUMB
- call [DWORD PTR XMSaddr] // DX holds largest available UMB
- or ax,ax
- jz done // another error...
- }
-gotone:
- __asm {
- mov [base],bx
- mov [size],dx
- }
-done:
- printf("base=%u ", base); printf("size=%u\n", size);
- MML_UseSpace(base,size, mm);
- mmi->XMSmem += size*16;
- mm->UMBbase[mm->numUMBs] = base;
- mm->numUMBs++;
- if(mm->numUMBs < MAXUMBS)
- goto getmemory;
-}
-
-
-/*
-======================
-=
-= MML_ShutdownXMS
-=
-======================
-*/
-
-void MML_ShutdownXMS(mminfo_t *mm)
-{
- int i;
- unsigned base;
-
- for (i=0;i<mm->numUMBs;i++)
- {
- base = mm->UMBbase[i];
- __asm {
- mov ah,XMS_FREEUMB
- mov dx,[base]
- call [DWORD PTR XMSaddr]
- }
- }
-}
-
-//==========================================================================
-
-/*
-======================
-=
-= MML_UseSpace
-=
-= Marks a range of paragraphs as usable by the memory manager
-= This is used to mark space for the near heap, far heap, ems page frame,
-= and upper memory blocks
-=
-======================
-*/
-
-void MML_UseSpace(/*d*/word segstart, dword seglength, mminfo_t *mm)
-{
- mmblocktype huge *scan,huge *last;
- word segm;
- dword oldend;
- dword extra;
-
- scan = last = mm->mmhead;
- mm->mmrover = mm->mmhead; // reset rover to start of memory
-
-//
-// search for the block that contains the range of segments
-//
- while(scan->start+scan->length < segstart)
- {
- last = scan;
- scan = scan->next;
- }
-
- //find out how many blocks it spans!
- if(seglength>0xffffu)
- {
-// segm=seglength/0x4000u;
- segm=seglength/0xffffu;
- }
- else segm=1;
-
- //++++emsver stuff!
- if(segm>1/*extra>0xfffflu*/)
- {
- /*__asm
- {
- push ds
- mov ax,ds
- inc ax
- mov ds,ax
- }*/
-
-
-//MML_UseSpace(?segstart?, ?length?, mm);
-
- /*__asm
- {
- pop ds
- }*/
- //printf("MML_UseSpace: Segment spans two blocks!\n");
- }
-
-//
-// take the given range out of the block
-//
- oldend = scan->start + scan->length;
- extra = oldend - (segstart+seglength);
-/*
-printf("segm=%u ", segm);
-printf("ex=%lu ", extra);
-printf("start+seglen=%lu ", segstart+seglength);
-printf("len=%u ", scan->length);
-printf("segsta=%x ", segstart);
-printf("seglen=%lu\n", seglength);
-*/
-//segu:
-//++++todo: linked list of segment!
-//printf("segm=%lu\n", segm);
- if(segstart == scan->start)
- {
- last->next = scan->next; // unlink block
- MM_FreeBlock(scan, mm);
- scan = last;
- }
- else
- scan->length = segstart-scan->start; // shorten block
-
-// segm--;
-
- if(extra > 0)
- {
- MM_GetNewBlock(mm);
- mm->mmnew->next = scan->next;
- scan->next = mm->mmnew;
- mm->mmnew->start = segstart+seglength;
- mm->mmnew->length = extra;
- mm->mmnew->attributes = LOCKBIT;
- }//else if(segm>0) goto segu;
-
-}
-
-//==========================================================================
-
-/*
-====================
-=
-= MML_ClearBlock
-=
-= We are out of blocks, so free a purgable block
-=
-====================
-*/
-
-void MML_ClearBlock(mminfo_t *mm)
-{
- mmblocktype huge *scan,huge *last;
-
- scan = mm->mmhead->next;
-
- while(scan)
- {
- if(!(scan->attributes&LOCKBIT) && (scan->attributes&PURGEBITS))
- {
- MM_FreePtr(scan->useptr, mm);
- return;
- }
- scan = scan->next;
- }
-
- printf("MM_ClearBlock: No purgable blocks!\n");
-}
-
-
-//==========================================================================
-
-/*
-===================
-=
-= MM_Startup
-=
-= Grabs all space from turbo with malloc/farmalloc
-= Allocates bufferseg misc buffer
-=
-===================
-*/
-
-void MM_Startup(mminfo_t *mm, mminfotype *mmi)
-{
- int i;
- dword length,seglength;
- //dword length; word seglength;
- void huge *start;
- word segstart;//,endfree;
-
- if(mm->mmstarted)
- MM_Shutdown(mm);
-
- mm->mmstarted = true;
- mm->bombonerror = true;
-
-//
-// set up the linked list (everything in the free list;
-//
- //printf(" linked list making!\n");
- mm->mmhead = NULL;
- mm->mmfree = &(mm->mmblocks[0]);
- for(i=0;i<MAXBLOCKS-1;i++)
- {
- mm->mmblocks[i].next = &(mm->mmblocks[i+1]);
- }
- mm->mmblocks[i].next = NULL;
-
-//
-// locked block of all memory until we punch out free space
-//
- //printf(" newblock making!\n");
- MM_GetNewBlock(mm);
- mm->mmhead = mm->mmnew; // this will allways be the first node
- mm->mmnew->start = 0;
- mm->mmnew->length = 0xffff;
- mm->mmnew->attributes = LOCKBIT;
- mm->mmnew->next = NULL;
- mm->mmrover = mm->mmhead;
-
-//
-// get all available near conventional memory segments
-//
- length=coreleft();
- printf(" nearheap making!\n");
- //_heapgrow();
- //length=_memmax();//(dword)GetFreeSize();
- start = (void huge *)(mm->nearheap = malloc(length));
- length -= 16-(FP_OFF(start)&15);
- length -= SAVENEARHEAP;
- seglength = length / 16; // now in paragraphs
- segstart = FP_SEG(start)+(FP_OFF(start)+15)/16;
- MML_UseSpace(segstart,seglength, mm);
- mmi->nearheap = length;
- printf("start=%Fp segstart=%x seglen=%l len=%l\n", start, segstart, seglength, length);
- printf(" near heap ok!\n");
-
-//
-// get all available far conventional memory segments
-//
- length=farcoreleft();
- //printf(" farheap making!\n");
- //_fheapgrow();
- //length=(dword)GetFarFreeSize();//0xffffUL*4UL;
- //start = mm->farheap = halloc(length, 1);
- start = mm->farheap = _fmalloc(length);
- length -= 16-(FP_OFF(start)&15);
- length -= SAVEFARHEAP;
- seglength = length / 16; // now in paragraphs
- segstart = FP_SEG(start)+(FP_OFF(start)+15)/16;
- MML_UseSpace(segstart,seglength, mm);
- mmi->farheap = length;
- printf("start=%Fp segstart=%x seglen=%l len=%l\n", start, segstart, seglength, length);
- printf(" far heap ok!\n");
-
- mmi->mainmem = mmi->nearheap + mmi->farheap;
-
- getch();
-
-//
-// detect EMS and allocate up to 64K at page frame
-//
-printf(" EMS1\n");
-printf("\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"); //bug!
- mmi->EMSmem = 0;
- for(i = 1;i < _argc;i++)
- {
- if(US_CheckParm(_argv[i],ParmStringsexmm) == 0)
- goto emsskip; // param NOEMS
- }
-printf("\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"); //bug!
- if(MML_CheckForEMS())
- {
-printf(" EMS2\n");
-printf("\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"); //bug!
- MML_SetupEMS(mm); // allocate space
-printf(" EMS3\n");
-printf("\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"); //bug!
- //TODO: EMS4! AND EMS 3.2 MASSIVE DATA HANDLMENT!
- MML_UseSpace(mm->EMSpageframe,(MAPPAGES)*0x4000lu, mm);
-printf("\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"); //bug!
-printf(" EMS4\n");
- //if(mm->EMSVer<0x40)
- MM_MapEMS(mm, mmi); // map in used pages
- //else
- //MM_MapXEMS(mm, mmi); // map in used pages
- }
-
-//
-// detect XMS and get upper memory blocks
-//
-emsskip:
- mmi->XMSmem = 0;
- for(i = 1;i < _argc;i++)
- {
- if(US_CheckParm(_argv[i],ParmStringsexmm) == 0)
- goto xmsskip; // param NOXMS
- }
-printf("\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"); //bug!
- if(MML_CheckForXMS(mm))
- {
-printf("\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"); //bug!
-printf(" XMS!\n");
- MML_SetupXMS(mm, mmi); // allocate as many UMBs as possible
- }
-
-//
-// allocate the misc buffer
-//
-xmsskip:
- mm->mmrover = mm->mmhead; // start looking for space after low block
-
- MM_GetPtr(&(mm->bufferseg),BUFFERSIZE, mm, mmi);
-}
-
-//==========================================================================
-
-/*
-====================
-=
-= MM_Shutdown
-=
-= Frees all conventional, EMS, and XMS allocated
-=
-====================
-*/
-
-void MM_Shutdown(mminfo_t *mm)
-{
- if(!(mm->mmstarted))
- return;
-
- _ffree(mm->farheap); printf(" far freed\n");
- free(mm->nearheap); printf(" near freed\n");
- if(MML_CheckForEMS()){ MML_ShutdownEMS(mm); printf(" EMS freed\n"); }
- if(MML_CheckForXMS(mm)){ MML_ShutdownXMS(mm); printf(" XMS freed\n"); }
-}
-
-//==========================================================================
-
-/*
-====================
-=
-= MM_GetPtr
-=
-= Allocates an unlocked, unpurgable block
-=
-====================
-*/
-
-void MM_GetPtr(memptr *baseptr,dword size, mminfo_t *mm, mminfotype *mmi)
-{
- mmblocktype huge *scan,huge *lastscan,huge *endscan,huge *purge,huge *next;
- int search;
- unsigned needed,startseg;
-
- needed = (size+15)/16; // convert size from bytes to paragraphs
-
- MM_GetNewBlock(mm); // fill in start and next after a spot is found
- mm->mmnew->length = needed;
- mm->mmnew->useptr = baseptr;
- mm->mmnew->attributes = BASEATTRIBUTES;
-
- for(search = 0; search<3; search++)
- {
- //
- // first search: try to allocate right after the rover, then on up
- // second search: search from the head pointer up to the rover
- // third search: compress memory, then scan from start
- if(search == 1 && mm->mmrover == mm->mmhead)
- search++;
-
- switch(search)
- {
- case 0:
- lastscan = mm->mmrover;
- scan = mm->mmrover->next;
- endscan = NULL;
- break;
- case 1:
- lastscan = mm->mmhead;
- scan = mm->mmhead->next;
- endscan = mm->mmrover;
- break;
- case 2:
- MM_SortMem(mm);
- lastscan = mm->mmhead;
- scan = mm->mmhead->next;
- endscan = NULL;
- break;
- }
-
- startseg = lastscan->start + lastscan->length;
-
- while(scan != endscan)
- {
- if(scan->start - startseg >= needed)
- {
- //
- // got enough space between the end of lastscan and
- // the start of scan, so throw out anything in the middle
- // and allocate the new block
- //
- purge = lastscan->next;
- lastscan->next = mm->mmnew;
- mm->mmnew->start = *(unsigned *)baseptr = startseg;
- mm->mmnew->next = scan;
- while(purge != scan)
- { // free the purgable block
- next = purge->next;
- MM_FreeBlock(purge, mm);
- purge = next; // purge another if not at scan
- }
- mm->mmrover = mm->mmnew;
- return; // good allocation!
- }
-
- //
- // if this block is purge level zero or locked, skip past it
- //
- if((scan->attributes & LOCKBIT)
- || !(scan->attributes & PURGEBITS) )
- {
- lastscan = scan;
- startseg = lastscan->start + lastscan->length;
- }
-
-
- scan=scan->next; // look at next line
- }
- }
-
- if (mm->bombonerror)
- {
- printf(OUT_OF_MEM_MSG,(size-mmi->nearheap));
- exit(-5);
- }
- else
- mm->mmerror = true;
-}
-
-//==========================================================================
-
-/*
-====================
-=
-= MM_FreePtr
-=
-= Allocates an unlocked, unpurgable block
-=
-====================
-*/
-
-void MM_FreePtr(memptr *baseptr, mminfo_t *mm)
-{
- mmblocktype huge *scan,huge *last;
-
- last = mm->mmhead;
- scan = last->next;
-
- if(baseptr == mm->mmrover->useptr) // removed the last allocated block
- mm->mmrover = mm->mmhead;
-
- while(scan->useptr != baseptr && scan)
- {
- last = scan;
- scan = scan->next;
- }
-
- if(!scan)
- {
- printf("MM_FreePtr: Block not found!\n");
- return;
- }
-
- last->next = scan->next;
-
- MM_FreeBlock(scan, mm);
-}
-//==========================================================================
-
-/*
-=====================
-=
-= MM_SetPurge
-=
-= Sets the purge level for a block (locked blocks cannot be made purgable)
-=
-=====================
-*/
-
-void MM_SetPurge(memptr *baseptr, int purge, mminfo_t *mm)
-{
- mmblocktype huge *start;
-
- start = mm->mmrover;
-
- do
- {
- if(mm->mmrover->useptr == baseptr)
- break;
-
- mm->mmrover = mm->mmrover->next;
-
- if(!mm->mmrover)
- mm->mmrover = mm->mmhead;
- else if(mm->mmrover == start)
- {
- printf("MM_SetPurge: Block not found!");
- return;
- }
-
- } while(1);
-
- mm->mmrover->attributes &= ~PURGEBITS;
- mm->mmrover->attributes |= purge;
-}
-
-//==========================================================================
-
-/*
-=====================
-=
-= MM_SetLock
-=
-= Locks / unlocks the block
-=
-=====================
-*/
-
-void MM_SetLock(memptr *baseptr, boolean locked, mminfo_t *mm)
-{
- mmblocktype huge *start;
-
- start = mm->mmrover;
-
- do
- {
- if(mm->mmrover->useptr == baseptr)
- break;
-
- mm->mmrover = mm->mmrover->next;
-
- if(!mm->mmrover)
- mm->mmrover = mm->mmhead;
- else if(mm->mmrover == start)
- {
- printf("MM_SetLock: Block not found!");
- return;
- }
-
- } while(1);
-
- mm->mmrover->attributes &= ~LOCKBIT;
- mm->mmrover->attributes |= locked*LOCKBIT;
-}
-
-//==========================================================================
-
-/*
-=====================
-=
-= MM_SortMem
-=
-= Throws out all purgable stuff and compresses movable blocks
-=
-=====================
-*/
-
-void MM_SortMem(mminfo_t *mm)
-{
- mmblocktype huge *scan,huge *last,huge *next;
- unsigned start,length,source,dest,oldborder;
- int playing;
-
- //
- // lock down a currently playing sound
- //
-/*++++ playing = SD_SoundPlaying ();
- if(playing)
- {
- switch (SoundMode)
- {
- case sdm_PC:
- playing += STARTPCSOUNDS;
- break;
- case sdm_AdLib:
- playing += STARTADLIBSOUNDS;
- break;
- }
- MM_SetLock(&(memptr)audiosegs[playing],true);
- }
-
-
- SD_StopSound();*/
-// oldborder = bordercolor;
-// VW_ColorBorder (15);
-
- if(beforesort)
- beforesort();
-
- scan = mm->mmhead;
-
- last = NULL; // shut up compiler warning
-
- while(scan)
- {
- if(scan->attributes & LOCKBIT)
- {
- //
- // block is locked, so try to pile later blocks right after it
- //
- start = scan->start + scan->length;
- }
- else
- {
- if(scan->attributes & PURGEBITS)
- {
- //
- // throw out the purgable block
- //
- next = scan->next;
- MM_FreeBlock(scan, mm);
- last->next = next;
- scan = next;
- continue;
- }
- else
- {
- //
- // push the non purgable block on top of the last moved block
- //
- if(scan->start != start)
- {
- length = scan->length;
- source = scan->start;
- dest = start;
- while(length > 0xf00)
- {
- movedata(source,0,dest,0,0xf00*16);
- length -= 0xf00;
- source += 0xf00;
- dest += 0xf00;
- }
- movedata(source,0,dest,0,length*16);
-
- scan->start = start;
- *(unsigned *)scan->useptr = start;
- }
- start = scan->start + scan->length;
- }
- }
-
- last = scan;
- scan = scan->next; // go to next block
- }
-
- mm->mmrover = mm->mmhead;
-
- if(aftersort)
- aftersort();
-
-// VW_ColorBorder (oldborder);
-
-/*++++ if(playing)
- MM_SetLock(&(memptr)audiosegs[playing],false);*/
-}
-
-
-//==========================================================================
-
-//****#if 0
-/*
-=====================
-=
-= MM_ShowMemory
-=
-=====================
-*/
-
-void MM_ShowMemory(/*page_t *page, */mminfo_t *mm)
-{
- mmblocktype huge *scan;
- word color,temp;
- long end,owner;
- word chx,chy;
- byte scratch[160],str[16];
-
-//**** VW_SetDefaultColors();
-//**** VW_SetLineWidth(40);
-//++++mh temp = bufferofs;
-//++++mh bufferofs = 0;
-//**** VW_SetScreen (0,0);
-
- scan = mm->mmhead;
-
- end = -1;
-
-CA_OpenDebug ();
-
- chx=0;
- chy=0;
-
- while(scan)
- {
- if(scan->attributes & PURGEBITS)
- color = 5; // dark purple = purgable
- else
- color = 9; // medium blue = non purgable
- if(scan->attributes & LOCKBIT)
- color = 12; // red = locked
- if(scan->start<=end)
- {
- //printf(");
- write(debughandle,"\nMM_ShowMemory: Memory block order currupted!\n",strlen("\nMM_ShowMemory: Memory block order currupted!\n"));
- //modexprint(&page, chx, chy, 1, 0, 24, "\nMM_ShowMemory: Memory block order currupted!\n");
- return;
- }
- end = scan->start+scan->length-1;
- chy = scan->start/320;
- chx = scan->start%320;
- //modexhlin(page, scan->start, (unsigned)end, chy, color);
- //for(chx=scan->start;chx+4>=(word)end;chx+=4)
- //{
-//++++ modexClearRegion(page, chx, chy, 4, 4, color);
- //}
-
-//++++ VW_Hlin(scan->start,(unsigned)end,0,color);
-
-//++++ VW_Plot(scan->start,0,15);
-//++++ modexClearRegion(page, chx, chy, 4, 4, 15);
- if(scan->next->start > end+1)
-//++++ VW_Hlin(end+1,scan->next->start,0,0); // black = free
- //for(chx=scan->next->start;chx+4>=(word)end+1;chx+=4)
- //{
-//++++ chx+=scan->next->start;
-//++++ modexClearRegion(page, chx, chy, 4, 4, 2);
- //}
- //modexhlin(page, end+1,scan->next->start, chy, 0);
-
-/*
- end = scan->length-1;
- y = scan->start/320;
- x = scan->start%320;
- VW_Hlin(x,x+end,y,color);
- VW_Plot(x,y,15);
- if (scan->next && scan->next->start > end+1)
- VW_Hlin(x+end+1,x+(scan->next->start-scan->start),y,0); // black = free
-*/
-
-//****#if 0
-printf("\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"); //bug!
-strcpy(scratch,"Seg:");
-ultoa (scan->start,str,16);
-strcat (scratch,str);
-strcat (scratch,"\tSize:");
-ultoa ((dword)scan->length,str,10);
-strcat (scratch,str);
-strcat (scratch,"\tOwner:0x");
-owner = (unsigned)scan->useptr;
-ultoa (owner,str,16);
-strcat (scratch,str);
-strcat (scratch,"\n");
-write(debughandle,scratch,strlen(scratch));
-//modexprint(page, chx, chy, 1, 0, 24, &scratch);
-//++++chy+=4;
-//fprintf(stdout, "%s", scratch);
-//****#endif
-
- scan = scan->next;
- }
-
-CA_CloseDebug ();
-
-//++++mh IN_Ack();
-//**** VW_SetLineWidth(64);
-//++++mh bufferofs = temp;
-}
-//****#endif
-
-//==========================================================================
-
-/*
-=====================
-=
-= MM_DumpData
-=
-=====================
-*/
-
-void MM_DumpData(mminfo_t *mm)
-{
- mmblocktype far *scan,far *best;
- long lowest,oldlowest;
- word owner;
- byte lock,purge;
- FILE *dumpfile;
-
-
- //++++free(mm->nearheap);
- dumpfile = fopen ("mmdump.16","w");
- if (!dumpfile){
- printf("MM_DumpData: Couldn't open MMDUMP.16!\n");
- return;
- }
-
- lowest = -1;
- do
- {
- oldlowest = lowest;
- lowest = 0xffff;
-
- scan = mm->mmhead;
- while (scan)
- {
- owner = (word)scan->useptr;
-
- if (owner && owner<lowest && owner > oldlowest)
- {
- best = scan;
- lowest = owner;
- }
-
- scan = scan->next;
- }
-
- if (lowest != 0xffff)
- {
- if (best->attributes & PURGEBITS)
- purge = 'P';
- else
- purge = '-';
- if (best->attributes & LOCKBIT)
- lock = 'L';
- else
- lock = '-';
- fprintf (dumpfile,"0x%p (%c%c) = %u\n"
- ,(word)lowest,lock,purge,best->length);
- }
-
- } while (lowest != 0xffff);
-
- fclose(dumpfile);
- printf("MMDUMP.16 created.\n");
-}
-
-//==========================================================================
-
-
-/*
-======================
-=
-= MM_UnusedMemory
-=
-= Returns the total free space without purging
-=
-======================
-*/
-
-dword MM_UnusedMemory(mminfo_t *mm)
-{
- dword free;
- mmblocktype huge *scan;
-
- free = 0;
- scan = mm->mmhead;
-
- while(scan->next)
- {
- free += scan->next->start - (scan->start + scan->length);
- scan = scan->next;
- }
-
-// return free*16l;
- return free;
-}
-
-//==========================================================================
-
-
-/*
-======================
-=
-= MM_TotalFree
-=
-= Returns the total free space with purging
-=
-======================
-*/
-
-dword MM_TotalFree(mminfo_t *mm)
-{
- dword free;
- mmblocktype huge *scan;
-
- free = 0;
- scan = mm->mmhead;
-
- while(scan->next)
- {
- if((scan->attributes&PURGEBITS) && !(scan->attributes&LOCKBIT))
- free += scan->length;
- free += scan->next->start - (scan->start + scan->length);
- scan = scan->next;
- }
-
-// return free*16l;
- return free;
-}
-
-//==========================================================================
-
-/*
-=====================
-=
-= MM_Report
-=
-=====================
-*/
-
-void MM_Report(/*page_t *page, */mminfo_t *mm, mminfotype *mmi)
-{
- if(MML_CheckForEMS())
- {
- printf("EMM v%x.%x available\n", mm->EMSVer>>4,mm->EMSVer&0x0F);
- printf("totalEMSpages=%u\n", mm->totalEMSpages);
- printf("freeEMSpages=%u\n", mm->freeEMSpages);
- printf("EMSpageframe=%x\n", mm->EMSpageframe);
- }
- if(MML_CheckForXMS(mm)) printf("XMSaddr=%X\n", *XMSaddr);
- printf("near=%lu\n", mmi->nearheap);
- printf("far=%lu\n", mmi->farheap);
- printf("EMSmem=%lu\n", mmi->EMSmem);
- printf("XMSmem=%lu\n", mmi->XMSmem);
- printf("mainmem=%lu\n", mmi->mainmem);
- printf("UnusedMemory=%lu\n", MM_UnusedMemory(mm));
- printf("TotalFree=%lu\n", MM_TotalFree(mm));
- //mmi->nearheap+mmi->farheap+
- printf("TotalUsed=%lu\n", mmi->mainmem+mmi->EMSmem+mmi->XMSmem);//+);
-// printf("\n");
-// printf("UnusedMemory=%lu kb\n", MM_UnusedMemory()/10248);
-// printf("TotalFree=%lu kb\n", MM_TotalFree()/10248);
-}
-
-//==========================================================================
-
-/*
-=====================
-=
-= MM_EMSerr
-=
-=====================
-*/
-
-void MM_EMSerr(byte *stri, byte err)
-{
- //Returns a text string describing the error code in EMS.Error.
- switch(err)
- {
- case 0x0:
- strcat(stri, "successful");
- break;
- case 0x80:
- strcat(stri, "internal error");
- break;
- case 0x81:
- strcat(stri, "hardware malfunction");
- break;
- case 0x82:
- strcat(stri, "busy .. retry later");
- break;
- case 0x83:
- strcat(stri, "invalid handle");
- break;
- case 0x84:
- strcat(stri, "undefined function requested by application");
- break;
- case 0x85:
- strcat(stri, "no more handles available");
- break;
- case 0x86:
- strcat(stri, "error in save or restore of mapping context");
- break;
- case 0x87:
- strcat(stri, "insufficient memory pages in system");
- break;
- case 0x88:
- strcat(stri, "insufficient memory pages available");
- break;
- case 0x89:
- strcat(stri, "zero pages requested");
- break;
- case 0x8A:
- strcat(stri, "invalid logical page number encountered");
- break;
- case 0x8B:
- strcat(stri, "invalid physical page number encountered");
- break;
- case 0x8C:
- strcat(stri, "page-mapping hardware state save area is full");
- break;
- case 0x8D:
- strcat(stri, "save of mapping context failed");
- break;
- case 0x8E:
- strcat(stri, "restore of mapping context failed");
- break;
- case 0x8F:
- strcat(stri, "undefined subfunction");
- break;
- case 0x90:
- strcat(stri, "undefined attribute type");
- break;
- case 0x91:
- strcat(stri, "feature not supported");
- break;
- case 0x92:
- strcat(stri, "successful, but a portion of the source region has been overwritten");
- break;
- case 0x93:
- strcat(stri, "length of source or destination region exceeds length of region allocated to either source or destination handle");
- break;
- case 0x94:
- strcat(stri, "conventional and expanded memory regions overlap");
- break;
- case 0x95:
- strcat(stri, "offset within logical page exceeds size of logical page");
- break;
- case 0x96:
- strcat(stri, "region length exceeds 1 MB");
- break;
- case 0x97:
- strcat(stri, "source and destination EMS regions have same handle and overlap");
- break;
- case 0x98:
- strcat(stri, "memory source or destination type undefined");
- break;
- case 0x9A:
- strcat(stri, "specified alternate map register or DMA register set not supported");
- break;
- case 0x9B:
- strcat(stri, "all alternate map register or DMA register sets currently allocated");
- break;
- case 0x9C:
- strcat(stri, "alternate map register or DMA register sets not supported");
- break;
- case 0x9D:
- strcat(stri, "undefined or unallocated alternate map register or DMA register set");
- break;
- case 0x9E:
- strcat(stri, "dedicated DMA channels not supported");
- break;
- case 0x9F:
- strcat(stri, "specified dedicated DMA channel not supported");
- break;
- case 0xA0:
- strcat(stri, "no such handle name");
- break;
- case 0xA1:
- strcat(stri, "a handle found had no name, or duplicate handle name");
- break;
- case 0xA2:
- strcat(stri, "attempted to wrap around 1M conventional address space");
- break;
- case 0xA3:
- strcat(stri, "source array corrupted");
- break;
- case 0xA4:
- strcat(stri, "operating system denied access");
- break;
- default:
- strcat(stri, "undefined error");
- }
-}
-
-//==========================================================================
-
-/*
-=====================
-=
-= MM_BombOnError
-=
-=====================
-*/
-
-void MM_BombOnError(boolean bomb, mminfo_t *mm)
-{
- mm->bombonerror = bomb;
-}
-
-void MM_GetNewBlock(mminfo_t *mm)
-{
- if(!mm->mmfree)
- MML_ClearBlock(mm);
- mm->mmnew=mm->mmfree;
- mm->mmfree=mm->mmfree->next;
- //if(!(mm->mmnew=mm->mmfree))
- //{
- //printf("MM_GETNEWBLOCK: No free blocks!");
-// return;
- //}
- //mm->mmfree=mm->mmfree->next;
-}
-
-void MM_FreeBlock(mmblocktype *x, mminfo_t *mm)
-{
- x->useptr=NULL;
- x->next=mm->mmfree;
- mm->mmfree=x;
-}
-
-/*void MM_seguin(void)
-{
- __asm
- {
- push ds
- mov ax,ds
- inc ax
- mov ds,ax
- }
-}
-
-void MM_segude(void)
-{
- __asm
- {
- pop ds
- }
-}*/
-
-/*
-pull data from far and put it into ds var
-mov ax,es:si
-mov x,ax
-*/
-/*
-ss stack segment
-sp top of stack
-bp bottem of stack
-*/
+++ /dev/null
-/* Catacomb Apocalypse Source Code
- * Copyright (C) 1993-2014 Flat Rock Software
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License along
- * with this program; if not, write to the Free Software Foundation, Inc.,
- * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
- */
-
-// ID_MM.H
-
-#ifndef __16_EXMM__
-#define __16_EXMM__
-
-#include <string.h>
-#include <malloc.h>
-//#include <bios.h>
-#include "16_head.h"
-//#include "modex16.h"
-//#include "src/lib/16_ca.h"
-//++++mh #include "src/lib/16_in.h"
-
-#ifdef __DEBUG__ // 1 == Debug/Dev ; 0 == Production/final
-#define OUT_OF_MEM_MSG "MM_GetPtr: Out of memory!\nYou were short :%lu bytes"
-#else
-#define OUT_OF_MEM_MSG "\npee\n"
-#endif
-
-
-#define SAVENEARHEAP 0x200 // space to leave in data segment
-#define SAVEFARHEAP 0x400 // space to leave in far heap
-
-#define BUFFERSIZE 0x1000 // miscelanious, allways available buffer
-
-#define MAXBLOCKS 720
-
-
-
-//--------
-
-#define EMS_INT 0x67
-
-#define EMS_STATUS 0x40
-#define EMS_GETFRAME 0x41
-#define EMS_GETPAGES 0x42
-#define EMS_ALLOCPAGES 0x43
-#define EMS_MAPPAGE 0x44
-#define EMS_MAPXPAGE 0x50
-#define EMS_FREEPAGES 0x45
-#define EMS_VERSION 0x46
-
-//--------
-
-#define XMS_VERSION 0x00
-
-#define XMS_ALLOCHMA 0x01
-#define XMS_FREEHMA 0x02
-
-#define XMS_GENABLEA20 0x03
-#define XMS_GDISABLEA20 0x04
-#define XMS_LENABLEA20 0x05
-#define XMS_LDISABLEA20 0x06
-#define XMS_QUERYA20 0x07
-
-#define XMS_QUERYREE 0x08
-#define XMS_ALLOC 0x09
-#define XMS_FREE 0x0A
-#define XMS_MOVE 0x0B
-#define XMS_LOCK 0x0C
-#define XMS_UNLOCK 0x0D
-#define XMS_GETINFO 0x0E
-#define XMS_RESIZE 0x0F
-
-#define XMS_ALLOCUMB 0x10
-#define XMS_FREEUMB 0x11
-
-//==========================================================================
-
-typedef struct
-{
- dword nearheap,farheap,EMSmem,XMSmem,mainmem;
- //__segment segu;
-} mminfotype;
-
-//==========================================================================
-
-extern void (* beforesort) (void);
-extern void (* aftersort) (void);
-extern void (* XMSaddr) (void); // far pointer to XMS driver
-
-//==========================================================================
-
-/*
-=============================================================================
-
- LOCAL INFO
-
-=============================================================================
-*/
-
-#define LOCKBIT 0x80 // if set in attributes, block cannot be moved
-#define PURGEBITS 3 // 0-3 level, 0= unpurgable, 3= purge first
-#define PURGEMASK 0xfffc
-#define BASEATTRIBUTES 0 // unlocked, non purgable
-
-#define MAXUMBS 12
-#define MAPPAGES 4//mm->EMSpagesmapped
-
-typedef struct mmblockstruct
-{
- //word start,length;
- word start; dword length;
- unsigned attributes;
- memptr *useptr; // pointer to the segment start
- struct mmblockstruct huge *next;
-} mmblocktype;
-
-
-typedef struct
-{
- memptr bufferseg;
- boolean mmstarted, bombonerror, mmerror;
- void huge *farheap;
- void *nearheap;
- //byte EMS_status;
- unsigned totalEMSpages,freeEMSpages,EMSpageframe,EMSpagesmapped,EMShandle;
- unsigned int EMSVer;
- word numUMBs,UMBbase[MAXUMBS];
- //dword numUMBs,UMBbase[MAXUMBS];
- mmblocktype huge mmblocks[MAXBLOCKS],huge *mmhead,huge *mmfree,huge *mmrover,huge *mmnew;
-} mminfo_t;
-
-/*
-=============================================================================
-
- GLOBAL VARIABLES
-
-=============================================================================
-*/
-
-
-/*
-=============================================================================
-
- LOCAL VARIABLES
-
-=============================================================================
-*/
-
-//==========================================================================
-
-boolean MML_CheckForEMS(void);
-byte MML_SetupEMS(mminfo_t *mm);
-void MML_ShutdownEMS(mminfo_t *mm);
-byte MM_MapEMS(mminfo_t *mm, mminfotype *mmi);
-byte MM_MapXEMS(mminfo_t *mm, mminfotype *mmi);
-boolean MML_CheckForXMS(mminfo_t *mm);
-void MML_SetupXMS(mminfo_t *mm, mminfotype *mmi);
-void MML_ShutdownXMS(mminfo_t *mm);
-void MML_UseSpace(/*d*/word segstart, dword seglength, mminfo_t *mm);
-void MML_ClearBlock(mminfo_t *mm);
-
-void MM_Startup(mminfo_t *mm, mminfotype *mmi);
-void MM_Shutdown(mminfo_t *mm);
-
-void MM_GetPtr(memptr *baseptr,dword size, mminfo_t *mm, mminfotype *mmi);
-void MM_FreePtr(memptr *baseptr, mminfo_t *mm);
-void MM_SetPurge(memptr *baseptr, int purge, mminfo_t *mm);
-void MM_SetLock(memptr *baseptr, boolean locked, mminfo_t *mm);
-void MM_SortMem(mminfo_t *mm);
-void MM_ShowMemory(/*page_t *page, */mminfo_t *mm);
-void MM_DumpData(mminfo_t *mm);
-dword MM_UnusedMemory(mminfo_t *mm);
-dword MM_TotalFree(mminfo_t *mm);
-void MM_Report(/*page_t *page, */mminfo_t *mm, mminfotype *mmi);
-static void MM_EMSerr(byte *stri, byte err);
-void MM_BombOnError(boolean bomb, mminfo_t *mm);
-void MM_GetNewBlock(mminfo_t *mm);
-void MM_FreeBlock(mmblocktype *x, mminfo_t *mm);
-
-//==========================================================================
-
-#endif
+++ /dev/null
-/* Catacomb Apocalypse 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
-#include "ID_STRS.H"\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
-= 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."EXT,\r
- O_RDONLY | O_BINARY, S_IREAD)) == -1)\r
- Quit ("Can't open "GREXT"DICT."EXT"!");\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."EXT,\r
- O_RDONLY | O_BINARY, S_IREAD)) == -1)\r
- Quit ("Can't open "GREXT"HEAD."EXT"!");\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."EXT, O_RDONLY | O_BINARY);\r
- if (grhandle == -1)\r
- Quit ("Cannot open "GREXT"GRAPH."EXT"!");\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."EXT,\r
- O_RDONLY | O_BINARY, S_IREAD)) == -1)\r
- Quit ("Can't open MAPHEAD."EXT"!");\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."EXT,\r
- O_RDONLY | O_BINARY, S_IREAD)) == -1)\r
- Quit ("Can't open GAMEMAPS."EXT"!");\r
-#else\r
- if ((maphandle = open("MAPTEMP."EXT,\r
- O_RDONLY | O_BINARY, S_IREAD)) == -1)\r
- Quit ("Can't open MAPTEMP."EXT"!");\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."EXT,\r
- O_RDONLY | O_BINARY, S_IREAD)) == -1)\r
- Quit ("Can't open AUDIOHED."EXT"!");\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."EXT,\r
- O_RDONLY | O_BINARY, S_IREAD)) == -1)\r
- Quit ("Can't open AUDIOT."EXT"!");\r
-#else\r
- if ((audiohandle = open("AUDIO."EXT,\r
- O_RDONLY | O_BINARY, S_IREAD)) == -1)\r
- Quit ("Can't open AUDIO."EXT"!");\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
-// MDM begin - (GAMERS EDGE)\r
-//\r
- if (!FindFile("AUDIO."EXT,NULL,2))\r
- Quit("CA_Startup(): Can't find audio files.");\r
-//\r
-// MDM end\r
-\r
-#ifndef NOAUDIO\r
- CAL_SetupAudioFile ();\r
-#endif\r
-\r
-// MDM begin - (GAMERS EDGE)\r
-//\r
- if (!FindFile("GAMEMAPS."EXT,NULL,1))\r
- Quit("CA_Startup(): Can't find level files.");\r
-//\r
-// MDM end\r
-\r
-#ifndef NOMAPS\r
- CAL_SetupMapFile ();\r
-#endif\r
-\r
-// MDM begin - (GAMERS EDGE)\r
-//\r
- if (!FindFile("EGAGRAPH."EXT,NULL,2))\r
- Quit("CA_Startup(): Can't find graphics files.");\r
-//\r
-// MDM end\r
-\r
-#ifndef NOGRAPHICS\r
- CAL_SetupGrFile ();\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
-// MDM begin - (GAMERS EDGE)\r
-//\r
- if (!FindFile("AUDIO."EXT,NULL,2))\r
- Quit("CA_CacheAudioChunk(): Can't find audio files.");\r
-//\r
-// MDM end\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
-boolean static dothemask;\r
-\r
-void CAL_ShiftSprite (unsigned segment,unsigned source,unsigned dest,\r
- unsigned width, unsigned height, unsigned pixshift, boolean domask)\r
-{\r
-\r
- sheight = height; // because we are going to reassign bp\r
- swidth = width;\r
- dothemask = domask;\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
-asm cmp [ss:dothemask],0\r
-asm je skipmask\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
-skipmask:\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,true);\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,true);\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,true);\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,true);\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
-= 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
-// MDM begin - (GAMERS EDGE)\r
-//\r
- if (!FindFile("EGAGRAPH."EXT,NULL,2))\r
- Quit("CA_CacheGrChunk(): Can't find graphics files.");\r
-//\r
-// MDM end\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
-// MDM begin - (GAMERS EDGE)\r
-//\r
- if (!FindFile("GAMEMAPS."EXT,NULL,1))\r
- Quit("CA_CacheMap(): Can't find level files.");\r
-//\r
-// MDM end\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
- 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
-\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
-// MDM begin - (GAMERS EDGE)\r
-//\r
- if (!FindFile("EGAGRAPH."EXT,NULL,2))\r
- Quit("CA_CacheMarks(): Can't find graphics files.");\r
-//\r
-// MDM end\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
+++ /dev/null
-/* Catacomb Apocalypse 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.H\r
-\r
-#ifndef __TYPES__\r
-#include "ID_TYPES.H"\r
-#endif\r
-\r
-#ifndef __ID_MM__\r
-#include "ID_MM.H"\r
-#endif\r
-\r
-#ifndef __ID_GLOB__\r
-#include "ID_GLOB.H"\r
-#endif\r
-\r
-#define __ID_CA__\r
-\r
-//===========================================================================\r
-\r
-//#define NOMAPS\r
-//#define NOGRAPHICS\r
-//#define NOAUDIO\r
-\r
-#define MAPHEADERLINKED\r
-#define GRHEADERLINKED\r
-#define AUDIOHEADERLINKED\r
-\r
-#define NUMMAPS 39\r
-#define MAPPLANES 3\r
-\r
-//===========================================================================\r
-\r
-typedef struct\r
-{\r
- long planestart[3];\r
- unsigned planelength[3];\r
- unsigned width,height;\r
- char name[16];\r
-} maptype;\r
-\r
-//===========================================================================\r
-\r
-extern byte _seg *tinf;\r
-extern int mapon;\r
-\r
-extern unsigned _seg *mapsegs[3];\r
-extern maptype _seg *mapheaderseg[NUMMAPS];\r
-extern byte _seg *audiosegs[NUMSNDCHUNKS];\r
-extern void _seg *grsegs[NUMCHUNKS];\r
-\r
-extern byte far grneeded[NUMCHUNKS];\r
-extern byte ca_levelbit,ca_levelnum;\r
-\r
-extern char *titleptr[8];\r
-\r
-extern int profilehandle,debughandle;\r
-\r
-//\r
-// hooks for custom cache dialogs\r
-//\r
-extern void (*drawcachebox) (char *title, unsigned numcache);\r
-extern void (*updatecachebox) (void);\r
-extern void (*finishcachebox) (void);\r
-\r
-//===========================================================================\r
-\r
-// just for the score box reshifting\r
-\r
-void CAL_ShiftSprite (unsigned segment,unsigned source,unsigned dest,\r
- unsigned width, unsigned height, unsigned pixshift, boolean domask);\r
-\r
-//===========================================================================\r
-\r
-void CA_OpenDebug (void);\r
-void CA_CloseDebug (void);\r
-boolean CA_FarRead (int handle, byte far *dest, long length);\r
-boolean CA_FarWrite (int handle, byte far *source, long length);\r
-boolean CA_ReadFile (char *filename, memptr *ptr);\r
-boolean CA_LoadFile (char *filename, memptr *ptr);\r
-\r
-long CA_RLEWCompress (unsigned huge *source, long length, unsigned huge *dest,\r
- unsigned rlewtag);\r
-\r
-void CA_RLEWexpand (unsigned huge *source, unsigned huge *dest,long length,\r
- unsigned rlewtag);\r
-\r
-void CA_Startup (void);\r
-void CA_Shutdown (void);\r
-\r
-void CA_CacheAudioChunk (int chunk);\r
-void CA_LoadAllSounds (void);\r
-\r
-void CA_UpLevel (void);\r
-void CA_DownLevel (void);\r
-\r
-void CA_SetAllPurge (void);\r
-\r
-void CA_ClearMarks (void);\r
-void CA_ClearAllMarks (void);\r
-\r
-#define CA_MarkGrChunk(chunk) grneeded[chunk]|=ca_levelbit\r
-\r
-void CA_CacheGrChunk (int chunk);\r
-void CA_CacheMap (int mapnum);\r
-\r
-void CA_CacheMarks (char *title);\r
-\r
+++ /dev/null
-/* Catacomb Apocalypse 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
-// NEWMM.C\r
-\r
-/*\r
-=============================================================================\r
-\r
- ID software memory manager\r
- --------------------------\r
-\r
-Primary coder: John Carmack\r
-\r
-RELIES ON\r
----------\r
-Quit (char *error) function\r
-\r
-\r
-WORK TO DO\r
-----------\r
-MM_SizePtr to change the size of a given pointer\r
-\r
-Multiple purge levels utilized\r
-\r
-EMS / XMS unmanaged routines\r
-\r
-=============================================================================\r
-*/\r
-\r
-#include "ID_HEADS.H"\r
-#pragma hdrstop\r
-\r
-#pragma warn -pro\r
-#pragma warn -use\r
-\r
-\r
-#if 0 // 1 == Debug/Dev ; 0 == Production/final\r
-\r
-#define OUT_OF_MEM_MSG "MM_GetPtr: Out of memory!\nYou were short :%ld bytes"\r
-\r
-#else\r
-\r
-\r
-#define OUT_OF_MEM_MSG "\n" \\r
- "You need more memory to run CATACOMB APOCALYPSE. Read the INSTRUCTION\n" \\r
- "section of the START program for tips on getting more memory.\n"\r
-#endif\r
-\r
-\r
-/*\r
-=============================================================================\r
-\r
- LOCAL INFO\r
-\r
-=============================================================================\r
-*/\r
-\r
-#define LOCKBIT 0x80 // if set in attributes, block cannot be moved\r
-#define PURGEBITS 3 // 0-3 level, 0= unpurgable, 3= purge first\r
-#define PURGEMASK 0xfffc\r
-#define BASEATTRIBUTES 0 // unlocked, non purgable\r
-\r
-#define MAXUMBS 10\r
-\r
-typedef struct mmblockstruct\r
-{\r
- unsigned start,length;\r
- unsigned attributes;\r
- memptr *useptr; // pointer to the segment start\r
- struct mmblockstruct far *next;\r
-} mmblocktype;\r
-\r
-\r
-//#define GETNEWBLOCK {if(!(mmnew=mmfree))Quit("MM_GETNEWBLOCK: No free blocks!")\\r
-// ;mmfree=mmfree->next;}\r
-\r
-#define GETNEWBLOCK {if(!mmfree)MML_ClearBlock();mmnew=mmfree;mmfree=mmfree->next;}\r
-\r
-#define FREEBLOCK(x) {*x->useptr=NULL;x->next=mmfree;mmfree=x;}\r
-\r
-/*\r
-=============================================================================\r
-\r
- GLOBAL VARIABLES\r
-\r
-=============================================================================\r
-*/\r
-\r
-mminfotype mminfo;\r
-memptr bufferseg;\r
-boolean mmerror;\r
-\r
-void (* beforesort) (void);\r
-void (* aftersort) (void);\r
-\r
-/*\r
-=============================================================================\r
-\r
- LOCAL VARIABLES\r
-\r
-=============================================================================\r
-*/\r
-\r
-boolean mmstarted;\r
-\r
-void far *farheap;\r
-void *nearheap;\r
-\r
-mmblocktype far mmblocks[MAXBLOCKS]\r
- ,far *mmhead,far *mmfree,far *mmrover,far *mmnew;\r
-\r
-boolean bombonerror;\r
-\r
-unsigned totalEMSpages,freeEMSpages,EMSpageframe,EMSpagesmapped,EMShandle;\r
-\r
-void (* XMSaddr) (void); // far pointer to XMS driver\r
-\r
-unsigned numUMBs,UMBbase[MAXUMBS];\r
-\r
-//==========================================================================\r
-\r
-//\r
-// local prototypes\r
-//\r
-\r
-boolean MML_CheckForEMS (void);\r
-void MML_ShutdownEMS (void);\r
-void MM_MapEMS (void);\r
-boolean MML_CheckForXMS (void);\r
-void MML_ShutdownXMS (void);\r
-void MML_UseSpace (unsigned segstart, unsigned seglength);\r
-void MML_ClearBlock (void);\r
-\r
-//==========================================================================\r
-\r
-/*\r
-======================\r
-=\r
-= MML_CheckForEMS\r
-=\r
-= Routine from p36 of Extending DOS\r
-=\r
-=======================\r
-*/\r
-\r
-char emmname[9] = "EMMXXXX0";\r
-\r
-boolean MML_CheckForEMS (void)\r
-{\r
-asm mov dx,OFFSET emmname[0]\r
-asm mov ax,0x3d00\r
-asm int 0x21 // try to open EMMXXXX0 device\r
-asm jc error\r
-\r
-asm mov bx,ax\r
-asm mov ax,0x4400\r
-\r
-asm int 0x21 // get device info\r
-asm jc error\r
-\r
-asm and dx,0x80\r
-asm jz error\r
-\r
-asm mov ax,0x4407\r
-\r
-asm int 0x21 // get status\r
-asm jc error\r
-asm or al,al\r
-asm jz error\r
-\r
-asm mov ah,0x3e\r
-asm int 0x21 // close handle\r
-asm jc error\r
-\r
-//\r
-// EMS is good\r
-//\r
- return true;\r
-\r
-error:\r
-//\r
-// EMS is bad\r
-//\r
- return false;\r
-}\r
-\r
-\r
-/*\r
-======================\r
-=\r
-= MML_SetupEMS\r
-=\r
-=======================\r
-*/\r
-\r
-void MML_SetupEMS (void)\r
-{\r
- char str[80],str2[10];\r
- unsigned error;\r
-\r
- totalEMSpages = freeEMSpages = EMSpageframe = EMSpagesmapped = 0;\r
-\r
-asm {\r
- mov ah,EMS_STATUS\r
- int EMS_INT // make sure EMS hardware is present\r
- or ah,ah\r
- jnz error\r
-\r
- mov ah,EMS_VERSION\r
- int EMS_INT\r
- or ah,ah\r
- jnz error\r
- cmp al,0x32 // only work on ems 3.2 or greater\r
- jb error\r
-\r
- mov ah,EMS_GETFRAME\r
- int EMS_INT // find the page frame address\r
- or ah,ah\r
- jnz error\r
- mov [EMSpageframe],bx\r
-\r
- mov ah,EMS_GETPAGES\r
- int EMS_INT // find out how much EMS is there\r
- or ah,ah\r
- jnz error\r
- mov [totalEMSpages],dx\r
- mov [freeEMSpages],bx\r
- or bx,bx\r
- jz noEMS // no EMS at all to allocate\r
-\r
- cmp bx,4\r
- jle getpages // there is only 1,2,3,or 4 pages\r
- mov bx,4 // we can't use more than 4 pages\r
- }\r
-\r
-getpages:\r
-asm {\r
- mov [EMSpagesmapped],bx\r
- mov ah,EMS_ALLOCPAGES // allocate up to 64k of EMS\r
- int EMS_INT\r
- or ah,ah\r
- jnz error\r
- mov [EMShandle],dx\r
- }\r
- return;\r
-\r
-error:\r
- error = _AH;\r
- strcpy (str,"MML_SetupEMS: EMS error 0x");\r
- itoa(error,str2,16);\r
- strcpy (str,str2);\r
- Quit (str);\r
-\r
-noEMS:\r
-;\r
-}\r
-\r
-\r
-/*\r
-======================\r
-=\r
-= MML_ShutdownEMS\r
-=\r
-=======================\r
-*/\r
-\r
-void MML_ShutdownEMS (void)\r
-{\r
- if (!EMShandle)\r
- return;\r
-\r
-asm {\r
- mov ah,EMS_FREEPAGES\r
- mov dx,[EMShandle]\r
- int EMS_INT\r
- or ah,ah\r
- jz ok\r
- }\r
-\r
- Quit ("MML_ShutdownEMS: Error freeing EMS!");\r
-\r
-ok:\r
-;\r
-}\r
-\r
-/*\r
-====================\r
-=\r
-= MM_MapEMS\r
-=\r
-= Maps the 64k of EMS used by memory manager into the page frame\r
-= for general use. This only needs to be called if you are keeping\r
-= other things in EMS.\r
-=\r
-====================\r
-*/\r
-\r
-void MM_MapEMS (void)\r
-{\r
- char str[80],str2[10];\r
- unsigned error;\r
- int i;\r
-\r
- for (i=0;i<EMSpagesmapped;i++)\r
- {\r
- asm {\r
- mov ah,EMS_MAPPAGE\r
- mov bx,[i] // logical page\r
- mov al,bl // physical page\r
- mov dx,[EMShandle] // handle\r
- int EMS_INT\r
- or ah,ah\r
- jnz error\r
- }\r
- }\r
-\r
- return;\r
-\r
-error:\r
- error = _AH;\r
- strcpy (str,"MM_MapEMS: EMS error 0x");\r
- itoa(error,str2,16);\r
- strcpy (str,str2);\r
- Quit (str);\r
-}\r
-\r
-//==========================================================================\r
-\r
-/*\r
-======================\r
-=\r
-= MML_CheckForXMS\r
-=\r
-= Check for XMM driver\r
-=\r
-=======================\r
-*/\r
-\r
-boolean MML_CheckForXMS (void)\r
-{\r
- numUMBs = 0;\r
-\r
-asm {\r
- mov ax,0x4300\r
- int 0x2f // query status of installed diver\r
- cmp al,0x80\r
- je good\r
- }\r
- return false;\r
-good:\r
- return true;\r
-}\r
-\r
-\r
-/*\r
-======================\r
-=\r
-= MML_SetupXMS\r
-=\r
-= Try to allocate all upper memory block\r
-=\r
-=======================\r
-*/\r
-\r
-void MML_SetupXMS (void)\r
-{\r
- unsigned base,size;\r
-\r
-asm {\r
- mov ax,0x4310\r
- int 0x2f\r
- mov [WORD PTR XMSaddr],bx\r
- mov [WORD PTR XMSaddr+2],es // function pointer to XMS driver\r
- }\r
-\r
-getmemory:\r
-asm {\r
- mov ah,XMS_ALLOCUMB\r
- mov dx,0xffff // try for largest block possible\r
- call [DWORD PTR XMSaddr]\r
- or ax,ax\r
- jnz gotone\r
-\r
- cmp bl,0xb0 // error: smaller UMB is available\r
- jne done;\r
-\r
- mov ah,XMS_ALLOCUMB\r
- call [DWORD PTR XMSaddr] // DX holds largest available UMB\r
- or ax,ax\r
- jz done // another error...\r
- }\r
-\r
-gotone:\r
-asm {\r
- mov [base],bx\r
- mov [size],dx\r
- }\r
- MML_UseSpace (base,size);\r
- mminfo.XMSmem += size*16;\r
- UMBbase[numUMBs] = base;\r
- numUMBs++;\r
- if (numUMBs < MAXUMBS)\r
- goto getmemory;\r
-\r
-done:;\r
-}\r
-\r
-\r
-/*\r
-======================\r
-=\r
-= MML_ShutdownXMS\r
-=\r
-======================\r
-*/\r
-\r
-void MML_ShutdownXMS (void)\r
-{\r
- int i;\r
- unsigned base;\r
-\r
- for (i=0;i<numUMBs;i++)\r
- {\r
- base = UMBbase[i];\r
-\r
-asm mov ah,XMS_FREEUMB\r
-asm mov dx,[base]\r
-asm call [DWORD PTR XMSaddr]\r
- }\r
-}\r
-\r
-//==========================================================================\r
-\r
-/*\r
-======================\r
-=\r
-= MML_UseSpace\r
-=\r
-= Marks a range of paragraphs as usable by the memory manager\r
-= This is used to mark space for the near heap, far heap, ems page frame,\r
-= and upper memory blocks\r
-=\r
-======================\r
-*/\r
-\r
-void MML_UseSpace (unsigned segstart, unsigned seglength)\r
-{\r
- mmblocktype far *scan,far *last;\r
- unsigned oldend;\r
- long extra;\r
-\r
- scan = last = mmhead;\r
- mmrover = mmhead; // reset rover to start of memory\r
-\r
-//\r
-// search for the block that contains the range of segments\r
-//\r
- while (scan->start+scan->length < segstart)\r
- {\r
- last = scan;\r
- scan = scan->next;\r
- }\r
-\r
-//\r
-// take the given range out of the block\r
-//\r
- oldend = scan->start + scan->length;\r
- extra = oldend - (segstart+seglength);\r
- if (extra < 0)\r
- Quit ("MML_UseSpace: Segment spans two blocks!");\r
-\r
- if (segstart == scan->start)\r
- {\r
- last->next = scan->next; // unlink block\r
- FREEBLOCK(scan);\r
- scan = last;\r
- }\r
- else\r
- scan->length = segstart-scan->start; // shorten block\r
-\r
- if (extra > 0)\r
- {\r
- GETNEWBLOCK;\r
- mmnew->next = scan->next;\r
- scan->next = mmnew;\r
- mmnew->start = segstart+seglength;\r
- mmnew->length = extra;\r
- mmnew->attributes = LOCKBIT;\r
- }\r
-\r
-}\r
-\r
-//==========================================================================\r
-\r
-/*\r
-====================\r
-=\r
-= MML_ClearBlock\r
-=\r
-= We are out of blocks, so free a purgable block\r
-=\r
-====================\r
-*/\r
-\r
-void MML_ClearBlock (void)\r
-{\r
- mmblocktype far *scan,far *last;\r
-\r
- scan = mmhead->next;\r
-\r
- while (scan)\r
- {\r
- if (!(scan->attributes&LOCKBIT) && (scan->attributes&PURGEBITS) )\r
- {\r
- MM_FreePtr(scan->useptr);\r
- return;\r
- }\r
- scan = scan->next;\r
- }\r
-\r
- Quit ("MM_ClearBlock: No purgable blocks!");\r
-}\r
-\r
-\r
-//==========================================================================\r
-\r
-/*\r
-===================\r
-=\r
-= MM_Startup\r
-=\r
-= Grabs all space from turbo with malloc/farmalloc\r
-= Allocates bufferseg misc buffer\r
-=\r
-===================\r
-*/\r
-\r
-static char *ParmStrings[] = {"noems","noxms",""};\r
-\r
-void MM_Startup (void)\r
-{\r
- int i;\r
- unsigned long length;\r
- void far *start;\r
- unsigned segstart,seglength,endfree;\r
-\r
- if (mmstarted)\r
- MM_Shutdown ();\r
-\r
-\r
- mmstarted = true;\r
- bombonerror = true;\r
-//\r
-// set up the linked list (everything in the free list;\r
-//\r
- mmhead = NULL;\r
- mmfree = &mmblocks[0];\r
- for (i=0;i<MAXBLOCKS-1;i++)\r
- mmblocks[i].next = &mmblocks[i+1];\r
- mmblocks[i].next = NULL;\r
-\r
-//\r
-// locked block of all memory until we punch out free space\r
-//\r
- GETNEWBLOCK;\r
- mmhead = mmnew; // this will allways be the first node\r
- mmnew->start = 0;\r
- mmnew->length = 0xffff;\r
- mmnew->attributes = LOCKBIT;\r
- mmnew->next = NULL;\r
- mmrover = mmhead;\r
-\r
-\r
-//\r
-// get all available near conventional memory segments\r
-//\r
- length=coreleft();\r
- start = (void far *)(nearheap = malloc(length));\r
-\r
- length -= 16-(FP_OFF(start)&15);\r
- length -= SAVENEARHEAP;\r
- seglength = length / 16; // now in paragraphs\r
- segstart = FP_SEG(start)+(FP_OFF(start)+15)/16;\r
- MML_UseSpace (segstart,seglength);\r
- mminfo.nearheap = length;\r
-\r
-//\r
-// get all available far conventional memory segments\r
-//\r
- length=farcoreleft();\r
- start = farheap = farmalloc(length);\r
- length -= 16-(FP_OFF(start)&15);\r
- length -= SAVEFARHEAP;\r
- seglength = length / 16; // now in paragraphs\r
- segstart = FP_SEG(start)+(FP_OFF(start)+15)/16;\r
- MML_UseSpace (segstart,seglength);\r
- mminfo.farheap = length;\r
- mminfo.mainmem = mminfo.nearheap + mminfo.farheap;\r
-\r
-\r
-//\r
-// detect EMS and allocate up to 64K at page frame\r
-//\r
- mminfo.EMSmem = 0;\r
- for (i = 1;i < _argc;i++)\r
- {\r
- if ( US_CheckParm(_argv[i],ParmStrings) == 0)\r
- goto emsskip; // param NOEMS\r
- }\r
-\r
- if (MML_CheckForEMS())\r
- {\r
- MML_SetupEMS(); // allocate space\r
- MML_UseSpace (EMSpageframe,EMSpagesmapped*0x400);\r
- MM_MapEMS(); // map in used pages\r
- mminfo.EMSmem = EMSpagesmapped*0x4000l;\r
- }\r
-\r
-//\r
-// detect XMS and get upper memory blocks\r
-//\r
-emsskip:\r
- mminfo.XMSmem = 0;\r
- for (i = 1;i < _argc;i++)\r
- {\r
- if ( US_CheckParm(_argv[i],ParmStrings) == 0)\r
- goto xmsskip; // param NOXMS\r
- }\r
-\r
- if (MML_CheckForXMS())\r
- MML_SetupXMS(); // allocate as many UMBs as possible\r
-\r
-//\r
-// allocate the misc buffer\r
-//\r
-xmsskip:\r
- mmrover = mmhead; // start looking for space after low block\r
-\r
- MM_GetPtr (&bufferseg,BUFFERSIZE);\r
-}\r
-\r
-//==========================================================================\r
-\r
-/*\r
-====================\r
-=\r
-= MM_Shutdown\r
-=\r
-= Frees all conventional, EMS, and XMS allocated\r
-=\r
-====================\r
-*/\r
-\r
-void MM_Shutdown (void)\r
-{\r
- if (!mmstarted)\r
- return;\r
-\r
- farfree (farheap);\r
- free (nearheap);\r
- MML_ShutdownEMS ();\r
- MML_ShutdownXMS ();\r
-}\r
-\r
-//==========================================================================\r
-\r
-/*\r
-====================\r
-=\r
-= MM_GetPtr\r
-=\r
-= Allocates an unlocked, unpurgable block\r
-=\r
-====================\r
-*/\r
-\r
-void MM_GetPtr (memptr *baseptr,unsigned long size)\r
-{\r
- mmblocktype far *scan,far *lastscan,far *endscan\r
- ,far *purge,far *next;\r
- int search;\r
- unsigned needed,startseg;\r
-\r
- needed = (size+15)/16; // convert size from bytes to paragraphs\r
-\r
- GETNEWBLOCK; // fill in start and next after a spot is found\r
- mmnew->length = needed;\r
- mmnew->useptr = baseptr;\r
- mmnew->attributes = BASEATTRIBUTES;\r
-\r
- for (search = 0; search<3; search++)\r
- {\r
- //\r
- // first search: try to allocate right after the rover, then on up\r
- // second search: search from the head pointer up to the rover\r
- // third search: compress memory, then scan from start\r
- if (search == 1 && mmrover == mmhead)\r
- search++;\r
-\r
- switch (search)\r
- {\r
- case 0:\r
- lastscan = mmrover;\r
- scan = mmrover->next;\r
- endscan = NULL;\r
- break;\r
- case 1:\r
- lastscan = mmhead;\r
- scan = mmhead->next;\r
- endscan = mmrover;\r
- break;\r
- case 2:\r
- MM_SortMem ();\r
- lastscan = mmhead;\r
- scan = mmhead->next;\r
- endscan = NULL;\r
- break;\r
- }\r
-\r
- startseg = lastscan->start + lastscan->length;\r
-\r
- while (scan != endscan)\r
- {\r
- if (scan->start - startseg >= needed)\r
- {\r
- //\r
- // got enough space between the end of lastscan and\r
- // the start of scan, so throw out anything in the middle\r
- // and allocate the new block\r
- //\r
- purge = lastscan->next;\r
- lastscan->next = mmnew;\r
- mmnew->start = *(unsigned *)baseptr = startseg;\r
- mmnew->next = scan;\r
- while ( purge != scan)\r
- { // free the purgable block\r
- next = purge->next;\r
- FREEBLOCK(purge);\r
- purge = next; // purge another if not at scan\r
- }\r
- mmrover = mmnew;\r
- return; // good allocation!\r
- }\r
-\r
- //\r
- // if this block is purge level zero or locked, skip past it\r
- //\r
- if ( (scan->attributes & LOCKBIT)\r
- || !(scan->attributes & PURGEBITS) )\r
- {\r
- lastscan = scan;\r
- startseg = lastscan->start + lastscan->length;\r
- }\r
-\r
-\r
- scan=scan->next; // look at next line\r
- }\r
- }\r
-\r
- if (bombonerror)\r
- Quit (OUT_OF_MEM_MSG,(size-mminfo.nearheap));\r
- else\r
- mmerror = true;\r
-}\r
-\r
-//==========================================================================\r
-\r
-/*\r
-====================\r
-=\r
-= MM_FreePtr\r
-=\r
-= Allocates an unlocked, unpurgable block\r
-=\r
-====================\r
-*/\r
-\r
-void MM_FreePtr (memptr *baseptr)\r
-{\r
- mmblocktype far *scan,far *last;\r
-\r
- last = mmhead;\r
- scan = last->next;\r
-\r
- if (baseptr == mmrover->useptr) // removed the last allocated block\r
- mmrover = mmhead;\r
-\r
- while (scan->useptr != baseptr && scan)\r
- {\r
- last = scan;\r
- scan = scan->next;\r
- }\r
-\r
- if (!scan)\r
- Quit ("MM_FreePtr: Block not found!");\r
-\r
- last->next = scan->next;\r
-\r
- FREEBLOCK(scan);\r
-}\r
-//==========================================================================\r
-\r
-/*\r
-=====================\r
-=\r
-= MM_SetPurge\r
-=\r
-= Sets the purge level for a block (locked blocks cannot be made purgable)\r
-=\r
-=====================\r
-*/\r
-\r
-void MM_SetPurge (memptr *baseptr, int purge)\r
-{\r
- mmblocktype far *start;\r
-\r
- start = mmrover;\r
-\r
- do\r
- {\r
- if (mmrover->useptr == baseptr)\r
- break;\r
-\r
- mmrover = mmrover->next;\r
-\r
- if (!mmrover)\r
- mmrover = mmhead;\r
- else if (mmrover == start)\r
- Quit ("MM_SetPurge: Block not found!");\r
-\r
- } while (1);\r
-\r
- mmrover->attributes &= ~PURGEBITS;\r
- mmrover->attributes |= purge;\r
-}\r
-\r
-//==========================================================================\r
-\r
-/*\r
-=====================\r
-=\r
-= MM_SetLock\r
-=\r
-= Locks / unlocks the block\r
-=\r
-=====================\r
-*/\r
-\r
-void MM_SetLock (memptr *baseptr, boolean locked)\r
-{\r
- mmblocktype far *start;\r
-\r
- start = mmrover;\r
-\r
- do\r
- {\r
- if (mmrover->useptr == baseptr)\r
- break;\r
-\r
- mmrover = mmrover->next;\r
-\r
- if (!mmrover)\r
- mmrover = mmhead;\r
- else if (mmrover == start)\r
- Quit ("MM_SetLock: Block not found!");\r
-\r
- } while (1);\r
-\r
- mmrover->attributes &= ~LOCKBIT;\r
- mmrover->attributes |= locked*LOCKBIT;\r
-}\r
-\r
-//==========================================================================\r
-\r
-/*\r
-=====================\r
-=\r
-= MM_SortMem\r
-=\r
-= Throws out all purgable stuff and compresses movable blocks\r
-=\r
-=====================\r
-*/\r
-\r
-void MM_SortMem (void)\r
-{\r
- mmblocktype far *scan,far *last,far *next;\r
- unsigned start,length,source,dest,oldborder;\r
- int playing;\r
-\r
- //\r
- // lock down a currently playing sound\r
- //\r
- playing = SD_SoundPlaying ();\r
- if (playing)\r
- {\r
- switch (SoundMode)\r
- {\r
- case sdm_PC:\r
- playing += STARTPCSOUNDS;\r
- break;\r
- case sdm_AdLib:\r
- playing += STARTADLIBSOUNDS;\r
- break;\r
- }\r
- MM_SetLock(&(memptr)audiosegs[playing],true);\r
- }\r
-\r
-\r
- SD_StopSound();\r
-// oldborder = bordercolor;\r
-// VW_ColorBorder (15);\r
-\r
- if (beforesort)\r
- beforesort();\r
-\r
- scan = mmhead;\r
-\r
- last = NULL; // shut up compiler warning\r
-\r
- while (scan)\r
- {\r
- if (scan->attributes & LOCKBIT)\r
- {\r
- //\r
- // block is locked, so try to pile later blocks right after it\r
- //\r
- start = scan->start + scan->length;\r
- }\r
- else\r
- {\r
- if (scan->attributes & PURGEBITS)\r
- {\r
- //\r
- // throw out the purgable block\r
- //\r
- next = scan->next;\r
- FREEBLOCK(scan);\r
- last->next = next;\r
- scan = next;\r
- continue;\r
- }\r
- else\r
- {\r
- //\r
- // push the non purgable block on top of the last moved block\r
- //\r
- if (scan->start != start)\r
- {\r
- length = scan->length;\r
- source = scan->start;\r
- dest = start;\r
- while (length > 0xf00)\r
- {\r
- movedata(source,0,dest,0,0xf00*16);\r
- length -= 0xf00;\r
- source += 0xf00;\r
- dest += 0xf00;\r
- }\r
- movedata(source,0,dest,0,length*16);\r
-\r
- scan->start = start;\r
- *(unsigned *)scan->useptr = start;\r
- }\r
- start = scan->start + scan->length;\r
- }\r
- }\r
-\r
- last = scan;\r
- scan = scan->next; // go to next block\r
- }\r
-\r
- mmrover = mmhead;\r
-\r
- if (aftersort)\r
- aftersort();\r
-\r
-// VW_ColorBorder (oldborder);\r
-\r
- if (playing)\r
- MM_SetLock(&(memptr)audiosegs[playing],false);\r
-}\r
-\r
-\r
-//==========================================================================\r
-\r
-#if 0\r
-/*\r
-=====================\r
-=\r
-= MM_ShowMemory\r
-=\r
-=====================\r
-*/\r
-\r
-void MM_ShowMemory (void)\r
-{\r
- mmblocktype far *scan;\r
- unsigned color,temp;\r
- long end,owner;\r
- char scratch[80],str[10];\r
-\r
- VW_SetDefaultColors();\r
- VW_SetLineWidth(40);\r
- temp = bufferofs;\r
- bufferofs = 0;\r
- VW_SetScreen (0,0);\r
-\r
- scan = mmhead;\r
-\r
- end = -1;\r
-\r
-//CA_OpenDebug ();\r
-\r
- while (scan)\r
- {\r
- if (scan->attributes & PURGEBITS)\r
- color = 5; // dark purple = purgable\r
- else\r
- color = 9; // medium blue = non purgable\r
- if (scan->attributes & LOCKBIT)\r
- color = 12; // red = locked\r
- if (scan->start<=end)\r
- Quit ("MM_ShowMemory: Memory block order currupted!");\r
- end = scan->start+scan->length-1;\r
- VW_Hlin(scan->start,(unsigned)end,0,color);\r
- VW_Plot(scan->start,0,15);\r
- if (scan->next->start > end+1)\r
- VW_Hlin(end+1,scan->next->start,0,0); // black = free\r
-\r
-#if 0\r
-strcpy (scratch,"Size:");\r
-ltoa ((long)scan->length*16,str,10);\r
-strcat (scratch,str);\r
-strcat (scratch,"\tOwner:0x");\r
-owner = (unsigned)scan->useptr;\r
-ultoa (owner,str,16);\r
-strcat (scratch,str);\r
-strcat (scratch,"\n");\r
-write (debughandle,scratch,strlen(scratch));\r
-#endif\r
-\r
- scan = scan->next;\r
- }\r
-\r
-//CA_CloseDebug ();\r
-\r
- IN_Ack();\r
- VW_SetLineWidth(64);\r
- bufferofs = temp;\r
-}\r
-#endif\r
-\r
-//==========================================================================\r
-\r
-\r
-/*\r
-======================\r
-=\r
-= MM_UnusedMemory\r
-=\r
-= Returns the total free space without purging\r
-=\r
-======================\r
-*/\r
-\r
-long MM_UnusedMemory (void)\r
-{\r
- unsigned free;\r
- mmblocktype far *scan;\r
-\r
- free = 0;\r
- scan = mmhead;\r
-\r
- while (scan->next)\r
- {\r
- free += scan->next->start - (scan->start + scan->length);\r
- scan = scan->next;\r
- }\r
-\r
- return free*16l;\r
-}\r
-\r
-//==========================================================================\r
-\r
-\r
-/*\r
-======================\r
-=\r
-= MM_TotalFree\r
-=\r
-= Returns the total free space with purging\r
-=\r
-======================\r
-*/\r
-\r
-long MM_TotalFree (void)\r
-{\r
- unsigned free;\r
- mmblocktype far *scan;\r
-\r
- free = 0;\r
- scan = mmhead;\r
-\r
- while (scan->next)\r
- {\r
- if ((scan->attributes&PURGEBITS) && !(scan->attributes&LOCKBIT))\r
- free += scan->length;\r
- free += scan->next->start - (scan->start + scan->length);\r
- scan = scan->next;\r
- }\r
-\r
- return free*16l;\r
-}\r
-\r
-//==========================================================================\r
-\r
-/*\r
-=====================\r
-=\r
-= MM_BombOnError\r
-=\r
-=====================\r
-*/\r
-\r
-void MM_BombOnError (boolean bomb)\r
-{\r
- bombonerror = bomb;\r
-}\r
-\r
-\r
+++ /dev/null
-/* Catacomb Apocalypse 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_MM.H\r
-\r
-#ifndef __ID_CA__\r
-\r
-#define __ID_CA__\r
-\r
-#define SAVENEARHEAP 0x400 // space to leave in data segment\r
-#define SAVEFARHEAP 0 // space to leave in far heap\r
-\r
-#define BUFFERSIZE 0x1000 // miscelanious, allways available buffer\r
-\r
-#define MAXBLOCKS 600\r
-\r
-\r
-//--------\r
-\r
-#define EMS_INT 0x67\r
-\r
-#define EMS_STATUS 0x40\r
-#define EMS_GETFRAME 0x41\r
-#define EMS_GETPAGES 0x42\r
-#define EMS_ALLOCPAGES 0x43\r
-#define EMS_MAPPAGE 0x44\r
-#define EMS_FREEPAGES 0x45\r
-#define EMS_VERSION 0x46\r
-\r
-//--------\r
-\r
-#define XMS_VERSION 0x00\r
-\r
-#define XMS_ALLOCHMA 0x01\r
-#define XMS_FREEHMA 0x02\r
-\r
-#define XMS_GENABLEA20 0x03\r
-#define XMS_GDISABLEA20 0x04\r
-#define XMS_LENABLEA20 0x05\r
-#define XMS_LDISABLEA20 0x06\r
-#define XMS_QUERYA20 0x07\r
-\r
-#define XMS_QUERYREE 0x08\r
-#define XMS_ALLOC 0x09\r
-#define XMS_FREE 0x0A\r
-#define XMS_MOVE 0x0B\r
-#define XMS_LOCK 0x0C\r
-#define XMS_UNLOCK 0x0D\r
-#define XMS_GETINFO 0x0E\r
-#define XMS_RESIZE 0x0F\r
-\r
-#define XMS_ALLOCUMB 0x10\r
-#define XMS_FREEUMB 0x11\r
-\r
-//==========================================================================\r
-\r
-typedef void _seg * memptr;\r
-\r
-typedef struct\r
-{\r
- long nearheap,farheap,EMSmem,XMSmem,mainmem;\r
-} mminfotype;\r
-\r
-//==========================================================================\r
-\r
-extern mminfotype mminfo;\r
-extern memptr bufferseg;\r
-extern boolean mmerror;\r
-\r
-extern void (* beforesort) (void);\r
-extern void (* aftersort) (void);\r
-\r
-//==========================================================================\r
-\r
-void MM_Startup (void);\r
-void MM_Shutdown (void);\r
-void MM_MapEMS (void);\r
-\r
-void MM_GetPtr (memptr *baseptr,unsigned long size);\r
-void MM_FreePtr (memptr *baseptr);\r
-\r
-void MM_SetPurge (memptr *baseptr, int purge);\r
-void MM_SetLock (memptr *baseptr, boolean locked);\r
-void MM_SortMem (void);\r
-\r
-void MM_ShowMemory (void);\r
-\r
-long MM_UnusedMemory (void);\r
-long MM_TotalFree (void);\r
-\r
-void MM_BombOnError (boolean bomb);\r
-\r
-#endif
\ No newline at end of file
+++ /dev/null
-/* Project 16 Source Code~
- * Copyright (C) 2012-2015 sparky4 & pngwen & andrius4669
- *
- * This file is part of Project 16.
- *
- * Project 16 is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 3 of the License, or
- * (at your option) any later version.
- *
- * Project 16 is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>, or
- * write to the Free Software Foundation, Inc., 51 Franklin Street,
- * Fifth Floor, Boston, MA 02110-1301 USA.
- *
- */
-/*
- exmm test borland c ver
-*/
-#include <stdio.h>
-#include <bios.h>
-
-/*#include "src/lib/16_head.h"
-#include "src/lib/16_ca.h"
-#include "src/lib/16_mm.h"*/
-#include "16_head.h"
-#include "16_ca.h"
-#include "16_mm.h"
-//#include "src/lib/modex16.h"
-/*#pragma hdrstop\r
-\r
-#pragma warn -pro\r
-#pragma warn -use*/
-
-//file load or read definition
-#define FILERL
-//#define FILEREAD
-
-void
-main(int argc, char *argv[])
-{
- mminfo_t mm; mminfotype mmi;
- memptr bigbuffer;
-#ifdef FILERL
- char *bakapee;
-// int bakapeehandle;
- word baka;
-#endif
- //static page_t screen;
-
- //mmi.segu=FP_SEG(segu);
-
- printf("&main()= %Fp\n", *argv[0]);
- //printf("segu= %Fp\n", segu);
- printf("bigbuffer= %Fp\n", bigbuffer);
- printf("&bigbuffer= %Fp\n", &bigbuffer);
- printf("bigbuffer= %04x\n", bigbuffer);
- printf("&bigbuffer= %04x\n", &bigbuffer);
-
-#ifdef FILERL
- bakapee = malloc(64);
-// memset(bakapee, 0, 64);
-#endif
- mm.mmstarted=0;
-
-#ifdef FILERL
- if(argv[1]) bakapee = argv[1];
- else bakapee = "../../data/koishi~~.pcx";
-#endif
-
- //textInit();\r
-
- /* setup camera and screen~ */
- //bug!!!\r
- //screen = modexDefaultPage();\r
- /*screen.width += (16*2);\r
- screen.height += (16*2);*/
-
- printf("main()=%Fp start MM\n", *argv[0]);
- MM_Startup(&mm, &mmi);
- //PM_Startup();\r
- //PM_UnlockMainMem();\r
- CA_Startup();
- printf(" done!\n");
- /*if(FP_SEG(*argv[0])==0)
- {
- MM_Report(&screen, &mm, &mmi);
- MM_Shutdown(&mm);
- printf("&main()=%Fp\n", *argv[0]);
- printf("&main() == %u\n", FP_SEG(*argv[0]));
- exit(-5);
- }*/
- printf("&main()= %Fp\n", *argv[0]);
- //printf("segu= %Fp\n", segu);
- printf("bigbuffer= %Fp\n", bigbuffer);
- printf("&bigbuffer= %Fp\n", &bigbuffer);\r
- printf("bigbuffer= %04x\n", bigbuffer);
- printf("&bigbuffer= %04x\n", &bigbuffer);
-#ifdef FILERL
-// bakapeehandle = open(bakapee,O_RDONLY | O_BINARY, S_IREAD);
-//wat printf("size of big buffer~=%u\n", _bmsize(segu, bigbuffer));
-// if(CA_FarRead(bakapeehandle,(void far *)&bigbuffer,sizeof(bigbuffer),&mm))
-#ifdef FILEREAD
- printf(" read\n");
- if(CA_ReadFile(bakapee, &bigbuffer, &mm))
-#else
- printf(" load\n");
- if(CA_LoadFile(bakapee, &bigbuffer, &mm, &mmi))
-#endif
- baka=1;
- else
- baka=0;
-// close(bakapeehandle);
- //hmm functions in cache system use the buffered stuff
-// printf("size of big buffer~=%u\n", _bmsize(segu, bigbuffer));
-#endif
- printf("dark purple = purgable\n");
- printf("medium blue = non purgable\n");
- printf("red = locked\n");
- getch();
- //++++modexEnter();
- //++++modexShowPage(&screen);
- MM_ShowMemory(/*&screen, */&mm);
- //getch();
- MM_DumpData(&mm);
- //++++modexLeave();
- MM_Report(&mm, &mmi);
- printf(" stop!\n");
-#ifdef FILERL
- MM_FreePtr(&bigbuffer, &mm);
-#endif
- //PM_Shutdown();
- CA_Shutdown();
- MM_Shutdown(&mm);
- printf(" done!\n");
-#ifdef FILERL
- free(bakapee);
- if(baka) printf("\nyay!\n");
- else printf("\npoo!\n");
-#endif
- printf("bigbuffer= %Fp\n", bigbuffer);
- printf("&bigbuffer= %Fp\n", &bigbuffer);
- printf("bigbuffer= %04x\n", bigbuffer);
- printf("&bigbuffer= %04x\n", &bigbuffer);
- printf("\n\n");
- printf("Total free: %lu\n", (dword)(GetFreeSize()));
- //printf("Total near free: %zu\n", GetNearFreeSize());
- printf("Total far free: %lu\n", (dword)(GetFarFreeSize()));
- printf("\n");
- printf("core left: %u\n", coreleft());
- printf("far core left: %lu\n", farcoreleft());
-}
main(int argc, char *argv[])\r
{\r
mminfo_t mm; mminfotype mmi;\r
+#ifdef __WATCOMC__\r
__segment sega;\r
void __based(sega)* bigbuffer;\r
+#endif\r
+#ifdef __BORLANDC__\r
+ void memptr* bigbuffer;\r
+#endif\r
#ifdef FILERL\r
char *bakapee;\r
word baka;\r
--- /dev/null
+/* Project 16 Source Code~
+ * Copyright (C) 2012-2015 sparky4 & pngwen & andrius4669
+ *
+ * This file is part of Project 16.
+ *
+ * Project 16 is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * Project 16 is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>, or
+ * write to the Free Software Foundation, Inc., 51 Franklin Street,
+ * Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ */
+/*
+ heap test stuff
+*/
+
+#include "src/lib/16_hc.h"
+
+int heaphandle;
+
+void __near* LargestFreeBlock(size_t* Size)
+{
+ size_t s0, s1;
+ void __near* p;
+
+ s0 = ~(size_t)0 ^ (~(size_t)0 >> 1);
+ while (s0 && (p = _nmalloc(s0)) == NULL)
+ s0 >>= 1;
+
+ if (p)
+ _nfree(p);
+
+ s1 = s0 >> 1;
+ while (s1)
+ {
+ if ((p = _nmalloc(s0 + s1)) != NULL)
+ {
+ s0 += s1;
+ _nfree(p);
+ }
+ s1 >>= 1;
+ }
+ while (s0 && (p = _nmalloc(s0)) == NULL)
+ s0 ^= s0 & -s0;
+
+ *Size = s0;
+ return p;
+}
+
+size_t _coreleft(void)
+{
+ size_t total = 0;
+ void __near* pFirst = NULL;
+ void __near* pLast = NULL;
+ for(;;)
+ {
+ size_t largest;
+ void __near* p = LargestFreeBlock(&largest);
+ if (largest < sizeof(void __near*))
+ {
+ if (p != NULL)
+ _nfree(p);
+ break;
+ }
+ *(void __near* __near*)p = NULL;
+ total += largest;
+ if (pFirst == NULL)
+ pFirst = p;
+
+ if (pLast != NULL)
+ *(void __near* __near*)pLast = p;
+ pLast = p;
+ }
+
+ while (pFirst != NULL)
+ {
+ void __near* p = *(void __near* __near*)pFirst;
+ _nfree(pFirst);
+ pFirst = p;
+ }
+ return total;
+}
+
+void far* LargestFarFreeBlock(size_t* Size)
+{
+ size_t s0, s1;
+ void far* p;
+
+ s0 = ~(size_t)0 ^ (~(size_t)0 >> 1);
+ while (s0 && (p = _fmalloc(s0)) == NULL)
+ s0 >>= 1;
+
+ if (p)
+ _ffree(p);
+
+ s1 = s0 >> 1;
+ while (s1)
+ {
+ if ((p = _fmalloc(s0 + s1)) != NULL)
+ {
+ s0 += s1;
+ _ffree(p);
+ }
+ s1 >>= 1;
+ }
+ while (s0 && (p = _fmalloc(s0)) == NULL)
+ s0 ^= s0 & -s0;
+
+ *Size = s0;
+ return p;
+}
+
+size_t _farcoreleft(void)
+{
+ size_t total = 0;
+ void far* pFirst = NULL;
+ void far* pLast = NULL;
+ for(;;)
+ {
+ size_t largest;
+ void far* p = LargestFarFreeBlock(&largest);
+ if (largest < sizeof(void far*))
+ {
+ if (p != NULL)
+ _ffree(p);
+ break;
+ }
+ *(void far* far*)p = NULL;
+ total += largest;
+ if (pFirst == NULL)
+ pFirst = p;
+
+ if (pLast != NULL)
+ *(void far* far*)pLast = p;
+ pLast = p;
+ }
+
+ while (pFirst != NULL)
+ {
+ void far* p = *(void far* far*)pFirst;
+ _ffree(pFirst);
+ pFirst = p;
+ }
+ return total;
+}
+
+void huge* LargestHugeFreeBlock(size_t* Size)
+{
+ size_t s0, s1;
+ void huge* p;
+
+ s0 = ~(size_t)0 ^ (~(size_t)0 >> 1);
+ while (s0 && (p = halloc((dword)s0, 1)) == NULL)
+ s0 >>= 1;
+
+ if (p)
+ hfree(p);
+
+ s1 = s0 >> 1;
+ while (s1)
+ {
+ if ((p = halloc((dword)(s0 + s1), 1)) != NULL)
+ {
+ s0 += s1;
+ hfree(p);
+ }
+ s1 >>= 1;
+ }
+ while (s0 && (p = halloc((dword)s0, 1)) == NULL)
+ s0 ^= s0 & -s0;
+
+ *Size = s0;
+ return p;
+}
+
+size_t _hugecoreleft(void)
+{
+ size_t total = 0;
+ void huge* pFirst = NULL;
+ void huge* pLast = NULL;
+ for(;;)
+ {
+ size_t largest;
+ void huge* p = LargestHugeFreeBlock(&largest);
+ if (largest < sizeof(void huge*))
+ {
+ if (p != NULL)
+ hfree(p);
+ break;
+ }
+ *(void huge* huge*)p = NULL;
+ total += largest;
+ if (pFirst == NULL)
+ pFirst = p;
+
+ if (pLast != NULL)
+ *(void huge* huge*)pLast = p;
+ pLast = p;
+ }
+
+ while (pFirst != NULL)
+ {
+ void huge* p = *(void huge* huge*)pFirst;
+ hfree(pFirst);
+ pFirst = p;
+ }
+ return total;
+}
+
+/*void __based(__self)* LargestBasedFreeBlock(size_t* Size)
+{
+ __segment segu;
+ size_t s0, s1;
+ void __based(__self)* p;
+
+ s0 = ~(size_t)0 ^ (~(size_t)0 >> 1);
+ while (s0 && (p = _bmalloc(segu, s0)) == NULL)
+ s0 >>= 1;
+
+ if (p)
+ _ffree(p);
+
+ s1 = s0 >> 1;
+ while (s1)
+ {
+ if ((p = _bmalloc(segu, s0 + s1)) != NULL)
+ {
+ s0 += s1;
+ _ffree(p);
+ }
+ s1 >>= 1;
+ }
+ while (s0 && (p = _bmalloc(segu, s0)) == NULL)
+ s0 ^= s0 & -s0;
+
+ *Size = s0;
+ return p;
+}
+
+size_t _basedcoreleft(void)
+{
+ __segment segu;
+ size_t total = 0;
+ void __based(segu)* pFirst = NULL;
+ void __based(segu)* pLast = NULL;
+ // allocate based heap
+ segu = _bheapseg( 1024 );
+ if( segu == _NULLSEG ) {
+ printf( "Unable to allocate based heap\n" );
+ return 0;
+ //exit( 1 );
+ }
+ else
+
+ for(;;)
+ {
+ size_t largest;
+ void __based(segu)* p = LargestBasedFreeBlock(&largest);
+ if (largest < sizeof(void far*))
+ {
+ if (p != NULL)
+ _ffree(p);
+ break;
+ }
+ *(void far* far*)p = NULL;
+ total += largest;
+ if (pFirst == NULL)
+ pFirst = p;
+
+ if (pLast != NULL)
+ *(void far* far*)pLast = p;
+ pLast = p;
+ }
+
+ while (pFirst != NULL)
+ {
+ void far* p = *(void far* far*)pFirst;
+ _ffree(pFirst);
+ pFirst = p;
+ }
+ return total;
+}*/
+
+size_t GetFreeSize(void)
+{
+ struct _heapinfo h_info;
+ int heap_status;
+ size_t h_free=0, h_total=0, h_used=0;
+
+ h_info._pentry = NULL;
+ for(;;) {
+ heap_status = _heapwalk( &h_info );
+ if( heap_status != _HEAPOK ) break;
+ if((h_info._useflag == _USEDENTRY ? "USED" : "FREE")=="FREE") h_free += h_info._size;
+ if((h_info._useflag == _USEDENTRY ? "USED" : "FREE")=="USED") h_used += h_info._size;
+ h_total += h_info._size;
+ }
+ heapstat0(heap_status);
+ return h_free;
+}
+
+size_t GetFarFreeSize(void)
+{
+ struct _heapinfo fh_info;
+ int heap_status;
+ size_t fh_free=0, fh_total=0, fh_used=0;
+
+ fh_info._pentry = NULL;
+ for(;;) {
+ heap_status = _fheapwalk( &fh_info );
+ if( heap_status != _HEAPOK ) break;
+ if((fh_info._useflag == _USEDENTRY ? "USED" : "FREE")=="FREE") fh_free += fh_info._size;
+ if((fh_info._useflag == _USEDENTRY ? "USED" : "FREE")=="USED") fh_used += fh_info._size;
+ fh_total += fh_info._size;
+ }
+ heapstat0(heap_status);
+ return fh_free;
+}
+
+size_t GetNearFreeSize(void)
+{
+ struct _heapinfo nh_info;
+ int heap_status;
+ size_t nh_free=0, nh_total=0, nh_used=0;
+
+ nh_info._pentry = NULL;
+ for(;;) {
+ heap_status = _nheapwalk( &nh_info );
+ if( heap_status != _HEAPOK ) break;
+ if((nh_info._useflag == _USEDENTRY ? "USED" : "FREE")=="FREE") nh_free += nh_info._size;
+ if((nh_info._useflag == _USEDENTRY ? "USED" : "FREE")=="USED") nh_used += nh_info._size;
+ nh_total += nh_info._size;
+ }
+ heapstat0(heap_status);
+ return nh_free;
+}
+
+void heapdump(void)
+{
+ struct _heapinfo fh_info, nh_info, h_info;
+ int heap_status;
+ size_t h_free, nh_free, fh_free, h_total, nh_total, fh_total, h_used, nh_used, fh_used;
+ byte scratch[1024],str[16];
+
+ HC_OpenDebug();
+
+ strcpy(scratch,"\n == default ==\n\n");
+ write(heaphandle,scratch,strlen(scratch));
+ h_info._pentry = NULL;
+ h_free=0; h_total=0; h_used=0;
+ for(;;) {
+ heap_status = _heapwalk( &h_info );
+ if( heap_status != _HEAPOK ) break;
+ strcpy(scratch," "); strcat(scratch,(h_info._useflag == _USEDENTRY ? "USED" : "FREE")); strcat(scratch," block at "); ultoa((dword)h_info._pentry,str,16); strcat(scratch,str); strcat(scratch," of size "); ultoa(h_info._size,str,10); strcat(scratch,str); strcat(scratch,"\n");
+ if((h_info._useflag == _USEDENTRY ? "USED" : "FREE")=="FREE") h_free += h_info._size;
+ if((h_info._useflag == _USEDENTRY ? "USED" : "FREE")=="USED") h_used += h_info._size;
+ h_total += h_info._size;
+ write(heaphandle,scratch,strlen(scratch));
+ }
+ heapstat(heap_status, &scratch);
+
+ //near
+ strcpy(scratch,"\n == near ==\n\n");
+ write(heaphandle,scratch,strlen(scratch));
+ nh_info._pentry = NULL;
+ nh_free=0; nh_total=0; nh_used=0;
+ for(;;) {
+ heap_status = _nheapwalk( &nh_info );
+ if( heap_status != _HEAPOK ) break;
+ strcpy(scratch," "); strcat(scratch,(h_info._useflag == _USEDENTRY ? "USED" : "FREE")); strcat(scratch," block at "); ultoa((dword)h_info._pentry,str,16); strcat(scratch,str); strcat(scratch," of size "); ultoa(h_info._size,str,10); strcat(scratch,str); strcat(scratch,"\n");
+/* printf( " %s block at %Fp of size %4.4X\n",
+(nh_info._useflag == _USEDENTRY ? "USED" : "FREE"),
+nh_info._pentry, nh_info._size );*/
+ if((nh_info._useflag == _USEDENTRY ? "USED" : "FREE")=="FREE") nh_free += nh_info._size;
+ if((nh_info._useflag == _USEDENTRY ? "USED" : "FREE")=="USED") nh_used += nh_info._size;
+ nh_total += nh_info._size;
+ write(heaphandle,scratch,strlen(scratch));
+ }
+ heapstat(heap_status, &scratch);
+
+ //far
+ strcpy(scratch,"\n == far ==\n\n");
+ write(heaphandle,scratch,strlen(scratch));
+ fh_info._pentry = NULL;
+ fh_free=0; fh_total=0; fh_used=0;
+ for(;;) {
+ heap_status = _fheapwalk( &fh_info );
+ if( heap_status != _HEAPOK ) break;
+ strcpy(scratch," "); strcat(scratch,(h_info._useflag == _USEDENTRY ? "USED" : "FREE")); strcat(scratch," block at "); ultoa((dword)h_info._pentry,str,16); strcat(scratch,str); strcat(scratch," of size "); ultoa(h_info._size,str,10); strcat(scratch,str); strcat(scratch,"\n");
+ /*printf( " %s block at %Fp of size %4.4X\n",
+(fh_info._useflag == _USEDENTRY ? "USED" : "FREE"),
+fh_info._pentry, fh_info._size );*/
+ if((fh_info._useflag == _USEDENTRY ? "USED" : "FREE")=="FREE") fh_free += fh_info._size;
+ if((fh_info._useflag == _USEDENTRY ? "USED" : "FREE")=="USED") fh_used += fh_info._size;
+ fh_total += fh_info._size;
+ write(heaphandle,scratch,strlen(scratch));
+ }
+ heapstat(heap_status, &scratch);
+
+ strcpy(scratch,"\n");
+ strcat(scratch,kittengets(2,0,"Memory Type Total Used Free\n"));
+ strcat(scratch,"---------------- -------- -------- --------\n");
+ printmeminfoline(&scratch, "Default", h_total, h_used, h_free);
+ printmeminfoline(&scratch, "Near", nh_total, nh_used, nh_free);
+ printmeminfoline(&scratch, "Far", fh_total, fh_used, fh_free);
+ strcat(scratch,"---------------- -------- -------- --------\n");
+ strcat(scratch,"coreleft = "); ultoa((dword)_coreleft(),str,10); strcat(scratch,str); strcat(scratch,"\n");
+ strcat(scratch,"farcoreleft = "); ultoa((dword)_farcoreleft(),str,10); strcat(scratch,str); strcat(scratch,"\n");
+ strcat(scratch,"GetFreeSize = "); ultoa((dword)GetFreeSize(),str,10); strcat(scratch,str); strcat(scratch,"\n");
+ strcat(scratch,"GetNearFreeSize = "); ultoa((dword)GetNearFreeSize(),str,10); strcat(scratch,str); strcat(scratch,"\n");
+ strcat(scratch,"GetFarFreeSize = "); ultoa((dword)GetFarFreeSize(),str,10); strcat(scratch,str); strcat(scratch,"\n");
+ strcat(scratch,"memavl = "); ultoa((dword)_memavl(),str,10); strcat(scratch,str); strcat(scratch,"\n");
+ strcat(scratch,"stackavail = "); ultoa((dword)stackavail(),str,10); strcat(scratch,str); strcat(scratch,"\n");
+ write(heaphandle,scratch,strlen(scratch));
+ HC_CloseDebug();
+}
+
+void heapstat(int heap_status, byte *str)
+{
+ switch( heap_status ) {
+ case _HEAPEND:
+ strcpy((str),"OK - end of heap\n");
+ break;
+ case _HEAPEMPTY:
+ strcpy((str),"OK - heap is empty\n");
+
+ break;
+ case _HEAPBADBEGIN:
+ strcpy((str),"ERROR - heap is damaged\n");
+ break;
+ case _HEAPBADPTR:
+ strcpy((str),"ERROR - bad pointer to heap\n");
+ break;
+ case _HEAPBADNODE:
+ strcpy((str),"ERROR - bad node in heap\n");
+ }
+ write(heaphandle,(str),strlen((str)));
+}
+
+void heapstat0(int heap_status)
+{
+ switch( heap_status ) {
+ case _HEAPEND:
+ //printf("OK - end of heap\n");
+ break;
+ case _HEAPEMPTY:
+ //printf("OK - heap is empty\n");
+
+ break;
+ case _HEAPBADBEGIN:
+ printf("ERROR - heap is damaged\n");
+ break;
+ case _HEAPBADPTR:
+ printf("ERROR - bad pointer to heap\n");
+ break;
+ case _HEAPBADNODE:
+ printf("ERROR - bad node in heap\n");
+ }
+}
+
+/*
+============================
+=
+= HC_OpenDebug / HC_CloseDebug
+=
+= Opens a binary file with the handle "heaphandle"
+=
+============================
+*/
+void HC_OpenDebug()
+{
+ unlink("heap.16");
+ heaphandle = open("heap.16", O_CREAT | O_WRONLY | O_TEXT);
+}
+
+void HC_CloseDebug()
+{
+ close(heaphandle);
+}
--- /dev/null
+/* Project 16 Source Code~
+ * Copyright (C) 2012-2015 sparky4 & pngwen & andrius4669
+ *
+ * This file is part of Project 16.
+ *
+ * Project 16 is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * Project 16 is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>, or
+ * write to the Free Software Foundation, Inc., 51 Franklin Street,
+ * Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ */
+/*
+ heap test stuff
+*/
+
+#ifndef __16HC__
+#define __16HC__
+
+#include "src/lib/16_head.h"
+
+extern int heaphandle;
+
+void __near* LargestFreeBlock(size_t* Size);
+size_t _coreleft(void);
+void far* LargestFarFreeBlock(size_t* Size);
+size_t _farcoreleft(void);
+void huge* LargestHugeFreeBlock(size_t* Size);
+size_t _hugecoreleft(void);
+//void __based(__self)* LargestBasedFreeBlock(size_t* Size);
+//size_t _basedcoreleft(void);
+size_t GetFreeSize(void);
+size_t GetFarFreeSize(void);
+size_t GetNearFreeSize(void);
+void heapdump(void);
+void heapstat(int heap_status, byte *str);
+void heapstat0(int heap_status);
+
+void HC_OpenDebug();
+void HC_CloseDebug();
+
+#endif /* __16HC__ */
\r
#ifndef _LIBHEAD_H_\r
#define _LIBHEAD_H_\r
-#include <i86.h>\r
#include <dos.h>\r
#include <stdio.h>\r
#include <conio.h> // just for wait\r
#include <stdlib.h>\r
#include <malloc.h>\r
#include <ctype.h>\r
-#include <unistd.h>\r
#include <fcntl.h>\r
#include <sys/stat.h>\r
#include <mem.h>\r
+#ifdef __WATCOMC__\r
+#include <i86.h>\r
+#include <unistd.h>\r
#include <alloca.h>\r
#include "src/lib/nyan/kitten.h"\r
+#endif\r
#include "src/lib/types.h"\r
\r
//0000 test type def wwww\r
//#include <bios.h>
#include "src/lib/16_head.h"
#include "src/lib/16_hc.h"
-#include "src/lib/modex16.h"
+//#include "src/lib/modex16.h"
//#include "src/lib/16_ca.h"
//++++mh #include "src/lib/16_in.h"
--- /dev/null
+/* Project 16 Source Code~\r
+ * Copyright (C) 2012-2015 sparky4 & pngwen & andrius4669\r
+ *\r
+ * This file is part of Project 16.\r
+ *\r
+ * Project 16 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 3 of the License, or\r
+ * (at your option) any later version.\r
+ *\r
+ * Project 16 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\r
+ * along with this program. If not, see <http://www.gnu.org/licenses/>, or\r
+ * write to the Free Software Foundation, Inc., 51 Franklin Street,\r
+ * Fifth Floor, Boston, MA 02110-1301 USA.\r
+ *\r
+ */\r
+/*\r
+ * Just some handy typedefs that make it easier to think about the low\r
+ * level code\r
+ */\r
+\r
+#ifndef _TYPE_H_\r
+#define _TYPE_H_\r
+\r
+typedef unsigned char byte;\r
+typedef unsigned short word;\r
+typedef unsigned long dword;\r
+typedef signed char sbyte;\r
+typedef signed short sword;\r
+typedef signed long sdword;\r
+\r
+#endif/*_TYPE_H_*/\r
+++ /dev/null
-\r
- == default ==\r
-\r
- USED block at 1d470016 of size 136\r
- USED block at 1d47009e of size 66\r
- USED block at 1d4700e0 of size 7966\r
- FREE block at 1d471ffe of size 8190\r
-OK - end of heap\r
-\r
- == near ==\r
-\r
- USED block at 0 of size 0\r
- USED block at 0 of size 0\r
- USED block at 0 of size 0\r
- USED block at 0 of size 0\r
- USED block at 0 of size 0\r
- USED block at 0 of size 0\r
- USED block at 0 of size 0\r
- USED block at 0 of size 0\r
- USED block at 0 of size 0\r
-OK - end of heap\r
-\r
- == far ==\r
-\r
- USED block at 0 of size 0\r
- USED block at 0 of size 0\r
- USED block at 0 of size 0\r
- USED block at 0 of size 0\r
-OK - end of heap\r
-\r
-Memory Type Total Used Free\r
----------------- -------- -------- --------\r
-Default 16358 8168 8190\r
-Near 31286 31286 0\r
-Far 16358 8168 8190\r
----------------- -------- -------- --------\r
-coreleft = 0\r
-farcoreleft = 65340\r
-GetFreeSize = 65358\r
-GetNearFreeSize = 0\r
-GetFarFreeSize = 65358\r
-memavl = 0\r
-stackavail = 17041\r
@$(REMOVECOMMAND) __WCL__.LNK
# @$(REMOVECOMMAND) *.smp
@$(REMOVECOMMAND) *.SMP
- @$(REMOVECOMMAND) 16.hed
- @$(REMOVECOMMAND) bakapi.hed
+ @$(REMOVECOMMAND) *.hed
@$(COPYCOMMAND) $(SRC)exmmtest.c $(EXMMTESTDIR)$(SRC)
@$(COPYCOMMAND) $(SRCLIB)16_mm.* $(EXMMTESTDIR)$(SRCLIB)
@$(COPYCOMMAND) $(SRCLIB)16_head.* $(EXMMTESTDIR)$(SRCLIB)
@$(COPYCOMMAND) $(SRCLIB)16_ca.* $(EXMMTESTDIR)$(SRCLIB)
+ @$(COPYCOMMAND) $(SRCLIB)16_hc.* $(EXMMTESTDIR)$(SRCLIB)
+ @$(COPYCOMMAND) $(SRCLIB)types.h* $(EXMMTESTDIR)$(SRCLIB)
main(int argc, char *argv[])\r
{\r
mminfo_t mm; mminfotype mmi;\r
+#ifdef __WATCOMC__\r
__segment sega;\r
void __based(sega)* bigbuffer;\r
+#endif\r
+#ifdef __BORLANDC__\r
+ void memptr* bigbuffer;\r
+#endif\r
#ifdef FILERL\r
char *bakapee;\r
word baka;\r
\r
#ifndef _LIBHEAD_H_\r
#define _LIBHEAD_H_\r
-#include <i86.h>\r
#include <dos.h>\r
#include <stdio.h>\r
#include <conio.h> // just for wait\r
#include <stdlib.h>\r
#include <malloc.h>\r
#include <ctype.h>\r
-#include <unistd.h>\r
#include <fcntl.h>\r
#include <sys/stat.h>\r
#include <mem.h>\r
+#ifdef __WATCOMC__\r
+#include <i86.h>\r
+#include <unistd.h>\r
#include <alloca.h>\r
#include "src/lib/nyan/kitten.h"\r
+#endif\r
#include "src/lib/types.h"\r
\r
//0000 test type def wwww\r
//#include <bios.h>
#include "src/lib/16_head.h"
#include "src/lib/16_hc.h"
-#include "src/lib/modex16.h"
+//#include "src/lib/modex16.h"
//#include "src/lib/16_ca.h"
//++++mh #include "src/lib/16_in.h"