- 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;
- 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
-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));
-printf("%s\n", 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
-=
-======================
-*/
-
-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;
-}
-
-///////////////////////////////////////////////////////////////////////////
-//
-// 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);
-}
-
+ printf("EMS freed\n");\r
+//++++ MML_ShutdownXMS ();
+ printf("XMS freed\n");\r
+}\r
+\r
+//==========================================================================\r
+\r
+/*\r
+====================\r
+=\r
+= MM_GetPtr\r
+=\r
+= Allocates an unlocked, unpurgable block\r
+=\r
+====================\r
+*/\r
+\r
+void MM_GetPtr (memptr *baseptr,dword size)\r
+{\r
+ mmblocktype far *scan,far *lastscan,far *endscan\r
+ ,far *purge,far *next;\r
+ int search;\r
+ unsigned needed,startseg;\r
+\r
+ needed = (size+15)/16; // convert size from bytes to paragraphs\r
+\r
+ GETNEWBLOCK; // fill in start and next after a spot is found\r
+ mmnew->length = needed;\r
+ mmnew->useptr = baseptr;\r
+ mmnew->attributes = BASEATTRIBUTES;\r
+\r
+ for (search = 0; search<3; search++)\r
+ {\r
+ //\r
+ // first search: try to allocate right after the rover, then on up\r
+ // second search: search from the head pointer up to the rover\r
+ // third search: compress memory, then scan from start\r
+ if (search == 1 && mmrover == mmhead)\r
+ search++;\r
+\r
+ switch (search)\r
+ {\r
+ case 0:\r
+ lastscan = mmrover;\r
+ scan = mmrover->next;\r
+ endscan = NULL;\r
+ break;\r
+ case 1:\r
+ lastscan = mmhead;\r
+ scan = mmhead->next;\r
+ endscan = mmrover;\r
+ break;\r
+ case 2:\r
+ MM_SortMem ();\r
+ lastscan = mmhead;\r
+ scan = mmhead->next;\r
+ endscan = NULL;\r
+ break;\r
+ }\r
+\r
+ startseg = lastscan->start + lastscan->length;\r
+\r
+ while (scan != endscan)\r
+ {\r
+ if (scan->start - startseg >= needed)\r
+ {\r
+ //\r
+ // got enough space between the end of lastscan and\r
+ // the start of scan, so throw out anything in the middle\r
+ // and allocate the new block\r
+ //\r
+ purge = lastscan->next;\r
+ lastscan->next = mmnew;\r
+ mmnew->start = *(unsigned *)baseptr = startseg;\r
+ mmnew->next = scan;\r
+ while ( purge != scan)\r
+ { // free the purgable block\r
+ next = purge->next;\r
+ FREEBLOCK(purge);\r
+ purge = next; // purge another if not at scan\r
+ }\r
+ mmrover = mmnew;\r
+ return; // good allocation!\r
+ }\r
+\r
+ //\r
+ // if this block is purge level zero or locked, skip past it\r
+ //\r
+ if ( (scan->attributes & LOCKBIT)\r
+ || !(scan->attributes & PURGEBITS) )\r
+ {\r
+ lastscan = scan;\r
+ startseg = lastscan->start + lastscan->length;\r
+ }\r
+\r
+\r
+ scan=scan->next; // look at next line\r
+ }\r
+ }\r
+\r
+ if (mminfo.bombonerror)\r
+ printf(OUT_OF_MEM_MSG,(size-mminfo.nearheap));\r
+ else\r
+ mminfo.mmerror = true;\r
+}\r
+\r
+//==========================================================================\r
+\r
+/*\r
+====================\r
+=\r
+= MM_FreePtr\r
+=\r
+= Allocates an unlocked, unpurgable block\r
+=\r
+====================\r
+*/\r
+\r
+void MM_FreePtr (memptr *baseptr)\r
+{\r
+ mmblocktype far *scan,far *last;\r
+\r
+ last = mmhead;\r
+ scan = last->next;\r
+\r
+ if (baseptr == mmrover->useptr) // removed the last allocated block\r
+ mmrover = mmhead;\r
+\r
+ while (scan->useptr != baseptr && scan)\r
+ {\r
+ last = scan;\r
+ scan = scan->next;\r
+ }\r
+\r
+ if (!scan)\r
+ {\r
+ printf("MM_FreePtr: Block not found!");\r
+ return;\r
+ }\r
+\r
+ last->next = scan->next;\r
+\r
+ FREEBLOCK(scan);\r
+}\r
+//==========================================================================\r
+\r
+/*\r
+=====================\r
+=\r
+= MM_SetPurge\r
+=\r
+= Sets the purge level for a block (locked blocks cannot be made purgable)\r
+=\r
+=====================\r
+*/\r
+\r
+void MM_SetPurge (memptr *baseptr, int purge)\r
+{\r
+ mmblocktype far *start;\r
+\r
+ start = mmrover;\r
+\r
+ do\r
+ {\r
+ if (mmrover->useptr == baseptr)\r
+ break;\r
+\r
+ mmrover = mmrover->next;\r
+\r
+ if (!mmrover)\r
+ mmrover = mmhead;\r
+ else if (mmrover == start)\r
+ {\r
+ printf("MM_SetPurge: Block not found!");\r
+ return;\r
+ }\r
+\r
+ } while (1);\r
+\r
+ mmrover->attributes &= ~PURGEBITS;\r
+ mmrover->attributes |= purge;\r
+}\r
+\r
+//==========================================================================\r
+\r
+/*\r
+=====================\r
+=\r
+= MM_SetLock\r
+=\r
+= Locks / unlocks the block\r
+=\r
+=====================\r
+*/\r
+\r
+void MM_SetLock (memptr *baseptr, boolean locked)\r
+{\r
+ mmblocktype far *start;\r
+\r
+ start = mmrover;\r
+\r
+ do\r
+ {\r
+ if (mmrover->useptr == baseptr)\r
+ break;\r
+\r
+ mmrover = mmrover->next;\r
+\r
+ if (!mmrover)\r
+ mmrover = mmhead;\r
+ else if (mmrover == start)\r
+ {\r
+ printf("MM_SetLock: Block not found!");\r
+ return;\r
+ }\r
+\r
+ } while (1);\r
+\r
+ mmrover->attributes &= ~LOCKBIT;\r
+ mmrover->attributes |= locked*LOCKBIT;\r
+}\r
+\r
+//==========================================================================\r
+\r
+/*\r
+=====================\r
+=\r
+= MM_SortMem\r
+=\r
+= Throws out all purgable stuff and compresses movable blocks\r
+=\r
+=====================\r
+*/\r
+\r
+void MM_SortMem (void)\r
+{\r
+ mmblocktype far *scan,far *last,far *next;\r
+ unsigned start,length,source,dest,oldborder;\r
+ int playing;\r
+\r
+ //\r
+ // lock down a currently playing sound\r
+ //\r
+/*++++ playing = SD_SoundPlaying ();\r
+ if (playing)\r
+ {\r
+ switch (SoundMode)\r
+ {\r
+ case sdm_PC:\r
+ playing += STARTPCSOUNDS;\r
+ break;\r
+ case sdm_AdLib:\r
+ playing += STARTADLIBSOUNDS;\r
+ break;\r
+ }\r
+ MM_SetLock(&(memptr)audiosegs[playing],true);\r
+ }\r
+\r
+\r
+ SD_StopSound();*/\r
+// oldborder = bordercolor;\r
+// VW_ColorBorder (15);\r
+\r
+ if (beforesort)\r
+ beforesort();\r
+\r
+ scan = mmhead;\r
+\r
+ last = NULL; // shut up compiler warning\r
+\r
+ while (scan)\r
+ {\r
+ if (scan->attributes & LOCKBIT)\r
+ {\r
+ //\r
+ // block is locked, so try to pile later blocks right after it\r
+ //\r
+ start = scan->start + scan->length;\r
+ }\r
+ else\r
+ {\r
+ if (scan->attributes & PURGEBITS)\r
+ {\r
+ //\r
+ // throw out the purgable block\r
+ //\r
+ next = scan->next;\r
+ FREEBLOCK(scan);\r
+ last->next = next;\r
+ scan = next;\r
+ continue;\r
+ }\r
+ else\r
+ {\r
+ //\r
+ // push the non purgable block on top of the last moved block\r
+ //\r
+ if (scan->start != start)\r
+ {\r
+ length = scan->length;\r
+ source = scan->start;\r
+ dest = start;\r
+ while (length > 0xf00)\r
+ {\r
+ movedata(source,0,dest,0,0xf00*16);\r
+ length -= 0xf00;\r
+ source += 0xf00;\r
+ dest += 0xf00;\r
+ }\r
+ movedata(source,0,dest,0,length*16);\r
+\r
+ scan->start = start;\r
+ *(unsigned *)scan->useptr = start;\r
+ }\r
+ start = scan->start + scan->length;\r
+ }\r
+ }\r
+\r
+ last = scan;\r
+ scan = scan->next; // go to next block\r
+ }\r
+\r
+ mmrover = mmhead;\r
+\r
+ if (aftersort)\r
+ aftersort();\r
+\r
+// VW_ColorBorder (oldborder);\r
+\r
+/*++++ if (playing)\r
+ MM_SetLock(&(memptr)audiosegs[playing],false);*/\r
+}\r
+\r
+\r
+//==========================================================================\r
+\r
+//****#if 0\r
+/*\r
+=====================\r
+=\r
+= MM_ShowMemory\r
+=\r
+=====================\r
+*/\r
+\r
+void MM_ShowMemory (void)\r
+{\r
+ mmblocktype far *scan;\r
+ unsigned color,temp;//, i;\r
+ long end,owner;\r
+ char scratch[80],str[10];\r
+\r
+//**** VW_SetDefaultColors();\r
+//**** VW_SetLineWidth(40);\r
+//++++mh temp = bufferofs;\r
+//++++mh bufferofs = 0;\r
+//**** VW_SetScreen (0,0);\r
+\r
+ scan = mmhead;\r
+\r
+ end = -1;\r
+\r
+//CA_OpenDebug ();\r
+\r
+ while (scan)\r
+ {\r
+ if (scan->attributes & PURGEBITS)\r
+ color = 5; // dark purple = purgable\r
+ else\r
+ color = 9; // medium blue = non purgable\r
+ if (scan->attributes & LOCKBIT)\r
+ color = 12; // red = locked\r
+ if (scan->start<=end)\r
+ {\r
+ printf("MM_ShowMemory: Memory block order currupted!");\r
+ return;\r
+ }\r
+ end = scan->start+scan->length-1;\r
+//++++ VW_Hlin(scan->start,(unsigned)end,0,color);\r
+//++++ VW_Plot(scan->start,0,15);\r
+ if (scan->next->start > end+1)\r
+//++++ VW_Hlin(end+1,scan->next->start,0,0); // black = free\r
+\r
+//****#if 0\r
+printf("Location:");\r
+printf("%Fp\t", scan->start);\r
+strcpy (scratch,"Size:");\r
+ltoa ((long)scan->length*16,str,10);\r
+strcat (scratch,str);\r
+strcat (scratch,"\tOwner:0x");\r
+owner = (unsigned)scan->useptr;\r
+ultoa (owner,str,16);\r
+strcat (scratch,str);\r
+strcat (scratch,"\n");\r
+//++++write (debughandle,scratch,strlen(scratch));\r
+fprintf(stdout, "%s", scratch);\r
+//****#endif\r
+\r
+ scan = scan->next;\r
+ }\r
+\r
+//CA_CloseDebug ();\r
+\r
+//++++mh IN_Ack();\r
+//**** VW_SetLineWidth(64);\r
+//++++mh bufferofs = temp;\r
+}\r
+//****#endif\r
+\r
+//==========================================================================\r
+\r
+\r
+/*\r
+======================\r
+=\r
+= MM_UnusedMemory\r
+=\r
+= Returns the total free space without purging\r
+=\r
+======================\r
+*/\r
+\r
+dword MM_UnusedMemory (void)\r
+{\r
+ unsigned free;\r
+ mmblocktype far *scan;\r
+\r
+ free = 0;\r
+ scan = mmhead;\r
+\r
+ while (scan->next)\r
+ {\r
+ free += scan->next->start - (scan->start + scan->length);\r
+ scan = scan->next;\r
+ }\r
+\r
+// return free*16l;\r
+ return free;\r
+}\r
+\r
+//==========================================================================\r
+\r
+\r
+/*\r
+======================\r
+=\r
+= MM_TotalFree\r
+=\r
+= Returns the total free space with purging\r
+=\r
+======================\r
+*/\r
+\r
+dword MM_TotalFree (void)\r
+{\r
+ unsigned free;\r
+ mmblocktype far *scan;\r
+\r
+ free = 0;\r
+ scan = mmhead;\r
+\r
+ while (scan->next)\r
+ {\r
+ if ((scan->attributes&PURGEBITS) && !(scan->attributes&LOCKBIT))\r
+ free += scan->length;\r
+ free += scan->next->start - (scan->start + scan->length);\r
+ scan = scan->next;\r
+ }\r
+\r
+// return free*16l;\r
+ return free;\r
+}\r
+\r
+//==========================================================================\r
+\r
+/*\r
+=====================\r
+=\r
+= MM_Report\r
+=\r
+=====================\r
+*/\r
+\r
+void MM_Report(void)\r
+{\r
+ printf("EMM %x available\n", EMSVer);\r
+ printf("totalEMSpages=%u\n", totalEMSpages);\r
+ printf("freeEMSpages=%u\n", freeEMSpages);\r
+ printf("EMSpageframe=%Fp\n", EMSpageframe);\r
+ printf("near=%lu\n", mminfo.nearheap);\r
+ printf("far=%lu\n", mminfo.farheap);\r
+ printf("EMSmem=%lu\n", mminfo.EMSmem);\r
+ printf("XMSmem=%lu\n", mminfo.XMSmem);\r
+ printf("mainmem=%lu\n", mminfo.mainmem);\r
+ printf("UnusedMemory=%lu\n", MM_UnusedMemory());\r
+ printf("TotalFree=%lu\n", MM_TotalFree());\r
+// printf("\n");\r
+// printf("UnusedMemory=%lu kb\n", MM_UnusedMemory()/10248);\r
+// printf("TotalFree=%lu kb\n", MM_TotalFree()/10248);\r
+}\r
+\r
+//==========================================================================\r
+\r
+/*\r
+=====================\r
+=\r
+= MM_EMSVer\r
+=\r
+=====================\r
+\r
+\r
+int MM_EMSVer(void)\r
+{\r
+ int EMSver;\r
+ __asm\r
+ {\r
+ mov ah,EMS_VERSION\r
+ int EMS_INT\r
+ mov EMSver,ax\r
+ }\r
+ return(EMSver);\r
+}*/\r
+\r
+//==========================================================================\r
+\r
+/*\r
+=====================\r
+=\r
+= MM_BombOnError\r
+=\r
+=====================\r
+*/\r
+\r
+void MM_BombOnError (boolean bomb)\r
+{\r
+ mminfo.bombonerror = bomb;\r
+}\r
+\r
+//==========================================================================\r
+\r
+///////////////////////////////////////////////////////////////////////////\r
+//\r
+// US_CheckParm() - checks to see if a string matches one of a set of\r
+// strings. The check is case insensitive. The routine returns the\r
+// index of the string that matched, or -1 if no matches were found\r
+//\r
+///////////////////////////////////////////////////////////////////////////\r
+int\r
+US_CheckParm(char *parm,char **strings)\r
+{\r
+ char cp,cs,\r
+ *p,*s;\r
+ int i;\r
+\r
+ while (!isalpha(*parm)) // Skip non-alphas\r
+ parm++;\r
+\r
+ for (i = 0;*strings && **strings;i++)\r
+ {\r
+ for (s = *strings++,p = parm,cs = cp = 0;cs == cp;)\r
+ {\r
+ cs = *s++;\r
+ if (!cs)\r
+ return(i);\r
+ cp = *p++;\r
+\r
+ if (isupper(cs))\r
+ cs = tolower(cs);\r
+ if (isupper(cp))\r
+ cp = tolower(cp);\r
+ }\r
+ }\r
+ return(-1);\r
+}\r