#include "ted5.h" #pragma hdrstop #define EMSINT 0x67 #define SPACEFREE 0x2000 // how much mem to leave alone in farheap #define EXTRASTACKSIZE 0x2000 #define MAXBLOCKS 1000 #define LOCKBIT 0x8000 // if set in attributes, block cannot be moved #define PURGEBITS 3 // 0-3 level, 0= unpurgable, 3= purge first #define BASEATTRIBUTES 0 // unlocked, non purgable unsigned totalmem; // total paragraphs available with 64k EMS int EMSpresent,XMSpresent; long TTLMainMem; void far *farheap; void *nearheap; int numblocks; struct { unsigned start; // in paragraphs unsigned length; unsigned attributes; memptr *useptr; } blocks[MAXBLOCKS],tempblock; //========================================================================== // // local prototypes // void CheckForEMS (void); int FindBlock (memptr *ptr); void RemoveBlock (int block); void InsertBlock (int block); // // public prototypes // void MMStartup (void); void MMShutdown (void); void MMMapEMS (void); void MMGetPtr (memptr *baseptr,unsigned size); void MMFreePtr (memptr *baseptr); void MMSetPurge (memptr *baseptr, int purge); void MMSortMem (void); void MMBlockDump (void); unsigned MMUnusedMemory (void); unsigned MMTotalFree (void); //========================================================================== // // CheckForEMS // // Routine from p36 of Extending DOS // void CheckForEMS (void) { char emmname[9] = "EMMXXXX0"; asm mov dx,OFFSET emmname asm mov ax,0x3d00 asm int 0x21 // try to open EMMXXXX0 device asm jc error asm mov bx,ax asm mov ax,0x4400 asm int 0x21 // get device info asm jc error asm and dx,0x80 asm jz error asm mov ax,0x4407 asm int 0x21 // get status asm jc error asm or al,al asm jz error asm mov ah,0x3e asm int 0x21 // close handle asm jc error // // EMS is good // return; error: // // EMS is bad // EMSpresent = 0; } //========================================================================== // // FindBlock // int FindBlock (memptr *ptr) { int i; for (i=1;i=MAXBLOCKS) Quit ("Memory manager error: Too many blocks!"); } // check numblocksdest) { asm cld while (paragraphs>0xfff) { MoveParaBase (source,dest,0xfff*8); source += 0xfff*8; dest += 0xfff*8; paragraphs -= 0xfff; } MoveParaBase (source,dest,paragraphs*8); } else { asm std source+=paragraphs; dest+=paragraphs; while (paragraphs>0xfff) { source-=0xfff; dest-=0xfff; MoveParaBaseUp (source,dest,0xfff*8); paragraphs -= 0xfff; } source-=paragraphs; dest-=paragraphs; MoveParaBaseUp (source,dest,paragraphs*8); asm cld } } /* ====================== = = MMSortMem = = Sorts all non locked blocks so lower purge levels are lower in memory = and all free space is at the top = ====================== */ int keyblock; // // PushUp // // Pushes the block (purgeable) as high in memory as possible // must be BELOW keyblock // If it can't fit above keyblock it will be freed // void PushUp (int move) { unsigned source,dest,size; int i; size = blocks[move].length; source = blocks[move].start; for (i=numblocks-1;i>keyblock;i--) { // // if the block can fit under this block, move it // dest = blocks[i].start - size; if (blocks[i-1].start+blocks[i-1].length <= dest) { // // make a copy of block 'move' under block 'i' // InsertBlock (i-1); blocks[i] = blocks[move]; blocks[i].start = dest; *(blocks[i].useptr) = (void _seg *)dest; // modify the pointer to the new spot MoveParas (source,dest,size); break; } } // // erase original position // RemoveBlock (move); keyblock--; // because a block below it was removed } // // PushDown // // Push keyblock (unpurgable) as low in memory as possible // void PushDown (void) { unsigned source,dest,size,end,lowblock,checkblock,i; size = blocks[keyblock].length; source = blocks[keyblock].start; // // find the lowest space it can be moved into // for (lowblock = 0;lowblocklowblock+1;i--) blocks[i]=blocks[i-1]; blocks[lowblock+1] = tempblock; } //MMBlockDump(); // DEBUG } return; nofit:; // keep looking... } } // // MMSortMem // void MMSortMem (void) { unsigned i,source,dest; keyblock = 0; do { keyblock++; // // non-purgable, unlocked blocks will be pushed low in memory // if ( !(blocks[keyblock].attributes & PURGEBITS) && !(blocks[keyblock].attributes & LOCKBIT) ) PushDown (); } while (keyblock0;i--) { // // push all purgable blocks as high as possible // Currently they are NOT moved around locked blocks! // if ( blocks[i].attributes & PURGEBITS ) { source= blocks[i].start; dest= blocks[i+1].start-blocks[i].length; if (source!=dest) { MoveParas (source,dest,blocks[i].length); blocks[i].start = dest; *(blocks[i].useptr) = (void _seg *)dest; // modify the pointer to the new spot } } } PatchPointers(); // let the main program fix up any // internal references } //========================================================================== /* ======================= = = MMBlockDump = = Dewbug tool = ======================= */ void MMBlockDump (void) { int i; unsigned free; fprintf (stdprn,"-------------\n"); for (i=0;i