1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147 |
- /* 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 "ID_HEADS.H"
- #pragma hdrstop
- #pragma warn -pro
- #pragma warn -use
- #if 0 // 1 == Debug/Dev ; 0 == Production/final
- #define OUT_OF_MEM_MSG "MM_GetPtr: Out of memory!\nYou were short :%ld bytes"
- #else
- #define OUT_OF_MEM_MSG "\n" \
- "You need more memory to run CATACOMB ARMAGEDDON. Read the INSTRUCTION\n" \
- "section of the START program for tips on getting more memory.\n"
- #endif
- /*
- =============================================================================
- 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 10
- typedef struct mmblockstruct
- {
- unsigned start,length;
- unsigned attributes;
- memptr *useptr; // pointer to the segment start
- struct mmblockstruct far *next;
- } mmblocktype;
- //#define GETNEWBLOCK {if(!(mmnew=mmfree))Quit("MM_GETNEWBLOCK: No free blocks!")\
- // ;mmfree=mmfree->next;}
- #define GETNEWBLOCK {if(!mmfree)MML_ClearBlock();mmnew=mmfree;mmfree=mmfree->next;}
- #define FREEBLOCK(x) {*x->useptr=NULL;x->next=mmfree;mmfree=x;}
- /*
- =============================================================================
- GLOBAL VARIABLES
- =============================================================================
- */
- mminfotype mminfo;
- memptr bufferseg;
- boolean mmerror;
- void (* beforesort) (void);
- void (* aftersort) (void);
- /*
- =============================================================================
- LOCAL VARIABLES
- =============================================================================
- */
- boolean mmstarted;
- void far *farheap;
- void *nearheap;
- mmblocktype far mmblocks[MAXBLOCKS]
- ,far *mmhead,far *mmfree,far *mmrover,far *mmnew;
- boolean bombonerror;
- unsigned totalEMSpages,freeEMSpages,EMSpageframe,EMSpagesmapped,EMShandle;
- void (* XMSaddr) (void); // far pointer to XMS driver
- unsigned numUMBs,UMBbase[MAXUMBS];
- //==========================================================================
- //
- // local prototypes
- //
- boolean MML_CheckForEMS (void);
- void MML_ShutdownEMS (void);
- void MM_MapEMS (void);
- boolean MML_CheckForXMS (void);
- void MML_ShutdownXMS (void);
- void MML_UseSpace (unsigned segstart, unsigned seglength);
- void MML_ClearBlock (void);
- //==========================================================================
- /*
- ======================
- =
- = MML_CheckForEMS
- =
- = Routine from p36 of Extending DOS
- =
- =======================
- */
- char emmname[9] = "EMMXXXX0";
- boolean MML_CheckForEMS (void)
- {
- asm mov dx,OFFSET emmname[0]
- 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 true;
- error:
- //
- // EMS is bad
- //
- return false;
- }
- /*
- ======================
- =
- = MML_SetupEMS
- =
- =======================
- */
- void MML_SetupEMS (void)
- {
- char str[80],str2[10];
- unsigned error;
- 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
- 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:
- asm {
- mov [EMSpagesmapped],bx
- mov ah,EMS_ALLOCPAGES // allocate up to 64k of EMS
- int EMS_INT
- or ah,ah
- jnz error
- mov [EMShandle],dx
- }
- return;
- error:
- error = _AH;
- strcpy (str,"MML_SetupEMS: EMS error 0x");
- itoa(error,str2,16);
- strcpy (str,str2);
- Quit (str);
- noEMS:
- ;
- }
- /*
- ======================
- =
- = MML_ShutdownEMS
- =
- =======================
- */
- void MML_ShutdownEMS (void)
- {
- if (!EMShandle)
- return;
- asm {
- mov ah,EMS_FREEPAGES
- mov dx,[EMShandle]
- int EMS_INT
- or ah,ah
- jz ok
- }
- Quit ("MML_ShutdownEMS: Error freeing EMS!");
- ok:
- ;
- }
- /*
- ====================
- =
- = 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 error;
- int i;
- for (i=0;i<EMSpagesmapped;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
- }
- }
- return;
- error:
- error = _AH;
- strcpy (str,"MM_MapEMS: EMS error 0x");
- itoa(error,str2,16);
- strcpy (str,str2);
- Quit (str);
- }
- //==========================================================================
- /*
- ======================
- =
- = MML_CheckForXMS
- =
- = Check for XMM driver
- =
- =======================
- */
- boolean MML_CheckForXMS (void)
- {
- numUMBs = 0;
- asm {
- mov ax,0x4300
- int 0x2f // query status of installed diver
- cmp al,0x80
- je good
- }
- return false;
- good:
- return true;
- }
- /*
- ======================
- =
- = MML_SetupXMS
- =
- = Try to allocate all upper memory block
- =
- =======================
- */
- void MML_SetupXMS (void)
- {
- unsigned base,size;
- asm {
- mov ax,0x4310
- int 0x2f
- mov [WORD PTR XMSaddr],bx
- mov [WORD PTR XMSaddr+2],es // function pointer to XMS driver
- }
- getmemory:
- asm {
- mov ah,XMS_ALLOCUMB
- mov dx,0xffff // try for largest block possible
- call [DWORD PTR XMSaddr]
- or ax,ax
- jnz gotone
- cmp bl,0xb0 // error: smaller UMB is available
- jne done;
- mov ah,XMS_ALLOCUMB
- call [DWORD PTR XMSaddr] // DX holds largest available UMB
- or ax,ax
- jz done // another error...
- }
- gotone:
- asm {
- mov [base],bx
- mov [size],dx
- }
- MML_UseSpace (base,size);
- mminfo.XMSmem += size*16;
- UMBbase[numUMBs] = base;
- numUMBs++;
- if (numUMBs < MAXUMBS)
- goto getmemory;
- done:;
- }
- /*
- ======================
- =
- = MML_ShutdownXMS
- =
- ======================
- */
- void MML_ShutdownXMS (void)
- {
- int i;
- unsigned base;
- for (i=0;i<numUMBs;i++)
- {
- base = UMBbase[i];
- asm mov ah,XMS_FREEUMB
- asm mov dx,[base]
- asm 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 (unsigned segstart, unsigned seglength)
- {
- mmblocktype far *scan,far *last;
- unsigned oldend;
- long extra;
- scan = last = mmhead;
- mmrover = 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;
- }
- //
- // take the given range out of the block
- //
- oldend = scan->start + scan->length;
- extra = oldend - (segstart+seglength);
- if (extra < 0)
- Quit ("MML_UseSpace: Segment spans two blocks!");
- 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;
- }
- Quit ("MM_ClearBlock: No purgable blocks!");
- }
- //==========================================================================
- /*
- ===================
- =
- = MM_Startup
- =
- = Grabs all space from turbo with malloc/farmalloc
- = Allocates bufferseg misc buffer
- =
- ===================
- */
- static char *ParmStrings[] = {"noems","noxms",""};
- void MM_Startup (void)
- {
- int i;
- unsigned long 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;i<MAXBLOCKS-1;i++)
- mmblocks[i].next = &mmblocks[i+1];
- mmblocks[i].next = NULL;
- //
- // locked block of all memory until we punch out free space
- //
- GETNEWBLOCK;
- mmhead = mmnew; // this will allways be the first node
- mmnew->start = 0;
- mmnew->length = 0xffff;
- mmnew->attributes = LOCKBIT;
- mmnew->next = NULL;
- mmrover = mmhead;
- //
- // get all available near conventional memory segments
- //
- length=coreleft();
- 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();
- start = farheap = farmalloc(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],ParmStrings) == 0)
- goto emsskip; // param NOEMS
- }
- if (MML_CheckForEMS())
- {
- MML_SetupEMS(); // allocate space
- MML_UseSpace (EMSpageframe,EMSpagesmapped*0x400);
- MM_MapEMS(); // map in used pages
- 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],ParmStrings) == 0)
- goto xmsskip; // param NOXMS
- }
- if (MML_CheckForXMS())
- 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;
- farfree (farheap);
- free (nearheap);
- MML_ShutdownEMS ();
- MML_ShutdownXMS ();
- }
- //==========================================================================
- /*
- ====================
- =
- = MM_GetPtr
- =
- = Allocates an unlocked, unpurgable block
- =
- ====================
- */
- void MM_GetPtr (memptr *baseptr,unsigned long 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)
- Quit (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)
- Quit ("MM_FreePtr: Block not found!");
- 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)
- Quit ("MM_SetPurge: Block not found!");
- } 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)
- Quit ("MM_SetLock: Block not found!");
- } 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;
- long end,owner;
- char scratch[80],str[10];
- VW_SetDefaultColors();
- VW_SetLineWidth(40);
- temp = bufferofs;
- 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)
- Quit ("MM_ShowMemory: Memory block order currupted!");
- 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
- 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));
- #endif
- scan = scan->next;
- }
- //CA_CloseDebug ();
- IN_Ack();
- VW_SetLineWidth(64);
- bufferofs = temp;
- }
- #endif
- //==========================================================================
- /*
- ======================
- =
- = MM_UnusedMemory
- =
- = Returns the total free space without purging
- =
- ======================
- */
- long 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
- =
- ======================
- */
- long 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_BombOnError
- =
- =====================
- */
- void MM_BombOnError (boolean bomb)
- {
- bombonerror = bomb;
- }
|