From e06d8430cdbbeef6b261ac47f7bd17cf2045666f Mon Sep 17 00:00:00 2001 From: sparky4 Date: Sat, 27 Jun 2015 15:16:09 -0500 Subject: [PATCH] wwww Signed-off-by: sparky4 --- exmmtest.exe | Bin 54691 -> 55124 bytes src/lib/16_mm.c | 2327 ++++++++++++++++++++++++----------------------- src/lib/16_mm.h | 7 +- 3 files changed, 1168 insertions(+), 1166 deletions(-) diff --git a/exmmtest.exe b/exmmtest.exe index 4708e6851c8c8821c1b72bacaeabf1c41fb213d1..ac09f6b42d28066cd10af0caa701048640ebcc8d 100644 GIT binary patch delta 16688 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%0D}Eqdj2V|)7MKmLxs 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 delta 16049 zcmb7r30#!b`u~}C8JPjbK@dT3L{!|;L~Y0@a$|4-#0|=u3?MUtvi*huty_&{i?2gm z>a^E234hhCuD61U)QrU4EJZU?v#z$Fc#Ug*%#;hi?>X;mSoi<={9iuLyyraIdCqg5 z^PFXdV_U?Aw?tRQ(pxndAhU9K;iV z(|{Bh@C{&91R-}1B;+l?alk$({|;~w<%yAmbO3$@Xa^B87;rz}DL@NgN)#bW0iT2a zuXw)=*ap}Q_!4jpppAABa(gr(w!wrP0UQJKkAQ8lgp>~<Lv;t-fC1i9w zA=QAxfPVwJ0k)BZd;s`5fsg~E2ssP*4`ASELgE3F0hxdzz*@itz-xeiy6|xwFnA0h zRe(Cch_Qqu0x|%11AYV)-%QAxcMy`CLdb)F@iPcn0w@MJ0FMG{0nfwumjMkZ9|L>^ z_ywSwNyuEl62M!4LdY4w{513! za2C*SHX(U)2zeC^zXm8n`2^lG<`Qyx9wC&2rNWULK`H zejqERt#a^5=kRscr3b}r5>ZUs<))dO-cO0#A=CH8QNrp7dRm+&{40XSNt4Fi9=2{* zkaA&}HFxRVe>%8m!NTku^l;q;VUMMUnAfH3kco3dQ>vRuKOjX5SB>;}X;k=j*&&|W zN}6W5H(u-A(8|ee(pVuUoc2i5ghSzUnmkE}HBzTMR%nswCfPisPOi~DB{vzj_V)Ig z>g3>-s{U)Qzf(1!$%rcbMIJumjsbP=O3I$v6K+e-(eD!5G*Z}N!R$7-$cg)#@0XAK zc;rY;oAL`B8$Li~>o)glTVzFor7g1F@d#ZjN6->&$lWb+<@gtrBg&pYxsKgobzDwT zEZt3E?q|EXCB2rO&iw&C@VG#)d}`ip&Xbj2YI1wbin&5I*O(mih&Fq?Q#QL(s^wZs zPlA%BPf%PToW%rujkX#Row1S4TX{s>ZlH_%jdFofUoAh{QWf;*l`6!*y#)PIkx*TN z(Jqr~+uir;l?Si5?+;NPyy|}Nidji<%I*iR;;lC3Mq_SQh%!sB+#do3kgJDWZjZ8B zucU>TcbiIN%>iW)FSsq&lr(`C_eQ2kYYFcn8|8&8ido;NF=)g+C*;nk+7r9e^h#^Z ziOyq@&1YbE$E;8mtjltj{^?+MKv$dE`W#*&XSWl}Ap+`FzsGd=l3Chd#MS z?_L~YR+w{@$ZC9GOrTocD-ojhE=}m|^_0*}Pf1V6-n0;~xFf+|Uoe@8V+olM$0TE&(yCUWi)hI=#q

