OSDN Git Service

reverted to older ver of 16_mm because of bugs
authorsparky4 <sparky4@cock.li>
Thu, 22 Sep 2016 19:44:04 +0000 (14:44 -0500)
committersparky4 <sparky4@cock.li>
Thu, 22 Sep 2016 19:44:04 +0000 (14:44 -0500)
17 files changed:
16/16_mm.c [new file with mode: 0755]
DEBUG.16B
DEBUG.16W
HEAP.16W
MMDUMP.16B
MMDUMP.16W
bcexmm.exe
bcexmm.prj
src/exmmtest.c
src/lib/16_head.h
src/lib/16_mm.c
src/lib/16_mm.h
src/lib/16_pm.c
src/lib/16_pm.h
src/lib/length [new file with mode: 0755]
src/lib/next [new file with mode: 0755]
src/lib/typdefst.h

diff --git a/16/16_mm.c b/16/16_mm.c
new file mode 100755 (executable)
index 0000000..9f10fd3
--- /dev/null
@@ -0,0 +1,1802 @@
+/* Catacomb Apocalypse Source Code\r
+ * Copyright (C) 1993-2014 Flat Rock Software\r
+ *\r
+ * This program is free software; you can redistribute it and/or modify\r
+ * it under the terms of the GNU General Public License as published by\r
+ * the Free Software Foundation; either version 2 of the License, or\r
+ * (at your option) any later version.\r
+ *\r
+ * This program is distributed in the hope that it will be useful,\r
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of\r
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r
+ * GNU General Public License for more details.\r
+ *\r
+ * You should have received a copy of the GNU General Public License along\r
+ * with this program; if not, write to the Free Software Foundation, Inc.,\r
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.\r
+ */\r
+\r
+// NEWMM.C\r
+\r
+/*\r
+=============================================================================\r
+\r
+                       ID software memory manager\r
+                       --------------------------\r
+\r
+Primary coder: John Carmack\r
+\r
+RELIES ON\r
+---------\r
+Quit (char *error) function\r
+\r
+\r
+WORK TO DO\r
+----------\r
+MM_SizePtr to change the size of a given pointer\r
+\r
+Multiple purge levels utilized\r
+\r
+EMS / XMS unmanaged routines\r
+\r
+=============================================================================\r
+*/\r
+/*\r
+\r
+Open Watcom port by sparky4\r
+\r
+*/\r
+#include "src/lib/16_mm.h"\r
+#include "src/lib/16_ca.h"\r
+#pragma hdrstop\r
+\r
+#pragma warn -pro\r
+#pragma warn -use\r
+\r
+/*\r
+=============================================================================\r
+\r
+                                                GLOBAL VARIABLES\r
+\r
+=============================================================================\r
+*/\r
+\r
+void           (* beforesort) (void);\r
+void           (* aftersort) (void);\r
+void           (* XMSaddr) (void);             // far pointer to XMS driver\r
+\r
+/*\r
+=============================================================================\r
+\r
+                                                LOCAL VARIABLES\r
+\r
+=============================================================================\r
+*/\r
+\r
+/*\r
+======================\r
+=\r
+= MML_CheckForEMS\r
+=\r
+= Routine from p36 of Extending DOS\r
+=\r
+=======================\r
+*/\r
+\r
+boolean MML_CheckForEMS(void)\r
+{\r
+       boolean emmcfems;\r
+       static char     emmname[] = "EMMXXXX0"; //fix by andrius4669\r
+       __asm {\r
+               mov     dx,OFFSET emmname       //fix by andrius4669\r
+               mov     ax,0x3d00\r
+               int     0x21            // try to open EMMXXXX0 device\r
+               jc      error\r
+\r
+               mov     bx,ax\r
+               mov     ax,0x4400\r
+\r
+               int     0x21            // get device info\r
+               jc      error\r
+\r
+               and     dx,0x80\r
+               jz      error\r
+\r
+               mov     ax,0x4407\r
+\r
+               int     0x21            // get status\r
+               jc      error\r
+               or      al,al\r
+               jz      error\r
+\r
+               mov     ah,0x3e\r
+               int     0x21            // close handle\r
+               jc      error\r
+               //\r
+               // EMS is good\r
+               //\r
+               mov     emmcfems,1\r
+               jmp End\r
+#ifdef __BORLANDC__\r
+       }\r
+#endif\r
+               error:\r
+#ifdef __BORLANDC__\r
+       __asm {\r
+#endif\r
+               //\r
+               // EMS is bad\r
+               //\r
+               mov     emmcfems,0\r
+#ifdef __BORLANDC__\r
+       }\r
+#endif\r
+               End:\r
+#ifdef __WATCOMC__\r
+       }\r
+#endif\r
+       return(emmcfems);\r
+}\r
+\r
+\r
+/*\r
+======================\r
+=\r
+= MML_SetupEMS\r
+=\r
+=======================\r
+*/\r
+\r
+byte MML_SetupEMS(global_game_variables_t *gvar)\r
+{\r
+       byte    str[160];\r
+       byte    err;\r
+       boolean errorflag=false;\r
+\r
+       unsigned int EMSVer = 0;\r
+       //byte  EMS_status;\r
+       unsigned        totalEMSpages,freeEMSpages,EMSPageFrame,EMSpagesmapped,EMSHandle;\r
+       totalEMSpages = freeEMSpages = EMSPageFrame = EMSpagesmapped = 0;\r
+\r
+       __asm {\r
+               mov     ah,EMS_STATUS\r
+               int     EMS_INT                                         // make sure EMS hardware is present\r
+               or      ah,ah\r
+               //mov   [EMS_status],ah\r
+               jnz     error\r
+\r
+               mov     ah,EMS_VERSION\r
+               int     EMS_INT\r
+               or      ah,ah\r
+               jnz     error\r
+               mov     [EMSVer],ax                             //      set EMSVer\r
+               cmp     al,0x32                                         // only work on ems 3.2 or greater\r
+               jb      error\r
+\r
+               mov     ah,EMS_GETFRAME\r
+               int     EMS_INT                                         // find the page frame address\r
+               or      ah,ah\r
+               jnz     error\r
+               mov     [EMSPageFrame],bx\r
+\r
+               mov     ah,EMS_GETPAGES\r
+               int     EMS_INT                                         // find out how much EMS is there\r
+               or      ah,ah\r
+               jnz     error\r
+               mov     [totalEMSpages],dx\r
+               mov     [freeEMSpages],bx\r
+               or      bx,bx\r
+               jz      noEMS                                           // no EMS at all to allocate\r
+                                                                                       //EXPAND DONG!!!!\r
+               cmp     [EMSVer],0x40\r
+               jb      low\r
+               cmp     bx,[freeEMSpages]\r
+               jle     getpages\r
+               mov     bx,[freeEMSpages]\r
+               jmp     getpages\r
+#ifdef __BORLANDC__\r
+       }\r
+#endif\r
+       low:\r
+#ifdef __BORLANDC__\r
+       __asm {\r
+#endif\r
+               cmp     bx,4\r
+               jle     getpages                                        // there is only 1,2,3,or 4 pages\r
+               mov     bx,4                                            // we can't use more than 4 pages\r
+#ifdef __BORLANDC__\r
+       }\r
+#endif\r
+       getpages:\r
+#ifdef __BORLANDC__\r
+       __asm {\r
+#endif\r
+               mov     [EMSpagesmapped],bx\r
+               mov     ah,EMS_ALLOCPAGES                       // allocate up to 64k of EMS\r
+               int     EMS_INT\r
+               or      ah,ah\r
+               jnz     error\r
+               mov     [EMSHandle],dx\r
+               jmp End\r
+#ifdef __BORLANDC__\r
+       }\r
+#endif\r
+       error:\r
+#ifdef __BORLANDC__\r
+       __asm {\r
+#endif\r
+               mov     err,ah\r
+               mov     errorflag,1\r
+               jmp End\r
+#ifdef __BORLANDC__\r
+       }\r
+#endif\r
+noEMS:\r
+End:\r
+#ifdef __WATCOMC__\r
+       }\r
+#endif\r
+       if(errorflag==true)\r
+       {\r
+               strcpy(str,"MM_SetupEMS: EMS error ");\r
+               MM_EMSerr(str, err);\r
+               printf("%s\n",str);\r
+               return err;\r
+       }\r
+       gvar->pm.emm.totalEMSpages=totalEMSpages;\r
+       gvar->pm.emm.freeEMSpages=freeEMSpages;\r
+       gvar->pm.emm.EMSPageFrame=EMSPageFrame;\r
+       gvar->pm.emm.EMSpagesmapped=EMSpagesmapped;\r
+       gvar->pm.emm.EMSHandle=EMSHandle;\r
+       gvar->pm.emm.EMSVer=EMSVer;\r
+       return 0;\r
+}\r
+\r
+\r
+/*\r
+======================\r
+=\r
+= MML_ShutdownEMS\r
+=\r
+=======================\r
+*/\r
+\r
+void MML_ShutdownEMS(global_game_variables_t *gvar)\r
+{\r
+       boolean errorflag=false;\r
+       unsigned EMSHandle=gvar->pm.emm.EMSHandle;\r
+\r
+       if(!EMSHandle)\r
+               return;\r
+       __asm {\r
+               mov     ah,EMS_FREEPAGES\r
+               mov     dx,[EMSHandle]\r
+               int     EMS_INT\r
+               or      ah,ah\r
+               jz      ok\r
+               mov     errorflag,1\r
+#ifdef __BORLANDC__\r
+       }\r
+#endif\r
+               ok:\r
+#ifdef __WATCOMC__\r
+       }\r
+#endif\r
+       if(errorflag==true)\r
+               Quit("MML_ShutdownEMS: Error freeing EMS!\n");  //++++ add something\r
+}\r
+\r
+/*\r
+====================\r
+=\r
+= MM_MapEMS\r
+=\r
+= Maps the 64k of EMS used by memory manager into the page frame\r
+= for general use.  This only needs to be called if you are keeping\r
+= other things in EMS.\r
+=\r
+====================\r
+*/\r
+\r
+byte MM_MapEMS(global_game_variables_t *gvar)\r
+{\r
+       byte    str[160];\r
+       unsigned        EMSHandle;\r
+       byte err;\r
+       boolean errorflag=false;\r
+       int     i;\r
+       EMSHandle=gvar->pm.emm.EMSHandle;\r
+\r
+       for (i=0;i<4/*MAPPAGES*/;i++)\r
+       {\r
+               __asm {\r
+                       mov     ah,EMS_MAPPAGE\r
+                       mov     bx,[i]                  // logical page\r
+                       mov     al,bl                   // physical page\r
+                       mov     dx,[EMSHandle]  // handle\r
+                       int     EMS_INT\r
+                       or      ah,ah\r
+                       jnz     error\r
+                       jmp End\r
+#ifdef __BORLANDC__\r
+               }\r
+#endif\r
+                       error:\r
+#ifdef __BORLANDC__\r
+               __asm {\r
+#endif\r
+                       mov     err,ah\r
+                       mov     errorflag,1\r
+#ifdef __BORLANDC__\r
+               }\r
+#endif\r
+                       End:\r
+#ifdef __WATCOMC__\r
+               }\r
+#endif\r
+               if(errorflag==true)\r
+               {\r
+                       strcpy(str,"MM_MapEMS: EMS error ");\r
+                       MM_EMSerr(str, err);\r
+                       printf("%s\n",str);\r
+                       return err;\r
+               }\r
+       }\r
+       gvar->mmi.EMSmem = (i)*0x4000lu;\r
+       //printf("              gvar->mmi.EMSmem=%lu\n", gvar->mmi.EMSmem);\r
+       return 0;\r
+}\r
+\r
+byte MM_MapXEMS(global_game_variables_t *gvar)\r
+{\r
+//SUB EMS.MapXPages (PhysicalStart, LogicalStart, NumPages, Handle)\r
+\r
+       //Maps up to 4 logical EMS pages to physical pages in the page frame, where:\r
+       //PhysicalStart = Physical page first logical page is mapped to\r
+       //LogicalStart  = First logical page to map\r
+       //NumPages      = Number of pages to map (1 to 4)\r
+       //Handle        = EMS handle logical pages are allocated to\r
+\r
+  /*//Create a buffer containing the page information\r
+//  FOR x = 0 TO NumPages - 1\r
+//    MapInfo$ = MapInfo$ + MKI$(LogicalStart + x) + MKI$(PhysicalStart + x)\r
+//  NEXT*/\r
+\r
+//  Regs.ax = 0x5000                           //Map the pages in the buffer\r
+//  Regs.cx = NumPages                         //to the pageframe\r
+//  Regs.dx = Handle\r
+//  Regs.ds = VARSEG(MapInfo$)\r
+//  Regs.si = SADD(MapInfo$)\r
+//  InterruptX 0x67, Regs, Regs\r
+//     EMS.Error = (Regs.ax AND 0xFF00&) \ 0x100  //Store the status code\r
+\r
+//END SUB\r
+       byte    str[160];\r
+       byte err;\r
+       word    EMSHandle;\r
+       boolean errorflag=false;\r
+       int     i;\r
+       EMSHandle=gvar->pm.emm.EMSHandle;\r
+\r
+       if(gvar->pm.emm.EMSVer<0x40)\r
+               return 5;\r
+\r
+       for (i=0;i<MAPPAGES;i++)\r
+       {\r
+               __asm {\r
+                       mov     ah,EMS_MAPXPAGE\r
+                       mov     cx,[i]                  // logical page\r
+                       mov     al,bl                   // physical page\r
+                       mov     dx,[EMSHandle]  // handle\r
+                       int     EMS_INT\r
+                       or      ah,ah\r
+                       jnz     error\r
+                       jmp End\r
+#ifdef __BORLANDC__\r
+               }\r
+#endif\r
+                       error:\r
+#ifdef __BORLANDC__\r
+               __asm {\r
+#endif\r
+                       mov     err,ah\r
+                       mov     errorflag,1\r
+#ifdef __BORLANDC__\r
+               }\r
+#endif\r
+                       End:\r
+#ifdef __WATCOMC__\r
+               }\r
+#endif\r
+               if(errorflag==true)\r
+               {\r
+                       //strcpy(str,"MM_MapXEMS: EMS error 0x");\r
+                       strcpy(str,"MM_MapXEMS: EMS error ");\r
+                       //itoa(err,str2,16);\r
+                       MM_EMSerr(str, err);\r
+                       printf("%s\n",str);\r
+                       //printf("%s%x\n",str, err);\r
+                       //printf("FACK! %x\n", err);\r
+                       return err;\r
+               }\r
+       }\r
+       gvar->mmi.EMSmem = (i)*0x4000lu;\r
+       return 0;\r
+}\r
+\r
+//==========================================================================\r
+\r
+/*\r
+======================\r
+=\r
+= MML_CheckForXMS\r
+=\r
+= Check for XMM driver\r
+=\r
+=======================\r
+*/\r
+\r
+boolean MML_CheckForXMS(global_game_variables_t *gvar)\r
+{\r
+       boolean errorflag=false;\r
+       gvar->mm.numUMBs = 0;\r
+\r
+       __asm {\r
+               mov     ax,0x4300\r
+               int     0x2f                            // query status of installed diver\r
+               cmp     al,0x80\r
+               je      good\r
+               mov     errorflag,1\r
+#ifdef __BORLANDC__\r
+       }\r
+#endif\r
+               good:\r
+#ifdef __WATCOMC__\r
+       }\r
+#endif\r
+       if(errorflag==true) return false;\r
+       else return true;\r
+}\r
+\r
+\r
+/*\r
+======================\r
+=\r
+= MML_SetupXMS\r
+=\r
+= Try to allocate all upper memory block\r
+=\r
+=======================\r
+*/\r
+\r
+void MML_SetupXMS(global_game_variables_t *gvar)\r
+{\r
+       word    base,size;\r
+\r
+\r
+       __asm {\r
+               mov     ax,0x4310\r
+               int     0x2f\r
+               mov     [WORD PTR XMSaddr],bx\r
+               mov     [WORD PTR XMSaddr+2],es         // function pointer to XMS driver\r
+       }\r
+getmemory:\r
+       __asm {\r
+               mov     ah,XMS_ALLOCUMB\r
+               mov     dx,0xffff                                       // try for largest block possible\r
+               //mov     ax,dx                                         // Set available Kbytes.\r
+               call    [DWORD PTR XMSaddr]\r
+               or      ax,ax\r
+               jnz     gotone\r
+\r
+               cmp     bl,0xb0                                         // error: smaller UMB is available\r
+               jne     done;\r
+\r
+               mov     ah,XMS_ALLOCUMB\r
+               call    [DWORD PTR XMSaddr]             // DX holds largest available UMB\r
+               or      ax,ax\r
+               jz      done                                            // another error...\r
+#ifdef __BORLANDC__\r
+       }\r
+#endif\r
+               gotone:\r
+#ifdef __BORLANDC__\r
+       __asm {\r
+#endif\r
+               mov     [base],bx\r
+               mov     [size],dx\r
+#ifdef __BORLANDC__\r
+       }\r
+#endif\r
+               done:\r
+#ifdef __WATCOMC__\r
+       }\r
+#endif\r
+//     printf("base=%u ", base); printf("size=%u\n", size);\r
+       MML_UseSpace(base,size, gvar);\r
+       gvar->mmi.XMSmem += size*16;\r
+       gvar->mm.UMBbase[gvar->mm.numUMBs] = base;\r
+       gvar->mm.numUMBs++;\r
+       if(gvar->mm.numUMBs < MAXUMBS)\r
+               goto getmemory;\r
+}\r
+\r
+\r
+/*\r
+======================\r
+=\r
+= MML_ShutdownXMS\r
+=\r
+======================\r
+*/\r
+\r
+void MML_ShutdownXMS(global_game_variables_t *gvar)\r
+{\r
+       int     i;\r
+       unsigned        base;\r
+\r
+       for (i=0;i<gvar->mm.numUMBs;i++)\r
+       {\r
+               base = gvar->mm.UMBbase[i];\r
+               __asm {\r
+                       mov     ah,XMS_FREEUMB\r
+                       mov     dx,[base]\r
+                       call    [DWORD PTR XMSaddr]\r
+               }\r
+       }\r
+}\r
+\r
+//==========================================================================\r
+\r
+/*\r
+======================\r
+=\r
+= MML_UseSpace\r
+=\r
+= Marks a range of paragraphs as usable by the memory manager\r
+= This is used to mark space for the near heap, far heap, ems page frame,\r
+= and upper memory blocks\r
+=\r
+======================\r
+*/\r
+\r
+/*void MML_UseSpace(word segstart, dword seglength, global_game_variables_t *gvar)\r
+{\r
+       //huge mmblocktype huge *scan,huge *last;\r
+       word            segm=1;\r
+       word    oldend;\r
+       dword           segmlen;\r
+       dword           extra;\r
+\r
+       scan = last = gvar->mm.mmhead;\r
+       gvar->mm.mmrover = gvar->mm.mmhead;             // reset rover to start of memory\r
+\r
+//\r
+// search for the block that contains the range of segments\r
+//\r
+       while(scan->start+scan->length < segstart)\r
+       {\r
+               last = scan;\r
+               scan = scan->next;\r
+       }\r
+\r
+//\r
+// take the given range out of the block\r
+//\r
+       oldend = scan->start + scan->length;\r
+       extra = oldend - (segstart+seglength);\r
+\r
+       segmlen=extra;\r
+\r
+       //++++emsver stuff!\r
+       if(segm>1)/// || extra>=0x10000lu)\r
+       //if(extra>0xfffflu)\r
+       {\r
+               scan->blob=segm;\r
+\r
+               //MML_UseSpace(segstart, seglength, gvar);\r
+\r
+               printf("MML_UseSpace: Segment spans two blocks!\n");\r
+       //}\r
+       printf("segm=%u         ", segm);\r
+       printf("ex=%lu  ", extra);\r
+       printf("old=%u  ", oldend);\r
+       printf("start+seglen=%lu\n", segstart+seglength);\r
+       printf("segsta=%x       ", segstart);\r
+       printf("len=%lu ", scan->length);\r
+       printf("seglen=%lu      ", seglength);\r
+       printf("segmlen=%lu\n", segmlen);\r
+       }\r
+//++++todo: linked list of segment!\r
+       if(segstart == scan->start)\r
+       {\r
+               last->next = scan->next;                        // unlink block\r
+               FREEBLOCK(scan);\r
+               scan = last;\r
+       }\r
+       else\r
+               scan->length = segstart-scan->start;    // shorten block\r
+\r
+       if(extra > 0)\r
+       {\r
+               GETNEWBLOCK;\r
+               gvar->mm.mmnew->useptr = NULL;\r
+\r
+               gvar->mm.mmnew->next = scan->next;\r
+               scan->next = gvar->mm.mmnew;\r
+               gvar->mm.mmnew->start = segstart+seglength;\r
+               gvar->mm.mmnew->length = extra;\r
+               gvar->mm.mmnew->attributes = LOCKBIT;\r
+       }//else if(segm>0) goto segu;\r
+\r
+}*/\r
+void MML_UseSpace(word segstart, dword seglength, global_game_variables_t *gvar)\r
+{\r
+       mmblocktype far *scan,far *last;\r
+       word    oldend;\r
+       sdword          extra;\r
+       //word segm=1;\r
+\r
+       scan = last = gvar->mm.mmhead;\r
+       gvar->mm.mmrover = gvar->mm.mmhead;             // reset rover to start of memory\r
+\r
+//\r
+// search for the block that contains the range of segments\r
+//\r
+       while (scan->start+scan->length < segstart)\r
+       {\r
+               last = scan;\r
+               scan = scan->next;\r
+       }\r
+\r
+//\r
+// find out how many blocks it spans!\r
+//\r
+       /*for(;seglength>=0x10000;seglength-=0xFFFF)\r
+       {\r
+               //printf("      seglen=%lu\n", segmlen);\r
+               segm++;\r
+       }*/\r
+\r
+//\r
+// take the given range out of the block\r
+//\r
+       oldend = scan->start + scan->length;\r
+       extra = oldend - (segstart+((unsigned)seglength));\r
+       if (extra < 0)\r
+       {\r
+               printf("========================================\n");\r
+               printf("start=%x        ", scan->start);\r
+               printf("old=%u  ", oldend);\r
+               printf("start+seglen=%lu\n", segstart+seglength);\r
+               printf("segsta=%x       ", segstart);\r
+               printf("len=%lu ", scan->length);\r
+               printf("seglen=%lu      ", seglength);\r
+               printf("\n");\r
+               printf("MML_UseSpace: Segment spans two blocks! %d\n", extra);\r
+               printf("========================================\n");\r
+               //return;\r
+       }\r
+\r
+       if (segstart == scan->start)\r
+       {\r
+               last->next = scan->next;                        // unlink block\r
+               FREEBLOCK(scan);\r
+               scan = last;\r
+       }\r
+       else\r
+               scan->length = segstart-scan->start;    // shorten block\r
+\r
+       if (extra > 0)\r
+       {\r
+               GETNEWBLOCK;\r
+               gvar->mm.mmnew->useptr = NULL;\r
+\r
+               gvar->mm.mmnew->next = scan->next;\r
+               scan->next = gvar->mm.mmnew;\r
+               gvar->mm.mmnew->start = segstart+seglength;\r
+               gvar->mm.mmnew->length = extra;\r
+               gvar->mm.mmnew->attributes = LOCKBIT;\r
+       }\r
+\r
+}\r
+\r
+//==========================================================================\r
+\r
+/*\r
+====================\r
+=\r
+= MML_ClearBlock\r
+=\r
+= We are out of blocks, so free a purgable block\r
+=\r
+====================\r
+*/\r
+\r
+void MML_ClearBlock(global_game_variables_t *gvar)\r
+{\r
+       //huge mmblocktype huge *scan,huge *last;\r
+       mmblocktype far *scan,far *last;\r
+\r
+       scan = gvar->mm.mmhead->next;\r
+\r
+       while(scan)\r
+       {\r
+               if(!(scan->attributes&LOCKBIT) && (scan->attributes&PURGEBITS))\r
+               {\r
+                       MM_FreePtr(scan->useptr, gvar);\r
+                       return;\r
+               }\r
+               scan = scan->next;\r
+       }\r
+\r
+       printf("MM_ClearBlock: No purgable blocks!\n");\r
+}\r
+\r
+\r
+//==========================================================================\r
+\r
+/*\r
+===================\r
+=\r
+= MM_Startup\r
+=\r
+= Grabs all space from turbo with malloc/farmalloc\r
+= Allocates bufferseg misc buffer\r
+=\r
+===================\r
+*/\r
+\r
+void MM_Startup(global_game_variables_t *gvar)\r
+{\r
+       int i;\r
+       //dword length,seglength;\r
+       dword length;\r
+       //huge void huge        *start;\r
+       void far        *start;\r
+       word    segstart,seglength,endfree;\r
+       //memptr *peeonself;\r
+\r
+       if(gvar->mm.mmstarted)\r
+               MM_Shutdown(gvar);\r
+\r
+\r
+       gvar->mm.mmstarted = true;\r
+       gvar->mm.bombonerror = true;\r
+//\r
+// set up the linked list (everything in the free list;\r
+//\r
+       gvar->mm.mmhead = NULL;\r
+       gvar->mm.mmfree = &(gvar->mm.mmblocks[0]);\r
+       for(i=0;i<MAXBLOCKS-1;i++)\r
+       {\r
+               gvar->mm.mmblocks[i].next = &(gvar->mm.mmblocks[i+1]);\r
+       }\r
+       gvar->mm.mmblocks[i].next = NULL;\r
+\r
+//\r
+// locked block of all memory until we punch out free space\r
+//\r
+       GETNEWBLOCK;\r
+       gvar->mm.mmhead = gvar->mm.mmnew;                               // this will allways be the first node\r
+       gvar->mm.mmnew->start = 0;\r
+       gvar->mm.mmnew->length = 0xffff;\r
+       gvar->mm.mmnew->attributes = LOCKBIT;\r
+       gvar->mm.mmnew->next = NULL;\r
+       //gvar->mm.mmnew->useptr = peeonself;\r
+       gvar->mm.mmrover = gvar->mm.mmhead;\r
+\r
+       //printf("              %x\n", peeonself);\r
+       //printf("              %x\n", *peeonself);\r
+//\r
+// get all available near conventional memory segments\r
+//\r
+#ifdef __WATCOMC__\r
+       _nheapgrow();\r
+       length=(dword)_memavl();//(dword)GetFreeSize();\r
+       //huge start = (void huge *)(gvar->mm.nearheap = _nmalloc(length));\r
+       start = (void far *)(gvar->mm.nearheap = _nmalloc(length));\r
+#endif\r
+#ifdef __BORLANDC__\r
+       length=coreleft();\r
+       //huge start = (void huge *)(gvar->mm.nearheap = malloc(length));\r
+       start = (void far *)(gvar->mm.nearheap = malloc(length));\r
+       printf("Borland C unique function\n");\r
+       printf("        coreleft()                              %lu\n", coreleft());\r
+#endif\r
+       length -= 16-(FP_OFF(start)&15);\r
+       length -= SAVENEARHEAP;\r
+       seglength = length / 16;                        // now in paragraphs\r
+       segstart = FP_SEG(start)+(FP_OFF(start)+15)/16;\r
+       MML_UseSpace(segstart,seglength, gvar);\r
+       gvar->mmi.nearheap = length;\r
+       //printf("start=%Fp     segstart=%x     seglen=%lu      len=%lu\n", start, segstart, seglength, length);\r
+\r
+//\r
+// get all available far conventional memory segments\r
+//\r
+       //printf("_FARCORELEFT                          %lu\n", _FCORELEFT);\r
+#ifdef __WATCOMC__\r
+       _fheapgrow();\r
+#endif\r
+#ifdef __BORLANDC__\r
+       printf("        farcoreleft()                           %lu\n", farcoreleft());\r
+       printf("        (farcoreleft()+32)-_FCORELEFT   %d\n", (sword)((farcoreleft()+32)-_FCORELEFT));\r
+#endif\r
+       length=_FCORELEFT;//_fcoreleft();//(dword)GetFarFreeSize();//0xffffUL*4UL;\r
+       start = gvar->mm.farheap = _fmalloc(length);\r
+       //start = gvar->mm.farheap = halloc(length, 1);\r
+       length -= 16-(FP_OFF(start)&15);\r
+       length -= SAVEFARHEAP;\r
+       seglength = length / 16;                        // now in paragraphs\r
+       segstart = FP_SEG(start)+(FP_OFF(start)+15)/16;\r
+       MML_UseSpace(segstart,seglength, gvar);\r
+       gvar->mmi.farheap = length;\r
+       gvar->mmi.mainmem = gvar->mmi.nearheap + gvar->mmi.farheap;\r
+       //printf("start=%Fp     segstart=%x     seglen=%lu      len=%lu\n", start, segstart, seglength, length);\r
+\r
+#ifdef __DEBUG_PM__\r
+goto xmsskip;  //INFO: 16_PM dose this job better\r
+#endif\r
+\r
+//\r
+// detect EMS and allocate up to 64K at page frame\r
+//\r
+       gvar->mmi.EMSmem = 0;\r
+//goto emsskip;        //0000\r
+       if(MML_CheckForEMS())\r
+       {\r
+               MML_SetupEMS(gvar);                                     // allocate space\r
+               //TODO: EMS4! AND EMS 3.2 MASSIVE DATA HANDLMENT!\r
+               MML_UseSpace(gvar->pm.emm.EMSPageFrame,(MAPPAGES)*0x4000lu, gvar);\r
+               //if(gvar->pm.emm.EMSVer<0x40)\r
+                       MM_MapEMS(gvar);                                        // map in used pages\r
+               //else\r
+                       //MM_MapXEMS(gvar);                                     // map in used pages\r
+       }\r
+\r
+//\r
+// detect XMS and get upper memory blocks\r
+//\r
+//emsskip:\r
+       gvar->mmi.XMSmem = 0;\r
+goto xmsskip;//0000\r
+       if(MML_CheckForXMS(gvar))\r
+       {\r
+               MML_SetupXMS(gvar);                                     // allocate as many UMBs as possible\r
+       }\r
+\r
+//\r
+// allocate the misc buffer\r
+//\r
+xmsskip:\r
+       gvar->mm.mmrover = gvar->mm.mmhead;             // start looking for space after low block\r
+\r
+       MM_GetPtr(&(gvar->mm.bufferseg),BUFFERSIZE, gvar);\r
+}\r
+\r
+//==========================================================================\r
+\r
+/*\r
+====================\r
+=\r
+= MM_Shutdown\r
+=\r
+= Frees all conventional, EMS, and XMS allocated\r
+=\r
+====================\r
+*/\r
+\r
+void MM_Shutdown(global_game_variables_t *gvar)\r
+{\r
+       if(!(gvar->mm.mmstarted))\r
+               return;\r
+\r
+       _ffree(gvar->mm.farheap);//     printf("                far freed\n");\r
+#ifdef __WATCOMC__\r
+       _nfree(gvar->mm.nearheap);//    printf("                near freed\n");\r
+#endif\r
+#ifdef __BORLANDC__\r
+       free(gvar->mm.nearheap);//      printf("                near freed\n");\r
+#endif\r
+#ifndef __DEBUG_PM__\r
+       if(MML_CheckForEMS()){ MML_ShutdownEMS(gvar); }//printf("               EMS freed\n"); }\r
+       if(MML_CheckForXMS(gvar)){ MML_ShutdownXMS(gvar); }//printf("           XMS freed\n"); }        //INFO: 16_PM dose this job better\r
+#endif\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, global_game_variables_t *gvar)\r
+{\r
+       //huge mmblocktype huge *scan,huge *lastscan,huge *endscan,huge *purge,huge *next;\r
+       mmblocktype far *scan,far *lastscan,far *endscan,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
+       gvar->mm.mmnew->length = needed;\r
+       gvar->mm.mmnew->useptr = baseptr;\r
+       //if(gvar->mm.mmnew->useptr==NULL){\r
+#ifdef __DEBUG__\r
+               printf("        MM_GetPtr\n");\r
+               printf("                baseptr=%04x    ", baseptr); printf("useptr=%04x\n", gvar->mm.mmnew->useptr);\r
+               printf("                *baseptr=%04x   ", *baseptr); printf("*useptr=%04x\n", *(gvar->mm.mmnew->useptr));\r
+               printf("                *baseptr=%Fp    ", *baseptr); printf("*useptr=%Fp\n", *(gvar->mm.mmnew->useptr));\r
+#endif\r
+       //exit(-5); }\r
+       gvar->mm.mmnew->attributes = BASEATTRIBUTES;\r
+\r
+//tryagain:\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 && gvar->mm.mmrover == gvar->mm.mmhead)\r
+                       search++;\r
+\r
+               switch (search)\r
+               {\r
+               case 0:\r
+                       lastscan = gvar->mm.mmrover;\r
+                       scan = gvar->mm.mmrover->next;\r
+                       endscan = NULL;\r
+                       break;\r
+               case 1:\r
+                       lastscan = gvar->mm.mmhead;\r
+                       scan = gvar->mm.mmhead->next;\r
+                       endscan = gvar->mm.mmrover;\r
+                       break;\r
+               case 2:\r
+                       MM_SortMem (gvar);\r
+                       lastscan = gvar->mm.mmhead;\r
+                       scan = gvar->mm.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 = gvar->mm.mmnew;\r
+                               gvar->mm.mmnew->start = *(unsigned *)baseptr = startseg;\r
+                               gvar->mm.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
+                               gvar->mm.mmrover = gvar->mm.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 (gvar->mm.bombonerror)\r
+       {\r
+#ifdef __WATCOMC__\r
+               //heapdump();\r
+#endif\r
+               printf(OUT_OF_MEM_MSG,(size-gvar->mmi.nearheap));\r
+               printf("for stability reasons the program will shut down! wwww\n");\r
+               MM_Shutdown(gvar);\r
+               exit(-1);\r
+       }\r
+       else\r
+               gvar->mm.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, global_game_variables_t *gvar)\r
+{\r
+       //huge mmblocktype huge *scan,huge *last;\r
+       mmblocktype far *scan,far *last;\r
+\r
+       last = gvar->mm.mmhead;\r
+       scan = last->next;\r
+\r
+       if(baseptr == gvar->mm.mmrover->useptr) // removed the last allocated block\r
+               gvar->mm.mmrover = gvar->mm.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!\n");\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, global_game_variables_t *gvar)\r
+{\r
+       //huge mmblocktype huge *start;\r
+       mmblocktype far *start;\r
+\r
+       start = gvar->mm.mmrover;\r
+\r
+       do\r
+       {\r
+               if(gvar->mm.mmrover->useptr == baseptr)\r
+                       break;\r
+\r
+               gvar->mm.mmrover = gvar->mm.mmrover->next;\r
+\r
+               if(!gvar->mm.mmrover)\r
+                       gvar->mm.mmrover = gvar->mm.mmhead;\r
+               else if(gvar->mm.mmrover == start)\r
+               {\r
+#ifdef __DEBUG_PM__\r
+                       printf("\nstart->useptr gvar->mm.mmhead->useptr\n");\r
+                       printf("        %Fp     %Fp\n", start->useptr, gvar->mm.mmhead->useptr);\r
+                       printf("&       %Fp     %Fp\n", &(start->useptr), &(gvar->mm.mmhead->useptr));\r
+                       printf("baseptr                 gvar->mm.mmrover->useptr\n");\r
+                       printf("        %Fp     %Fp\n", baseptr, gvar->mm.mmrover->useptr);\r
+                       printf("&       %Fp     %Fp\n", &(baseptr), &(gvar->mm.mmrover->useptr));\r
+                       printf("*       %Fp     %Fp\n", *(baseptr), *(gvar->mm.mmrover->useptr));\r
+                       printf("start                   gvar->mm.mmrover gvar->mm.mmrover->next\n");\r
+                       printf("        %Fp     %Fp     %Fp\n", start, gvar->mm.mmrover, gvar->mm.mmrover->next);\r
+                       printf("&       %Fp     %Fp     %Fp\n", &start, &gvar->mm.mmrover, gvar->mm.mmrover->next);\r
+                       getch();\r
+                       MM_ShowMemory(gvar);\r
+                       MM_DumpData(gvar);\r
+                       MM_Report_(gvar);\r
+                       getch();\r
+#endif\r
+                       Quit("MM_SetPurge: Block not found!");\r
+                       return;\r
+               }\r
+\r
+       } while(1);\r
+\r
+       gvar->mm.mmrover->attributes &= ~PURGEBITS;\r
+       gvar->mm.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, global_game_variables_t *gvar)\r
+{\r
+       //huge mmblocktype huge *start;\r
+       mmblocktype far *start;\r
+\r
+       start = gvar->mm.mmrover;\r
+\r
+       do\r
+       {\r
+               if(gvar->mm.mmrover->useptr == baseptr)\r
+                       break;\r
+\r
+               gvar->mm.mmrover = gvar->mm.mmrover->next;\r
+\r
+               if(!gvar->mm.mmrover)\r
+                       gvar->mm.mmrover = gvar->mm.mmhead;\r
+               else if(gvar->mm.mmrover == start)\r
+               {\r
+                       Quit("MM_SetLock: Block not found!");\r
+                       //return;\r
+               }\r
+\r
+       } while(1);\r
+\r
+       gvar->mm.mmrover->attributes &= ~LOCKBIT;\r
+       gvar->mm.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(global_game_variables_t *gvar)\r
+{\r
+       //huge mmblocktype huge *scan,huge *last,huge *next;\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 = gvar->mm.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
+                               //MM_FreeBlock(scan, gvar);\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
+       gvar->mm.mmrover = gvar->mm.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
+=====================\r
+=\r
+= MM_ShowMemory\r
+=\r
+=====================\r
+*/\r
+\r
+void MM_ShowMemory(global_game_variables_t *gvar)\r
+{\r
+       //huge mmblocktype huge *scan;\r
+       mmblocktype far *scan;\r
+       word temp;\r
+       sdword  end,owner;\r
+       //word chx,chy;\r
+       word w;\r
+       //dword wwww;\r
+       byte    scratch[160],scratch0[4096],scratch1[160],str[16];\r
+       //byte d = '#';\r
+//**** VW_SetDefaultColors();\r
+//**** VW_SetLineWidth(40);\r
+//++++mh       temp = bufferofs;\r
+//++++mh       bufferofs = 0;\r
+//**** VW_SetScreen (0,0);\r
+       scan = gvar->mm.mmhead;\r
+       end = -1;\r
+\r
+       CA_OpenDebug (gvar);\r
+       w=0;\r
+       while(scan)\r
+       {\r
+               strcpy(scratch, AARESET);\r
+               if(scan->attributes & PURGEBITS)\r
+                       strcpy(scratch0, AAMAGENTA);            // dark purple = purgable\r
+               else\r
+                       strcpy(scratch0, AABLUE);               // medium blue = non purgable\r
+               if(scan->attributes & LOCKBIT)\r
+                       strcpy(scratch0, AARED);                // red = locked\r
+               if(scan->start<=end)\r
+               {\r
+                       printf("\nend==%d\n\n", end);\r
+                       strcat(scratch, "MM_ShowMemory: Memory block order currupted!\n");\r
+                       strcat(scratch, "End's Size: ");\r
+                       ultoa (end,str,10);\r
+                       strcat (scratch,str);\r
+                       strcat(scratch, "\nscan->start's Size: ");\r
+                       ultoa (scan->start,str,10);\r
+                       strcat (scratch,str);\r
+                       write(gvar->handle.debughandle,scratch,strlen(scratch));\r
+                       //modexprint(&page, chx, chy, 1, 0, 24, "\nMM_ShowMemory: Memory block order currupted!\n");\r
+                       break;\r
+               }\r
+               end = scan->start+(scan->length)-1;\r
+//++++         chy = scan->start/320;\r
+//++++         chx = scan->start%320;\r
+                               //modexhlin(page, scan->start, (unsigned)end, chy, color);\r
+                               //for(chx=scan->start;chx+4>=(word)end;chx+=4)\r
+                               //{\r
+//++++                                 modexClearRegion(page, chx, chy, 4, 4, color);\r
+                               //}\r
+//++++         VW_Hlin(scan->start,(unsigned)end,0,color);\r
+               for(w=(scan->start)/80;w<=end/80;w++)\r
+               {\r
+                       //printf("+     %u      %lu\n", w, scan->length);\r
+                       strcat(scratch0, "+");\r
+               }\r
+               //++==++==optional strcat(scratch0, AARESET); strcat(scratch0, AAGREY); strcat(scratch0,"_");\r
+//++++         VW_Plot(scan->start,0,15);\r
+//++++                         modexClearRegion(page, chx, chy, 4, 4, 15);\r
+//++++                 VW_Hlin(end+1,scan->next->start,0,0);   // black = free\r
+\r
+               //wwww=(dword)(scan->next->start)-(dword)scan->start;\r
+               //wwww=(dword)scan->start+(dword)(scan->next->start);\r
+               if (scan->next && scan->next->start >= end+1)\r
+               {\r
+                       strcat(scratch0, AARESET);\r
+                       //++==++==optional strcat(scratch0, "\n");\r
+                       strcat(scratch0,AAGREEN);\r
+                       for(w=(end+1)/80;w<=((scan->next->start-scan->start)/80);w++)\r
+                       //for(w=(wwww)/80;w<=((end+1)/80);w++)\r
+                       //for(w=(end+1)/80;w<=((wwww)/80);w++)\r
+                       {\r
+                               //printf("0     %x      %u      %lu\n", scan->next->start, w, scan->length);\r
+                               strcat(scratch0,"0");\r
+                       }\r
+                       //printf("==================\n");\r
+                       //printf("w=%u  wwww=%lu        start=%04x      next=%04x       end=%lu\n", w/80, wwww/80, scan->start, (scan->next->start), end+1);\r
+                       //printf("==================\n");\r
+                       strcat(scratch0, "\n");\r
+                       //getch();\r
+               }/*else {//if(scan->next->start <= scan->start){\r
+                       scan->next->start=scan->start+0x1000;\r
+                       wwww=(dword)(scan->next->start)-(dword)scan->start;\r
+                       strcat(scratch0, AARESET);\r
+                       strcat(scratch0, "\n");\r
+                       strcat(scratch0,AAGREEN);\r
+                       for(w=(end+1);w<=(0x1000/80);w++)\r
+                       {\r
+                               //printf("0     %x      %x      %u\n", scan->start, w);\r
+                               strcat(scratch0,"0");\r
+                       }\r
+                       printf("================\n");\r
+                       printf("w=%x    start=%x        next=%x end=%u  %lu\n", w, scan->start, (scan->next->start), end+1, wwww);\r
+                       printf("================\n");\r
+                       getch();\r
+               }*/\r
+               strcat(scratch0, AARESET);\r
+               //strcat(scratch0,"\n");\r
+                       //for(chx=scan->next->start;chx+4>=(word)end+1;chx+=4)\r
+                       //{\r
+//                             chx+=scan->next->start;\r
+//                             modexClearRegion(page, chx, chy, 4, 4, 2);\r
+                       //}\r
+                                       //modexhlin(page, end+1,scan->next->start, chy, 0);\r
+/*             y = scan->start/320;\r
+               x = scan->start%320;\r
+               VW_Hlin(x,x+end,y,color);\r
+               VW_Plot(x,y,15);*/\r
+//++++                 VW_Hlin(x+end+1,x+(scan->next->start-scan->start),y,0); // black = free\r
+               strcat(scratch,"Seg:");\r
+               ultoa (scan->start,str,16);\r
+               strcat (scratch,str);\r
+               strcat (scratch,"\tSize:");\r
+               ultoa ((unsigned)scan->length,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(gvar->handle.debughandle,scratch,strlen(scratch));\r
+               write(gvar->handle.debughandle,scratch0,strlen(scratch0));\r
+//modexprint(page, chx, chy, 1, 0, 24, &scratch);\r
+//++++chy+=4;\r
+//fprintf(stdout, "%s", scratch);\r
+\r
+               scan = scan->next;\r
+       }\r
+       /*strcpy(scratch1, AARESET);\r
+       strcat(scratch1, "========================================\n");\r
+       strcat(scratch1, "near=  ");\r
+       ultoa (*(gvar->mm.nearheap),str,10);\r
+       strcat (scratch1,str);\r
+       strcat(scratch1, "      far= ");\r
+       ultoa (*(gvar->mm.farheap),str,10);\r
+       strcat (scratch1,str);\r
+       strcat(scratch1, "\n");\r
+       //strcat(scratch1, "&near=      %Fp ", &(gvar->mm.nearheap));\r
+       //strcat(scratch1, "&far=       %Fp", &(gvar->mm.farheap));\r
+       //strcat(scratch1, "\n");\r
+       strcat(scratch1, "========================================\n");\r
+       write(gvar->handle.debughandle,scratch1,strlen(scratch1));*/\r
+\r
+\r
+       CA_CloseDebug (gvar);\r
+\r
+//++++mh       IN_Ack();\r
+//**** VW_SetLineWidth(64);\r
+//++++mh       bufferofs = temp;\r
+}\r
+\r
+//==========================================================================\r
+\r
+/*\r
+=====================\r
+=\r
+= MM_DumpData\r
+=\r
+=====================\r
+*/\r
+\r
+void MM_DumpData(global_game_variables_t *gvar)\r
+{\r
+       //huge mmblocktype huge *scan,huge *best;\r
+       mmblocktype far *scan,far *best;\r
+       long    lowest,oldlowest;\r
+       word    owner;\r
+       byte    lock,purge;\r
+       FILE    *dumpfile;\r
+\r
+       free(gvar->mm.nearheap);\r
+#ifdef __BORLANDC__\r
+               dumpfile = fopen ("mmdump.16b","w");\r
+#endif\r
+#ifdef __WATCOMC__\r
+               dumpfile = fopen ("mmdump.16w","w");\r
+#endif\r
+       if (!dumpfile){\r
+               printf("MM_DumpData: Couldn't open MMDUMP.16!\n");\r
+               return;\r
+       }\r
+\r
+       lowest = -1;\r
+       do\r
+       {\r
+               oldlowest = lowest;\r
+               lowest = 0xffff;\r
+\r
+               scan = gvar->mm.mmhead;\r
+               while (scan)\r
+               {\r
+                       owner = (unsigned)scan->useptr;\r
+\r
+                       if (owner && owner<lowest && owner > oldlowest)\r
+                       {\r
+                               best = scan;\r
+                               lowest = owner;\r
+                       }\r
+\r
+                       scan = scan->next;\r
+               }\r
+\r
+               if (lowest != 0xffff)\r
+               {\r
+                       if (best->attributes & PURGEBITS)\r
+                               purge = 'P';\r
+                       else\r
+                               purge = '-';\r
+                       if (best->attributes & LOCKBIT)\r
+                               lock = 'L';\r
+                       else\r
+                               lock = '-';\r
+                       fprintf (dumpfile,"0x%p (%c%c) = %u\n"\r
+                       ,(unsigned)lowest,lock,purge,best->length);\r
+               }\r
+\r
+       } while (lowest != 0xffff);\r
+\r
+       fclose(dumpfile);\r
+       printf("MMDUMP.16 created.\n");\r
+}\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(global_game_variables_t *gvar)\r
+{\r
+       dword free;\r
+       //huge mmblocktype huge *scan;\r
+       mmblocktype far *scan;\r
+\r
+       free = 0;\r
+       scan = gvar->mm.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*16lu;\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(global_game_variables_t *gvar)\r
+{\r
+       dword free;\r
+       //huge mmblocktype huge *scan;\r
+       mmblocktype far *scan;\r
+\r
+       free = 0;\r
+       scan = gvar->mm.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*16lu;\r
+//     return free;\r
+}\r
+\r
+//==========================================================================\r
+\r
+/*\r
+=====================\r
+=\r
+= MM_Report\r
+=\r
+=====================\r
+*/\r
+\r
+void MM_Report_(global_game_variables_t *gvar)\r
+{\r
+       printf("========================================\n");\r
+       printf("                MM_Report\n");\r
+       printf("========================================\n");\r
+       if(MML_CheckForEMS())\r
+       {\r
+               printf("        LIMEMS\n");\r
+               printf("                EMM v%x.%x available\n", gvar->pm.emm.EMSVer>>4,gvar->pm.emm.EMSVer&0x0F);\r
+               printf("                totalEMSpages:  %u      ", gvar->pm.emm.totalEMSpages); printf("freeEMSpages:   %u\n", gvar->pm.emm.freeEMSpages);\r
+               printf("                EMSPageFrame:   %x\n", gvar->pm.emm.EMSPageFrame);\r
+       }\r
+       if(MML_CheckForXMS(gvar))\r
+       {\r
+               printf("        XMS\n");\r
+               printf("                XMSaddr:        %X\n", *XMSaddr);\r
+       }\r
+       printf("near:   %lu     ", gvar->mmi.nearheap); printf("far:    %lu\n", gvar->mmi.farheap); if(MML_CheckForEMS())\r
+       printf("EMSmem: %lu     ", gvar->mmi.EMSmem); if(MML_CheckForXMS(gvar)) printf("XMSmem: %lu", gvar->mmi.XMSmem); printf("\n");\r
+       //printf("mainmem:      %lu\n", gvar->mmi.mainmem);\r
+       printf("Total convmem:  %lu     ", gvar->mmi.mainmem); printf("TotalFree:       %lu     ", MM_TotalFree(gvar)); printf("TotalUsed:      %lu\n", gvar->mmi.mainmem+gvar->mmi.EMSmem+gvar->mmi.XMSmem+gvar->mmi.XMSmem);\r
+       printf("                        UnusedMemory:   %lu\n", MM_UnusedMemory(gvar));\r
+}\r
+\r
+//==========================================================================\r
+\r
+/*\r
+=====================\r
+=\r
+= MM_EMSerr\r
+=\r
+=====================\r
+*/\r
+\r
+void MM_EMSerr(byte *stri, byte err)\r
+{\r
+       //Returns a text string describing the error code in EMS.Error.\r
+       switch(err)\r
+       {\r
+               case 0x0:\r
+                       strcat(stri, "successful");\r
+               break;\r
+               case 0x80:\r
+                       strcat(stri, "internal error");\r
+               break;\r
+               case 0x81:\r
+                       strcat(stri, "hardware malfunction");\r
+               break;\r
+               case 0x82:\r
+                       strcat(stri, "busy .. retry later");\r
+               break;\r
+               case 0x83:\r
+                       strcat(stri, "invalid handle");\r
+               break;\r
+               case 0x84:\r
+                       strcat(stri, "undefined function requested by application");\r
+               break;\r
+               case 0x85:\r
+                       strcat(stri, "no more handles available");\r
+               break;\r
+               case 0x86:\r
+                       strcat(stri, "error in save or restore of mapping context");\r
+               break;\r
+               case 0x87:\r
+                       strcat(stri, "insufficient memory pages in system");\r
+               break;\r
+               case 0x88:\r
+                       strcat(stri, "insufficient memory pages available");\r
+               break;\r
+               case 0x89:\r
+                       strcat(stri, "zero pages requested");\r
+               break;\r
+               case 0x8A:\r
+                       strcat(stri, "invalid logical page number encountered");\r
+               break;\r
+               case 0x8B:\r
+                       strcat(stri, "invalid physical page number encountered");\r
+               break;\r
+               case 0x8C:\r
+                       strcat(stri, "page-mapping hardware state save area is full");\r
+               break;\r
+               case 0x8D:\r
+                       strcat(stri, "save of mapping context failed");\r
+               break;\r
+               case 0x8E:\r
+                       strcat(stri, "restore of mapping context failed");\r
+               break;\r
+               case 0x8F:\r
+                       strcat(stri, "undefined subfunction");\r
+               break;\r
+               case 0x90:\r
+                       strcat(stri, "undefined attribute type");\r
+               break;\r
+               case 0x91:\r
+                       strcat(stri, "feature not supported");\r
+               break;\r
+               case 0x92:\r
+                       strcat(stri, "successful, but a portion of the source region has been overwritten");\r
+               break;\r
+               case 0x93:\r
+                       strcat(stri, "length of source or destination region exceeds length of region allocated to either source or destination handle");\r
+               break;\r
+               case 0x94:\r
+                       strcat(stri, "conventional and expanded memory regions overlap");\r
+               break;\r
+               case 0x95:\r
+                       strcat(stri, "offset within logical page exceeds size of logical page");\r
+               break;\r
+               case 0x96:\r
+                       strcat(stri, "region length exceeds 1 MB");\r
+               break;\r
+               case 0x97:\r
+                       strcat(stri, "source and destination EMS regions have same handle and overlap");\r
+               break;\r
+               case 0x98:\r
+                       strcat(stri, "memory source or destination type undefined");\r
+               break;\r
+               case 0x9A:\r
+                       strcat(stri, "specified alternate map register or DMA register set not supported");\r
+               break;\r
+               case 0x9B:\r
+                       strcat(stri, "all alternate map register or DMA register sets currently allocated");\r
+               break;\r
+               case 0x9C:\r
+                       strcat(stri, "alternate map register or DMA register sets not supported");\r
+               break;\r
+               case 0x9D:\r
+                       strcat(stri, "undefined or unallocated alternate map register or DMA register set");\r
+               break;\r
+               case 0x9E:\r
+                       strcat(stri, "dedicated DMA channels not supported");\r
+               break;\r
+               case 0x9F:\r
+                       strcat(stri, "specified dedicated DMA channel not supported");\r
+               break;\r
+               case 0xA0:\r
+                       strcat(stri, "no such handle name");\r
+               break;\r
+               case 0xA1:\r
+                       strcat(stri, "a handle found had no name, or duplicate handle name");\r
+               break;\r
+               case 0xA2:\r
+                       strcat(stri, "attempted to wrap around 1M conventional address space");\r
+               break;\r
+               case 0xA3:\r
+                       strcat(stri, "source array corrupted");\r
+               break;\r
+               case 0xA4:\r
+                       strcat(stri, "operating system denied access");\r
+               break;\r
+               default:\r
+                       strcat(stri, "undefined error");\r
+       }\r
+}\r
+\r
+//==========================================================================\r
+\r
+/*\r
+=====================\r
+=\r
+= MM_BombOnError\r
+=\r
+=====================\r
+*/\r
+\r
+void MM_BombOnError(boolean bomb, global_game_variables_t *gvar)\r
+{\r
+       gvar->mm.bombonerror = bomb;\r
+}\r
+\r
+/*void MM_GetNewBlock(global_game_variables_t *gvar)\r
+{\r
+       if(!gvar->mm.mmfree)\r
+               MML_ClearBlock(gvar);\r
+       gvar->mm.mmnew=gvar->mm.mmfree;\r
+       gvar->mm.mmfree=gvar->mm.mmfree->next;\r
+       if(!(gvar->mm.mmnew=gvar->mm.mmfree))\r
+       {\r
+               printf("MM_GETNEWBLOCK: No free blocks!\n");\r
+               return;\r
+       }\r
+       gvar->mm.mmfree=gvar->mm.mmfree->next;\r
+}\r
+\r
+void MM_FreeBlock(mmblocktype *x, global_game_variables_t *gvar)\r
+{\r
+       x->useptr=NULL;\r
+       x->next=gvar->mm.mmfree;\r
+       gvar->mm.mmfree=x;\r
+}*/\r
+\r
+/*void MM_seguin(void)\r
+{\r
+       __asm {\r
+               push    ds\r
+               mov     ax,ds\r
+               inc             ax\r
+               mov     ds,ax\r
+       }\r
+}\r
+\r
+void MM_segude(void)\r
+{\r
+       __asm {\r
+               pop ds\r
+       }\r
+}*/\r
+\r
+/*\r
+pull data from far and put it into ds var\r
+mov ax,es:si\r
+mov x,ax\r
+*/\r
+/*\r
+ss stack segment\r
+sp top of stack\r
+bp bottem of stack\r
+*/\r
index 97df503..f5605e8 100755 (executable)
--- a/DEBUG.16B
+++ b/DEBUG.16B
@@ -1,12 +1,10 @@
-\e[0mSeg:0      Size:3016       Owner:0x2065\r
-\e[41;31m++++++++++++++++++++++++++++++++++++++\e[0m\e[42;32m0\r
-\e[0m\e[0mSeg:bc8        Size:256        Owner:0xcf79\r
+\e[0mSeg:0      Size:3547       Owner:0x696c\r
+\e[41;31m+++++++++++++++++++++++++++++++++++++++++++++\e[0m\e[42;32m0\r
+\e[0m\e[0mSeg:ddb        Size:256        Owner:0xcf85\r
 \e[44;34m++++\e[0m\e[42;32m\r
-\e[0m\e[0mSeg:cc8        Size:273        Owner:0xfde\r
-\e[44;34m+++++\e[0m\e[42;32m0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000\r
+\e[0m\e[0mSeg:edb        Size:273        Owner:0xfde\r
+\e[44;34m++++\e[0m\e[42;32m0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000\r
 \e[0m\e[0mSeg:9fde       Size:28706      Owner:0x0\r
 \e[41;31m\e[0m\e[42;32m\r
-\e[0m\e[0mSeg:9ffe       Size:16386      Owner:0x0\r
-\e[41;31m++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++\e[0m\e[42;32m\r
-\e[0m\e[0mSeg:e000       Size:8191       Owner:0x0\r
-\e[41;31m++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++\e[0m
\ No newline at end of file
+\e[0m\e[0mSeg:9ffe       Size:24577      Owner:0x0\r
+\e[41;31m+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++\e[0m
\ No newline at end of file
index e42fdf0..7e2f4f1 100755 (executable)
--- a/DEBUG.16W
+++ b/DEBUG.16W
@@ -1,8 +1,12 @@
-\e[0mSeg:0      Size:8601       Owner:0x0\r
+\e[0mSeg:0      Size:8567       Owner:0xfc7e\r
 \e[41;31m++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++\e[0m\e[42;32m0\r
-\e[0m\e[0mSeg:2199       Size:256        Owner:0x5424\r
+\e[0m\e[0mSeg:2177       Size:256        Owner:0x5428\r
 \e[44;34m++++\e[0m\e[42;32m\r
-\e[0m\e[0mSeg:280e       Size:44 Owner:0x0\r
-\e[41;31m+\e[0m\e[42;32m0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000\r
-\e[0m\e[0mSeg:b83a       Size:18373      Owner:0x0\r
-\e[41;31m+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++\e[0m
\ No newline at end of file
+\e[0m\e[0mSeg:2277       Size:17 Owner:0x9480\r
+\e[44;34m+\e[0m\e[42;32m\r
+\e[0m\e[0mSeg:27eb       Size:44 Owner:0x0\r
+\e[41;31m++\e[0m\e[42;32m0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000\r
+\e[0m\e[0mSeg:b817       Size:10217      Owner:0x0\r
+\e[41;31m++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++\e[0m\e[42;32m\r
+\e[0m\e[0mSeg:e000       Size:8191       Owner:0x0\r
+\e[41;31m++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++\e[0m
\ No newline at end of file
index 11a19e8..c5de931 100755 (executable)
--- a/HEAP.16W
+++ b/HEAP.16W
@@ -1,71 +1,47 @@
 \r
        == default ==\r
 \r
-  FREE block at 2e330016 of size 18\r
-  USED block at 2e330028 of size 136\r
-  USED block at 2e3300b0 of size 50\r
-  USED block at 2e3300e2 of size 50\r
-  USED block at 2e330114 of size 50\r
-  USED block at 2e330146 of size 50\r
-  USED block at 2e330178 of size 50\r
-  USED block at 2e3301aa of size 50\r
-  USED block at 2e3301dc of size 50\r
-  USED block at 2e33020e of size 50\r
-  USED block at 2e330240 of size 50\r
-  USED block at 2e330272 of size 50\r
-  USED block at 2e3302a4 of size 50\r
-  USED block at 2e3302d6 of size 50\r
-  USED block at 2e330308 of size 50\r
-  FREE block at 2e33033a of size 14\r
-  USED block at 2e330348 of size 20\r
-  FREE block at 2e33035c of size 7328\r
+  USED block at 280d0016 of size 66\r
+  USED block at 280d0058 of size 66\r
+  FREE block at 280d009a of size 18\r
+  USED block at 280d00ac of size 136\r
+  USED block at 280d0134 of size 20\r
+  FREE block at 280d0148 of size 7860\r
 OK - end of heap\r
 \r
        == near ==\r
 \r
-  USED block at 1e32a466 of size 12\r
-  USED block at 1e32a472 of size 330\r
-  USED block at 1e32a5bc of size 52\r
-  USED block at 1e32a5f0 of size 20\r
-  USED block at 1e32a604 of size 20\r
-  USED block at 1e32a618 of size 20\r
-  USED block at 1e32a62c of size 20\r
-  USED block at 1e32a640 of size 20\r
-  USED block at 1e32a654 of size 22952\r
+  USED block at 180c94b6 of size 12\r
+  USED block at 180c94c2 of size 332\r
+  USED block at 180c960e of size 52\r
+  USED block at 180c9642 of size 20\r
+  USED block at 180c9656 of size 20\r
+  USED block at 180c966a of size 20\r
+  USED block at 180c967e of size 20\r
+  USED block at 180c9692 of size 20\r
+  USED block at 180c96a6 of size 26966\r
 OK - end of heap\r
 \r
        == far ==\r
 \r
-  USED block at 2e330016 of size 18\r
-  USED block at 2e330028 of size 136\r
-  USED block at 2e3300b0 of size 50\r
-  USED block at 2e3300e2 of size 50\r
-  USED block at 2e330114 of size 50\r
-  USED block at 2e330146 of size 50\r
-  USED block at 2e330178 of size 50\r
-  USED block at 2e3301aa of size 50\r
-  USED block at 2e3301dc of size 50\r
-  USED block at 2e33020e of size 50\r
-  USED block at 2e330240 of size 50\r
-  USED block at 2e330272 of size 50\r
-  USED block at 2e3302a4 of size 50\r
-  USED block at 2e3302d6 of size 50\r
-  USED block at 2e330308 of size 50\r
-  USED block at 2e33033a of size 14\r
-  USED block at 2e330348 of size 20\r
-  USED block at 2e33035c of size 7328\r
+  USED block at 280d0016 of size 66\r
+  USED block at 280d0058 of size 66\r
+  USED block at 280d009a of size 18\r
+  USED block at 280d00ac of size 136\r
+  USED block at 280d0134 of size 20\r
+  USED block at 280d0148 of size 7860\r
 OK - end of heap\r
 \r
 Memory Type         Total      Used       Free\r
 ----------------  --------   --------   --------\r
-Default                   8166         806       7360\r
-Near              23446        494       22952\r
-Far               8166         806       7360\r
+Default                   8166         288       7878\r
+Near              27462        496       26966\r
+Far               8166         288       7878\r
 ----------------  --------   --------   --------\r
-coreleft = 22950\r
-farcoreleft = 21944\r
-GetFreeSize = 64548\r
-GetNearFreeSize = 22952\r
-GetFarFreeSize = 64548\r
-memavl = 22950\r
-stackavail = 11203\r
+coreleft = 26964\r
+farcoreleft = 51072\r
+GetFreeSize = 24128\r
+GetNearFreeSize = 26966\r
+GetFarFreeSize = 24128\r
+memavl = 26964\r
+stackavail = 11268\r
index 5bad126..b9dba40 100755 (executable)
Binary files a/MMDUMP.16B and b/MMDUMP.16B differ
index 86d239b..023a748 100755 (executable)
Binary files a/MMDUMP.16W and b/MMDUMP.16W differ
index 88bb916..ebfd740 100755 (executable)
Binary files a/bcexmm.exe and b/bcexmm.exe differ
index 410c914..5778f27 100755 (executable)
Binary files a/bcexmm.prj and b/bcexmm.prj differ
index aa21497..a1e0391 100755 (executable)
@@ -97,9 +97,11 @@ main(int argc, char *argv[])
        }\r
        //printf("main()=%Fp    start MM\n", *argv[0]);\r
        MM_Startup(&gvar);\r
+#ifdef __DEBUG_PM__\r
        PM_Startup(&gvar);\r
-       PM_CheckMainMem(&gvar);\r
+       //PM_CheckMainMem(&gvar);\r
        PM_UnlockMainMem(&gvar);\r
+#endif\r
        CA_Startup(&gvar);\r
 //     printf("                done!\n");\r
        PRINTBB;\r
@@ -144,8 +146,12 @@ for(w=0;w<2;w++)
 #ifdef FILEREAD\r
 }\r
 #endif\r
+       printf("bakapee1=%s\n", bakapee1);\r
+       printf("bakapee2=%s\n", bakapee2);\r
        MM_FreePtr(&bigbuffer, &gvar);\r
+#ifdef __DEBUG_PM__\r
        PM_Shutdown(&gvar);\r
+#endif\r
        CA_Shutdown(&gvar);\r
        MM_Shutdown(&gvar);\r
        free(bakapee1); free(bakapee2);\r
index 0155c81..ec7db9f 100755 (executable)
@@ -152,7 +152,7 @@ static word far* clockw= (word far*) 0x046C; /* 18.2hz clock */
 extern int                     profilehandle,debughandle;      //make it into game global\r
 \r
 #define __DEBUG__\r
-#define __DEBUG_PM__\r
+//0000#define __DEBUG_PM__\r
 \r
 #define        nil     ((void *)0)\r
 #ifdef __BORLANDC__\r
@@ -199,7 +199,6 @@ int US_CheckParm(char *parm,char **strings);
 #ifdef __BORLANDC__\r
 void Quit (char *error);\r
 #endif\r
-void   XMS_CALL(byte v, global_game_variables_t *gvar);\r
 byte dirchar(byte in);\r
 \r
 #endif/*_LIBHEAD_H_*/\r
index 5f5b644..9eb93c6 100755 (executable)
-/* Catacomb Apocalypse Source Code\r
- * Copyright (C) 1993-2014 Flat Rock Software\r
- *\r
- * This program is free software; you can redistribute it and/or modify\r
- * it under the terms of the GNU General Public License as published by\r
- * the Free Software Foundation; either version 2 of the License, or\r
- * (at your option) any later version.\r
- *\r
- * This program is distributed in the hope that it will be useful,\r
- * but WITHOUT ANY WARRANTY; without even the implied warranty of\r
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r
- * GNU General Public License for more details.\r
- *\r
- * You should have received a copy of the GNU General Public License along\r
- * with this program; if not, write to the Free Software Foundation, Inc.,\r
- * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.\r
- */\r
-\r
-// NEWMM.C\r
-\r
-/*\r
-=============================================================================\r
-\r
-                       ID software memory manager\r
-                       --------------------------\r
-\r
-Primary coder: John Carmack\r
-\r
-RELIES ON\r
----------\r
-Quit (char *error) function\r
-\r
-\r
-WORK TO DO\r
-----------\r
-MM_SizePtr to change the size of a given pointer\r
-\r
-Multiple purge levels utilized\r
-\r
-EMS / XMS unmanaged routines\r
-\r
-=============================================================================\r
-*/\r
-/*\r
-\r
-Open Watcom port by sparky4\r
-\r
-*/\r
-#include "src/lib/16_mm.h"\r
-#include "src/lib/16_ca.h"\r
-#pragma hdrstop\r
-\r
-#pragma warn -pro\r
-#pragma warn -use\r
-\r
-/*\r
-=============================================================================\r
-\r
-                                                GLOBAL VARIABLES\r
-\r
-=============================================================================\r
-*/\r
-\r
-void           (* beforesort) (void);\r
-void           (* aftersort) (void);\r
-void           (* XMSaddr) (void);             // far pointer to XMS driver\r
-\r
-/*\r
-=============================================================================\r
-\r
-                                                LOCAL VARIABLES\r
-\r
-=============================================================================\r
-*/\r
-\r
-/*\r
-======================\r
-=\r
-= MML_CheckForEMS\r
-=\r
-= Routine from p36 of Extending DOS\r
-=\r
-=======================\r
-*/\r
-\r
-boolean MML_CheckForEMS(void)\r
-{\r
-       boolean emmcfems;\r
-       static char     emmname[] = "EMMXXXX0"; //fix by andrius4669\r
-       __asm {\r
-               mov     dx,OFFSET emmname       //fix by andrius4669\r
-               mov     ax,0x3d00\r
-               int     0x21            // try to open EMMXXXX0 device\r
-               jc      error\r
-\r
-               mov     bx,ax\r
-               mov     ax,0x4400\r
-\r
-               int     0x21            // get device info\r
-               jc      error\r
-\r
-               and     dx,0x80\r
-               jz      error\r
-\r
-               mov     ax,0x4407\r
-\r
-               int     0x21            // get status\r
-               jc      error\r
-               or      al,al\r
-               jz      error\r
-\r
-               mov     ah,0x3e\r
-               int     0x21            // close handle\r
-               jc      error\r
-               //\r
-               // EMS is good\r
-               //\r
-               mov     emmcfems,1\r
-               jmp End\r
-#ifdef __BORLANDC__\r
-       }\r
-#endif\r
-               error:\r
-#ifdef __BORLANDC__\r
-       __asm {\r
-#endif\r
-               //\r
-               // EMS is bad\r
-               //\r
-               mov     emmcfems,0\r
-#ifdef __BORLANDC__\r
-       }\r
-#endif\r
-               End:\r
-#ifdef __WATCOMC__\r
-       }\r
-#endif\r
-       return(emmcfems);\r
-}\r
-\r
-\r
-/*\r
-======================\r
-=\r
-= MML_SetupEMS\r
-=\r
-=======================\r
-*/\r
-\r
-byte MML_SetupEMS(global_game_variables_t *gvar)\r
-{\r
-       byte    str[160];\r
-       byte    err;\r
-       boolean errorflag=false;\r
-\r
-       unsigned int EMSVer = 0;\r
-       //byte  EMS_status;\r
-       unsigned        totalEMSpages,freeEMSpages,EMSPageFrame,EMSpagesmapped,EMSHandle;\r
-       totalEMSpages = freeEMSpages = EMSPageFrame = EMSpagesmapped = 0;\r
-\r
-       __asm {\r
-               mov     ah,EMS_STATUS\r
-               int     EMS_INT                                         // make sure EMS hardware is present\r
-               or      ah,ah\r
-               //mov   [EMS_status],ah\r
-               jnz     error\r
-\r
-               mov     ah,EMS_VERSION\r
-               int     EMS_INT\r
-               or      ah,ah\r
-               jnz     error\r
-               mov     [EMSVer],ax                             //      set EMSVer\r
-               cmp     al,0x32                                         // only work on ems 3.2 or greater\r
-               jb      error\r
-\r
-               mov     ah,EMS_GETFRAME\r
-               int     EMS_INT                                         // find the page frame address\r
-               or      ah,ah\r
-               jnz     error\r
-               mov     [EMSPageFrame],bx\r
-\r
-               mov     ah,EMS_GETPAGES\r
-               int     EMS_INT                                         // find out how much EMS is there\r
-               or      ah,ah\r
-               jnz     error\r
-               mov     [totalEMSpages],dx\r
-               mov     [freeEMSpages],bx\r
-               or      bx,bx\r
-               jz      noEMS                                           // no EMS at all to allocate\r
-                                                                                       //EXPAND DONG!!!!\r
-               cmp     [EMSVer],0x40\r
-               jb      low\r
-               cmp     bx,[freeEMSpages]\r
-               jle     getpages\r
-               mov     bx,[freeEMSpages]\r
-               jmp     getpages\r
-#ifdef __BORLANDC__\r
-       }\r
-#endif\r
-       low:\r
-#ifdef __BORLANDC__\r
-       __asm {\r
-#endif\r
-               cmp     bx,4\r
-               jle     getpages                                        // there is only 1,2,3,or 4 pages\r
-               mov     bx,4                                            // we can't use more than 4 pages\r
-#ifdef __BORLANDC__\r
-       }\r
-#endif\r
-       getpages:\r
-#ifdef __BORLANDC__\r
-       __asm {\r
-#endif\r
-               mov     [EMSpagesmapped],bx\r
-               mov     ah,EMS_ALLOCPAGES                       // allocate up to 64k of EMS\r
-               int     EMS_INT\r
-               or      ah,ah\r
-               jnz     error\r
-               mov     [EMSHandle],dx\r
-               jmp End\r
-#ifdef __BORLANDC__\r
-       }\r
-#endif\r
-       error:\r
-#ifdef __BORLANDC__\r
-       __asm {\r
-#endif\r
-               mov     err,ah\r
-               mov     errorflag,1\r
-               jmp End\r
-#ifdef __BORLANDC__\r
-       }\r
-#endif\r
-noEMS:\r
-End:\r
-#ifdef __WATCOMC__\r
-       }\r
-#endif\r
-       if(errorflag==true)\r
-       {\r
-               strcpy(str,"MM_SetupEMS: EMS error ");\r
-               MM_EMSerr(str, err);\r
-               printf("%s\n",str);\r
-               return err;\r
-       }\r
-       gvar->pm.emm.totalEMSpages=totalEMSpages;\r
-       gvar->pm.emm.freeEMSpages=freeEMSpages;\r
-       gvar->pm.emm.EMSPageFrame=EMSPageFrame;\r
-       gvar->pm.emm.EMSpagesmapped=EMSpagesmapped;\r
-       gvar->pm.emm.EMSHandle=EMSHandle;\r
-       gvar->pm.emm.EMSVer=EMSVer;\r
-       return 0;\r
-}\r
-\r
-\r
-/*\r
-======================\r
-=\r
-= MML_ShutdownEMS\r
-=\r
-=======================\r
-*/\r
-\r
-void MML_ShutdownEMS(global_game_variables_t *gvar)\r
-{\r
-       boolean errorflag=false;\r
-       unsigned EMSHandle=gvar->pm.emm.EMSHandle;\r
-\r
-       if(!EMSHandle)\r
-               return;\r
-       __asm {\r
-               mov     ah,EMS_FREEPAGES\r
-               mov     dx,[EMSHandle]\r
-               int     EMS_INT\r
-               or      ah,ah\r
-               jz      ok\r
-               mov     errorflag,1\r
-#ifdef __BORLANDC__\r
-       }\r
-#endif\r
-               ok:\r
-#ifdef __WATCOMC__\r
-       }\r
-#endif\r
-       if(errorflag==true)\r
-               Quit("MML_ShutdownEMS: Error freeing EMS!\n");  //++++ add something\r
-}\r
-\r
-/*\r
-====================\r
-=\r
-= MM_MapEMS\r
-=\r
-= Maps the 64k of EMS used by memory manager into the page frame\r
-= for general use.  This only needs to be called if you are keeping\r
-= other things in EMS.\r
-=\r
-====================\r
-*/\r
-\r
-byte MM_MapEMS(global_game_variables_t *gvar)\r
-{\r
-       byte    str[160];\r
-       unsigned        EMSHandle;\r
-       byte err;\r
-       boolean errorflag=false;\r
-       int     i;\r
-       EMSHandle=gvar->pm.emm.EMSHandle;\r
-\r
-       for (i=0;i<4/*MAPPAGES*/;i++)\r
-       {\r
-               __asm {\r
-                       mov     ah,EMS_MAPPAGE\r
-                       mov     bx,[i]                  // logical page\r
-                       mov     al,bl                   // physical page\r
-                       mov     dx,[EMSHandle]  // handle\r
-                       int     EMS_INT\r
-                       or      ah,ah\r
-                       jnz     error\r
-                       jmp End\r
-#ifdef __BORLANDC__\r
-               }\r
-#endif\r
-                       error:\r
-#ifdef __BORLANDC__\r
-               __asm {\r
-#endif\r
-                       mov     err,ah\r
-                       mov     errorflag,1\r
-#ifdef __BORLANDC__\r
-               }\r
-#endif\r
-                       End:\r
-#ifdef __WATCOMC__\r
-               }\r
-#endif\r
-               if(errorflag==true)\r
-               {\r
-                       strcpy(str,"MM_MapEMS: EMS error ");\r
-                       MM_EMSerr(str, err);\r
-                       printf("%s\n",str);\r
-                       return err;\r
-               }\r
-       }\r
-       gvar->mmi.EMSmem = (i)*0x4000lu;\r
-       //printf("              gvar->mmi.EMSmem=%lu\n", gvar->mmi.EMSmem);\r
-       return 0;\r
-}\r
-\r
-byte MM_MapXEMS(global_game_variables_t *gvar)\r
-{\r
-//SUB EMS.MapXPages (PhysicalStart, LogicalStart, NumPages, Handle)\r
-\r
-       //Maps up to 4 logical EMS pages to physical pages in the page frame, where:\r
-       //PhysicalStart = Physical page first logical page is mapped to\r
-       //LogicalStart  = First logical page to map\r
-       //NumPages      = Number of pages to map (1 to 4)\r
-       //Handle        = EMS handle logical pages are allocated to\r
-\r
-  /*//Create a buffer containing the page information\r
-//  FOR x = 0 TO NumPages - 1\r
-//    MapInfo$ = MapInfo$ + MKI$(LogicalStart + x) + MKI$(PhysicalStart + x)\r
-//  NEXT*/\r
-\r
-//  Regs.ax = 0x5000                           //Map the pages in the buffer\r
-//  Regs.cx = NumPages                         //to the pageframe\r
-//  Regs.dx = Handle\r
-//  Regs.ds = VARSEG(MapInfo$)\r
-//  Regs.si = SADD(MapInfo$)\r
-//  InterruptX 0x67, Regs, Regs\r
-//     EMS.Error = (Regs.ax AND 0xFF00&) \ 0x100  //Store the status code\r
-\r
-//END SUB\r
-       byte    str[160];\r
-       byte err;\r
-       word    EMSHandle;\r
-       boolean errorflag=false;\r
-       int     i;\r
-       EMSHandle=gvar->pm.emm.EMSHandle;\r
-\r
-       if(gvar->pm.emm.EMSVer<0x40)\r
-               return 5;\r
-\r
-       for (i=0;i<MAPPAGES;i++)\r
-       {\r
-               __asm {\r
-                       mov     ah,EMS_MAPXPAGE\r
-                       mov     cx,[i]                  // logical page\r
-                       mov     al,bl                   // physical page\r
-                       mov     dx,[EMSHandle]  // handle\r
-                       int     EMS_INT\r
-                       or      ah,ah\r
-                       jnz     error\r
-                       jmp End\r
-#ifdef __BORLANDC__\r
-               }\r
-#endif\r
-                       error:\r
-#ifdef __BORLANDC__\r
-               __asm {\r
-#endif\r
-                       mov     err,ah\r
-                       mov     errorflag,1\r
-#ifdef __BORLANDC__\r
-               }\r
-#endif\r
-                       End:\r
-#ifdef __WATCOMC__\r
-               }\r
-#endif\r
-               if(errorflag==true)\r
-               {\r
-                       //strcpy(str,"MM_MapXEMS: EMS error 0x");\r
-                       strcpy(str,"MM_MapXEMS: EMS error ");\r
-                       //itoa(err,str2,16);\r
-                       MM_EMSerr(str, err);\r
-                       printf("%s\n",str);\r
-                       //printf("%s%x\n",str, err);\r
-                       //printf("FACK! %x\n", err);\r
-                       return err;\r
-               }\r
-       }\r
-       gvar->mmi.EMSmem = (i)*0x4000lu;\r
-       return 0;\r
-}\r
-\r
-//==========================================================================\r
-\r
-/*\r
-======================\r
-=\r
-= MML_CheckForXMS\r
-=\r
-= Check for XMM driver\r
-=\r
-=======================\r
-*/\r
-\r
-boolean MML_CheckForXMS(global_game_variables_t *gvar)\r
-{\r
-       boolean errorflag=false;\r
-       gvar->mm.numUMBs = 0;\r
-\r
-       __asm {\r
-               mov     ax,0x4300\r
-               int     0x2f                            // query status of installed diver\r
-               cmp     al,0x80\r
-               je      good\r
-               mov     errorflag,1\r
-#ifdef __BORLANDC__\r
-       }\r
-#endif\r
-               good:\r
-#ifdef __WATCOMC__\r
-       }\r
-#endif\r
-       if(errorflag==true) return false;\r
-       else return true;\r
-}\r
-\r
-\r
-/*\r
-======================\r
-=\r
-= MML_SetupXMS\r
-=\r
-= Try to allocate all upper memory block\r
-=\r
-=======================\r
-*/\r
-\r
-void MML_SetupXMS(global_game_variables_t *gvar)\r
-{\r
-       word    base,size;\r
-\r
-\r
-       __asm {\r
-               mov     ax,0x4310\r
-               int     0x2f\r
-               mov     [WORD PTR XMSaddr],bx\r
-               mov     [WORD PTR XMSaddr+2],es         // function pointer to XMS driver\r
-       }\r
-getmemory:\r
-       __asm {\r
-               mov     ah,XMS_ALLOCUMB\r
-               mov     dx,0xffff                                       // try for largest block possible\r
-               //mov     ax,dx                                         // Set available Kbytes.\r
-               call    [DWORD PTR XMSaddr]\r
-               or      ax,ax\r
-               jnz     gotone\r
-\r
-               cmp     bl,0xb0                                         // error: smaller UMB is available\r
-               jne     done;\r
-\r
-               mov     ah,XMS_ALLOCUMB\r
-               call    [DWORD PTR XMSaddr]             // DX holds largest available UMB\r
-               or      ax,ax\r
-               jz      done                                            // another error...\r
-#ifdef __BORLANDC__\r
-       }\r
-#endif\r
-               gotone:\r
-#ifdef __BORLANDC__\r
-       __asm {\r
-#endif\r
-               mov     [base],bx\r
-               mov     [size],dx\r
-#ifdef __BORLANDC__\r
-       }\r
-#endif\r
-               done:\r
-#ifdef __WATCOMC__\r
-       }\r
-#endif\r
-//     printf("base=%u ", base); printf("size=%u\n", size);\r
-       MML_UseSpace(base,size, gvar);\r
-       gvar->mmi.XMSmem += size*16;\r
-       gvar->mm.UMBbase[gvar->mm.numUMBs] = base;\r
-       gvar->mm.numUMBs++;\r
-       if(gvar->mm.numUMBs < MAXUMBS)\r
-               goto getmemory;\r
-}\r
-\r
-\r
-/*\r
-======================\r
-=\r
-= MML_ShutdownXMS\r
-=\r
-======================\r
-*/\r
-\r
-void MML_ShutdownXMS(global_game_variables_t *gvar)\r
-{\r
-       int     i;\r
-       unsigned        base;\r
-\r
-       for (i=0;i<gvar->mm.numUMBs;i++)\r
-       {\r
-               base = gvar->mm.UMBbase[i];\r
-               __asm {\r
-                       mov     ah,XMS_FREEUMB\r
-                       mov     dx,[base]\r
-                       call    [DWORD PTR XMSaddr]\r
-               }\r
-       }\r
-}\r
-\r
-//==========================================================================\r
-\r
-/*\r
-======================\r
-=\r
-= MML_UseSpace\r
-=\r
-= Marks a range of paragraphs as usable by the memory manager\r
-= This is used to mark space for the near heap, far heap, ems page frame,\r
-= and upper memory blocks\r
-=\r
-======================\r
-*/\r
-\r
-/*void MML_UseSpace(word segstart, dword seglength, global_game_variables_t *gvar)\r
-{\r
-       //huge mmblocktype huge *scan,huge *last;\r
-       word            segm=1;\r
-       word    oldend;\r
-       dword           segmlen;\r
-       dword           extra;\r
-\r
-       scan = last = gvar->mm.mmhead;\r
-       gvar->mm.mmrover = gvar->mm.mmhead;             // reset rover to start of memory\r
-\r
-//\r
-// search for the block that contains the range of segments\r
-//\r
-       while(scan->start+scan->length < segstart)\r
-       {\r
-               last = scan;\r
-               scan = scan->next;\r
-       }\r
-\r
-//\r
-// take the given range out of the block\r
-//\r
-       oldend = scan->start + scan->length;\r
-       extra = oldend - (segstart+seglength);\r
-\r
-       segmlen=extra;\r
-\r
-       //++++emsver stuff!\r
-       if(segm>1)/// || extra>=0x10000lu)\r
-       //if(extra>0xfffflu)\r
-       {\r
-               scan->blob=segm;\r
-\r
-               //MML_UseSpace(segstart, seglength, gvar);\r
-\r
-               printf("MML_UseSpace: Segment spans two blocks!\n");\r
-       //}\r
-       printf("segm=%u         ", segm);\r
-       printf("ex=%lu  ", extra);\r
-       printf("old=%u  ", oldend);\r
-       printf("start+seglen=%lu\n", segstart+seglength);\r
-       printf("segsta=%x       ", segstart);\r
-       printf("len=%lu ", scan->length);\r
-       printf("seglen=%lu      ", seglength);\r
-       printf("segmlen=%lu\n", segmlen);\r
-       }\r
-//++++todo: linked list of segment!\r
-       if(segstart == scan->start)\r
-       {\r
-               last->next = scan->next;                        // unlink block\r
-               FREEBLOCK(scan);\r
-               scan = last;\r
-       }\r
-       else\r
-               scan->length = segstart-scan->start;    // shorten block\r
-\r
-       if(extra > 0)\r
-       {\r
-               GETNEWBLOCK;\r
-               gvar->mm.mmnew->useptr = NULL;\r
-\r
-               gvar->mm.mmnew->next = scan->next;\r
-               scan->next = gvar->mm.mmnew;\r
-               gvar->mm.mmnew->start = segstart+seglength;\r
-               gvar->mm.mmnew->length = extra;\r
-               gvar->mm.mmnew->attributes = LOCKBIT;\r
-       }//else if(segm>0) goto segu;\r
-\r
-}*/\r
-void MML_UseSpace(word segstart, dword seglength, global_game_variables_t *gvar)\r
-{\r
-       mmblocktype far *scan,far *last;\r
-       word    oldend;\r
-       sdword          extra;\r
-       //word segm=1;\r
-\r
-       scan = last = gvar->mm.mmhead;\r
-       gvar->mm.mmrover = gvar->mm.mmhead;             // reset rover to start of memory\r
-\r
-//\r
-// search for the block that contains the range of segments\r
-//\r
-       while (scan->start+scan->length < segstart)\r
-       {\r
-               last = scan;\r
-               scan = scan->next;\r
-       }\r
-\r
-//\r
-// find out how many blocks it spans!\r
-//\r
-       /*for(;seglength>=0x10000;seglength-=0xFFFF)\r
-       {\r
-               //printf("      seglen=%lu\n", segmlen);\r
-               segm++;\r
-       }*/\r
-\r
-//\r
-// take the given range out of the block\r
-//\r
-       oldend = scan->start + scan->length;\r
-       extra = oldend - (segstart+((unsigned)seglength));\r
-       if (extra < 0)\r
-       {\r
-               printf("========================================\n");\r
-               printf("start=%x        ", scan->start);\r
-               printf("old=%u  ", oldend);\r
-               printf("start+seglen=%lu\n", segstart+seglength);\r
-               printf("segsta=%x       ", segstart);\r
-               printf("len=%lu ", scan->length);\r
-               printf("seglen=%lu      ", seglength);\r
-               printf("\n");\r
-               printf("MML_UseSpace: Segment spans two blocks! %d\n", extra);\r
-               printf("========================================\n");\r
-               //return;\r
-       }\r
-\r
-       if (segstart == scan->start)\r
-       {\r
-               last->next = scan->next;                        // unlink block\r
-               FREEBLOCK(scan);\r
-               scan = last;\r
-       }\r
-       else\r
-               scan->length = segstart-scan->start;    // shorten block\r
-\r
-       if (extra > 0)\r
-       {\r
-               GETNEWBLOCK;\r
-               gvar->mm.mmnew->useptr = NULL;\r
-\r
-               gvar->mm.mmnew->next = scan->next;\r
-               scan->next = gvar->mm.mmnew;\r
-               gvar->mm.mmnew->start = segstart+seglength;\r
-               gvar->mm.mmnew->length = extra;\r
-               gvar->mm.mmnew->attributes = LOCKBIT;\r
-       }\r
-\r
-}\r
-\r
-//==========================================================================\r
-\r
-/*\r
-====================\r
-=\r
-= MML_ClearBlock\r
-=\r
-= We are out of blocks, so free a purgable block\r
-=\r
-====================\r
-*/\r
-\r
-void MML_ClearBlock(global_game_variables_t *gvar)\r
-{\r
-       //huge mmblocktype huge *scan,huge *last;\r
-       mmblocktype far *scan,far *last;\r
-\r
-       scan = gvar->mm.mmhead->next;\r
-\r
-       while(scan)\r
-       {\r
-               if(!(scan->attributes&LOCKBIT) && (scan->attributes&PURGEBITS))\r
-               {\r
-                       MM_FreePtr(scan->useptr, gvar);\r
-                       return;\r
-               }\r
-               scan = scan->next;\r
-       }\r
-\r
-       printf("MM_ClearBlock: No purgable blocks!\n");\r
-}\r
-\r
-\r
-//==========================================================================\r
-\r
-/*\r
-===================\r
-=\r
-= MM_Startup\r
-=\r
-= Grabs all space from turbo with malloc/farmalloc\r
-= Allocates bufferseg misc buffer\r
-=\r
-===================\r
-*/\r
-\r
-void MM_Startup(global_game_variables_t *gvar)\r
-{\r
-       int i;\r
-       //dword length,seglength;\r
-       dword length;\r
-       //huge void huge        *start;\r
-       void far        *start;\r
-       word    segstart,seglength,endfree;\r
-       //memptr *peeonself;\r
-\r
-       if(gvar->mm.mmstarted)\r
-               MM_Shutdown(gvar);\r
-\r
-\r
-       gvar->mm.mmstarted = true;\r
-       gvar->mm.bombonerror = true;\r
-//\r
-// set up the linked list (everything in the free list;\r
-//\r
-       gvar->mm.mmhead = NULL;\r
-       gvar->mm.mmfree = &(gvar->mm.mmblocks[0]);\r
-       for(i=0;i<MAXBLOCKS-1;i++)\r
-       {\r
-               gvar->mm.mmblocks[i].next = &(gvar->mm.mmblocks[i+1]);\r
-       }\r
-       gvar->mm.mmblocks[i].next = NULL;\r
-\r
-//\r
-// locked block of all memory until we punch out free space\r
-//\r
-       GETNEWBLOCK;\r
-       gvar->mm.mmhead = gvar->mm.mmnew;                               // this will allways be the first node\r
-       gvar->mm.mmnew->start = 0;\r
-       gvar->mm.mmnew->length = 0xffff;\r
-       gvar->mm.mmnew->attributes = LOCKBIT;\r
-       gvar->mm.mmnew->next = NULL;\r
-       //gvar->mm.mmnew->useptr = peeonself;\r
-       gvar->mm.mmrover = gvar->mm.mmhead;\r
-\r
-       //printf("              %x\n", peeonself);\r
-       //printf("              %x\n", *peeonself);\r
-//\r
-// get all available near conventional memory segments\r
-//\r
-#ifdef __WATCOMC__\r
-       _nheapgrow();\r
-       length=(dword)_memavl();//(dword)GetFreeSize();\r
-       //huge start = (void huge *)(gvar->mm.nearheap = _nmalloc(length));\r
-       start = (void far *)(gvar->mm.nearheap = _nmalloc(length));\r
-#endif\r
-#ifdef __BORLANDC__\r
-       length=coreleft();\r
-       //huge start = (void huge *)(gvar->mm.nearheap = malloc(length));\r
-       start = (void far *)(gvar->mm.nearheap = malloc(length));\r
-       printf("Borland C unique function\n");\r
-       printf("        coreleft()                              %lu\n", coreleft());\r
-#endif\r
-       length -= 16-(FP_OFF(start)&15);\r
-       length -= SAVENEARHEAP;\r
-       seglength = length / 16;                        // now in paragraphs\r
-       segstart = FP_SEG(start)+(FP_OFF(start)+15)/16;\r
-       MML_UseSpace(segstart,seglength, gvar);\r
-       gvar->mmi.nearheap = length;\r
-       //printf("start=%Fp     segstart=%x     seglen=%lu      len=%lu\n", start, segstart, seglength, length);\r
-\r
-//\r
-// get all available far conventional memory segments\r
-//\r
-       //printf("_FARCORELEFT                          %lu\n", _FCORELEFT);\r
-#ifdef __WATCOMC__\r
-       _fheapgrow();\r
-#endif\r
-#ifdef __BORLANDC__\r
-       printf("        farcoreleft()                           %lu\n", farcoreleft());\r
-       printf("        (farcoreleft()+32)-_FCORELEFT   %d\n", (sword)((farcoreleft()+32)-_FCORELEFT));\r
-#endif\r
-       length=_FCORELEFT;//_fcoreleft();//(dword)GetFarFreeSize();//0xffffUL*4UL;\r
-       start = gvar->mm.farheap = _fmalloc(length);\r
-       //start = gvar->mm.farheap = halloc(length, 1);\r
-       length -= 16-(FP_OFF(start)&15);\r
-       length -= SAVEFARHEAP;\r
-       seglength = length / 16;                        // now in paragraphs\r
-       segstart = FP_SEG(start)+(FP_OFF(start)+15)/16;\r
-       MML_UseSpace(segstart,seglength, gvar);\r
-       gvar->mmi.farheap = length;\r
-       gvar->mmi.mainmem = gvar->mmi.nearheap + gvar->mmi.farheap;\r
-       //printf("start=%Fp     segstart=%x     seglen=%lu      len=%lu\n", start, segstart, seglength, length);\r
-\r
-goto xmsskip;  //INFO: 16_PM dose this job better\r
-\r
-//\r
-// detect EMS and allocate up to 64K at page frame\r
-//\r
-       gvar->mmi.EMSmem = 0;\r
-//goto emsskip;        //0000\r
-       if(MML_CheckForEMS())\r
-       {\r
-               MML_SetupEMS(gvar);                                     // allocate space\r
-               //TODO: EMS4! AND EMS 3.2 MASSIVE DATA HANDLMENT!\r
-               MML_UseSpace(gvar->pm.emm.EMSPageFrame,(MAPPAGES)*0x4000lu, gvar);\r
-               //if(gvar->pm.emm.EMSVer<0x40)\r
-                       MM_MapEMS(gvar);                                        // map in used pages\r
-               //else\r
-                       //MM_MapXEMS(gvar);                                     // map in used pages\r
-       }\r
-\r
-//\r
-// detect XMS and get upper memory blocks\r
-//\r
-//emsskip:\r
-       gvar->mmi.XMSmem = 0;\r
-//goto xmsskip;//0000\r
-       if(MML_CheckForXMS(gvar))\r
-       {\r
-               MML_SetupXMS(gvar);                                     // allocate as many UMBs as possible\r
-       }\r
-\r
-//\r
-// allocate the misc buffer\r
-//\r
-xmsskip:\r
-       gvar->mm.mmrover = gvar->mm.mmhead;             // start looking for space after low block\r
-\r
-       MM_GetPtr(&(gvar->mm.bufferseg),BUFFERSIZE, gvar);\r
-}\r
-\r
-//==========================================================================\r
-\r
-/*\r
-====================\r
-=\r
-= MM_Shutdown\r
-=\r
-= Frees all conventional, EMS, and XMS allocated\r
-=\r
-====================\r
-*/\r
-\r
-void MM_Shutdown(global_game_variables_t *gvar)\r
-{\r
-       if(!(gvar->mm.mmstarted))\r
-               return;\r
-\r
-       _ffree(gvar->mm.farheap);//     printf("                far freed\n");\r
-#ifdef __WATCOMC__\r
-       _nfree(gvar->mm.nearheap);//    printf("                near freed\n");\r
-#endif\r
-#ifdef __BORLANDC__\r
-       free(gvar->mm.nearheap);//      printf("                near freed\n");\r
-#endif\r
-       if(MML_CheckForEMS()){ MML_ShutdownEMS(gvar); }//printf("               EMS freed\n"); }\r
-       if(MML_CheckForXMS(gvar)){ MML_ShutdownXMS(gvar); }//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, global_game_variables_t *gvar)\r
-{\r
-       //huge mmblocktype huge *scan,huge *lastscan,huge *endscan,huge *purge,huge *next;\r
-       mmblocktype far *scan,far *lastscan,far *endscan,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
-       gvar->mm.mmnew->length = needed;\r
-       gvar->mm.mmnew->useptr = baseptr;\r
-       //if(gvar->mm.mmnew->useptr==NULL){\r
-#ifdef __DEBUG__\r
-               printf("        MM_GetPtr\n");\r
-               printf("                baseptr=%04x    ", baseptr); printf("useptr=%04x\n", gvar->mm.mmnew->useptr);\r
-               printf("                *baseptr=%04x   ", *baseptr); printf("*useptr=%04x\n", *(gvar->mm.mmnew->useptr));\r
-               printf("                *baseptr=%Fp    ", *baseptr); printf("*useptr=%Fp\n", *(gvar->mm.mmnew->useptr));\r
-#endif\r
-       //exit(-5); }\r
-       gvar->mm.mmnew->attributes = BASEATTRIBUTES;\r
-\r
-//tryagain:\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 && gvar->mm.mmrover == gvar->mm.mmhead)\r
-                       search++;\r
-\r
-               switch (search)\r
-               {\r
-               case 0:\r
-                       lastscan = gvar->mm.mmrover;\r
-                       scan = gvar->mm.mmrover->next;\r
-                       endscan = NULL;\r
-                       break;\r
-               case 1:\r
-                       lastscan = gvar->mm.mmhead;\r
-                       scan = gvar->mm.mmhead->next;\r
-                       endscan = gvar->mm.mmrover;\r
-                       break;\r
-               case 2:\r
-                       MM_SortMem (gvar);\r
-                       lastscan = gvar->mm.mmhead;\r
-                       scan = gvar->mm.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 = gvar->mm.mmnew;\r
-                               gvar->mm.mmnew->start = *(unsigned *)baseptr = startseg;\r
-                               gvar->mm.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
-                               gvar->mm.mmrover = gvar->mm.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 (gvar->mm.bombonerror)\r
-       {\r
-#ifdef __WATCOMC__\r
-               //heapdump();\r
-#endif\r
-               printf(OUT_OF_MEM_MSG,(size-gvar->mmi.nearheap));\r
-               printf("for stability reasons the program will shut down! wwww\n");\r
-               MM_Shutdown(gvar);\r
-               exit(-1);\r
-       }\r
-       else\r
-               gvar->mm.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, global_game_variables_t *gvar)\r
-{\r
-       //huge mmblocktype huge *scan,huge *last;\r
-       mmblocktype far *scan,far *last;\r
-\r
-       last = gvar->mm.mmhead;\r
-       scan = last->next;\r
-\r
-       if(baseptr == gvar->mm.mmrover->useptr) // removed the last allocated block\r
-               gvar->mm.mmrover = gvar->mm.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!\n");\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, global_game_variables_t *gvar)\r
-{\r
-        mmblocktype huge *start;\r
-       //mmblocktype far *start;\r
-\r
-       start = gvar->mm.mmrover;\r
-\r
-       do\r
-       {\r
-               if(gvar->mm.mmrover->useptr == baseptr)\r
-                       break;\r
-\r
-               gvar->mm.mmrover = gvar->mm.mmrover->next;\r
-\r
-               if(!gvar->mm.mmrover)\r
-                       gvar->mm.mmrover = gvar->mm.mmhead;\r
-               else if(gvar->mm.mmrover == start)\r
-               {\r
-#ifdef __DEBUG_PM__\r
-                       printf("\n\nstart->useptr       gvar->mm.mmhead->useptr\n");\r
-                       printf("        %Fp     %Fp\n", start->useptr, gvar->mm.mmhead->useptr);\r
-                       printf("&       %Fp     %Fp\n", &(start->useptr), &(gvar->mm.mmhead->useptr));\r
-                       printf("baseptr                 gvar->mm.mmrover->useptr\n");\r
-                       printf("        %Fp     %Fp\n", baseptr, gvar->mm.mmrover->useptr);\r
-                       printf("&       %Fp     %Fp\n", &(baseptr), &(gvar->mm.mmrover->useptr));\r
-                       printf("*       %Fp     %Fp\n", *(baseptr), *(gvar->mm.mmrover->useptr));\r
-                       printf("start                   gvar->mm.mmrover gvar->mm.mmrover->next\n");\r
-                       printf("        %Fp     %Fp     %Fp\n", start, gvar->mm.mmrover, gvar->mm.mmrover->next);\r
-                       printf("&       %Fp     %Fp     %Fp\n", &start, &gvar->mm.mmrover, gvar->mm.mmrover->next);\r
-                       getch();\r
-                       MM_ShowMemory(gvar);\r
-                       MM_DumpData(gvar);\r
-                       MM_Report_(gvar);\r
-                       getch();\r
-#endif\r
-                       Quit("MM_SetPurge: Block not found!");\r
-                       return;\r
-               }\r
-\r
-       } while(1);\r
-\r
-       gvar->mm.mmrover->attributes &= ~PURGEBITS;\r
-       gvar->mm.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, global_game_variables_t *gvar)\r
-{\r
-       //huge mmblocktype huge *start;\r
-       mmblocktype far *start;\r
-\r
-       start = gvar->mm.mmrover;\r
-\r
-       do\r
-       {\r
-               if(gvar->mm.mmrover->useptr == baseptr)\r
-                       break;\r
-\r
-               gvar->mm.mmrover = gvar->mm.mmrover->next;\r
-\r
-               if(!gvar->mm.mmrover)\r
-                       gvar->mm.mmrover = gvar->mm.mmhead;\r
-               else if(gvar->mm.mmrover == start)\r
-               {\r
-                       Quit("MM_SetLock: Block not found!");\r
-                       //return;\r
-               }\r
-\r
-       } while(1);\r
-\r
-       gvar->mm.mmrover->attributes &= ~LOCKBIT;\r
-       gvar->mm.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(global_game_variables_t *gvar)\r
-{\r
-       //huge mmblocktype huge *scan,huge *last,huge *next;\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 = gvar->mm.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
-                               //MM_FreeBlock(scan, gvar);\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
-       gvar->mm.mmrover = gvar->mm.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
-=====================\r
-=\r
-= MM_ShowMemory\r
-=\r
-=====================\r
-*/\r
-\r
-void MM_ShowMemory(global_game_variables_t *gvar)\r
-{\r
-       //huge mmblocktype huge *scan;\r
-       mmblocktype far *scan;\r
-       word temp;\r
-       sdword  end,owner;\r
-       //word chx,chy;\r
-       word w;\r
-       //dword wwww;\r
-       byte    scratch[160],scratch0[4096],scratch1[160],str[16];\r
-       //byte d = '#';\r
-//**** VW_SetDefaultColors();\r
-//**** VW_SetLineWidth(40);\r
-//++++mh       temp = bufferofs;\r
-//++++mh       bufferofs = 0;\r
-//**** VW_SetScreen (0,0);\r
-       scan = gvar->mm.mmhead;\r
-       end = -1;\r
-\r
-       CA_OpenDebug (gvar);\r
-       w=0;\r
-       while(scan)\r
-       {\r
-               strcpy(scratch, AARESET);\r
-               if(scan->attributes & PURGEBITS)\r
-                       strcpy(scratch0, AAMAGENTA);            // dark purple = purgable\r
-               else\r
-                       strcpy(scratch0, AABLUE);               // medium blue = non purgable\r
-               if(scan->attributes & LOCKBIT)\r
-                       strcpy(scratch0, AARED);                // red = locked\r
-               if(scan->start<=end)\r
-               {\r
-                       printf("\nend==%d\n\n", end);\r
-                       strcat(scratch, "MM_ShowMemory: Memory block order currupted!\n");\r
-                       strcat(scratch, "End's Size: ");\r
-                       ultoa (end,str,10);\r
-                       strcat (scratch,str);\r
-                       strcat(scratch, "\nscan->start's Size: ");\r
-                       ultoa (scan->start,str,10);\r
-                       strcat (scratch,str);\r
-                       write(gvar->handle.debughandle,scratch,strlen(scratch));\r
-                       //modexprint(&page, chx, chy, 1, 0, 24, "\nMM_ShowMemory: Memory block order currupted!\n");\r
-                       break;\r
-               }\r
-               end = scan->start+(scan->length)-1;\r
-//++++         chy = scan->start/320;\r
-//++++         chx = scan->start%320;\r
-                               //modexhlin(page, scan->start, (unsigned)end, chy, color);\r
-                               //for(chx=scan->start;chx+4>=(word)end;chx+=4)\r
-                               //{\r
-//++++                                 modexClearRegion(page, chx, chy, 4, 4, color);\r
-                               //}\r
-//++++         VW_Hlin(scan->start,(unsigned)end,0,color);\r
-               for(w=(scan->start)/80;w<=end/80;w++)\r
-               {\r
-                       //printf("+     %u      %lu\n", w, scan->length);\r
-                       strcat(scratch0, "+");\r
-               }\r
-               //++==++==optional strcat(scratch0, AARESET); strcat(scratch0, AAGREY); strcat(scratch0,"_");\r
-//++++         VW_Plot(scan->start,0,15);\r
-//++++                         modexClearRegion(page, chx, chy, 4, 4, 15);\r
-//++++                 VW_Hlin(end+1,scan->next->start,0,0);   // black = free\r
-\r
-               //wwww=(dword)(scan->next->start)-(dword)scan->start;\r
-               //wwww=(dword)scan->start+(dword)(scan->next->start);\r
-               if (scan->next && scan->next->start >= end+1)\r
-               {\r
-                       strcat(scratch0, AARESET);\r
-                       //++==++==optional strcat(scratch0, "\n");\r
-                       strcat(scratch0,AAGREEN);\r
-                       for(w=(end+1)/80;w<=((scan->next->start-scan->start)/80);w++)\r
-                       //for(w=(wwww)/80;w<=((end+1)/80);w++)\r
-                       //for(w=(end+1)/80;w<=((wwww)/80);w++)\r
-                       {\r
-                               //printf("0     %x      %u      %lu\n", scan->next->start, w, scan->length);\r
-                               strcat(scratch0,"0");\r
-                       }\r
-                       //printf("==================\n");\r
-                       //printf("w=%u  wwww=%lu        start=%04x      next=%04x       end=%lu\n", w/80, wwww/80, scan->start, (scan->next->start), end+1);\r
-                       //printf("==================\n");\r
-                       strcat(scratch0, "\n");\r
-                       //getch();\r
-               }/*else {//if(scan->next->start <= scan->start){\r
-                       scan->next->start=scan->start+0x1000;\r
-                       wwww=(dword)(scan->next->start)-(dword)scan->start;\r
-                       strcat(scratch0, AARESET);\r
-                       strcat(scratch0, "\n");\r
-                       strcat(scratch0,AAGREEN);\r
-                       for(w=(end+1);w<=(0x1000/80);w++)\r
-                       {\r
-                               //printf("0     %x      %x      %u\n", scan->start, w);\r
-                               strcat(scratch0,"0");\r
-                       }\r
-                       printf("================\n");\r
-                       printf("w=%x    start=%x        next=%x end=%u  %lu\n", w, scan->start, (scan->next->start), end+1, wwww);\r
-                       printf("================\n");\r
-                       getch();\r
-               }*/\r
-               strcat(scratch0, AARESET);\r
-               //strcat(scratch0,"\n");\r
-                       //for(chx=scan->next->start;chx+4>=(word)end+1;chx+=4)\r
-                       //{\r
-//                             chx+=scan->next->start;\r
-//                             modexClearRegion(page, chx, chy, 4, 4, 2);\r
-                       //}\r
-                                       //modexhlin(page, end+1,scan->next->start, chy, 0);\r
-/*             y = scan->start/320;\r
-               x = scan->start%320;\r
-               VW_Hlin(x,x+end,y,color);\r
-               VW_Plot(x,y,15);*/\r
-//++++                 VW_Hlin(x+end+1,x+(scan->next->start-scan->start),y,0); // black = free\r
-               strcat(scratch,"Seg:");\r
-               ultoa (scan->start,str,16);\r
-               strcat (scratch,str);\r
-               strcat (scratch,"\tSize:");\r
-               ultoa ((unsigned)scan->length,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(gvar->handle.debughandle,scratch,strlen(scratch));\r
-               write(gvar->handle.debughandle,scratch0,strlen(scratch0));\r
-//modexprint(page, chx, chy, 1, 0, 24, &scratch);\r
-//++++chy+=4;\r
-//fprintf(stdout, "%s", scratch);\r
-\r
-               scan = scan->next;\r
-       }\r
-       /*strcpy(scratch1, AARESET);\r
-       strcat(scratch1, "========================================\n");\r
-       strcat(scratch1, "near=  ");\r
-       ultoa (*(gvar->mm.nearheap),str,10);\r
-       strcat (scratch1,str);\r
-       strcat(scratch1, "      far= ");\r
-       ultoa (*(gvar->mm.farheap),str,10);\r
-       strcat (scratch1,str);\r
-       strcat(scratch1, "\n");\r
-       //strcat(scratch1, "&near=      %Fp ", &(gvar->mm.nearheap));\r
-       //strcat(scratch1, "&far=       %Fp", &(gvar->mm.farheap));\r
-       //strcat(scratch1, "\n");\r
-       strcat(scratch1, "========================================\n");\r
-       write(gvar->handle.debughandle,scratch1,strlen(scratch1));*/\r
-\r
-\r
-       CA_CloseDebug (gvar);\r
-\r
-//++++mh       IN_Ack();\r
-//**** VW_SetLineWidth(64);\r
-//++++mh       bufferofs = temp;\r
-}\r
-\r
-//==========================================================================\r
-\r
-/*\r
-=====================\r
-=\r
-= MM_DumpData\r
-=\r
-=====================\r
-*/\r
-\r
-void MM_DumpData(global_game_variables_t *gvar)\r
-{\r
-       //huge mmblocktype huge *scan,huge *best;\r
-       mmblocktype far *scan,far *best;\r
-       long    lowest,oldlowest;\r
-       word    owner;\r
-       byte    lock,purge;\r
-       FILE    *dumpfile;\r
-\r
-       free(gvar->mm.nearheap);\r
-#ifdef __BORLANDC__\r
-               dumpfile = fopen ("mmdump.16b","w");\r
-#endif\r
-#ifdef __WATCOMC__\r
-               dumpfile = fopen ("mmdump.16w","w");\r
-#endif\r
-       if (!dumpfile){\r
-               printf("MM_DumpData: Couldn't open MMDUMP.16!\n");\r
-               return;\r
-       }\r
-\r
-       lowest = -1;\r
-       do\r
-       {\r
-               oldlowest = lowest;\r
-               lowest = 0xffff;\r
-\r
-               scan = gvar->mm.mmhead;\r
-               while (scan)\r
-               {\r
-                       owner = (unsigned)scan->useptr;\r
-\r
-                       if (owner && owner<lowest && owner > oldlowest)\r
-                       {\r
-                               best = scan;\r
-                               lowest = owner;\r
-                       }\r
-\r
-                       scan = scan->next;\r
-               }\r
-\r
-               if (lowest != 0xffff)\r
-               {\r
-                       if (best->attributes & PURGEBITS)\r
-                               purge = 'P';\r
-                       else\r
-                               purge = '-';\r
-                       if (best->attributes & LOCKBIT)\r
-                               lock = 'L';\r
-                       else\r
-                               lock = '-';\r
-                       fprintf (dumpfile,"0x%p (%c%c) = %u\n"\r
-                       ,(unsigned)lowest,lock,purge,best->length);\r
-               }\r
-\r
-       } while (lowest != 0xffff);\r
-\r
-       fclose(dumpfile);\r
-       printf("MMDUMP.16 created.\n");\r
-}\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(global_game_variables_t *gvar)\r
-{\r
-       dword free;\r
-       //huge mmblocktype huge *scan;\r
-       mmblocktype far *scan;\r
-\r
-       free = 0;\r
-       scan = gvar->mm.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*16lu;\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(global_game_variables_t *gvar)\r
-{\r
-       dword free;\r
-       //huge mmblocktype huge *scan;\r
-       mmblocktype far *scan;\r
-\r
-       free = 0;\r
-       scan = gvar->mm.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*16lu;\r
-//     return free;\r
-}\r
-\r
-//==========================================================================\r
-\r
-/*\r
-=====================\r
-=\r
-= MM_Report\r
-=\r
-=====================\r
-*/\r
-\r
-void MM_Report_(global_game_variables_t *gvar)\r
-{\r
-       printf("========================================\n");\r
-       printf("                MM_Report\n");\r
-       printf("========================================\n");\r
-       if(MML_CheckForEMS())\r
-       {\r
-               printf("        LIMEMS\n");\r
-               printf("                EMM v%x.%x available\n", gvar->pm.emm.EMSVer>>4,gvar->pm.emm.EMSVer&0x0F);\r
-               printf("                totalEMSpages:  %u      ", gvar->pm.emm.totalEMSpages); printf("freeEMSpages:   %u\n", gvar->pm.emm.freeEMSpages);\r
-               printf("                EMSPageFrame:   %x\n", gvar->pm.emm.EMSPageFrame);\r
-       }\r
-       if(MML_CheckForXMS(gvar))\r
-       {\r
-               printf("        XMS\n");\r
-               printf("                XMSaddr:        %X\n", *XMSaddr);\r
-       }\r
-       printf("near:   %lu     ", gvar->mmi.nearheap); printf("far:    %lu\n", gvar->mmi.farheap); if(MML_CheckForEMS())\r
-       printf("EMSmem: %lu     ", gvar->mmi.EMSmem); if(MML_CheckForXMS(gvar)) printf("XMSmem: %lu", gvar->mmi.XMSmem); printf("\n");\r
-       //printf("mainmem:      %lu\n", gvar->mmi.mainmem);\r
-       printf("Total convmem:  %lu     ", gvar->mmi.mainmem); printf("TotalFree:       %lu     ", MM_TotalFree(gvar)); printf("TotalUsed:      %lu\n", gvar->mmi.mainmem+gvar->mmi.EMSmem+gvar->mmi.XMSmem+gvar->mmi.XMSmem);\r
-       printf("                        UnusedMemory:   %lu\n", MM_UnusedMemory(gvar));\r
-}\r
-\r
-//==========================================================================\r
-\r
-/*\r
-=====================\r
-=\r
-= MM_EMSerr\r
-=\r
-=====================\r
-*/\r
-\r
-void MM_EMSerr(byte *stri, byte err)\r
-{\r
-       //Returns a text string describing the error code in EMS.Error.\r
-       switch(err)\r
-       {\r
-               case 0x0:\r
-                       strcat(stri, "successful");\r
-               break;\r
-               case 0x80:\r
-                       strcat(stri, "internal error");\r
-               break;\r
-               case 0x81:\r
-                       strcat(stri, "hardware malfunction");\r
-               break;\r
-               case 0x82:\r
-                       strcat(stri, "busy .. retry later");\r
-               break;\r
-               case 0x83:\r
-                       strcat(stri, "invalid handle");\r
-               break;\r
-               case 0x84:\r
-                       strcat(stri, "undefined function requested by application");\r
-               break;\r
-               case 0x85:\r
-                       strcat(stri, "no more handles available");\r
-               break;\r
-               case 0x86:\r
-                       strcat(stri, "error in save or restore of mapping context");\r
-               break;\r
-               case 0x87:\r
-                       strcat(stri, "insufficient memory pages in system");\r
-               break;\r
-               case 0x88:\r
-                       strcat(stri, "insufficient memory pages available");\r
-               break;\r
-               case 0x89:\r
-                       strcat(stri, "zero pages requested");\r
-               break;\r
-               case 0x8A:\r
-                       strcat(stri, "invalid logical page number encountered");\r
-               break;\r
-               case 0x8B:\r
-                       strcat(stri, "invalid physical page number encountered");\r
-               break;\r
-               case 0x8C:\r
-                       strcat(stri, "page-mapping hardware state save area is full");\r
-               break;\r
-               case 0x8D:\r
-                       strcat(stri, "save of mapping context failed");\r
-               break;\r
-               case 0x8E:\r
-                       strcat(stri, "restore of mapping context failed");\r
-               break;\r
-               case 0x8F:\r
-                       strcat(stri, "undefined subfunction");\r
-               break;\r
-               case 0x90:\r
-                       strcat(stri, "undefined attribute type");\r
-               break;\r
-               case 0x91:\r
-                       strcat(stri, "feature not supported");\r
-               break;\r
-               case 0x92:\r
-                       strcat(stri, "successful, but a portion of the source region has been overwritten");\r
-               break;\r
-               case 0x93:\r
-                       strcat(stri, "length of source or destination region exceeds length of region allocated to either source or destination handle");\r
-               break;\r
-               case 0x94:\r
-                       strcat(stri, "conventional and expanded memory regions overlap");\r
-               break;\r
-               case 0x95:\r
-                       strcat(stri, "offset within logical page exceeds size of logical page");\r
-               break;\r
-               case 0x96:\r
-                       strcat(stri, "region length exceeds 1 MB");\r
-               break;\r
-               case 0x97:\r
-                       strcat(stri, "source and destination EMS regions have same handle and overlap");\r
-               break;\r
-               case 0x98:\r
-                       strcat(stri, "memory source or destination type undefined");\r
-               break;\r
-               case 0x9A:\r
-                       strcat(stri, "specified alternate map register or DMA register set not supported");\r
-               break;\r
-               case 0x9B:\r
-                       strcat(stri, "all alternate map register or DMA register sets currently allocated");\r
-               break;\r
-               case 0x9C:\r
-                       strcat(stri, "alternate map register or DMA register sets not supported");\r
-               break;\r
-               case 0x9D:\r
-                       strcat(stri, "undefined or unallocated alternate map register or DMA register set");\r
-               break;\r
-               case 0x9E:\r
-                       strcat(stri, "dedicated DMA channels not supported");\r
-               break;\r
-               case 0x9F:\r
-                       strcat(stri, "specified dedicated DMA channel not supported");\r
-               break;\r
-               case 0xA0:\r
-                       strcat(stri, "no such handle name");\r
-               break;\r
-               case 0xA1:\r
-                       strcat(stri, "a handle found had no name, or duplicate handle name");\r
-               break;\r
-               case 0xA2:\r
-                       strcat(stri, "attempted to wrap around 1M conventional address space");\r
-               break;\r
-               case 0xA3:\r
-                       strcat(stri, "source array corrupted");\r
-               break;\r
-               case 0xA4:\r
-                       strcat(stri, "operating system denied access");\r
-               break;\r
-               default:\r
-                       strcat(stri, "undefined error");\r
-       }\r
-}\r
-\r
-//==========================================================================\r
-\r
-/*\r
-=====================\r
-=\r
-= MM_BombOnError\r
-=\r
-=====================\r
-*/\r
-\r
-void MM_BombOnError(boolean bomb, global_game_variables_t *gvar)\r
-{\r
-       gvar->mm.bombonerror = bomb;\r
-}\r
-\r
-/*void MM_GetNewBlock(global_game_variables_t *gvar)\r
-{\r
-       if(!gvar->mm.mmfree)\r
-               MML_ClearBlock(gvar);\r
-       gvar->mm.mmnew=gvar->mm.mmfree;\r
-       gvar->mm.mmfree=gvar->mm.mmfree->next;\r
-       if(!(gvar->mm.mmnew=gvar->mm.mmfree))\r
-       {\r
-               printf("MM_GETNEWBLOCK: No free blocks!\n");\r
-               return;\r
-       }\r
-       gvar->mm.mmfree=gvar->mm.mmfree->next;\r
-}\r
-\r
-void MM_FreeBlock(mmblocktype *x, global_game_variables_t *gvar)\r
-{\r
-       x->useptr=NULL;\r
-       x->next=gvar->mm.mmfree;\r
-       gvar->mm.mmfree=x;\r
-}*/\r
-\r
-void   XMS_CALL(byte v, global_game_variables_t *gvar)\r
-{\r
-       XMSD;\r
-       //XMSDriver=gvar->pm.xmm.XMSDriver;\r
-       __asm {\r
-               mov v,ah\r
-               call [WORD PTR XMSDriver]\r
-       }\r
-}\r
-\r
-/*void MM_seguin(void)\r
-{\r
-       __asm {\r
-               push    ds\r
-               mov     ax,ds\r
-               inc             ax\r
-               mov     ds,ax\r
-       }\r
-}\r
-\r
-void MM_segude(void)\r
-{\r
-       __asm {\r
-               pop ds\r
-       }\r
-}*/\r
-\r
-/*\r
-pull data from far and put it into ds var\r
-mov ax,es:si\r
-mov x,ax\r
-*/\r
-/*\r
-ss stack segment\r
-sp top of stack\r
-bp bottem of stack\r
-*/\r
+/* 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"
+#include "src/lib/16_ca.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
+       __asm {
+               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
+#ifdef __BORLANDC__
+       }
+#endif
+               error:
+#ifdef __BORLANDC__
+       __asm {
+#endif
+               //
+               // EMS is bad
+               //
+               mov     emmcfems,0
+#ifdef __BORLANDC__
+       }
+#endif
+               End:
+#ifdef __WATCOMC__
+       }
+#endif
+       return(emmcfems);
+}
+
+
+/*
+======================
+=
+= MML_SetupEMS
+=
+=======================
+*/
+
+byte MML_SetupEMS(global_game_variables_t *gvar)
+{
+       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
+#ifdef __BORLANDC__
+       }
+#endif
+       low:
+#ifdef __BORLANDC__
+       __asm {
+#endif
+               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
+#ifdef __BORLANDC__
+       }
+#endif
+       getpages:
+#ifdef __BORLANDC__
+       __asm {
+#endif
+               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
+#ifdef __BORLANDC__
+       }
+#endif
+       error:
+#ifdef __BORLANDC__
+       __asm {
+#endif
+               mov     err,ah
+               mov     errorflag,1
+               jmp End
+#ifdef __BORLANDC__
+       }
+#endif
+noEMS:
+End:
+#ifdef __WATCOMC__
+       }
+#endif
+       if(errorflag==true)
+       {
+               strcpy(str,"MM_SetupEMS: EMS error ");
+               MM_EMSerr(str, err);
+               printf("%s\n",str);
+               return err;
+       }
+       gvar->mm.totalEMSpages=totalEMSpages;
+       gvar->mm.freeEMSpages=freeEMSpages;
+       gvar->mm.EMSpageframe=EMSpageframe;
+       gvar->mm.EMSpagesmapped=EMSpagesmapped;
+       gvar->mm.EMShandle=EMShandle;
+       gvar->mm.EMSVer=EMSVer;
+       return 0;
+}
+
+
+/*
+======================
+=
+= MML_ShutdownEMS
+=
+=======================
+*/
+
+void MML_ShutdownEMS(global_game_variables_t *gvar)
+{
+       boolean errorflag=false;
+       unsigned EMShandle=gvar->mm.EMShandle;
+
+       if(!EMShandle)
+               return;
+       __asm {
+               mov     ah,EMS_FREEPAGES
+               mov     dx,[EMShandle]
+               int     EMS_INT
+               or      ah,ah
+               jz      ok
+               mov     errorflag,1
+#ifdef __BORLANDC__
+       }
+#endif
+               ok:
+#ifdef __WATCOMC__
+       }
+#endif
+       if(errorflag==true)
+               Quit("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(global_game_variables_t *gvar)
+{
+       byte    str[160];
+       unsigned        EMShandle;
+       byte err;
+       boolean errorflag=false;
+       int     i;
+       EMShandle=gvar->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
+#ifdef __BORLANDC__
+               }
+#endif
+                       error:
+#ifdef __BORLANDC__
+               __asm {
+#endif
+                       mov     err,ah
+                       mov     errorflag,1
+#ifdef __BORLANDC__
+               }
+#endif
+                       End:
+#ifdef __WATCOMC__
+               }
+#endif
+               if(errorflag==true)
+               {
+                       strcpy(str,"MM_MapEMS: EMS error ");
+                       MM_EMSerr(str, err);
+                       printf("%s\n",str);
+                       return err;
+               }
+       }
+       gvar->mmi.EMSmem = (i)*0x4000lu;
+       //printf("              gvar->mmi.EMSmem=%lu\n", gvar->mmi.EMSmem);
+       return 0;
+}
+
+byte MM_MapXEMS(global_game_variables_t *gvar)
+{
+//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=gvar->mm.EMShandle;
+
+       if(gvar->mm.EMSVer<0x40)
+               return 5;
+
+       for (i=0;i<MAPPAGES;i++)
+       {
+               __asm {
+                       mov     ah,EMS_MAPXPAGE
+                       mov     cx,[i]                  // logical page
+                       mov     al,bl                   // physical page
+                       mov     dx,[EMShandle]  // handle
+                       int     EMS_INT
+                       or      ah,ah
+                       jnz     error
+                       jmp End
+#ifdef __BORLANDC__
+               }
+#endif
+                       error:
+#ifdef __BORLANDC__
+               __asm {
+#endif
+                       mov     err,ah
+                       mov     errorflag,1
+#ifdef __BORLANDC__
+               }
+#endif
+                       End:
+#ifdef __WATCOMC__
+               }
+#endif
+               if(errorflag==true)
+               {
+                       //strcpy(str,"MM_MapXEMS: EMS error 0x");
+                       strcpy(str,"MM_MapXEMS: EMS error ");
+                       //itoa(err,str2,16);
+                       MM_EMSerr(str, err);
+                       printf("%s\n",str);
+                       //printf("%s%x\n",str, err);
+                       //printf("FACK! %x\n", err);
+                       return err;
+               }
+       }
+       gvar->mmi.EMSmem = (i)*0x4000lu;
+       return 0;
+}
+
+//==========================================================================
+
+/*
+======================
+=
+= MML_CheckForXMS
+=
+= Check for XMM driver
+=
+=======================
+*/
+
+boolean MML_CheckForXMS(global_game_variables_t *gvar)
+{
+       boolean errorflag=false;
+       gvar->mm.numUMBs = 0;
+
+       __asm {
+               mov     ax,0x4300
+               int     0x2f                            // query status of installed diver
+               cmp     al,0x80
+               je      good
+               mov     errorflag,1
+#ifdef __BORLANDC__
+       }
+#endif
+               good:
+#ifdef __WATCOMC__
+       }
+#endif
+       if(errorflag==true) return false;
+       else return true;
+}
+
+
+/*
+======================
+=
+= MML_SetupXMS
+=
+= Try to allocate all upper memory block
+=
+=======================
+*/
+
+void MML_SetupXMS(global_game_variables_t *gvar)
+{
+       word    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
+               //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...
+#ifdef __BORLANDC__
+       }
+#endif
+               gotone:
+#ifdef __BORLANDC__
+       __asm {
+#endif
+               mov     [base],bx
+               mov     [size],dx
+#ifdef __BORLANDC__
+       }
+#endif
+               done:
+#ifdef __WATCOMC__
+       }
+#endif
+//     printf("base=%u ", base); printf("size=%u\n", size);
+       MML_UseSpace(base,size, gvar);
+       gvar->mmi.XMSmem += size*16;
+       gvar->mm.UMBbase[gvar->mm.numUMBs] = base;
+       gvar->mm.numUMBs++;
+       if(gvar->mm.numUMBs < MAXUMBS)
+               goto getmemory;
+}
+
+
+/*
+======================
+=
+= MML_ShutdownXMS
+=
+======================
+*/
+
+void MML_ShutdownXMS(global_game_variables_t *gvar)
+{
+       int     i;
+       unsigned        base;
+
+       for (i=0;i<gvar->mm.numUMBs;i++)
+       {
+               base = gvar->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(word segstart, dword seglength, global_game_variables_t *gvar)
+{
+       //huge mmblocktype huge *scan,huge *last;
+       word            segm=1;
+       word    oldend;
+       dword           segmlen;
+       dword           extra;
+
+       scan = last = gvar->mm.mmhead;
+       gvar->mm.mmrover = gvar->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;
+       }
+
+//
+// take the given range out of the block
+//
+       oldend = scan->start + scan->length;
+       extra = oldend - (segstart+seglength);
+
+       segmlen=extra;
+
+       //++++emsver stuff!
+       if(segm>1)/// || extra>=0x10000lu)
+       //if(extra>0xfffflu)
+       {
+               scan->blob=segm;
+
+               //MML_UseSpace(segstart, seglength, gvar);
+
+               printf("MML_UseSpace: Segment spans two blocks!\n");
+       //}
+       printf("segm=%u         ", segm);
+       printf("ex=%lu  ", extra);
+       printf("old=%u  ", oldend);
+       printf("start+seglen=%lu\n", segstart+seglength);
+       printf("segsta=%x       ", segstart);
+       printf("len=%lu ", scan->length);
+       printf("seglen=%lu      ", seglength);
+       printf("segmlen=%lu\n", segmlen);
+       }
+//++++todo: linked list of segment!
+       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;
+               gvar->mm.mmnew->useptr = NULL;
+
+               gvar->mm.mmnew->next = scan->next;
+               scan->next = gvar->mm.mmnew;
+               gvar->mm.mmnew->start = segstart+seglength;
+               gvar->mm.mmnew->length = extra;
+               gvar->mm.mmnew->attributes = LOCKBIT;
+       }//else if(segm>0) goto segu;
+
+}*/
+void MML_UseSpace(word segstart, dword seglength, global_game_variables_t *gvar)
+{
+       mmblocktype far *scan,far *last;
+       word    oldend;
+       sdword          extra;
+       //word segm=1;
+
+       scan = last = gvar->mm.mmhead;
+       gvar->mm.mmrover = gvar->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!
+//
+       /*for(;seglength>=0x10000;seglength-=0xFFFF)
+       {
+               //printf("      seglen=%lu\n", segmlen);
+               segm++;
+       }*/
+
+//
+// take the given range out of the block
+//
+       oldend = scan->start + scan->length;
+       extra = oldend - (segstart+((unsigned)seglength));
+       if (extra < 0)
+       {
+               printf("========================================\n");
+               printf("start=%x        ", scan->start);
+               printf("old=%u  ", oldend);
+               printf("start+seglen=%lu\n", segstart+seglength);
+               printf("segsta=%x       ", segstart);
+               printf("len=%lu ", scan->length);
+               printf("seglen=%lu      ", seglength);
+               printf("\n");
+               printf("MML_UseSpace: Segment spans two blocks! %d\n", extra);
+               printf("========================================\n");
+               //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;
+               gvar->mm.mmnew->useptr = NULL;
+
+               gvar->mm.mmnew->next = scan->next;
+               scan->next = gvar->mm.mmnew;
+               gvar->mm.mmnew->start = segstart+seglength;
+               gvar->mm.mmnew->length = extra;
+               gvar->mm.mmnew->attributes = LOCKBIT;
+       }
+
+}
+
+//==========================================================================
+
+/*
+====================
+=
+= MML_ClearBlock
+=
+= We are out of blocks, so free a purgable block
+=
+====================
+*/
+
+void MML_ClearBlock(global_game_variables_t *gvar)
+{
+       //huge mmblocktype huge *scan,huge *last;
+       mmblocktype far *scan,far *last;
+
+       scan = gvar->mm.mmhead->next;
+
+       while(scan)
+       {
+               if(!(scan->attributes&LOCKBIT) && (scan->attributes&PURGEBITS))
+               {
+                       MM_FreePtr(scan->useptr, gvar);
+                       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(global_game_variables_t *gvar)
+{
+       int i;
+       //dword length,seglength;
+       dword length; word seglength;
+       //huge void huge        *start;
+       void far        *start;
+       word    segstart;//,endfree;
+       //memptr *peeonself;
+
+       if(gvar->mm.mmstarted)
+               MM_Shutdown(gvar);
+
+       gvar->mm.mmstarted = true;
+       gvar->mm.bombonerror = true;
+
+//
+// set up the linked list (everything in the free list;
+//
+       gvar->mm.mmhead = NULL;
+       gvar->mm.mmfree = &(gvar->mm.mmblocks[0]);
+       for(i=0;i<MAXBLOCKS-1;i++)
+       {
+               gvar->mm.mmblocks[i].next = &(gvar->mm.mmblocks[i+1]);
+       }
+       gvar->mm.mmblocks[i].next = NULL;
+
+//
+// locked block of all memory until we punch out free space
+//
+       GETNEWBLOCK;
+       gvar->mm.mmhead = gvar->mm.mmnew;                               // this will allways be the first node
+       gvar->mm.mmnew->start = 0;
+       gvar->mm.mmnew->length = 0xffff;
+       gvar->mm.mmnew->attributes = LOCKBIT;
+       gvar->mm.mmnew->next = NULL;
+       //gvar->mm.mmnew->useptr = peeonself;
+       gvar->mm.mmrover = gvar->mm.mmhead;
+
+       //printf("              %x\n", peeonself);
+       //printf("              %x\n", *peeonself);
+//
+// get all available near conventional memory segments
+//
+#ifdef __WATCOMC__
+       _nheapgrow();
+       length=(dword)_memavl();//(dword)GetFreeSize();
+       //huge start = (void huge *)(gvar->mm.nearheap = _nmalloc(length));
+       start = (void far *)(gvar->mm.nearheap = _nmalloc(length));
+#endif
+#ifdef __BORLANDC__
+       length=coreleft();
+       //huge start = (void huge *)(gvar->mm.nearheap = malloc(length));
+       start = (void far *)(gvar->mm.nearheap = malloc(length));
+#endif
+       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, gvar);
+       gvar->mmi.nearheap = length;
+       //printf("start=%Fp     segstart=%x     seglen=%lu      len=%lu\n", start, segstart, seglength, length);
+
+//
+// get all available far conventional memory segments
+//
+       //printf("_FARCORELEFT                          %lu\n", _FCORELEFT);
+#ifdef __WATCOMC__
+       _fheapgrow();
+#endif
+#ifdef __BORLANDC__
+       printf("farcoreleft()                           %lu\n", farcoreleft());
+       printf("(farcoreleft()+32)-_FCORELEFT   %d\n", (sword)((farcoreleft()+32)-_FCORELEFT));
+#endif
+       length=_FCORELEFT;//_fcoreleft();//(dword)GetFarFreeSize();//0xffffUL*4UL;
+       start = gvar->mm.farheap = _fmalloc(length);
+       //start = gvar->mm.farheap = halloc(length, 1);
+       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, gvar);
+       gvar->mmi.farheap = length;
+       //printf("start=%Fp     segstart=%x     seglen=%lu      len=%lu\n", start, segstart, seglength, length);
+
+       gvar->mmi.mainmem = gvar->mmi.nearheap + gvar->mmi.farheap;
+
+//
+// detect EMS and allocate up to 64K at page frame
+//
+       gvar->mmi.EMSmem = 0;
+//goto emsskip;        //0000
+       for(i = 1;i <
+#ifdef __WATCOMC__
+       __argc
+#endif
+#ifdef __BORLANDC__
+       _argc
+#endif
+       ;i++)
+       {
+               if(US_CheckParm(
+#ifdef __WATCOMC__
+       __argv[i]
+#endif
+#ifdef __BORLANDC__
+       _argv[i]
+#endif
+                       ,ParmStringsexmm) == 0)
+                       goto emsskip;                           // param NOEMS
+       }
+       if(MML_CheckForEMS())
+       {
+               MML_SetupEMS(gvar);                                     // allocate space
+               //TODO: EMS4! AND EMS 3.2 MASSIVE DATA HANDLMENT!
+               MML_UseSpace(gvar->mm.EMSpageframe,(MAPPAGES)*0x4000lu, gvar);
+               //if(gvar->pm.emm.EMSVer<0x40)
+                       MM_MapEMS(gvar);                                        // map in used pages
+               //else
+                       //MM_MapXEMS(gvar);                                     // map in used pages
+       }
+
+//
+// detect XMS and get upper memory blocks
+//
+emsskip:
+       gvar->mmi.XMSmem = 0;
+goto xmsskip;//0000
+       for(i = 1;i <
+#ifdef __WATCOMC__
+       __argc
+#endif
+#ifdef __BORLANDC__
+       _argc
+#endif
+       ;i++)
+       {
+               if(US_CheckParm(
+#ifdef __WATCOMC__
+       __argv[i]
+#endif
+#ifdef __BORLANDC__
+       _argv[i]
+#endif
+                       ,ParmStringsexmm) == 0)
+                       goto xmsskip;                           // param NOXMS
+       }
+       if(MML_CheckForXMS(gvar))
+       {
+               MML_SetupXMS(gvar);                                     // allocate as many UMBs as possible
+       }
+
+//
+// allocate the misc buffer
+//
+xmsskip:
+       gvar->mm.mmrover = gvar->mm.mmhead;             // start looking for space after low block
+
+       MM_GetPtr(&(gvar->mm.bufferseg),BUFFERSIZE, gvar);
+}
+
+//==========================================================================
+
+/*
+====================
+=
+= MM_Shutdown
+=
+= Frees all conventional, EMS, and XMS allocated
+=
+====================
+*/
+
+void MM_Shutdown(global_game_variables_t *gvar)
+{
+       if(!(gvar->mm.mmstarted))
+               return;
+
+       _ffree(gvar->mm.farheap);//     printf("                far freed\n");
+#ifdef __WATCOMC__
+       _nfree(gvar->mm.nearheap);//    printf("                near freed\n");
+#endif
+#ifdef __BORLANDC__
+       free(gvar->mm.nearheap);//      printf("                near freed\n");
+#endif
+       if(MML_CheckForEMS()){ MML_ShutdownEMS(gvar); }//printf("               EMS freed\n"); }
+       if(MML_CheckForXMS(gvar)){ MML_ShutdownXMS(gvar); }//printf("           XMS freed\n"); }
+}
+
+//==========================================================================
+
+/*
+====================
+=
+= MM_GetPtr
+=
+= Allocates an unlocked, unpurgable block
+=
+====================
+*/
+
+void MM_GetPtr (memptr *baseptr, dword size, global_game_variables_t *gvar)
+{
+       //huge mmblocktype huge *scan,huge *lastscan,huge *endscan,huge *purge,huge *next;
+       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
+       gvar->mm.mmnew->length = needed;
+       gvar->mm.mmnew->useptr = baseptr;
+       //if(gvar->mm.mmnew->useptr==NULL){
+#ifdef __DEBUG__
+               printf("baseptr=%04x    ", baseptr); printf("useptr=%04x\n", gvar->mm.mmnew->useptr);
+               printf("*baseptr=%04x   ", *baseptr); printf("*useptr=%04x\n", *(gvar->mm.mmnew->useptr));
+               printf("*baseptr=%Fp    ", *baseptr); printf("*useptr=%Fp\n", *(gvar->mm.mmnew->useptr));
+#endif
+       //exit(-5); }
+       gvar->mm.mmnew->attributes = BASEATTRIBUTES;
+
+//tryagain:
+       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 && gvar->mm.mmrover == gvar->mm.mmhead)
+                       search++;
+
+               switch (search)
+               {
+               case 0:
+                       lastscan = gvar->mm.mmrover;
+                       scan = gvar->mm.mmrover->next;
+                       endscan = NULL;
+                       break;
+               case 1:
+                       lastscan = gvar->mm.mmhead;
+                       scan = gvar->mm.mmhead->next;
+                       endscan = gvar->mm.mmrover;
+                       break;
+               case 2:
+                       MM_SortMem (gvar);
+                       lastscan = gvar->mm.mmhead;
+                       scan = gvar->mm.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 = gvar->mm.mmnew;
+                               gvar->mm.mmnew->start = *(unsigned *)baseptr = startseg;
+                               gvar->mm.mmnew->next = scan;
+                               while ( purge != scan)
+                               {       // free the purgable block
+                                       next = purge->next;
+                                       FREEBLOCK(purge);
+                                       purge = next;           // purge another if not at scan
+                               }
+                               gvar->mm.mmrover = gvar->mm.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 (gvar->mm.bombonerror)
+       {
+#ifdef __WATCOMC__
+               //heapdump();
+#endif
+               printf(OUT_OF_MEM_MSG,(size-gvar->mmi.nearheap));
+               printf("for stability reasons the program will shut down! wwww\n");
+               MM_Shutdown(gvar);
+               exit(-1);
+       }
+       else
+               gvar->mm.mmerror = true;
+}
+
+//==========================================================================
+
+/*
+====================
+=
+= MM_FreePtr
+=
+= Allocates an unlocked, unpurgable block
+=
+====================
+*/
+
+void MM_FreePtr(memptr *baseptr, global_game_variables_t *gvar)
+{
+       //huge mmblocktype huge *scan,huge *last;
+       mmblocktype far *scan,far *last;
+
+       last = gvar->mm.mmhead;
+       scan = last->next;
+
+       if(baseptr == gvar->mm.mmrover->useptr) // removed the last allocated block
+               gvar->mm.mmrover = gvar->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;
+
+       FREEBLOCK(scan);
+}
+//==========================================================================
+
+/*
+=====================
+=
+= MM_SetPurge
+=
+= Sets the purge level for a block (locked blocks cannot be made purgable)
+=
+=====================
+*/
+
+void MM_SetPurge(memptr *baseptr, int purge, global_game_variables_t *gvar)
+{
+       //huge mmblocktype huge *start;
+       mmblocktype far *start;
+
+       start = gvar->mm.mmrover;
+
+       do
+       {
+               if(gvar->mm.mmrover->useptr == baseptr)
+                       break;
+
+               gvar->mm.mmrover = gvar->mm.mmrover->next;
+
+               if(!gvar->mm.mmrover)
+                       gvar->mm.mmrover = gvar->mm.mmhead;
+               else if(gvar->mm.mmrover == start)
+               {
+                       Quit("MM_SetPurge: Block not found!");
+                       //return;
+               }
+
+       } while(1);
+
+       gvar->mm.mmrover->attributes &= ~PURGEBITS;
+       gvar->mm.mmrover->attributes |= purge;
+}
+
+//==========================================================================
+
+/*
+=====================
+=
+= MM_SetLock
+=
+= Locks / unlocks the block
+=
+=====================
+*/
+
+void MM_SetLock(memptr *baseptr, boolean locked, global_game_variables_t *gvar)
+{
+       //huge mmblocktype huge *start;
+       mmblocktype far *start;
+
+       start = gvar->mm.mmrover;
+
+       do
+       {
+               if(gvar->mm.mmrover->useptr == baseptr)
+                       break;
+
+               gvar->mm.mmrover = gvar->mm.mmrover->next;
+
+               if(!gvar->mm.mmrover)
+                       gvar->mm.mmrover = gvar->mm.mmhead;
+               else if(gvar->mm.mmrover == start)
+               {
+                       Quit("MM_SetLock: Block not found!");
+                       //return;
+               }
+
+       } while(1);
+
+       gvar->mm.mmrover->attributes &= ~LOCKBIT;
+       gvar->mm.mmrover->attributes |= locked*LOCKBIT;
+}
+
+//==========================================================================
+
+/*
+=====================
+=
+= MM_SortMem
+=
+= Throws out all purgable stuff and compresses movable blocks
+=
+=====================
+*/
+
+void MM_SortMem(global_game_variables_t *gvar)
+{
+       //huge mmblocktype huge *scan,huge *last,huge *next;
+       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 = gvar->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;
+                               FREEBLOCK(scan);
+                               //MM_FreeBlock(scan, gvar);
+                               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
+       }
+
+       gvar->mm.mmrover = gvar->mm.mmhead;
+
+       if(aftersort)
+               aftersort();
+
+//     VW_ColorBorder (oldborder);
+
+/*++++ if(playing)
+               MM_SetLock(&(memptr)audiosegs[playing],false);*/
+}
+
+//==========================================================================
+
+/*
+=====================
+=
+= MM_ShowMemory
+=
+=====================
+*/
+
+void MM_ShowMemory(global_game_variables_t *gvar)
+{
+       //huge mmblocktype huge *scan;
+       mmblocktype far *scan;
+       word temp;
+       sdword  end,owner;
+       //word chx,chy;
+       word w;
+       //dword wwww;
+       byte    scratch[160],scratch0[4096],scratch1[160],str[16];
+       //byte d = '#';
+//**** VW_SetDefaultColors();
+//**** VW_SetLineWidth(40);
+//++++mh       temp = bufferofs;
+//++++mh       bufferofs = 0;
+//**** VW_SetScreen (0,0);
+       scan = gvar->mm.mmhead;
+       end = -1;
+
+       CA_OpenDebug (gvar);
+       w=0;
+       while(scan)
+       {
+               strcpy(scratch, AARESET);
+               if(scan->attributes & PURGEBITS)
+                       strcpy(scratch0, AAMAGENTA);            // dark purple = purgable
+               else
+                       strcpy(scratch0, AABLUE);               // medium blue = non purgable
+               if(scan->attributes & LOCKBIT)
+                       strcpy(scratch0, AARED);                // red = locked
+               if(scan->start<=end)
+               {
+                       printf("\nend==%d\n\n", end);
+                       strcat(scratch, "MM_ShowMemory: Memory block order currupted!\n");
+                       strcat(scratch, "End's Size: ");
+                       ultoa (end,str,10);
+                       strcat (scratch,str);
+                       strcat(scratch, "\nscan->start's Size: ");
+                       ultoa (scan->start,str,10);
+                       strcat (scratch,str);
+                       write(gvar->handle.debughandle,scratch,strlen(scratch));
+                       //modexprint(&page, chx, chy, 1, 0, 24, "\nMM_ShowMemory: Memory block order currupted!\n");
+                       break;
+               }
+               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);
+               for(w=(scan->start)/80;w<=end/80;w++)
+               {
+                       //printf("+     %u      %lu\n", w, scan->length);
+                       strcat(scratch0, "+");
+               }
+               //++==++==optional strcat(scratch0, AARESET); strcat(scratch0, AAGREY); strcat(scratch0,"_");
+//++++         VW_Plot(scan->start,0,15);
+//++++                         modexClearRegion(page, chx, chy, 4, 4, 15);
+//++++                 VW_Hlin(end+1,scan->next->start,0,0);   // black = free
+
+               //wwww=(dword)(scan->next->start)-(dword)scan->start;
+               //wwww=(dword)scan->start+(dword)(scan->next->start);
+               if (scan->next && scan->next->start >= end+1)
+               {
+                       strcat(scratch0, AARESET);
+                       //++==++==optional strcat(scratch0, "\n");
+                       strcat(scratch0,AAGREEN);
+                       for(w=(end+1)/80;w<=((scan->next->start-scan->start)/80);w++)
+                       //for(w=(wwww)/80;w<=((end+1)/80);w++)
+                       //for(w=(end+1)/80;w<=((wwww)/80);w++)
+                       {
+                               //printf("0     %x      %u      %lu\n", scan->next->start, w, scan->length);
+                               strcat(scratch0,"0");
+                       }
+                       //printf("==================\n");
+                       //printf("w=%u  wwww=%lu        start=%04x      next=%04x       end=%lu\n", w/80, wwww/80, scan->start, (scan->next->start), end+1);
+                       //printf("==================\n");
+                       strcat(scratch0, "\n");
+                       //getch();
+               }/*else {//if(scan->next->start <= scan->start){
+                       scan->next->start=scan->start+0x1000;
+                       wwww=(dword)(scan->next->start)-(dword)scan->start;
+                       strcat(scratch0, AARESET);
+                       strcat(scratch0, "\n");
+                       strcat(scratch0,AAGREEN);
+                       for(w=(end+1);w<=(0x1000/80);w++)
+                       {
+                               //printf("0     %x      %x      %u\n", scan->start, w);
+                               strcat(scratch0,"0");
+                       }
+                       printf("================\n");
+                       printf("w=%x    start=%x        next=%x end=%u  %lu\n", w, scan->start, (scan->next->start), end+1, wwww);
+                       printf("================\n");
+                       getch();
+               }*/
+               strcat(scratch0, AARESET);
+               //strcat(scratch0,"\n");
+                       //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);
+/*             y = scan->start/320;
+               x = scan->start%320;
+               VW_Hlin(x,x+end,y,color);
+               VW_Plot(x,y,15);*/
+//++++                 VW_Hlin(x+end+1,x+(scan->next->start-scan->start),y,0); // black = free
+               strcat(scratch,"Seg:");
+               ultoa (scan->start,str,16);
+               strcat (scratch,str);
+               strcat (scratch,"\tSize:");
+               ultoa ((unsigned)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(gvar->handle.debughandle,scratch,strlen(scratch));
+               write(gvar->handle.debughandle,scratch0,strlen(scratch0));
+//modexprint(page, chx, chy, 1, 0, 24, &scratch);
+//++++chy+=4;
+//fprintf(stdout, "%s", scratch);
+
+               scan = scan->next;
+       }
+       /*strcpy(scratch1, AARESET);
+       strcat(scratch1, "========================================\n");
+       strcat(scratch1, "near=  ");
+       ultoa (*(gvar->mm.nearheap),str,10);
+       strcat (scratch1,str);
+       strcat(scratch1, "      far= ");
+       ultoa (*(gvar->mm.farheap),str,10);
+       strcat (scratch1,str);
+       strcat(scratch1, "\n");
+       //strcat(scratch1, "&near=      %Fp ", &(gvar->mm.nearheap));
+       //strcat(scratch1, "&far=       %Fp", &(gvar->mm.farheap));
+       //strcat(scratch1, "\n");
+       strcat(scratch1, "========================================\n");
+       write(gvar->handle.debughandle,scratch1,strlen(scratch1));*/
+
+
+       CA_CloseDebug (gvar);
+
+//++++mh       IN_Ack();
+//**** VW_SetLineWidth(64);
+//++++mh       bufferofs = temp;
+}
+
+//==========================================================================
+
+/*
+=====================
+=
+= MM_DumpData
+=
+=====================
+*/
+
+void MM_DumpData(global_game_variables_t *gvar)
+{
+       //huge mmblocktype huge *scan,huge *best;
+       mmblocktype far *scan,far *best;
+       long    lowest,oldlowest;
+       word    owner;
+       byte    lock,purge;
+       FILE    *dumpfile;
+
+       free(gvar->mm.nearheap);
+#ifdef __BORLANDC__
+               dumpfile = fopen ("mmdump.16b","w");
+#endif
+#ifdef __WATCOMC__
+               dumpfile = fopen ("mmdump.16w","w");
+#endif
+       if (!dumpfile){
+               printf("MM_DumpData: Couldn't open MMDUMP.16!\n");
+               return;
+       }
+
+       lowest = -1;
+       do
+       {
+               oldlowest = lowest;
+               lowest = 0xffff;
+
+               scan = gvar->mm.mmhead;
+               while (scan)
+               {
+                       owner = (unsigned)scan->useptr;
+
+                       if (owner && owner<lowest && 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"
+                       ,(unsigned)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(global_game_variables_t *gvar)
+{
+       dword free;
+       //huge mmblocktype huge *scan;
+       mmblocktype far *scan;
+
+       free = 0;
+       scan = gvar->mm.mmhead;
+
+       while(scan->next)
+       {
+               free += scan->next->start - (scan->start + scan->length);
+               scan = scan->next;
+       }
+
+       return free*16lu;
+//     return free;
+}
+
+//==========================================================================
+
+
+/*
+======================
+=
+= MM_TotalFree
+=
+= Returns the total free space with purging
+=
+======================
+*/
+
+dword MM_TotalFree(global_game_variables_t *gvar)
+{
+       dword free;
+       //huge mmblocktype huge *scan;
+       mmblocktype far *scan;
+
+       free = 0;
+       scan = gvar->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*16lu;
+//     return free;
+}
+
+//==========================================================================
+
+/*
+=====================
+=
+= MM_Report
+=
+=====================
+*/
+
+void MM_Report_(global_game_variables_t *gvar)
+{
+       printf("========================================\n");
+       printf("                MM_Report\n");
+       printf("========================================\n");
+       if(MML_CheckForEMS())
+       {
+               printf("        LIMEMS\n");
+               printf("                EMM v%x.%x available\n", gvar->mm.EMSVer>>4,gvar->mm.EMSVer&0x0F);
+               printf("                totalEMSpages:  %u      ", gvar->mm.totalEMSpages); printf("freeEMSpages:       %u\n", gvar->mm.freeEMSpages);
+               printf("                EMSpageframe:   %x\n", gvar->mm.EMSpageframe);
+       }
+       if(MML_CheckForXMS(gvar))
+       {
+               printf("        XMS\n");
+               printf("                XMSaddr:        %X\n", *XMSaddr);
+       }
+       printf("near:   %lu     ", gvar->mmi.nearheap); printf("far:    %lu\n", gvar->mmi.farheap); if(MML_CheckForEMS())
+       printf("EMSmem: %lu     ", gvar->mmi.EMSmem); if(MML_CheckForXMS(gvar)) printf("XMSmem: %lu", gvar->mmi.XMSmem); printf("\n");
+       //printf("mainmem:      %lu\n", gvar->mmi.mainmem);
+       printf("Total convmem:  %lu     ", gvar->mmi.mainmem); printf("TotalFree:       %lu     ", MM_TotalFree(gvar)); printf("TotalUsed:      %lu\n", gvar->mmi.mainmem+gvar->mmi.EMSmem+gvar->mmi.XMSmem+gvar->mmi.XMSmem);
+       printf("                        UnusedMemory:   %lu\n", MM_UnusedMemory(gvar));
+}
+
+//==========================================================================
+
+/*
+=====================
+=
+= 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, global_game_variables_t *gvar)
+{
+       gvar->mm.bombonerror = bomb;
+}
+
+/*void MM_GetNewBlock(global_game_variables_t *gvar)
+{
+       if(!gvar->mm.mmfree)
+               MML_ClearBlock(gvar);
+       gvar->mm.mmnew=gvar->mm.mmfree;
+       gvar->mm.mmfree=gvar->mm.mmfree->next;
+       if(!(gvar->mm.mmnew=gvar->mm.mmfree))
+       {
+               printf("MM_GETNEWBLOCK: No free blocks!\n");
+               return;
+       }
+       gvar->mm.mmfree=gvar->mm.mmfree->next;
+}
+
+void MM_FreeBlock(mmblocktype *x, global_game_variables_t *gvar)
+{
+       x->useptr=NULL;
+       x->next=gvar->mm.mmfree;
+       gvar->mm.mmfree=x;
+}*/
+
+/*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
+*/
index d351abf..1a448a2 100755 (executable)
@@ -66,7 +66,9 @@
 //--------\r
 \r
 #define        XMS_INT                 0x2f\r
-#define        XMSD                    dword XMSDriver=gvar->pm.xmm.XMSDriver;\r
+#define        XMS_CALL(v)             _AH = (v);\\r
+                                               __asm call [WORD PTR XMSDriver]\r
+/*__asm { //mov (v),ah*/\r
 \r
 #define        XMS_VERSION             0x00\r
 \r
@@ -205,7 +207,6 @@ void MM_Report_(global_game_variables_t *gvar);
 void MM_BombOnError(boolean bomb, global_game_variables_t *gvar);\r
 //void MM_GetNewBlock(mminfo_t *mm);\r
 //void MM_FreeBlock(mmblocktype *x, mminfo_t *mm);\r
-void   XMS_CALL(byte v, global_game_variables_t *gvar);\r
 \r
 //==========================================================================\r
 \r
index 139b72c..e699fcb 100755 (executable)
@@ -44,9 +44,9 @@
 \r
 //     XMS specific variables\r
        boolean                 gvar->pm.xmm.XMSPresent;\r
-       word                    gvar->pm.xmm.XMSAvail,gvar->pm.xmm.XMSPagesAvail,gvar->pm.xmm.XMSHandle;\r
-       dword           XMSDriver;\r
-       int                             gvar->pm.xmm.XMSProtectPage = -1;\r
+       word                    gvar->pm.xmm.XMSAvail,gvar->pm.xmm.XMSPagesAvail,gvar->pm.xmm.XMSHandle;*/\r
+       word            XMSDriver;\r
+/*     int                             gvar->pm.xmm.XMSProtectPage = -1;\r
 \r
 //     File specific variables\r
        char                    gvar->pm.fi.PageFileName[13] = {"VSWAP."};\r
@@ -293,7 +293,7 @@ PML_ShutdownEMS(global_game_variables_t *gvar)
 boolean\r
 PML_StartupXMS(global_game_variables_t *gvar)\r
 {\r
-       XMSD;\r
+       //XMSD;\r
        gvar->pm.xmm.XMSPresent = false;                                        // Assume failure\r
        gvar->pm.xmm.XMSAvail = 0;\r
 \r
@@ -310,7 +310,7 @@ PML_StartupXMS(global_game_variables_t *gvar)
                mov     [WORD PTR XMSDriver+2],es               // function pointer to XMS driver\r
        }\r
 \r
-       XMS_CALL(XMS_QUERYFREE, gvar);                  // Find out how much XMS is available\r
+       XMS_CALL(XMS_QUERYFREE);                        // Find out how much XMS is available\r
        gvar->pm.xmm.XMSAvail = _AX;\r
        if (!_AX)                               // AJR: bugfix 10/8/92\r
                goto error;\r
@@ -320,7 +320,7 @@ PML_StartupXMS(global_game_variables_t *gvar)
                goto error;\r
 \r
        _DX = gvar->pm.xmm.XMSAvail;\r
-       XMS_CALL(XMS_ALLOC, gvar);                              // And do the allocation\r
+       XMS_CALL(XMS_ALLOC);                            // And do the allocation\r
        gvar->pm.xmm.XMSHandle = _DX;\r
 \r
        if (!_AX)                               // AJR: bugfix 10/8/92\r
@@ -344,7 +344,7 @@ void
 PML_XMSCopy(boolean toxms,byte far *addr,word xmspage,word length, global_game_variables_t *gvar)\r
 {\r
 #ifdef __WATCOMC__\r
-       XMSD;\r
+       //XMSD;\r
 #endif\r
        dword   xoffset;\r
        struct\r
@@ -374,7 +374,7 @@ PML_XMSCopy(boolean toxms,byte far *addr,word xmspage,word length, global_game_v
                push si\r
        }\r
        _SI = (word)&copy;\r
-       XMS_CALL(XMS_MOVE, gvar);\r
+       XMS_CALL(XMS_MOVE);\r
        __asm {\r
                pop     si\r
        }\r
@@ -416,11 +416,11 @@ PML_CopyFromXMS(byte far *target,int sourcepage,word length, global_game_variabl
 void\r
 PML_ShutdownXMS(global_game_variables_t *gvar)\r
 {\r
-       XMSD;\r
+       //XMSD;\r
        if (gvar->pm.xmm.XMSPresent)\r
        {\r
                _DX = gvar->pm.xmm.XMSHandle;\r
-               XMS_CALL(XMS_FREE, gvar);\r
+               XMS_CALL(XMS_FREE);\r
                if (_BL)\r
                {\r
                        Quit("PML_ShutdownXMS: Error freeing XMS");\r
@@ -1277,6 +1277,9 @@ PM_Reset(global_game_variables_t *gvar)
 \r
        gvar->pm.PMPanicMode = false;\r
 \r
+       gvar->pm.fi.PageFile = -1;\r
+       gvar->pm.xmm.XMSProtectPage = -1;\r
+\r
        // Initialize page list\r
        for (i = 0,page = gvar->pm.PMPages;i < gvar->pm.PMNumBlocks;i++,page++)\r
        {\r
@@ -1300,8 +1303,6 @@ PM_Startup(global_game_variables_t *gvar)
                return;\r
 \r
        strcat(&(gvar->pm.fi.PageFileName), "VSWAP.");\r
-       gvar->pm.fi.PageFile = -1;\r
-       gvar->pm.xmm.XMSProtectPage = -1;\r
 \r
        nomain = noems = noxms = false;\r
        for (i = 1;i <\r
index 85135d9..b9d801e 100755 (executable)
@@ -110,5 +110,5 @@ extern      void    PM_Startup(global_game_variables_t *gvar),
 extern memptr  PM_GetPageAddress(int pagenum, global_game_variables_t *gvar),\r
                                PM_GetPage(int pagenum, global_game_variables_t *gvar);         // Use this one to cache page\r
 \r
-void PM_SetMainMemPurge(int level, global_game_variables_t *gvar);\r
+//void PM_SetMainMemPurge(int level, global_game_variables_t *gvar);\r
 #endif\r
diff --git a/src/lib/length b/src/lib/length
new file mode 100755 (executable)
index 0000000..ff49ecd
--- /dev/null
@@ -0,0 +1,4 @@
+             total       used       free     shared    buffers     cached
+Mem:       7879884    7039184     840700     199796     367668    4095452
+-/+ buffers/cache:    2576064    5303820
+Swap:      2097148          0    2097148
diff --git a/src/lib/next b/src/lib/next
new file mode 100755 (executable)
index 0000000..e69de29
index 4d031f9..d069b92 100755 (executable)
@@ -171,6 +171,7 @@ typedef struct
 #endif\r
        //byte          EMS_status;\r
        word numUMBs,UMBbase[MAXUMBS];\r
+       word                    totalEMSpages, freeEMSpages, EMSpagesmapped, EMShandle, EMSpageframe,EMSVer;\r
        //dword numUMBs,UMBbase[MAXUMBS];\r
        //huge mmblocktype      huge mmblocks[MAXBLOCKS],huge *mmhead,huge *mmfree,huge *mmrover,huge *mmnew;\r
        mmblocktype     far mmblocks[MAXBLOCKS],far *mmhead,far *mmfree,far *mmrover,far *mmnew;\r