From: sparky4 Date: Tue, 4 Aug 2015 23:43:30 +0000 (-0500) Subject: making a universal version ^^ X-Git-Url: http://4ch.mooo.com/gitweb/?a=commitdiff_plain;h=ae78bd882805933536b727ae5623b2d2606ca503;p=16.git making a universal version ^^ new file: 16/exmmtest/src/exmmtest.c new file: 16/exmmtest/src/lib/16_ca.c new file: 16/exmmtest/src/lib/16_ca.h new file: 16/exmmtest/src/lib/16_head.c new file: 16/exmmtest/src/lib/16_head.h new file: 16/exmmtest/src/lib/16_mm.c new file: 16/exmmtest/src/lib/16_mm.h modified: makefile modified: src/lib/16_head.h --- diff --git a/16/exmmtest/src/exmmtest.c b/16/exmmtest/src/exmmtest.c new file mode 100644 index 00000000..bee5e1dc --- /dev/null +++ b/16/exmmtest/src/exmmtest.c @@ -0,0 +1,147 @@ +/* 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 , or + * write to the Free Software Foundation, Inc., 51 Franklin Street, + * Fifth Floor, Boston, MA 02110-1301 USA. + * + */ +/* + exmm test +*/ +#include +#include + +#include "src/lib/16_head.h" +#include "src/lib/16_ca.h" +#include "src/lib/16_mm.h" +#include "src/lib/16_hc.h" +//#include "src/lib/modex16.h" +#pragma hdrstop + +#pragma warn -pro +#pragma warn -use + +//file load or read definition +#define FILERL +//#define FILEREAD + +void +main(int argc, char *argv[]) +{ + mminfo_t mm; mminfotype mmi; + __segment sega; + void __based(sega)* bigbuffer; +#ifdef FILERL + char *bakapee; + word baka; +#endif + //static page_t screen; + + printf("&main()= %Fp\n", *argv[0]); + 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); +#endif + mm.mmstarted=0; + +#ifdef FILERL + if(argv[1]) bakapee = argv[1]; + else bakapee = "data/koishi~.pcx"; +#endif + + textInit(); + + /* setup camera and screen~ */ + //bug!!! + //screen = modexDefaultPage(); + /*screen.width += (16*2); + screen.height += (16*2);*/ + + printf("main()=%Fp start MM\n", *argv[0]); + MM_Startup(&mm, &mmi); + //PM_Startup(); + //PM_UnlockMainMem(); + CA_Startup(); + printf(" done!\n"); + printf("&main()= %Fp\n", *argv[0]); + printf("bigbuffer= %Fp\n", bigbuffer); + printf("&bigbuffer= %Fp\n", &bigbuffer); + printf("bigbuffer= %04x\n", bigbuffer); + printf("&bigbuffer= %04x\n", &bigbuffer); +// getch(); +#ifdef FILERL +// bakapeehandle = open(bakapee,O_RDONLY | O_BINARY, S_IREAD); +// 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(sega, 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: %lu\n", (dword)(GetNearFreeSize())); + printf("Total far free: %lu\n", (dword)(GetFarFreeSize())); + getch();*/ + printf("\n"); + heapdump(); + //printf("core left: %lu\n", (dword)_coreleft()); + //printf("far core left: %lu\n", (dword)_farcoreleft()); + //printf("based core left: %lu\n", (dword)_basedcoreleft()); + //printf("huge core left: %lu\n", (dword)_hugecoreleft()); +} diff --git a/16/exmmtest/src/lib/16_ca.c b/16/exmmtest/src/lib/16_ca.c new file mode 100644 index 00000000..f74a5710 --- /dev/null +++ b/16/exmmtest/src/lib/16_ca.c @@ -0,0 +1,2232 @@ +/* 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_CA.C + +/* +============================================================================= + +Id Software Caching Manager +--------------------------- + +Must be started BEFORE the memory manager, because it needs to get the headers +loaded into the data segment + +============================================================================= +*/ + +#include "src/lib/16_ca.h" +//#include "ID_STRS.H" + +//#define THREEBYTEGRSTARTS + +/* +============================================================================= + + LOCAL CONSTANTS + +============================================================================= +*/ + +typedef struct +{ + unsigned bit0,bit1; // 0-255 is a character, > is a pointer to a node +} huffnode; + + +/*typedef struct +{ + unsigned RLEWtag; + long headeroffsets[100]; + byte tileinfo[]; +} mapfiletype;*/ + + +/* +============================================================================= + + GLOBAL VARIABLES + +============================================================================= +*/ + +/*byte _seg *tinf; +int mapon; + +unsigned _seg *mapsegs[3]; +maptype _seg *mapheaderseg[NUMMAPS]; +byte _seg *audiosegs[NUMSNDCHUNKS]; +void _seg *grsegs[NUMCHUNKS]; + +byte far grneeded[NUMCHUNKS]; +byte ca_levelbit,ca_levelnum;*/ + +int profilehandle,debughandle; + +void (*drawcachebox) (char *title, unsigned numcache); +void (*updatecachebox) (void); +void (*finishcachebox) (void); + +/* +============================================================================= + + LOCAL VARIABLES + +============================================================================= +*/ + +/*extern long far CGAhead; +extern long far EGAhead; +extern byte CGAdict; +extern byte EGAdict; +extern byte far maphead; +extern byte mapdict; +extern byte far audiohead; +extern byte audiodict; + + +long _seg *grstarts; // array of offsets in egagraph, -1 for sparse +long _seg *audiostarts; // array of offsets in audio / audiot + +#ifdef GRHEADERLINKED +huffnode *grhuffman; +#else +huffnode grhuffman[255]; +#endif + +#ifdef AUDIOHEADERLINKED +huffnode *audiohuffman; +#else +huffnode audiohuffman[255]; +#endif + + +int grhandle; // handle to EGAGRAPH +int maphandle; // handle to MAPTEMP / GAMEMAPS +int audiohandle; // handle to AUDIOT / AUDIO + +long chunkcomplen,chunkexplen; + +SDMode oldsoundmode; + + + +void CAL_DialogDraw (char *title,unsigned numcache); +void CAL_DialogUpdate (void); +void CAL_DialogFinish (void);*/ +//void CAL_CarmackExpand (unsigned far *source, unsigned far *dest,unsigned length); + + +/*++++#ifdef THREEBYTEGRSTARTS +#define FILEPOSSIZE 3 +//#define GRFILEPOS(c) (*(long far *)(((byte far *)grstarts)+(c)*3)&0xffffff) +long GRFILEPOS(int c) +{ + long value; + int offset; + + offset = c*3; + + value = *(long far *)(((byte far *)grstarts)+offset); + + value &= 0x00ffffffl; + + if (value == 0xffffffl) + value = -1; + + return value; +}; +#else +#define FILEPOSSIZE 4 +#define GRFILEPOS(c) (grstarts[c]) +#endif*/ + +/* +============================================================================= + + LOW LEVEL ROUTINES + +============================================================================= +*/ + +/* +============================ += += CA_OpenDebug / CA_CloseDebug += += Opens a binary file with the handle "debughandle" += +============================ +*/ +void CA_OpenDebug(void) +{ + unlink("debug.16"); + debughandle = open("debug.16", O_CREAT | O_WRONLY | O_TEXT); +} + +void CA_CloseDebug(void) +{ + close(debughandle); +} + + + +/* +============================ += += CAL_GetGrChunkLength += += Gets the length of an explicit length chunk (not tiles) += The file pointer is positioned so the compressed data can be read in next. += +============================ +*/ +/*++++ +void CAL_GetGrChunkLength (int chunk) +{ + lseek(grhandle,GRFILEPOS(chunk),SEEK_SET); + read(grhandle,&chunkexplen,sizeof(chunkexplen)); + chunkcomplen = GRFILEPOS(chunk+1)-GRFILEPOS(chunk)-4; +}*/ + + +/* +========================== += += CA_FarRead += += Read from a file to a far pointer += +========================== +*/ + +boolean CA_FarRead(int handle, byte huge *dest, dword length, mminfo_t *mm) +{ + boolean flag; + /*dword fat=0; + word segm=0; + //if(mm->EMSVer<0x40) + if(length>0xfffflu) + { + printf("File is a fat bakapee\n"); + segm=(length%0xfffflu)-1; + fat=segm*0xfffflu; + length-=fat; +// printf("CA_FarRead doesn't support 64K reads yet!\n"); + } + + if(!fat&&!segm) + {*/ + __asm + { + push ds + mov bx,[handle] + mov cx,[WORD PTR length] + mov dx,[WORD PTR dest] + mov ds,[WORD PTR dest+2] + mov ah,0x3f // READ w/handle + int 21h + pop ds + jnc good + mov errno,ax + mov flag,0 + jmp End +good: + cmp ax,[WORD PTR length] + je done +// errno = EINVFMT; // user manager knows this is bad read + mov flag,0 + jmp End +done: + mov flag,1 +End: + } + return flag; + //}else return 0;//todo: EXPAND!!! +} + + +/* +========================== += += CA_SegWrite += += Write from a file to a far pointer += +========================== +*/ + +boolean CA_FarWrite(int handle, byte huge *source, dword length, mminfo_t *mm) +{ + boolean flag; + /*dword fat=0; + word segm=0; + //if(mm->EMSVer<0x40) + if(length>0xfffflu) + { + printf("File is a fat bakapee\n"); + segm=(length%0xfffflu)-1; + fat=segm*0xfffflu; + length-=fat; +// printf("CA_FarRead doesn't support 64K reads yet!\n"); + } + + if(!fat&&!segm) + {*/ + __asm + { + push ds + mov bx,[handle] + mov cx,[WORD PTR length] + mov dx,[WORD PTR source] + mov ds,[WORD PTR source+2] + mov ah,0x40 // WRITE w/handle + int 21h + pop ds + jnc good + mov errno,ax + mov flag,0 + jmp End +good: + cmp ax,[WORD PTR length] + je done + //errno = ENOMEM; // user manager knows this is bad write + mov flag,0 + jmp End +done: + mov flag,1 +End: + } + return flag; + //}else return 0; +} + + +/* +========================== += += CA_ReadFile += += Reads a file into an allready allocated buffer += +========================== +*/ + +boolean CA_ReadFile(char *filename, memptr *ptr, mminfo_t *mm) +{ + int handle; + dword size; + //long size; + + if((handle = open(filename,O_RDONLY | O_BINARY, S_IREAD)) == -1) + return false; + + size = filelength(handle); + if(!CA_FarRead(handle,*ptr,size, mm)) + { + close(handle); + return false; + } + close(handle); + return true; +} + + + +/* +========================== += += CA_LoadFile += += Allocate space for and load a file += +========================== +*/ + +boolean CA_LoadFile(char *filename, memptr *ptr, mminfo_t *mm, mminfotype *mmi) +{ + int handle; + dword size; + //long size; + + if((handle = open(filename,O_RDONLY | O_BINARY, S_IREAD)) == -1) + return false; + + size = filelength (handle); + MM_GetPtr(ptr,size, mm, mmi); + if(!CA_FarRead(handle,*ptr,size, mm)) + { + close(handle); + return false; + } + close(handle); + return true; +} + +/* +============================================================================ + + COMPRESSION routines, see JHUFF.C for more + +============================================================================ +*/ + + + +/* +=============== += += CAL_OptimizeNodes += += Goes through a huffman table and changes the 256-511 node numbers to the += actular address of the node. Must be called before CAL_HuffExpand += +=============== +*/ + +void CAL_OptimizeNodes(huffnode *table) +{ + huffnode *node; + int i; + + node = table; + + for (i=0;i<255;i++) + { + if (node->bit0 >= 256) + node->bit0 = (unsigned)(table+(node->bit0-256)); + if (node->bit1 >= 256) + node->bit1 = (unsigned)(table+(node->bit1-256)); + node++; + } +} + + + +/* +====================== += += CAL_HuffExpand += += Length is the length of the EXPANDED data += +====================== +*/ + +/*++++void CAL_HuffExpand (byte huge *source, byte huge *dest, + long length,huffnode *hufftable) +{ +// unsigned bit,byte,node,code; + unsigned sourceseg,sourceoff,destseg,destoff,endoff; + huffnode *headptr; +// huffnode *nodeon; + + headptr = hufftable+254; // head node is allways node 254 + + source++; // normalize + source--; + dest++; + dest--; + + sourceseg = FP_SEG(source); + sourceoff = FP_OFF(source); + destseg = FP_SEG(dest); + destoff = FP_OFF(dest); + endoff = destoff+length; + +// +// ds:si source +// es:di dest +// ss:bx node pointer +// + + if (length <0xfff0) + { + +//-------------------------- +// expand less than 64k of data +//-------------------------- + + __asm + { + mov bx,[headptr] + + mov si,[sourceoff] + mov di,[destoff] + mov es,[destseg] + mov ds,[sourceseg] + mov ax,[endoff] + + mov ch,[si] // load first byte + inc si + mov cl,1 + +expandshort: + test ch,cl // bit set? + jnz bit1short + mov dx,[ss:bx] // take bit0 path from node + shl cl,1 // advance to next bit position + jc newbyteshort + jnc sourceupshort + +bit1short: +asm mov dx,[ss:bx+2] // take bit1 path +asm shl cl,1 // advance to next bit position +asm jnc sourceupshort + +newbyteshort: +asm mov ch,[si] // load next byte +asm inc si +asm mov cl,1 // back to first bit + +sourceupshort: +asm or dh,dh // if dx<256 its a byte, else move node +asm jz storebyteshort +asm mov bx,dx // next node = (huffnode *)code +asm jmp expandshort + +storebyteshort: +asm mov [es:di],dl +asm inc di // write a decopmpressed byte out +asm mov bx,[headptr] // back to the head node for next bit + +asm cmp di,ax // done? +asm jne expandshort + } + } + else + { + +//-------------------------- +// expand more than 64k of data +//-------------------------- + + length--; + + __asm + { +asm mov bx,[headptr] +asm mov cl,1 + +asm mov si,[sourceoff] +asm mov di,[destoff] +asm mov es,[destseg] +asm mov ds,[sourceseg] + +asm lodsb // load first byte + +expand: +asm test al,cl // bit set? +asm jnz bit1 +asm mov dx,[ss:bx] // take bit0 path from node +asm jmp gotcode +bit1: +asm mov dx,[ss:bx+2] // take bit1 path + +gotcode: +asm shl cl,1 // advance to next bit position +asm jnc sourceup +asm lodsb +asm cmp si,0x10 // normalize ds:si +asm jb sinorm +asm mov cx,ds +asm inc cx +asm mov ds,cx +asm xor si,si +sinorm: +asm mov cl,1 // back to first bit + +sourceup: +asm or dh,dh // if dx<256 its a byte, else move node +asm jz storebyte +asm mov bx,dx // next node = (huffnode *)code +asm jmp expand + +storebyte: +asm mov [es:di],dl +asm inc di // write a decopmpressed byte out +asm mov bx,[headptr] // back to the head node for next bit + +asm cmp di,0x10 // normalize es:di +asm jb dinorm +asm mov dx,es +asm inc dx +asm mov es,dx +asm xor di,di +dinorm: + +asm sub [WORD PTR ss:length],1 +asm jnc expand +asm dec [WORD PTR ss:length+2] +asm jns expand // when length = ffff ffff, done + } + } + + __asm + { + mov ax,ss + mov ds,ax + } + +}*/ + + +/* +====================== += += CAL_CarmackExpand += += Length is the length of the EXPANDED data += +====================== +*/ +/*++++ +#define NEARTAG 0xa7 +#define FARTAG 0xa8 + +void CAL_CarmackExpand (unsigned far *source, unsigned far *dest, unsigned length) +{ + unsigned ch,chhigh,count,offset; + unsigned far *copyptr, far *inptr, far *outptr; + + length/=2; + + inptr = source; + outptr = dest; + + while (length) + { + ch = *inptr++; + chhigh = ch>>8; + if (chhigh == NEARTAG) + { + count = ch&0xff; + if (!count) + { // have to insert a word containing the tag byte + ch |= *((unsigned char far *)inptr)++; + *outptr++ = ch; + length--; + } + else + { + offset = *((unsigned char far *)inptr)++; + copyptr = outptr - offset; + length -= count; + while (count--) + *outptr++ = *copyptr++; + } + } + else if (chhigh == FARTAG) + { + count = ch&0xff; + if (!count) + { // have to insert a word containing the tag byte + ch |= *((unsigned char far *)inptr)++; + *outptr++ = ch; + length --; + } + else + { + offset = *inptr++; + copyptr = dest + offset; + length -= count; + while (count--) + *outptr++ = *copyptr++; + } + } + else + { + *outptr++ = ch; + length --; + } + } +} +*/ + + +/* +====================== += += CA_RLEWcompress += +====================== +*/ +/*++++ +long CA_RLEWCompress (unsigned huge *source, long length, unsigned huge *dest, + unsigned rlewtag) +{ + long complength; + unsigned value,count,i; + unsigned huge *start,huge *end; + + start = dest; + + end = source + (length+1)/2; + +// +// compress it +// + do + { + count = 1; + value = *source++; + while (*source == value && source3 || value == rlewtag) + { + // + // send a tag / count / value string + // + *dest++ = rlewtag; + *dest++ = count; + *dest++ = value; + } + else + { + // + // send word without compressing + // + for (i=1;i<=count;i++) + *dest++ = value; + } + + } while (source0 + MM_GetPtr(&(memptr)pictable,NUMPICS*sizeof(pictabletype)); + CAL_GetGrChunkLength(STRUCTPIC); // position file pointer + MM_GetPtr(&compseg,chunkcomplen); + CA_FarRead (grhandle,compseg,chunkcomplen); + CAL_HuffExpand (compseg, (byte huge *)pictable,NUMPICS*sizeof(pictabletype),grhuffman); + MM_FreePtr(&compseg); +#endif + +#if NUMPICM>0 + MM_GetPtr(&(memptr)picmtable,NUMPICM*sizeof(pictabletype)); + CAL_GetGrChunkLength(STRUCTPICM); // position file pointer + MM_GetPtr(&compseg,chunkcomplen); + CA_FarRead (grhandle,compseg,chunkcomplen); + CAL_HuffExpand (compseg, (byte huge *)picmtable,NUMPICS*sizeof(pictabletype),grhuffman); + MM_FreePtr(&compseg); +#endif + +#if NUMSPRITES>0 + MM_GetPtr(&(memptr)spritetable,NUMSPRITES*sizeof(spritetabletype)); + CAL_GetGrChunkLength(STRUCTSPRITE); // position file pointer + MM_GetPtr(&compseg,chunkcomplen); + CA_FarRead (grhandle,compseg,chunkcomplen); + CAL_HuffExpand (compseg, (byte huge *)spritetable,NUMSPRITES*sizeof(spritetabletype),grhuffman); + MM_FreePtr(&compseg); +#endif + +}*/ + +//========================================================================== + + +/* +====================== += += CAL_SetupMapFile += +====================== +*/ + +/*void CAL_SetupMapFile (void) +{ + int handle; + long length; + +// +// load maphead.ext (offsets and tileinfo for map file) +// +#ifndef MAPHEADERLINKED + if ((handle = open("MAPHEAD."EXT, + O_RDONLY | O_BINARY, S_IREAD)) == -1) + Quit ("Can't open MAPHEAD."EXT"!"); + length = filelength(handle); + MM_GetPtr (&(memptr)tinf,length); + CA_FarRead(handle, tinf, length); + close(handle); +#else + + tinf = (byte _seg *)FP_SEG(&maphead); + +#endif + +// +// open the data file +// +#ifdef MAPHEADERLINKED + if ((maphandle = open("GAMEMAPS."EXT, + O_RDONLY | O_BINARY, S_IREAD)) == -1) + Quit ("Can't open GAMEMAPS."EXT"!"); +#else + if ((maphandle = open("MAPTEMP."EXT, + O_RDONLY | O_BINARY, S_IREAD)) == -1) + Quit ("Can't open MAPTEMP."EXT"!"); +#endif +}*/ + +//========================================================================== + + +/* +====================== += += CAL_SetupAudioFile += +====================== +*/ + +/*void CAL_SetupAudioFile (void) +{ + int handle; + long length; + +// +// load maphead.ext (offsets and tileinfo for map file) +// +#ifndef AUDIOHEADERLINKED + if ((handle = open("AUDIOHED."EXT, + O_RDONLY | O_BINARY, S_IREAD)) == -1) + Quit ("Can't open AUDIOHED."EXT"!"); + length = filelength(handle); + MM_GetPtr (&(memptr)audiostarts,length); + CA_FarRead(handle, (byte far *)audiostarts, length); + close(handle); +#else + audiohuffman = (huffnode *)&audiodict; + CAL_OptimizeNodes (audiohuffman); + audiostarts = (long _seg *)FP_SEG(&audiohead); +#endif + +// +// open the data file +// +#ifndef AUDIOHEADERLINKED + if ((audiohandle = open("AUDIOT."EXT, + O_RDONLY | O_BINARY, S_IREAD)) == -1) + Quit ("Can't open AUDIOT."EXT"!"); +#else + if ((audiohandle = open("AUDIO."EXT, + O_RDONLY | O_BINARY, S_IREAD)) == -1) + Quit ("Can't open AUDIO."EXT"!"); +#endif +}*/ + +//========================================================================== + + +/* +====================== += += CA_Startup += += Open all files and load in headers += +====================== +*/ + +void CA_Startup(void) +{ +#ifdef PROFILE + unlink("profile.16"); + profilehandle = open("profile.16", O_CREAT | O_WRONLY | O_TEXT); +#endif +/*++++ +// MDM begin - (GAMERS EDGE) +// + if(!FindFile("AUDIO."EXT,NULL,2)) + Quit("CA_Startup(): Can't find audio files."); +// +// MDM end + +#ifndef NOAUDIO + CAL_SetupAudioFile(); +#endif + +// MDM begin - (GAMERS EDGE) +// + if (!FindFile("GAMEMAPS."EXT,NULL,1)) + Quit("CA_Startup(): Can't find level files."); +// +// MDM end + +#ifndef NOMAPS + CAL_SetupMapFile (); +#endif + +// MDM begin - (GAMERS EDGE) +// + if (!FindFile("EGAGRAPH."EXT,NULL,2)) + Quit("CA_Startup(): Can't find graphics files."); +// +// MDM end + +#ifndef NOGRAPHICS + CAL_SetupGrFile (); +#endif + + mapon = -1; + ca_levelbit = 1; + ca_levelnum = 0; + + drawcachebox = CAL_DialogDraw; + updatecachebox = CAL_DialogUpdate; + finishcachebox = CAL_DialogFinish;*/ +} + +//========================================================================== + + +/* +====================== += += CA_Shutdown += += Closes all files += +====================== +*/ + +void CA_Shutdown(void) +{ +#ifdef PROFILE + close(profilehandle); +#endif +/*++++ + close(maphandle); + close(grhandle); + close(audiohandle);*/ +} + +//=========================================================================== + +/* +====================== += += CA_CacheAudioChunk += +====================== +*/ +/*++++ +void CA_CacheAudioChunk (int chunk) +{ + long pos,compressed; +#ifdef AUDIOHEADERLINKED + long expanded; + memptr bigbufferseg; + byte far *source; +#endif + + if (audiosegs[chunk]) + { + MM_SetPurge (&(memptr)audiosegs[chunk],0); + return; // allready in memory + } + +// MDM begin - (GAMERS EDGE) +// + if (!FindFile("AUDIO."EXT,NULL,2)) + Quit("CA_CacheAudioChunk(): Can't find audio files."); +// +// MDM end + +// +// load the chunk into a buffer, either the miscbuffer if it fits, or allocate +// a larger buffer +// + pos = audiostarts[chunk]; + compressed = audiostarts[chunk+1]-pos; + + lseek(audiohandle,pos,SEEK_SET); + +#ifndef AUDIOHEADERLINKED + + MM_GetPtr (&(memptr)audiosegs[chunk],compressed); + if (mmerror) + return; + + CA_FarRead(audiohandle,audiosegs[chunk],compressed); + +#else + + if (compressed<=BUFFERSIZE) + { + CA_FarRead(audiohandle,bufferseg,compressed); + source = bufferseg; + } + else + { + MM_GetPtr(&bigbufferseg,compressed); + if (mmerror) + return; + MM_SetLock (&bigbufferseg,true); + CA_FarRead(audiohandle,bigbufferseg,compressed); + source = bigbufferseg; + } + + expanded = *(long far *)source; + source += 4; // skip over length + MM_GetPtr (&(memptr)audiosegs[chunk],expanded); + if (mmerror) + goto done; + CAL_HuffExpand (source,audiosegs[chunk],expanded,audiohuffman); + +done: + if (compressed>BUFFERSIZE) + MM_FreePtr(&bigbufferseg); +#endif +}*/ + +//=========================================================================== + +/* +====================== += += CA_LoadAllSounds += += Purges all sounds, then loads all new ones (mode switch) += +====================== +*/ +/*++++ +void CA_LoadAllSounds (void) +{ + unsigned start,i; + + switch (oldsoundmode) + { + case sdm_Off: + goto cachein; + case sdm_PC: + start = STARTPCSOUNDS; + break; + case sdm_AdLib: + start = STARTADLIBSOUNDS; + break; + } + + for (i=0;iwidth*spr->height; + MM_GetPtr (&grsegs[chunk],smallplane*2+MAXSHIFTS*6); + if (mmerror) + return; + dest = (spritetype _seg *)grsegs[chunk]; + dest->sourceoffset[0] = MAXSHIFTS*6; // start data after 3 unsigned tables + dest->planesize[0] = smallplane; + dest->width[0] = spr->width; + +// +// expand the unshifted shape +// + CAL_HuffExpand (compressed, &dest->data[0],smallplane*2,grhuffman); + +#endif + + +#if GRMODE == EGAGR + +// +// calculate sizes +// + spr = &spritetable[chunk-STARTSPRITES]; + smallplane = spr->width*spr->height; + bigplane = (spr->width+1)*spr->height; + + shiftstarts[0] = MAXSHIFTS*6; // start data after 3 unsigned tables + shiftstarts[1] = shiftstarts[0] + smallplane*5; // 5 planes in a sprite + shiftstarts[2] = shiftstarts[1] + bigplane*5; + shiftstarts[3] = shiftstarts[2] + bigplane*5; + shiftstarts[4] = shiftstarts[3] + bigplane*5; // nothing ever put here + + expanded = shiftstarts[spr->shifts]; + MM_GetPtr (&grsegs[chunk],expanded); + if (mmerror) + return; + dest = (spritetype _seg *)grsegs[chunk]; + +// +// expand the unshifted shape +// + CAL_HuffExpand (compressed, &dest->data[0],smallplane*5,grhuffman); + +// +// make the shifts! +// + switch (spr->shifts) + { + case 1: + for (i=0;i<4;i++) + { + dest->sourceoffset[i] = shiftstarts[0]; + dest->planesize[i] = smallplane; + dest->width[i] = spr->width; + } + break; + + case 2: + for (i=0;i<2;i++) + { + dest->sourceoffset[i] = shiftstarts[0]; + dest->planesize[i] = smallplane; + dest->width[i] = spr->width; + } + for (i=2;i<4;i++) + { + dest->sourceoffset[i] = shiftstarts[1]; + dest->planesize[i] = bigplane; + dest->width[i] = spr->width+1; + } + CAL_ShiftSprite ((unsigned)grsegs[chunk],dest->sourceoffset[0], + dest->sourceoffset[2],spr->width,spr->height,4,true); + break; + + case 4: + dest->sourceoffset[0] = shiftstarts[0]; + dest->planesize[0] = smallplane; + dest->width[0] = spr->width; + + dest->sourceoffset[1] = shiftstarts[1]; + dest->planesize[1] = bigplane; + dest->width[1] = spr->width+1; + CAL_ShiftSprite ((unsigned)grsegs[chunk],dest->sourceoffset[0], + dest->sourceoffset[1],spr->width,spr->height,2,true); + + dest->sourceoffset[2] = shiftstarts[2]; + dest->planesize[2] = bigplane; + dest->width[2] = spr->width+1; + CAL_ShiftSprite ((unsigned)grsegs[chunk],dest->sourceoffset[0], + dest->sourceoffset[2],spr->width,spr->height,4,true); + + dest->sourceoffset[3] = shiftstarts[3]; + dest->planesize[3] = bigplane; + dest->width[3] = spr->width+1; + CAL_ShiftSprite ((unsigned)grsegs[chunk],dest->sourceoffset[0], + dest->sourceoffset[3],spr->width,spr->height,6,true); + + break; + + default: + Quit ("CAL_CacheSprite: Bad shifts number!"); + } + +#endif +}*/ + +//=========================================================================== + + +/* +====================== += += CAL_ExpandGrChunk += += Does whatever is needed with a pointer to a compressed chunk += +====================== +*/ +/*++++ +void CAL_ExpandGrChunk (int chunk, byte far *source) +{ + long expanded; + + + if (chunk >= STARTTILE8 && chunk < STARTEXTERNS) + { + // + // expanded sizes of tile8/16/32 are implicit + // + +#if GRMODE == EGAGR +#define BLOCK 32 +#define MASKBLOCK 40 +#endif + +#if GRMODE == CGAGR +#define BLOCK 16 +#define MASKBLOCK 32 +#endif + + if (chunk=STARTSPRITES && chunk< STARTTILE8) + CAL_CacheSprite(chunk,source); + else + { + MM_GetPtr (&grsegs[chunk],expanded); + if (mmerror) + return; + CAL_HuffExpand (source,grsegs[chunk],expanded,grhuffman); + } +} +*/ + +/* +====================== += += CAL_ReadGrChunk += += Gets a chunk off disk, optimizing reads to general buffer += +====================== +*/ +/*++++ +void CAL_ReadGrChunk (int chunk) +{ + long pos,compressed; + memptr bigbufferseg; + byte far *source; + int next; + +// +// load the chunk into a buffer, either the miscbuffer if it fits, or allocate +// a larger buffer +// + pos = GRFILEPOS(chunk); + if (pos<0) // $FFFFFFFF start is a sparse tile + return; + + next = chunk +1; + while (GRFILEPOS(next) == -1) // skip past any sparse tiles + next++; + + compressed = GRFILEPOS(next)-pos; + + lseek(grhandle,pos,SEEK_SET); + + if (compressed<=BUFFERSIZE) + { + CA_FarRead(grhandle,bufferseg,compressed); + source = bufferseg; + } + else + { + MM_GetPtr(&bigbufferseg,compressed); + if (mmerror) + return; + MM_SetLock (&bigbufferseg,true); + CA_FarRead(grhandle,bigbufferseg,compressed); + source = bigbufferseg; + } + + CAL_ExpandGrChunk (chunk,source); + + if (compressed>BUFFERSIZE) + MM_FreePtr(&bigbufferseg); +} +*/ +/* +====================== += += CA_CacheGrChunk += += Makes sure a given chunk is in memory, loadiing it if needed += +====================== +*/ +/*++++ +void CA_CacheGrChunk (int chunk) +{ + long pos,compressed; + memptr bigbufferseg; + byte far *source; + int next; + + grneeded[chunk] |= ca_levelbit; // make sure it doesn't get removed + if (grsegs[chunk]) + { + MM_SetPurge (&grsegs[chunk],0); + return; // allready in memory + } + +// MDM begin - (GAMERS EDGE) +// + if (!FindFile("EGAGRAPH."EXT,NULL,2)) + Quit("CA_CacheGrChunk(): Can't find graphics files."); +// +// MDM end + +// +// load the chunk into a buffer, either the miscbuffer if it fits, or allocate +// a larger buffer +// + pos = GRFILEPOS(chunk); + if (pos<0) // $FFFFFFFF start is a sparse tile + return; + + next = chunk +1; + while (GRFILEPOS(next) == -1) // skip past any sparse tiles + next++; + + compressed = GRFILEPOS(next)-pos; + + lseek(grhandle,pos,SEEK_SET); + + if (compressed<=BUFFERSIZE) + { + CA_FarRead(grhandle,bufferseg,compressed); + source = bufferseg; + } + else + { + MM_GetPtr(&bigbufferseg,compressed); + MM_SetLock (&bigbufferseg,true); + CA_FarRead(grhandle,bigbufferseg,compressed); + source = bigbufferseg; + } + + CAL_ExpandGrChunk (chunk,source); + + if (compressed>BUFFERSIZE) + MM_FreePtr(&bigbufferseg); +} +*/ + + +//========================================================================== + +/* +====================== += += CA_CacheMap += +====================== +*/ +/*++++ +void CA_CacheMap (int mapnum) +{ + long pos,compressed; + int plane; + memptr *dest,bigbufferseg; + unsigned size; + unsigned far *source; +#ifdef MAPHEADERLINKED + memptr buffer2seg; + long expanded; +#endif + + +// MDM begin - (GAMERS EDGE) +// + if (!FindFile("GAMEMAPS."EXT,NULL,1)) + Quit("CA_CacheMap(): Can't find level files."); +// +// MDM end + + +// +// free up memory from last map +// + if (mapon>-1 && mapheaderseg[mapon]) + MM_SetPurge (&(memptr)mapheaderseg[mapon],3); + for (plane=0;planeheaderoffsets[mapnum]; + if (pos<0) // $FFFFFFFF start is a sparse map + Quit ("CA_CacheMap: Tried to load a non existent map!"); + + MM_GetPtr(&(memptr)mapheaderseg[mapnum],sizeof(maptype)); + lseek(maphandle,pos,SEEK_SET); + CA_FarRead (maphandle,(memptr)mapheaderseg[mapnum],sizeof(maptype)); + } + else + MM_SetPurge (&(memptr)mapheaderseg[mapnum],0); + +// +// load the planes in +// If a plane's pointer still exists it will be overwritten (levels are +// allways reloaded, never cached) +// + + size = mapheaderseg[mapnum]->width * mapheaderseg[mapnum]->height * 2; + + for (plane = 0; planeplanestart[plane]; + compressed = mapheaderseg[mapnum]->planelength[plane]; + + if (!compressed) + continue; // the plane is not used in this game + + dest = &(memptr)mapsegs[plane]; + MM_GetPtr(dest,size); + + lseek(maphandle,pos,SEEK_SET); + if (compressed<=BUFFERSIZE) + source = bufferseg; + else + { + MM_GetPtr(&bigbufferseg,compressed); + MM_SetLock (&bigbufferseg,true); + source = bigbufferseg; + } + + CA_FarRead(maphandle,(byte far *)source,compressed); +#ifdef MAPHEADERLINKED + // + // unhuffman, then unRLEW + // The huffman'd chunk has a two byte expanded length first + // The resulting RLEW chunk also does, even though it's not really + // needed + // + expanded = *source; + source++; + MM_GetPtr (&buffer2seg,expanded); + CAL_CarmackExpand (source, (unsigned far *)buffer2seg,expanded); + CA_RLEWexpand (((unsigned far *)buffer2seg)+1,*dest,size, + ((mapfiletype _seg *)tinf)->RLEWtag); + MM_FreePtr (&buffer2seg); + +#else + // + // unRLEW, skipping expanded length + // + CA_RLEWexpand (source+1, *dest,size, + ((mapfiletype _seg *)tinf)->RLEWtag); +#endif + + if (compressed>BUFFERSIZE) + MM_FreePtr(&bigbufferseg); + } +}*/ + +//=========================================================================== + +/* +====================== += += CA_UpLevel += += Goes up a bit level in the needed lists and clears it out. += Everything is made purgable += +====================== +*/ +/*++++ +void CA_UpLevel (void) +{ + if (ca_levelnum==7) + Quit ("CA_UpLevel: Up past level 7!"); + + ca_levelbit<<=1; + ca_levelnum++; +}*/ + +//=========================================================================== + +/* +====================== += += CA_DownLevel += += Goes down a bit level in the needed lists and recaches += everything from the lower level += +====================== +*/ +/*++ +void CA_DownLevel (void) +{ + if (!ca_levelnum) + Quit ("CA_DownLevel: Down past level 0!"); + ca_levelbit>>=1; + ca_levelnum--; + CA_CacheMarks(NULL); +}*/ + +//=========================================================================== + +/* +====================== += += CA_ClearMarks += += Clears out all the marks at the current level += +====================== +*/ +/* +void CA_ClearMarks (void) +{ + int i; + + for (i=0;i>16; + if (xh - lastx > BARSTEP) + { + for (x=lastx;x<=xh;x++) +#if GRMODE == EGAGR + VWB_Vlin (thy,thy+13,x,14); +#endif +#if GRMODE == CGAGR + VWB_Vlin (thy,thy+13,x,SECONDCOLOR); +#endif + lastx = xh; + VW_UpdateScreen(); + } +}*/ + +/* +====================== += += CAL_DialogFinish += +====================== +*/ +/* +void CAL_DialogFinish (void) +{ + unsigned x,xh; + + xh = thx + NUMBARS; + for (x=lastx;x<=xh;x++) +#if GRMODE == EGAGR + VWB_Vlin (thy,thy+13,x,14); +#endif +#if GRMODE == CGAGR + VWB_Vlin (thy,thy+13,x,SECONDCOLOR); +#endif + VW_UpdateScreen(); + +}*/ + +//=========================================================================== + +/* +====================== += += CA_CacheMarks += +====================== +*//* +#define MAXEMPTYREAD 1024 + +void CA_CacheMarks (char *title) +{ + boolean dialog; + int i,next,numcache; + long pos,endpos,nextpos,nextendpos,compressed; + long bufferstart,bufferend; // file position of general buffer + byte far *source; + memptr bigbufferseg; + + dialog = (title!=NULL); + + numcache = 0; +// +// go through and make everything not needed purgable +// + for (i=0;i= endpos) + { + // data is allready in buffer + source = (byte _seg *)bufferseg+(pos-bufferstart); + } + else + { + // load buffer with a new block from disk + // try to get as many of the needed blocks in as possible + while ( next < NUMCHUNKS ) + { + while (next < NUMCHUNKS && + !(grneeded[next]&ca_levelbit && !grsegs[next])) + next++; + if (next == NUMCHUNKS) + continue; + + nextpos = GRFILEPOS(next); + while (GRFILEPOS(++next) == -1) // skip past any sparse tiles + ; + nextendpos = GRFILEPOS(next); + if (nextpos - endpos <= MAXEMPTYREAD + && nextendpos-pos <= BUFFERSIZE) + endpos = nextendpos; + else + next = NUMCHUNKS; // read pos to posend + } + + lseek(grhandle,pos,SEEK_SET); + CA_FarRead(grhandle,bufferseg,endpos-pos); + bufferstart = pos; + bufferend = endpos; + source = bufferseg; + } + } + else + { + // big chunk, allocate temporary buffer + MM_GetPtr(&bigbufferseg,compressed); + if (mmerror) + return; + MM_SetLock (&bigbufferseg,true); + lseek(grhandle,pos,SEEK_SET); + CA_FarRead(grhandle,bigbufferseg,compressed); + source = bigbufferseg; + } + + CAL_ExpandGrChunk (i,source); + if (mmerror) + return; + + if (compressed>BUFFERSIZE) + MM_FreePtr(&bigbufferseg); + + } + +// +// finish up any thermometer remnants +// + if (dialog && finishcachebox) + finishcachebox(); +}*/ diff --git a/16/exmmtest/src/lib/16_ca.h b/16/exmmtest/src/lib/16_ca.h new file mode 100644 index 00000000..77809387 --- /dev/null +++ b/16/exmmtest/src/lib/16_ca.h @@ -0,0 +1,116 @@ +/* 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_CA.H +#ifndef __16_CA__ +#define __16_CA__ + +#ifndef __16_MM__ +#include "src/lib/16_head.h" +#include "src/lib/16_mm.h" +#endif + +//=========================================================================== + +//#define NOMAPS +//#define NOGRAPHICS +//#define NOAUDIO + +//#define MAPHEADERLINKED +//#define GRHEADERLINKED +//#define AUDIOHEADERLINKED + +//#define NUMMAPS 39 +//#define MAPPLANES 3 +#define PROFILE + +//=========================================================================== + +/*typedef struct +{ + long planestart[3]; + unsigned planelength[3]; + unsigned width,height; + char name[16]; +} maptype;*/ + +//=========================================================================== + +/*extern byte _seg *tinf; +extern int mapon; + +extern unsigned _seg *mapsegs[3]; +extern maptype _seg *mapheaderseg[NUMMAPS]; +extern byte _seg *audiosegs[NUMSNDCHUNKS]; +extern void _seg *grsegs[NUMCHUNKS]; + +extern byte far grneeded[NUMCHUNKS]; +extern byte ca_levelbit,ca_levelnum; + +extern char *titleptr[8];*/ + +extern int profilehandle,debughandle; + +// +// hooks for custom cache dialogs +// +extern void (*drawcachebox) (char *title, unsigned numcache); +extern void (*updatecachebox) (void); +extern void (*finishcachebox) (void); + +//=========================================================================== + +// just for the score box reshifting + +//void CAL_ShiftSprite (unsigned segment,unsigned source,unsigned dest,unsigned width, unsigned height, unsigned pixshift, boolean domask); + +//=========================================================================== + +void CA_OpenDebug (void); +void CA_CloseDebug (void); +boolean CA_FarRead (int handle, byte huge *dest, dword length, mminfo_t *mm); +boolean CA_FarWrite (int handle, byte huge *source, dword length, mminfo_t *mm); + +boolean CA_ReadFile (char *filename, memptr *ptr, mminfo_t *mm); +boolean CA_LoadFile (char *filename, memptr *ptr, mminfo_t *mm, mminfotype *mmi); + +//long CA_RLEWCompress (unsigned huge *source, long length, unsigned huge *dest,unsigned rlewtag); + +//void CA_RLEWexpand (unsigned huge *source, unsigned huge *dest,long length,unsigned rlewtag); + +void CA_Startup (void); +void CA_Shutdown (void); + +//void CA_CacheAudioChunk (int chunk); +//void CA_LoadAllSounds (void); + +/*void CA_UpLevel (void); +void CA_DownLevel (void); + +void CA_SetAllPurge (void); + +void CA_ClearMarks (void); +void CA_ClearAllMarks (void); + +#define CA_MarkGrChunk(chunk) grneeded[chunk]|=ca_levelbit + +void CA_CacheGrChunk (int chunk); +void CA_CacheMap (int mapnum); + +void CA_CacheMarks (char *title);*/ +#endif diff --git a/16/exmmtest/src/lib/16_head.c b/16/exmmtest/src/lib/16_head.c new file mode 100644 index 00000000..df0b31c7 --- /dev/null +++ b/16/exmmtest/src/lib/16_head.c @@ -0,0 +1,204 @@ +/* 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 , or + * write to the Free Software Foundation, Inc., 51 Franklin Street, + * Fifth Floor, Boston, MA 02110-1301 USA. + * + */ + +#include "src/lib/16_head.h" + +/* Function: Wait ********************************************************** +* +* Parameters: wait - time in microseconds +* +* Description: pauses for a specified number of microseconds. +* +*/ +void wait(clock_t wait){ + clock_t goal; + + if(!wait) return; + + goal = wait + clock(); + while((goal > clock()) && !kbhit()) ; +} /* End of wait */ + +long int +filesize(FILE *fp) +{ + long int save_pos, size_of_file; + + save_pos = ftell(fp); + fseek(fp, 0L, SEEK_END); + size_of_file = ftell(fp); + fseek(fp, save_pos, SEEK_SET); + return(size_of_file); +} + +void printmeminfoline(byte *strc, const byte *pee, size_t h_total, size_t h_used, size_t h_free) +{ + byte str[64]; + strcat(strc,pee); strcat(strc," "); ultoa((dword)h_total,str,10); strcat(strc,str); strcat(strc," "); ultoa((dword)h_used,str,10); strcat(strc,str); strcat(strc," "); ultoa((dword)h_free,str,10); strcat(strc,str); + strcat(strc,"\n"); +} + +void print_normal_entry(char *text, dword total, dword used, dword free, byte *str) +{ + printf("%-17s", text); + convert("%8sB ", total); + convert("%9sB ", used); + convert("%9sB\n", free); +} + +/* + * As for printf(), but format may only contain a single format specifier, + * which must be "%s" and is replaced with the string form of num with commas + * separating groups of three digits. + * + * e.g. convert("%s bytes", 1234567) -> "1,234,567 bytes" + */ +void convert(const char *format, dword num) +{ + int c, i, j, n; + char des[4*sizeof(dword)+3]; + union REGS regs; + struct SREGS sregs; + char mycountry[48]; /* probably 34 bytes are enough... */ + char ksep = ','; /* or . */ + + regs.x.ax = 0x3800; + sregs.ds = FP_SEG(&mycountry); + regs.x.dx = FP_OFF(&mycountry); + intdosx(®s,®s,&sregs); + if (regs.x.cflag == 0) { + ksep = mycountry[7]; /* 1000's separator */ + /* dsep = mycountry[9]; ** decimal separator */ + } + + n = sprintf(des, "%lu", num); + /* insert commas in the string */ + c = 3; + for (i = n - 3; i > 0; i--) { + if (c%3==0) { + for (j = n; j >= i; j--) + des[j+1] = des[j]; + des[i]=ksep; /* ',' */ + n++; + } + c++; + } + printf(format, des); +} + +/////////////////////////////////////////////////////////////////////////// +// +// US_CheckParm() - checks to see if a string matches one of a set of +// strings. The check is case insensitive. The routine returns the +// index of the string that matched, or -1 if no matches were found +// +/////////////////////////////////////////////////////////////////////////// +int +US_CheckParm(char *parm,char **strings) +{ + char cp,cs, + *p,*s; + int i; + + while (!isalpha(*parm)) // Skip non-alphas + parm++; + + for (i = 0;*strings && **strings;i++) + { + for (s = *strings++,p = parm,cs = cp = 0;cs == cp;) + { + cs = *s++; + if (!cs) + return(i); + cp = *p++; + + if (isupper(cs)) + cs = tolower(cs); + if (isupper(cp)) + cp = tolower(cp); + } + } + return(-1); +} + +/* +========================== += += Quit += +========================== +*/ + +/*void Quit(char *error, ...) +{ + short exit_code=0; + unsigned finscreen; + + va_list ap; + + va_start(ap,error); + +#ifndef CATALOG + if (!error) + { + CA_SetAllPurge (); + CA_CacheGrChunk (PIRACY); + finscreen = (unsigned)grsegs[PIRACY]; + } +#endif + + //ShutdownId (); + + if (error && *error) + { + vprintf(error,ap); + exit_code = 1; + } +#ifndef CATALOG + else + if (!NoWait) + { + movedata (finscreen,0,0xb800,0,4000); + bioskey (0); + } +#endif + + va_end(ap); + +#ifndef CATALOG + if (!error) + { + _argc = 2; + _argv[1] = "LAST.SHL"; + _argv[2] = "ENDSCN.SCN"; + _argv[3] = NULL; + if (execv("LOADSCN.EXE", _argv) == -1) + { + clrscr(); + puts("Couldn't find executable LOADSCN.EXE.\n"); + exit(1); + } + } +#endif + + exit(exit_code); +}*/ diff --git a/16/exmmtest/src/lib/16_head.h b/16/exmmtest/src/lib/16_head.h new file mode 100644 index 00000000..73cc0bda --- /dev/null +++ b/16/exmmtest/src/lib/16_head.h @@ -0,0 +1,194 @@ +/* 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 , 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 +#include +#include +#include // just for wait +#include // just for wait +#include +#include +#include +#include +#include +#include +#include +#include +#include "src/lib/nyan/kitten.h" +#include "src/lib/types.h" + +//0000 test type def wwww +struct list { + struct list __based(__self) *next; + int value; +}; + +/* 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 */ +extern int profilehandle,debughandle; //make it into game global + +#define __DEBUG__ + +#define nil ((void *)0) + +#ifdef __WATCOMC__ +#define peekb(segm,ofs) (*(byte far*)MK_FP((segm),(ofs))) +#define peekw(segm,ofs) (*(word far*)MK_FP((segm),(ofs))) +#define pokeb(segm,ofs,value) (peekb((segm),(ofs)) = (byte)(value)) +#define pokew(segm,ofs,value) (peekw((segm),(ofs)) = (word)(value)) + +typedef union REGPACK regs_t; +#endif + +typedef enum {false,true} boolean; + +#ifdef __WATCOMC__ +typedef void __based(__self) * memptr; +#endif +#ifdef __BORLANDC__ +typedef void _seg * memptr; +#endif +typedef struct +{ + int old_mode; //old video mode before game! + word frames_per_second; + clock_t t; + dword tiku; + word far* clock; + //handles for log files of the game gose here if wwww + //int heaphandle; +} global_game_variables_t; + +/* local function */ +void wait(clock_t wait); + +long int filesize(FILE *fp); +void printmeminfoline(byte *strc, const byte *pee, size_t h_total, size_t h_used, size_t h_free); +void print_normal_entry(char *text, dword total, dword used, dword free, byte *str); +void convert(const char *format, dword num); +int US_CheckParm(char *parm,char **strings); + +extern void CA_OpenDebug (void); +extern void CA_CloseDebug (void); + +#endif/*_LIBHEAD_H_*/ diff --git a/16/exmmtest/src/lib/16_mm.c b/16/exmmtest/src/lib/16_mm.c new file mode 100644 index 00000000..ba0b8bfe --- /dev/null +++ b/16/exmmtest/src/lib/16_mm.c @@ -0,0 +1,1610 @@ +/* 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 "src/lib/16_mm.h" +#pragma hdrstop + +#pragma warn -pro +#pragma warn -use + +/* +============================================================================= + + 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: + // + // 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: + 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: + 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: + 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: + 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;iEMSmem = (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: + 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;inumUMBs;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=(word)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; + mm->endid=0; + +// +// 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;immblocks[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"); + _nheapgrow(); + length=(dword)_memmax();//(dword)GetFreeSize(); + start = (void huge *)(mm->nearheap = _nmalloc(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=%lu len=%lu\n", start, segstart, seglength, length); + //heapdump(); + +// +// 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=%lu len=%lu\n", start, segstart, seglength, length); + //heapdump(); + + mmi->mainmem = mmi->nearheap + mmi->farheap; + +// getch(); + +//goto xmsskip; + +// +// 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 + } + +mmi->XMSmem=0; +goto xmsskip; + +// +// 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"); + _nfree(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; + dword needed; + word startseg; + + needed = (size+15)/16; // convert size from bytes to paragraphs +printf("."); //0000 + 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; +printf("."); //0000 + for(search = 0; searchendid; search++) + { +printf(" [case]"); //0000 + // + // 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: +printf("0 "); //0000 + lastscan = mm->mmrover; + scan = mm->mmrover->next; + endscan = NULL; + break; + case 1: +printf("1 "); //0000 + lastscan = mm->mmhead; + scan = mm->mmhead->next; + endscan = mm->mmrover; + break; + case 2: +printf("2 "); //0000 + MM_SortMem(mm); + lastscan = mm->mmhead; + scan = mm->mmhead->next; + endscan = NULL; + break; + } + + startseg = lastscan->start + (word)lastscan->length; + + while(scan != endscan) + { +//printf(","); //0000 + if(scan->start - startseg >= needed) + { +printf("."); //0000 + // + // 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 = *(word *)baseptr = startseg; + mm->mmnew->next = scan; + while(purge != scan) + { // free the purgable block +printf(" freeing block~\n"); //0000 + 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) ) + { +printf(" [lock] "); //0000 +printf("len=%lu ", scan->length); + lastscan = scan; + startseg = lastscan->start + (word)lastscan->length; + } + +printf("\n"); + scan=scan->next; // look at next line + } + } + + if (mm->bombonerror) + { + heapdump(); + printf(OUT_OF_MEM_MSG,(size-mmi->nearheap)); + printf("for stability reasons the program will shut down! wwww\n"); + printf(" endid=%u\n",(mm->endid)); + MM_Shutdown(mm); + exit(-1); + } + 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 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!\n"); + return; + } + mm->mmfree=mm->mmfree->next; + mm->endid++; //end of list +} + +void MM_FreeBlock(mmblocktype *x, mminfo_t *mm) +{ + x->useptr=NULL; + x->next=mm->mmfree; + mm->mmfree=x; + mm->endid--; //end of list +} + +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 +*/ diff --git a/16/exmmtest/src/lib/16_mm.h b/16/exmmtest/src/lib/16_mm.h new file mode 100644 index 00000000..575685c3 --- /dev/null +++ b/16/exmmtest/src/lib/16_mm.h @@ -0,0 +1,194 @@ +/* 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 +#include +//#include +#include "src/lib/16_head.h" +#include "src/lib/16_hc.h" +#include "src/lib/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\n" +#else +#define OUT_OF_MEM_MSG "\npee\n" +#endif + + +#define SAVENEARHEAP 0//_memavl()/4 // space to leave in data segment +#define SAVEFARHEAP 0//x400 // 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 __near *nearheap; + //byte EMS_status; + unsigned totalEMSpages,freeEMSpages,EMSpageframe,EMSpagesmapped,EMShandle; + unsigned int EMSVer; + word numUMBs,UMBbase[MAXUMBS]; + word endid; //end of list + //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 diff --git a/makefile b/makefile index 563c6bdd..76f83796 100644 --- a/makefile +++ b/makefile @@ -1,9 +1,11 @@ !ifdef __LINUX__ REMOVECOMMAND=rm -f +COPYCOMMAND=cp -f DIRSEP=/ OBJ=o !else REMOVECOMMAND=del +COPYCOMMAND=copy /y DIRSEP=\ OBJ=obj !endif @@ -12,6 +14,7 @@ TARGET_OS = dos #-zk0 = kanji support~ #-zkl = current codepage +EXMMTESTDIR=16$(DIRSEP)exmmtest$(DIRSEP) SRC=src$(DIRSEP) SRCLIB=$(SRC)lib$(DIRSEP) JSMNLIB=$(SRCLIB)jsmn$(DIRSEP) @@ -301,3 +304,7 @@ clean: .symbolic @$(REMOVECOMMAND) *.SMP @$(REMOVECOMMAND) 16.hed @$(REMOVECOMMAND) bakapi.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) diff --git a/src/lib/16_head.h b/src/lib/16_head.h index 84a4a9eb..73cc0bda 100644 --- a/src/lib/16_head.h +++ b/src/lib/16_head.h @@ -151,17 +151,23 @@ extern int profilehandle,debughandle; //make it into game global #define nil ((void *)0) +#ifdef __WATCOMC__ #define peekb(segm,ofs) (*(byte far*)MK_FP((segm),(ofs))) #define peekw(segm,ofs) (*(word far*)MK_FP((segm),(ofs))) #define pokeb(segm,ofs,value) (peekb((segm),(ofs)) = (byte)(value)) #define pokew(segm,ofs,value) (peekw((segm),(ofs)) = (word)(value)) typedef union REGPACK regs_t; -//typedef struct SREGS sregs_t; -//sregs_t sregs; +#endif + typedef enum {false,true} boolean; -//I hope this is correct! + +#ifdef __WATCOMC__ typedef void __based(__self) * memptr; +#endif +#ifdef __BORLANDC__ +typedef void _seg * memptr; +#endif typedef struct { int old_mode; //old video mode before game!