LHbNvAx;xPC#gbJC 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 E0a+start+scan->length < segstart) - { - last = scan; - scan = scan->next; - } - -// -// take the given range out of the block -// - oldend = scan->start + scan->length; - extra = oldend - (segstart+seglength); - if (extra < 0) - { - printf("MML_UseSpace: Segment spans two blocks!"); - return; - } - - - if (segstart == scan->start) - { - last->next = scan->next; // unlink block - FREEBLOCK(scan); - scan = last; - } - else - scan->length = segstart-scan->start; // shorten block - - if (extra > 0) - { - GETNEWBLOCK; - mmnew->next = scan->next; - scan->next = mmnew; - mmnew->start = segstart+seglength; - mmnew->length = extra; - mmnew->attributes = LOCKBIT; - } - -} - -//========================================================================== - -/* -==================== -= -= MML_ClearBlock -= -= We are out of blocks, so free a purgable block -= -==================== -*/ - -void MML_ClearBlock (void) -{ - mmblocktype far *scan,far *last; - - scan = mmhead->next; - - while (scan) - { - if (!(scan->attributes&LOCKBIT) && (scan->attributes&PURGEBITS) ) - { - MM_FreePtr(scan->useptr); - return; - } - scan = scan->next; - } - - printf("MM_ClearBlock: No purgable blocks!"); -} - - -//========================================================================== - -/* -=================== -= -= MM_Startup -= -= Grabs all space from turbo with malloc/farmalloc -= Allocates bufferseg misc buffer -= -=================== -*/ - -void MM_Startup (void) -{ - int i; - dword length; - void far *start; - unsigned segstart,seglength,endfree; - - if (mmstarted) - MM_Shutdown (); - - - mmstarted = true; - bombonerror = true; -// -// set up the linked list (everything in the free list; -// - mmhead = NULL; - mmfree = &mmblocks[0]; - for (i=0;istart = 0; - mmnew->length = 0xffff; - mmnew->attributes = LOCKBIT; - mmnew->next = NULL; - mmrover = mmhead; - - -// -// get all available near conventional memory segments -// -//---- length=coreleft(); - length=_memavl(); - start = (void far *)(nearheap = malloc(length)); - - length -= 16-(FP_OFF(start)&15); - length -= SAVENEARHEAP; - seglength = length / 16; // now in paragraphs - segstart = FP_SEG(start)+(FP_OFF(start)+15)/16; - MML_UseSpace (segstart,seglength); - mminfo.nearheap = length; - -// -// get all available far conventional memory segments -// -//---- length=farcoreleft(); - length=_memmax(); - start = 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); - mminfo.farheap = length; - mminfo.mainmem = mminfo.nearheap + mminfo.farheap; - - -// -// detect EMS and allocate up to 64K at page frame -// - mminfo.EMSmem = 0; - for (i = 1;i < __argc;i++) - { - if ( US_CheckParm(__argv[i],ParmStringsexmm) == 0) - goto emsskip; // param NOEMS - } - - if (MML_CheckForEMS()) - { - //printf("EMS1\n"); - MML_SetupEMS(); // allocate space - //printf("EMS2\n"); - MML_UseSpace (EMSpageframe,EMSpagesmapped*0x400); - //printf("EMS3\n"); - MM_MapEMS(); // map in used pages - //printf("EMS4\n"); - mminfo.EMSmem = EMSpagesmapped*0x4000l; - } - -// -// detect XMS and get upper memory blocks -// -emsskip: - mminfo.XMSmem = 0; - for (i = 1;i < __argc;i++) - { - if ( US_CheckParm(__argv[i],ParmStringsexmm) == 0) - goto xmsskip; // param NOXMS - } - - if (MML_CheckForXMS()) - { -// printf("XMS!\n"); - MML_SetupXMS(); // allocate as many UMBs as possible - } - -// -// allocate the misc buffer -// -xmsskip: - mmrover = mmhead; // start looking for space after low block - - MM_GetPtr (&bufferseg,BUFFERSIZE); -} - -//========================================================================== - -/* -==================== -= -= MM_Shutdown -= -= Frees all conventional, EMS, and XMS allocated -= -==================== -*/ - -void MM_Shutdown (void) -{ - if (!mmstarted) - return; - - _ffree (farheap); - free (nearheap); - hfree(hugeheap); - MML_ShutdownEMS (); - MML_ShutdownXMS (); -} - -//========================================================================== - -/* -==================== -= -= MM_GetPtr -= -= Allocates an unlocked, unpurgable block -= -==================== -*/ - -void MM_GetPtr (memptr *baseptr,dword size) -{ - mmblocktype far *scan,far *lastscan,far *endscan - ,far *purge,far *next; - int search; - unsigned needed,startseg; - - needed = (size+15)/16; // convert size from bytes to paragraphs - - GETNEWBLOCK; // fill in start and next after a spot is found - mmnew->length = needed; - mmnew->useptr = baseptr; - mmnew->attributes = BASEATTRIBUTES; - - for (search = 0; search<3; search++) - { - // - // first search: try to allocate right after the rover, then on up - // second search: search from the head pointer up to the rover - // third search: compress memory, then scan from start - if (search == 1 && mmrover == mmhead) - search++; - - switch (search) - { - case 0: - lastscan = mmrover; - scan = mmrover->next; - endscan = NULL; - break; - case 1: - lastscan = mmhead; - scan = mmhead->next; - endscan = mmrover; - break; - case 2: - MM_SortMem (); - lastscan = mmhead; - scan = mmhead->next; - endscan = NULL; - break; - } - - startseg = lastscan->start + lastscan->length; - - while (scan != endscan) - { - if (scan->start - startseg >= needed) - { - // - // got enough space between the end of lastscan and - // the start of scan, so throw out anything in the middle - // and allocate the new block - // - purge = lastscan->next; - lastscan->next = mmnew; - mmnew->start = *(unsigned *)baseptr = startseg; - mmnew->next = scan; - while ( purge != scan) - { // free the purgable block - next = purge->next; - FREEBLOCK(purge); - purge = next; // purge another if not at scan - } - mmrover = mmnew; - return; // good allocation! - } - - // - // if this block is purge level zero or locked, skip past it - // - if ( (scan->attributes & LOCKBIT) - || !(scan->attributes & PURGEBITS) ) - { - lastscan = scan; - startseg = lastscan->start + lastscan->length; - } - - - scan=scan->next; // look at next line - } - } - - if (bombonerror) - printf(OUT_OF_MEM_MSG,(size-mminfo.nearheap)); - else - mmerror = true; -} - -//========================================================================== - -/* -==================== -= -= MM_FreePtr -= -= Allocates an unlocked, unpurgable block -= -==================== -*/ - -void MM_FreePtr (memptr *baseptr) -{ - mmblocktype far *scan,far *last; - - last = mmhead; - scan = last->next; - - if (baseptr == mmrover->useptr) // removed the last allocated block - mmrover = mmhead; - - while (scan->useptr != baseptr && scan) - { - last = scan; - scan = scan->next; - } - - if (!scan) - { - printf("MM_FreePtr: Block not found!"); - return; - } - - last->next = scan->next; - - FREEBLOCK(scan); -} -//========================================================================== - -/* -===================== -= -= MM_SetPurge -= -= Sets the purge level for a block (locked blocks cannot be made purgable) -= -===================== -*/ - -void MM_SetPurge (memptr *baseptr, int purge) -{ - mmblocktype far *start; - - start = mmrover; - - do - { - if (mmrover->useptr == baseptr) - break; - - mmrover = mmrover->next; - - if (!mmrover) - mmrover = mmhead; - else if (mmrover == start) - { - printf("MM_SetPurge: Block not found!"); - return; - } - - } while (1); - - mmrover->attributes &= ~PURGEBITS; - mmrover->attributes |= purge; -} - -//========================================================================== - -/* -===================== -= -= MM_SetLock -= -= Locks / unlocks the block -= -===================== -*/ - -void MM_SetLock (memptr *baseptr, boolean locked) -{ - mmblocktype far *start; - - start = mmrover; - - do - { - if (mmrover->useptr == baseptr) - break; - - mmrover = mmrover->next; - - if (!mmrover) - mmrover = mmhead; - else if (mmrover == start) - { - printf("MM_SetLock: Block not found!"); - return; - } - - } while (1); - - mmrover->attributes &= ~LOCKBIT; - mmrover->attributes |= locked*LOCKBIT; -} - -//========================================================================== - -/* -===================== -= -= MM_SortMem -= -= Throws out all purgable stuff and compresses movable blocks -= -===================== -*/ - -void MM_SortMem (void) -{ - mmblocktype far *scan,far *last,far *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 = 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; - FREEBLOCK(scan); - 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 - } - - mmrover = mmhead; - - if (aftersort) - aftersort(); - -// VW_ColorBorder (oldborder); - -/*++++ if (playing) - MM_SetLock(&(memptr)audiosegs[playing],false);*/ -} - - -//========================================================================== - -//****#if 0 -/* -===================== -= -= MM_ShowMemory -= -===================== -*/ - -void MM_ShowMemory (void) -{ - mmblocktype far *scan; - unsigned color,temp;//, i; - long end,owner; - char scratch[80],str[10]; - -//**** VW_SetDefaultColors(); -//**** VW_SetLineWidth(40); -//++++mh temp = bufferofs; -//++++mh bufferofs = 0; -//**** VW_SetScreen (0,0); - - scan = mmhead; - - end = -1; - -//CA_OpenDebug (); - - 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("MM_ShowMemory: Memory block order currupted!"); - return; - } - end = scan->start+scan->length-1; -//++++ VW_Hlin(scan->start,(unsigned)end,0,color); -//++++ VW_Plot(scan->start,0,15); - if (scan->next->start > end+1) -//++++ VW_Hlin(end+1,scan->next->start,0,0); // black = free - -//****#if 0 -printf("Location:"); -printf("%Fp\t", scan->start); -strcpy (scratch,"Size:"); -ltoa ((long)scan->length*16,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)); -fprintf(stdout, "%s", scratch); -//****#endif - - scan = scan->next; - } - -//CA_CloseDebug (); - -//++++mh IN_Ack(); -//**** VW_SetLineWidth(64); -//++++mh bufferofs = temp; -} -//****#endif - -//========================================================================== - - -/* -====================== -= -= MM_UnusedMemory -= -= Returns the total free space without purging -= -====================== -*/ - -dword MM_UnusedMemory (void) -{ - unsigned free; - mmblocktype far *scan; - - free = 0; - scan = mmhead; - - while (scan->next) - { - free += scan->next->start - (scan->start + scan->length); - scan = scan->next; - } - - return free*16l; -} - -//========================================================================== - - -/* -====================== -= -= MM_TotalFree -= -= Returns the total free space with purging -= -====================== -*/ - -dword MM_TotalFree (void) -{ - unsigned free; - mmblocktype far *scan; - - free = 0; - scan = 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; -} - -//========================================================================== - -/* -===================== -= -= MM_Report -= -===================== -*/ - -void MM_Report(void) -{ - printf("EMM %x available\n", EMSVer); - printf("totalEMSpages=%u\n", totalEMSpages); - printf("freeEMSpages=%u\n", freeEMSpages); - printf("EMSpageframe=%Fp\n", EMSpageframe); - printf("UnusedMemory=%lu\n", MM_UnusedMemory()); - printf("TotalFree=%lu\n", MM_TotalFree()); -} - -//========================================================================== - -/* -===================== -= -= MM_EMSVer -= -===================== - - +/* Catacomb Armageddon 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 + +============================================================================= +*/ + +#include "src/lib/16_mm.h" + +/* +====================== += += MML_CheckForEMS += += Routine from p36 of Extending DOS += +======================= +*/ + +boolean MML_CheckForEMS (void) +{ + boolean emmcfems; + char emmname[] = "EMMXXXX0"; +// mov dx,OFFSET emmname + __asm { + LEA DX, 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 += +======================= +*/ + +void MML_SetupEMS (void) +{ + char str[80],str2[10]; + unsigned err; + boolean errorflag=false; + union REGS CPURegs; + + EMSVer = 0; + totalEMSpages = freeEMSpages = EMSpageframe = EMSpagesmapped = 0; + + __asm + { + mov ah,EMS_STATUS + int EMS_INT // make sure EMS hardware is present + or ah,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 + + 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 errorflag,1 + jmp End +noEMS: +End: + } + if(errorflag==true) + { + err = CPURegs.h.ah; + strcpy(str,"MML_SetupEMS: EMS error 0x"); + itoa(err,str2,16); + strcpy(str,str2); + printf("%s\n",str); + } +} + + +/* +====================== += += MML_ShutdownEMS += +======================= +*/ + +void MML_ShutdownEMS (void) +{ + boolean errorflag=false; + 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!"); //++++ 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. += +==================== +*/ + +void MM_MapEMS (void) +{ + char str[80],str2[10]; + unsigned err; + boolean errorflag=false; + int i; + union REGS CPURegs; + + for (i=0;istart+scan->length < segstart) + { + last = scan; + scan = scan->next; + } + +// +// take the given range out of the block +// + oldend = scan->start + scan->length; + extra = oldend - (segstart+seglength); + if (extra < 0) + { + printf("MML_UseSpace: Segment spans two blocks!"); + return; + } + + + if (segstart == scan->start) + { + last->next = scan->next; // unlink block + FREEBLOCK(scan); + scan = last; + } + else + scan->length = segstart-scan->start; // shorten block + + if (extra > 0) + { + GETNEWBLOCK; + mmnew->next = scan->next; + scan->next = mmnew; + mmnew->start = segstart+seglength; + mmnew->length = extra; + mmnew->attributes = LOCKBIT; + } + +} + +//========================================================================== + +/* +==================== += += MML_ClearBlock += += We are out of blocks, so free a purgable block += +==================== +*/ + +void MML_ClearBlock (void) +{ + mmblocktype far *scan,far *last; + + scan = mmhead->next; + + while (scan) + { + if (!(scan->attributes&LOCKBIT) && (scan->attributes&PURGEBITS) ) + { + MM_FreePtr(scan->useptr); + return; + } + scan = scan->next; + } + + printf("MM_ClearBlock: No purgable blocks!"); +} + + +//========================================================================== + +/* +=================== += += MM_Startup += += Grabs all space from turbo with malloc/farmalloc += Allocates bufferseg misc buffer += +=================== +*/ + +void MM_Startup (void) +{ + int i; + dword length; + void far *start; + unsigned segstart,seglength,endfree; + + if (mminfo.mmstarted) + MM_Shutdown (); + + + mminfo.mmstarted = true; + mminfo.bombonerror = true; +// +// set up the linked list (everything in the free list; +// + mmhead = NULL; + mmfree = &mmblocks[0]; + for (i=0;istart = 0; + mmnew->length = 0xffff; + mmnew->attributes = LOCKBIT; + mmnew->next = NULL; + mmrover = mmhead; + + +// +// get all available near conventional memory segments +// +//---- length=coreleft(); + length=_memavl(); + start = (void far *)(nearheap = malloc(length)); + + length -= 16-(FP_OFF(start)&15); + length -= SAVENEARHEAP; + seglength = length / 16; // now in paragraphs + segstart = FP_SEG(start)+(FP_OFF(start)+15)/16; + MML_UseSpace (segstart,seglength); + mminfo.nearheap = length; + +// +// get all available far conventional memory segments +// +//---- length=farcoreleft(); + length=_memmax(); + start = 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); + mminfo.farheap = length; + mminfo.mainmem = mminfo.nearheap + mminfo.farheap; + + +// +// detect EMS and allocate up to 64K at page frame +// + mminfo.EMSmem = 0; + for (i = 1;i < __argc;i++) + { + if ( US_CheckParm(__argv[i],ParmStringsexmm) == 0) + goto emsskip; // param NOEMS + } + + if (MML_CheckForEMS()) + { + //printf("EMS1\n"); + MML_SetupEMS(); // allocate space + //printf("EMS2\n"); + MML_UseSpace (EMSpageframe,EMSpagesmapped*0x400); + //printf("EMS3\n"); + MM_MapEMS(); // map in used pages + //printf("EMS4\n"); + mminfo.EMSmem = EMSpagesmapped*0x4000l; + } + +// +// detect XMS and get upper memory blocks +// +emsskip: + mminfo.XMSmem = 0; + for (i = 1;i < __argc;i++) + { + if ( US_CheckParm(__argv[i],ParmStringsexmm) == 0) + goto xmsskip; // param NOXMS + } + + if (MML_CheckForXMS()) + { +// printf("XMS!\n"); + MML_SetupXMS(); // allocate as many UMBs as possible + } + +// +// allocate the misc buffer +// +xmsskip: + mmrover = mmhead; // start looking for space after low block + + MM_GetPtr (&bufferseg,BUFFERSIZE); +} + +//========================================================================== + +/* +==================== += += MM_Shutdown += += Frees all conventional, EMS, and XMS allocated += +==================== +*/ + +void MM_Shutdown (void) +{ + if (!mminfo.mmstarted) + return; + + _ffree (farheap); + free (nearheap); + hfree(hugeheap); + MML_ShutdownEMS (); + MML_ShutdownXMS (); +} + +//========================================================================== + +/* +==================== += += MM_GetPtr += += Allocates an unlocked, unpurgable block += +==================== +*/ + +void MM_GetPtr (memptr *baseptr,dword size) +{ + mmblocktype far *scan,far *lastscan,far *endscan + ,far *purge,far *next; + int search; + unsigned needed,startseg; + + needed = (size+15)/16; // convert size from bytes to paragraphs + + GETNEWBLOCK; // fill in start and next after a spot is found + mmnew->length = needed; + mmnew->useptr = baseptr; + mmnew->attributes = BASEATTRIBUTES; + + for (search = 0; search<3; search++) + { + // + // first search: try to allocate right after the rover, then on up + // second search: search from the head pointer up to the rover + // third search: compress memory, then scan from start + if (search == 1 && mmrover == mmhead) + search++; + + switch (search) + { + case 0: + lastscan = mmrover; + scan = mmrover->next; + endscan = NULL; + break; + case 1: + lastscan = mmhead; + scan = mmhead->next; + endscan = mmrover; + break; + case 2: + MM_SortMem (); + lastscan = mmhead; + scan = mmhead->next; + endscan = NULL; + break; + } + + startseg = lastscan->start + lastscan->length; + + while (scan != endscan) + { + if (scan->start - startseg >= needed) + { + // + // got enough space between the end of lastscan and + // the start of scan, so throw out anything in the middle + // and allocate the new block + // + purge = lastscan->next; + lastscan->next = mmnew; + mmnew->start = *(unsigned *)baseptr = startseg; + mmnew->next = scan; + while ( purge != scan) + { // free the purgable block + next = purge->next; + FREEBLOCK(purge); + purge = next; // purge another if not at scan + } + mmrover = mmnew; + return; // good allocation! + } + + // + // if this block is purge level zero or locked, skip past it + // + if ( (scan->attributes & LOCKBIT) + || !(scan->attributes & PURGEBITS) ) + { + lastscan = scan; + startseg = lastscan->start + lastscan->length; + } + + + scan=scan->next; // look at next line + } + } + + if (mminfo.bombonerror) + printf(OUT_OF_MEM_MSG,(size-mminfo.nearheap)); + else + mminfo.mmerror = true; +} + +//========================================================================== + +/* +==================== += += MM_FreePtr += += Allocates an unlocked, unpurgable block += +==================== +*/ + +void MM_FreePtr (memptr *baseptr) +{ + mmblocktype far *scan,far *last; + + last = mmhead; + scan = last->next; + + if (baseptr == mmrover->useptr) // removed the last allocated block + mmrover = mmhead; + + while (scan->useptr != baseptr && scan) + { + last = scan; + scan = scan->next; + } + + if (!scan) + { + printf("MM_FreePtr: Block not found!"); + return; + } + + last->next = scan->next; + + FREEBLOCK(scan); +} +//========================================================================== + +/* +===================== += += MM_SetPurge += += Sets the purge level for a block (locked blocks cannot be made purgable) += +===================== +*/ + +void MM_SetPurge (memptr *baseptr, int purge) +{ + mmblocktype far *start; + + start = mmrover; + + do + { + if (mmrover->useptr == baseptr) + break; + + mmrover = mmrover->next; + + if (!mmrover) + mmrover = mmhead; + else if (mmrover == start) + { + printf("MM_SetPurge: Block not found!"); + return; + } + + } while (1); + + mmrover->attributes &= ~PURGEBITS; + mmrover->attributes |= purge; +} + +//========================================================================== + +/* +===================== += += MM_SetLock += += Locks / unlocks the block += +===================== +*/ + +void MM_SetLock (memptr *baseptr, boolean locked) +{ + mmblocktype far *start; + + start = mmrover; + + do + { + if (mmrover->useptr == baseptr) + break; + + mmrover = mmrover->next; + + if (!mmrover) + mmrover = mmhead; + else if (mmrover == start) + { + printf("MM_SetLock: Block not found!"); + return; + } + + } while (1); + + mmrover->attributes &= ~LOCKBIT; + mmrover->attributes |= locked*LOCKBIT; +} + +//========================================================================== + +/* +===================== += += MM_SortMem += += Throws out all purgable stuff and compresses movable blocks += +===================== +*/ + +void MM_SortMem (void) +{ + mmblocktype far *scan,far *last,far *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 = 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; + FREEBLOCK(scan); + 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 + } + + mmrover = mmhead; + + if (aftersort) + aftersort(); + +// VW_ColorBorder (oldborder); + +/*++++ if (playing) + MM_SetLock(&(memptr)audiosegs[playing],false);*/ +} + + +//========================================================================== + +//****#if 0 +/* +===================== += += MM_ShowMemory += +===================== +*/ + +void MM_ShowMemory (void) +{ + mmblocktype far *scan; + unsigned color,temp;//, i; + long end,owner; + char scratch[80],str[10]; + +//**** VW_SetDefaultColors(); +//**** VW_SetLineWidth(40); +//++++mh temp = bufferofs; +//++++mh bufferofs = 0; +//**** VW_SetScreen (0,0); + + scan = mmhead; + + end = -1; + +//CA_OpenDebug (); + + 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("MM_ShowMemory: Memory block order currupted!"); + return; + } + end = scan->start+scan->length-1; +//++++ VW_Hlin(scan->start,(unsigned)end,0,color); +//++++ VW_Plot(scan->start,0,15); + if (scan->next->start > end+1) +//++++ VW_Hlin(end+1,scan->next->start,0,0); // black = free + +//****#if 0 +printf("Location:"); +printf("%Fp\t", scan->start); +strcpy (scratch,"Size:"); +ltoa ((long)scan->length*16,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)); +fprintf(stdout, "%s", scratch); +//****#endif + + scan = scan->next; + } + +//CA_CloseDebug (); + +//++++mh IN_Ack(); +//**** VW_SetLineWidth(64); +//++++mh bufferofs = temp; +} +//****#endif + +//========================================================================== + + +/* +====================== += += MM_UnusedMemory += += Returns the total free space without purging += +====================== +*/ + +dword MM_UnusedMemory (void) +{ + unsigned free; + mmblocktype far *scan; + + free = 0; + scan = mmhead; + + while (scan->next) + { + free += scan->next->start - (scan->start + scan->length); + scan = scan->next; + } + + return free*16l; +} + +//========================================================================== + + +/* +====================== += += MM_TotalFree += += Returns the total free space with purging += +====================== +*/ + +dword MM_TotalFree (void) +{ + unsigned free; + mmblocktype far *scan; + + free = 0; + scan = 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; +} + +//========================================================================== + +/* +===================== += += MM_Report += +===================== +*/ + +void MM_Report(void) +{ + printf("EMM %x available\n", EMSVer); + printf("totalEMSpages=%u\n", totalEMSpages); + printf("freeEMSpages=%u\n", freeEMSpages); + printf("EMSpageframe=%Fp\n", EMSpageframe); + printf("near=%lu\n", mminfo.nearheap); + printf("far=%lu\n", mminfo.farheap); + printf("EMSmem=%lu\n", mminfo.EMSmem); + printf("XMSmem=%lu\n", mminfo.XMSmem); + printf("mainmem=%lu\n", mminfo.mainmem); + printf("UnusedMemory=%lu\n", MM_UnusedMemory()); + printf("TotalFree=%lu\n", MM_TotalFree()); +} + +//========================================================================== + +/* +===================== += += MM_EMSVer += +===================== + + int MM_EMSVer(void) -{ +{ int EMSver; - __asm - { + __asm + { mov ah,EMS_VERSION - int EMS_INT + int EMS_INT mov EMSver,ax - } + } return(EMSver); -}*/ - -//========================================================================== - -/* -===================== -= -= MM_BombOnError -= -===================== -*/ - -void MM_BombOnError (boolean bomb) -{ - bombonerror = bomb; -} - -//========================================================================== - -/////////////////////////////////////////////////////////////////////////// -// -// 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); -} - +}*/ + +//========================================================================== + +/* +===================== += += MM_BombOnError += +===================== +*/ + +void MM_BombOnError (boolean bomb) +{ + mminfo.bombonerror = bomb; +} + +//========================================================================== + +/////////////////////////////////////////////////////////////////////////// +// +// 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); +} + diff --git a/src/lib/16_mm.h b/src/lib/16_mm.h index a18f0db7..102c406c 100644 --- a/src/lib/16_mm.h +++ b/src/lib/16_mm.h @@ -84,7 +84,8 @@ typedef void /*__seg*/ * memptr; typedef struct { - long nearheap,farheap,EMSmem,XMSmem,mainmem; + dword nearheap,farheap,EMSmem,XMSmem,mainmem; + boolean mmstarted, bombonerror, mmerror; } mminfotype; //========================================================================== @@ -136,7 +137,6 @@ typedef struct mmblockstruct static mminfotype mminfo; static memptr bufferseg; -static boolean mmerror; static void (* beforesort) (void); static void (* aftersort) (void); @@ -149,8 +149,6 @@ static void (* aftersort) (void); ============================================================================= */ -static boolean mmstarted; - static void huge *hugeheap; static void far *farheap; static void *nearheap; @@ -158,7 +156,6 @@ static void *nearheap; static mmblocktype far mmblocks[MAXBLOCKS] ,far *mmhead,far *mmfree,far *mmrover,far *mmnew; -static boolean bombonerror; static unsigned totalEMSpages,freeEMSpages,EMSpageframe,EMSpagesmapped,EMShandle; static unsigned int EMSVer; -- 2.39.5