]> 4ch.mooo.com Git - 16.git/blobdiff - src/lib/16_mm.c
16_ca needs huge amounts of work and I should remember what needs to be done soon...
[16.git] / src / lib / 16_mm.c
index 5f5b6444a7cb70190cf9c367f4ee59c6fa7bd8f5..18c02bbb7da332a4260ca928391fd4d0cad08888 100755 (executable)
@@ -1,19 +1,23 @@
-/* Catacomb Apocalypse Source Code\r
- * Copyright (C) 1993-2014 Flat Rock Software\r
+/* Project 16 Source Code~\r
+ * Copyright (C) 2012-2017 sparky4 & pngwen & andrius4669 & joncampbell123 & yakui-lover\r
  *\r
- * This program is free software; you can redistribute it and/or modify\r
+ * This file is part of Project 16.\r
+ *\r
+ * Project 16 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
+ * the Free Software Foundation; either version 3 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
+ * Project 16 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
+ * You should have received a copy of the GNU General Public License\r
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>, or\r
+ * write to the Free Software Foundation, Inc., 51 Franklin Street,\r
+ * Fifth Floor, Boston, MA 02110-1301 USA.\r
+ *\r
  */\r
 \r
 // NEWMM.C\r
@@ -28,7 +32,7 @@ Primary coder: John Carmack
 \r
 RELIES ON\r
 ---------\r
-Quit (char *error) function\r
+Quit (global_game_variables_t *gvar, char *error) function\r
 \r
 \r
 WORK TO DO\r
@@ -48,11 +52,43 @@ Open Watcom port by sparky4
 */\r
 #include "src/lib/16_mm.h"\r
 #include "src/lib/16_ca.h"\r
+#include <malloc.h>\r
 #pragma hdrstop\r
 \r
 #pragma warn -pro\r
 #pragma warn -use\r
 \r
+/*\r
+=============================================================================\r
+\r
+                                                       LOCAL INFO\r
+\r
+=============================================================================\r
+*/\r
+\r
+#define LOCKBIT                0x80    // if set in attributes, block cannot be moved\r
+#define PURGEBITS      3               // 0-3 level, 0= unpurgable, 3= purge first\r
+#define PURGEMASK      0xfffc\r
+#define BASEATTRIBUTES 0       // unlocked, non purgable\r
+\r
+//#define MAXUMBS              10\r
+\r
+/*typedef struct mmblockstruct\r
+{\r
+       unsigned        start,length;\r
+       unsigned        attributes;\r
+       memptr          *useptr;        // pointer to the segment start\r
+       struct mmblockstruct far *next;\r
+} mmblocktype;*/\r
+\r
+\r
+//#define GETNEWBLOCK {if(!(mmnew=mmfree))Quit("MM_GETNEWBLOCK: No free blocks!") ;mmfree=mmfree->next;}\r
+//\r
+\r
+#define GETNEWBLOCK {if(!gvar->mm.mmfree)MML_ClearBlock(gvar);gvar->mm.mmnew=gvar->mm.mmfree;gvar->mm.mmfree=gvar->mm.mmfree->next;}\r
+\r
+#define FREEBLOCK(x) {*x->useptr=NULL;x->next=gvar->mm.mmfree;gvar->mm.mmfree=x;}\r
+\r
 /*\r
 =============================================================================\r
 \r
@@ -61,9 +97,12 @@ Open Watcom port by sparky4
 =============================================================================\r
 */\r
 \r
+/*mminfotype   mminfo;\r
+memptr         bufferseg;\r
+boolean                mmerror;*/\r
+\r
 void           (* beforesort) (void);\r
 void           (* aftersort) (void);\r
-void           (* XMSaddr) (void);             // far pointer to XMS driver\r
 \r
 /*\r
 =============================================================================\r
@@ -73,6 +112,42 @@ void                (* XMSaddr) (void);             // far pointer to XMS driver
 =============================================================================\r
 */\r
 \r
+/*boolean              mmstarted;\r
+\r
+void far       *farheap;\r
+void           *nearheap;\r
+\r
+mmblocktype    far mmblocks[MAXBLOCKS]\r
+                       ,far *mmhead,far *mmfree,far *mmrover,far *mmnew;\r
+\r
+boolean                bombonerror;*/\r
+\r
+//unsigned     totalEMSpages,freeEMSpages,EMSpageframe,EMSpagesmapped,EMShandle;\r
+\r
+void           (* XMSaddr) (void);             // far pointer to XMS driver\r
+\r
+/*unsigned     numUMBs,UMBbase[MAXUMBS];*/\r
+\r
+//==========================================================================\r
+\r
+//\r
+// local prototypes\r
+//\r
+\r
+boolean                MML_CheckForEMS (void);\r
+void           MML_ShutdownEMS (void);\r
+void           MM_MapEMS (void);\r
+boolean        MML_CheckForXMS (void);\r
+void           MML_ShutdownXMS (void);\r
+//void         MML_UseSpace (unsigned segstart, unsigned seglength);\r
+//void                 MML_ClearBlock (void);\r
+\r
+//==========================================================================\r
+#ifndef __16_PM__\r
+#if 0\r
+static char *ParmStringsexmm[] = {"noems","noxms",""};\r
+#endif\r
+#endif\r
 /*\r
 ======================\r
 =\r
@@ -85,18 +160,20 @@ void               (* XMSaddr) (void);             // far pointer to XMS driver
 \r
 boolean MML_CheckForEMS(void)\r
 {\r
-       boolean emmcfems;\r
+       boolean emmcfems = false;\r
+       word            EMSPageFrame = 0;\r
+       byte    err=0, str[64];\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
+               int     EMM_INT         // 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
+               int     EMM_INT         // get device info\r
                jc      error\r
 \r
                and     dx,0x80\r
@@ -104,19 +181,29 @@ boolean MML_CheckForEMS(void)
 \r
                mov     ax,0x4407\r
 \r
-               int     0x21            // get status\r
+               int     EMM_INT         // get status\r
                jc      error\r
                or      al,al\r
                jz      error\r
 \r
                mov     ah,0x3e\r
-               int     0x21            // close handle\r
+               int     EMM_INT         // close handle\r
                jc      error\r
+\r
+               //\r
+               // pageframe check\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
                //\r
                // EMS is good\r
                //\r
-               mov     emmcfems,1\r
-               jmp End\r
+               mov     emmcfems,1\r
+               jmp     End\r
 #ifdef __BORLANDC__\r
        }\r
 #endif\r
@@ -127,7 +214,8 @@ boolean MML_CheckForEMS(void)
                //\r
                // EMS is bad\r
                //\r
-               mov     emmcfems,0\r
+               mov     err,ah\r
+               mov     emmcfems,0\r
 #ifdef __BORLANDC__\r
        }\r
 #endif\r
@@ -135,10 +223,28 @@ boolean MML_CheckForEMS(void)
 #ifdef __WATCOMC__\r
        }\r
 #endif\r
+\r
+       //\r
+       // Pageframe switch to determine if there is one!\r
+       //\r
+       if(!EMSPageFrame)\r
+       {\r
+               emmcfems = false;\r
+#if defined(__DEBUG_PM__) || defined(__DEBUG_MM__)\r
+               printf("MML_CheckForEMS: EMS error No Pageframe!\nAddress detected to be %04x\n", EMSPageFrame);\r
+#endif\r
+       }else   if(!emmcfems)// if there is an error and page frame is not 0000\r
+       {\r
+               strcpy(str,"MML_CheckForEMS: EMS error ");\r
+               MM_EMSerr(str, err);\r
+               printf("%s\n",str);\r
+       }\r
+\r
        return(emmcfems);\r
 }\r
 \r
-\r
+#ifndef __16_PM__\r
+#if 0\r
 /*\r
 ======================\r
 =\r
@@ -243,12 +349,12 @@ End:
                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
+       gvar->mm.totalEMSpages=totalEMSpages;\r
+       gvar->mm.freeEMSpages=freeEMSpages;\r
+       gvar->mm.EMSPageFrame=EMSPageFrame;\r
+       gvar->mm.EMSpagesmapped=EMSpagesmapped;\r
+       gvar->mm.EMSHandle=EMSHandle;\r
+       gvar->mm.EMSVer=EMSVer;\r
        return 0;\r
 }\r
 \r
@@ -264,7 +370,7 @@ End:
 void MML_ShutdownEMS(global_game_variables_t *gvar)\r
 {\r
        boolean errorflag=false;\r
-       unsigned EMSHandle=gvar->pm.emm.EMSHandle;\r
+       unsigned EMSHandle=gvar->mm.EMSHandle;\r
 \r
        if(!EMSHandle)\r
                return;\r
@@ -283,7 +389,7 @@ void MML_ShutdownEMS(global_game_variables_t *gvar)
        }\r
 #endif\r
        if(errorflag==true)\r
-               Quit("MML_ShutdownEMS: Error freeing EMS!\n");  //++++ add something\r
+               Quit (gvar, "MML_ShutdownEMS: Error freeing EMS!\n");   //++++ add something\r
 }\r
 \r
 /*\r
@@ -305,7 +411,7 @@ byte MM_MapEMS(global_game_variables_t *gvar)
        byte err;\r
        boolean errorflag=false;\r
        int     i;\r
-       EMSHandle=gvar->pm.emm.EMSHandle;\r
+       EMSHandle=gvar->mm.EMSHandle;\r
 \r
        for (i=0;i<4/*MAPPAGES*/;i++)\r
        {\r
@@ -343,7 +449,6 @@ byte MM_MapEMS(global_game_variables_t *gvar)
                }\r
        }\r
        gvar->mmi.EMSmem = (i)*0x4000lu;\r
-       //printf("              gvar->mmi.EMSmem=%lu\n", gvar->mmi.EMSmem);\r
        return 0;\r
 }\r
 \r
@@ -376,9 +481,9 @@ byte MM_MapXEMS(global_game_variables_t *gvar)
        word    EMSHandle;\r
        boolean errorflag=false;\r
        int     i;\r
-       EMSHandle=gvar->pm.emm.EMSHandle;\r
+       EMSHandle=gvar->mm.EMSHandle;\r
 \r
-       if(gvar->pm.emm.EMSVer<0x40)\r
+       if(gvar->mm.EMSVer<0x40)\r
                return 5;\r
 \r
        for (i=0;i<MAPPAGES;i++)\r
@@ -423,7 +528,8 @@ byte MM_MapXEMS(global_game_variables_t *gvar)
        gvar->mmi.EMSmem = (i)*0x4000lu;\r
        return 0;\r
 }\r
-\r
+#endif\r
+#endif\r
 //==========================================================================\r
 \r
 /*\r
@@ -436,10 +542,10 @@ byte MM_MapXEMS(global_game_variables_t *gvar)
 =======================\r
 */\r
 \r
-boolean MML_CheckForXMS(global_game_variables_t *gvar)\r
+boolean MML_CheckForXMS(void)\r
 {\r
+       //numUMBs = 0;\r
        boolean errorflag=false;\r
-       gvar->mm.numUMBs = 0;\r
 \r
        __asm {\r
                mov     ax,0x4300\r
@@ -458,7 +564,8 @@ boolean MML_CheckForXMS(global_game_variables_t *gvar)
        else return true;\r
 }\r
 \r
-\r
+#ifndef __16_PM__\r
+#if 0\r
 /*\r
 ======================\r
 =\r
@@ -545,7 +652,8 @@ void MML_ShutdownXMS(global_game_variables_t *gvar)
                }\r
        }\r
 }\r
-\r
+#endif\r
+#endif\r
 //==========================================================================\r
 \r
 /*\r
@@ -560,30 +668,7 @@ void MML_ShutdownXMS(global_game_variables_t *gvar)
 ======================\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
+/*\r
        extra = oldend - (segstart+seglength);\r
 \r
        segmlen=extra;\r
@@ -608,32 +693,11 @@ void MML_ShutdownXMS(global_game_variables_t *gvar)
        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
+void MML_UseSpace (unsigned segstart, unsigned seglength, global_game_variables_t *gvar)\r
 {\r
        mmblocktype far *scan,far *last;\r
-       word    oldend;\r
+       unsigned        oldend;\r
        sdword          extra;\r
        //word segm=1;\r
 \r
@@ -662,8 +726,9 @@ void MML_UseSpace(word segstart, dword seglength, global_game_variables_t *gvar)
 // take the given range out of the block\r
 //\r
        oldend = scan->start + scan->length;\r
-       extra = oldend - (segstart+((unsigned)seglength));\r
+       extra = oldend - (segstart+seglength);\r
        if (extra < 0)\r
+#ifdef __DEBUG_MM__\r
        {\r
                printf("========================================\n");\r
                printf("start=%x        ", scan->start);\r
@@ -677,6 +742,9 @@ void MML_UseSpace(word segstart, dword seglength, global_game_variables_t *gvar)
                printf("========================================\n");\r
                //return;\r
        }\r
+#else\r
+               Quit (gvar, "MML_UseSpace: Segment spans two blocks!");\r
+#endif\r
 \r
        if (segstart == scan->start)\r
        {\r
@@ -697,7 +765,7 @@ void MML_UseSpace(word segstart, dword seglength, global_game_variables_t *gvar)
                gvar->mm.mmnew->start = segstart+seglength;\r
                gvar->mm.mmnew->length = extra;\r
                gvar->mm.mmnew->attributes = LOCKBIT;\r
-       }\r
+       }//else if(segm>0) goto segu;\r
 \r
 }\r
 \r
@@ -713,24 +781,55 @@ void MML_UseSpace(word segstart, dword seglength, global_game_variables_t *gvar)
 ====================\r
 */\r
 \r
-void MML_ClearBlock(global_game_variables_t *gvar)\r
+void MML_ClearBlock (global_game_variables_t *gvar)\r
 {\r
-       //huge mmblocktype huge *scan,huge *last;\r
-       mmblocktype far *scan,far *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
+               if(!(scan->attributes&LOCKBIT) && (scan->attributes&PURGEBITS) )\r
                {\r
-                       MM_FreePtr(scan->useptr, gvar);\r
+                       MM_FreePtr (scan->useptr, gvar);\r
                        return;\r
                }\r
                scan = scan->next;\r
        }\r
 \r
-       printf("MM_ClearBlock: No purgable blocks!\n");\r
+       Quit (gvar, "MM_ClearBlock: No purgable blocks!\n");\r
+}\r
+\r
+\r
+//==========================================================================\r
+\r
+/*\r
+===================\r
+=\r
+= MM_Reset\r
+=\r
+===================\r
+*/\r
+\r
+void MM_Reset (global_game_variables_t *gvar)\r
+{\r
+//     //has to be 16\r
+//     if(sizeof(mmblocktype)!=16)\r
+//             return;\r
+\r
+#ifdef __BORLANDC__\r
+       strcpy(gvar->handle.datadumpfilename, "mmdump.16b");\r
+#endif\r
+#ifdef __WATCOMC__\r
+       strcpy(gvar->handle.datadumpfilename, "mmdump.16w");\r
+#endif\r
+\r
+#ifdef __BORLANDC__\r
+       strcpy(gvar->handle.heapdumpfilename, "heap.16b");\r
+#endif\r
+#ifdef __WATCOMC__\r
+       strcpy(gvar->handle.heapdumpfilename, "heap.16w");\r
+#endif\r
 }\r
 \r
 \r
@@ -747,20 +846,17 @@ void MML_ClearBlock(global_game_variables_t *gvar)
 ===================\r
 */\r
 \r
-void MM_Startup(global_game_variables_t *gvar)\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
+       unsigned        long length;\r
        void far        *start;\r
-       word    segstart,seglength,endfree;\r
-       //memptr *peeonself;\r
+       unsigned        segstart,seglength;//,endfree;\r
 \r
        if(gvar->mm.mmstarted)\r
-               MM_Shutdown(gvar);\r
-\r
+               MM_Shutdown (gvar);\r
 \r
+       MM_Reset (gvar);\r
        gvar->mm.mmstarted = true;\r
        gvar->mm.bombonerror = true;\r
 //\r
@@ -768,10 +864,8 @@ void MM_Startup(global_game_variables_t *gvar)
 //\r
        gvar->mm.mmhead = NULL;\r
        gvar->mm.mmfree = &(gvar->mm.mmblocks[0]);\r
-       for(i=0;i<MAXBLOCKS-1;i++)\r
-       {\r
+       for (i=0;i<MAXBLOCKS-1;i++)\r
                gvar->mm.mmblocks[i].next = &(gvar->mm.mmblocks[i+1]);\r
-       }\r
        gvar->mm.mmblocks[i].next = NULL;\r
 \r
 //\r
@@ -783,70 +877,53 @@ void MM_Startup(global_game_variables_t *gvar)
        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
 //\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
+       length=(word)coreleft();\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
+\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
+       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
+       //0000printf("near:     start=%Fp       segstart=%x     seglen=%lu      len=%lu\n", start, segstart, (dword)seglength, length);\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=farcoreleft();\r
+       start = gvar->mm.farheap = farmalloc(length);\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
+       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
+       //0000printf("far:      start=%Fp       segstart=%x     seglen=%lu      len=%lu\n", start, segstart, (dword)seglength, length);\r
+#if !defined(__16_PM__)// && defined(__WATCOMC__)\r
+#if 0\r
+       if(!dbg_debugpm) {\r
 //\r
 // detect EMS and allocate up to 64K at page frame\r
 //\r
        gvar->mmi.EMSmem = 0;\r
 //goto emsskip;        //0000\r
+       for(i = 1;i < _argc;i++)\r
+       {\r
+               if(US_CheckParm(_argv[i],ParmStringsexmm) == 0)\r
+                       goto emsskip;                           // param NOEMS\r
+       }\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
+               //16_PM: EMS4! AND EMS 3.2 MASSIVE DATA HANDLMENT!\r
+               MML_UseSpace(gvar->mm.EMSPageFrame,(MAPPAGES)*0x4000lu, gvar);\r
                //if(gvar->pm.emm.EMSVer<0x40)\r
                        MM_MapEMS(gvar);                                        // map in used pages\r
                //else\r
@@ -856,21 +933,29 @@ goto xmsskip;     //INFO: 16_PM dose this job better
 //\r
 // detect XMS and get upper memory blocks\r
 //\r
-//emsskip:\r
+emsskip:\r
        gvar->mmi.XMSmem = 0;\r
-//goto xmsskip;//0000\r
-       if(MML_CheckForXMS(gvar))\r
+goto xmsskip;//0000\r
+       for(i = 1;i < _argc;i++)\r
+       {\r
+               if(US_CheckParm( _argv[i],ParmStringsexmm) == 0)\r
+                       goto xmsskip;                           // param NOXMS\r
+       }\r
+       if(MML_CheckForXMS())\r
        {\r
                MML_SetupXMS(gvar);                                     // allocate as many UMBs as possible\r
        }\r
 \r
+       }\r
+xmsskip:\r
+#endif\r
+#endif\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
+       MM_GetPtr (&(gvar->mm.bufferseg),BUFFERSIZE, gvar);\r
 }\r
 \r
 //==========================================================================\r
@@ -885,20 +970,25 @@ xmsskip:
 ====================\r
 */\r
 \r
-void MM_Shutdown(global_game_variables_t *gvar)\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
+#ifndef __16_PM__\r
+#if 0\r
+#ifdef __DEBUG__\r
+       if(!dbg_debugpm) {\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
+       if(MML_CheckForXMS()){ MML_ShutdownXMS(gvar); }//printf("               XMS freed\n"); }\r
+#ifdef __DEBUG__\r
+       }\r
+#endif\r
+#endif\r
+#endif\r
 }\r
 \r
 //==========================================================================\r
@@ -913,10 +1003,10 @@ void MM_Shutdown(global_game_variables_t *gvar)
 ====================\r
 */\r
 \r
-void MM_GetPtr (memptr *baseptr, dword size, global_game_variables_t *gvar)\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
+       mmblocktype far *scan,far *lastscan,far *endscan\r
+                               ,far *purge,far *next;\r
        int                     search;\r
        unsigned        needed,startseg;\r
 \r
@@ -925,15 +1015,26 @@ void MM_GetPtr (memptr *baseptr, dword size, global_game_variables_t *gvar)
        GETNEWBLOCK;                            // fill in start and next after a spot is found\r
        gvar->mm.mmnew->length = needed;\r
        gvar->mm.mmnew->useptr = baseptr;\r
+       gvar->mm.mmnew->attributes = BASEATTRIBUTES;\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
+#ifdef __DEBUG_MM__\r
+       if(dbg_debugmm>0){\r
+       printf("===============================================================================\n");\r
+       printf("                MM_GetPtr\n");\r
+       printf("===============================================================================\n");\r
+               //%04x\r
+//             printf("        baseptr=%Fp     ", baseptr); printf("useptr=%Fp\n", gvar->mm.mmnew->useptr);\r
+//             //printf("      *baseptr=%Fp    ", *baseptr); printf("*useptr=%Fp\n", *(gvar->mm.mmnew->useptr));\r
+//             printf("        &baseptr=%Fp    ", &baseptr); printf("&useptr=%Fp\n", &(gvar->mm.mmnew->useptr));\r
+\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=%04u   ", &baseptr); printf("&useptr=%04u\n", &(gvar->mm.mmnew->useptr));\r
+\r
+               printf("        size is %lu\n", size);\r
+       }\r
 #endif\r
-       //exit(-5); }\r
-       gvar->mm.mmnew->attributes = BASEATTRIBUTES;\r
+       //Quit (gvar, "gvar->mm.mmnew->useptr==NULL"); }\r
 \r
 //tryagain:\r
        for (search = 0; search<3; search++)\r
@@ -1011,9 +1112,7 @@ void MM_GetPtr (memptr *baseptr, dword size, global_game_variables_t *gvar)
                //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
+               Quit (gvar, "for stability reasons the program will shut down! wwww\n");\r
        }\r
        else\r
                gvar->mm.mmerror = true;\r
@@ -1026,33 +1125,29 @@ void MM_GetPtr (memptr *baseptr, dword size, global_game_variables_t *gvar)
 =\r
 = MM_FreePtr\r
 =\r
-= Allocates an unlocked, unpurgable block\r
+= Deallocates an unlocked, purgable block\r
 =\r
 ====================\r
 */\r
 \r
-void MM_FreePtr(memptr *baseptr, global_game_variables_t *gvar)\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
+       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
+       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
+       if (!scan)\r
+               Quit (gvar, "MM_FreePtr: Block not found!");\r
 \r
        last->next = scan->next;\r
 \r
@@ -1070,46 +1165,25 @@ void MM_FreePtr(memptr *baseptr, global_game_variables_t *gvar)
 =====================\r
 */\r
 \r
-void MM_SetPurge(memptr *baseptr, int purge, global_game_variables_t *gvar)\r
+void MM_SetPurge (memptr *baseptr, int purge, global_game_variables_t *gvar)\r
 {\r
-        mmblocktype huge *start;\r
-       //mmblocktype far *start;\r
+       mmblocktype far *start;\r
 \r
        start = gvar->mm.mmrover;\r
 \r
        do\r
        {\r
-               if(gvar->mm.mmrover->useptr == baseptr)\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
+               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
+               else if (gvar->mm.mmrover == start)\r
+                       Quit (gvar, "MM_SetPurge: Block not found!");\r
 \r
-       } while(1);\r
+       } while (1);\r
 \r
        gvar->mm.mmrover->attributes &= ~PURGEBITS;\r
        gvar->mm.mmrover->attributes |= purge;\r
@@ -1127,27 +1201,23 @@ void MM_SetPurge(memptr *baseptr, int purge, global_game_variables_t *gvar)
 =====================\r
 */\r
 \r
-void MM_SetLock(memptr *baseptr, boolean locked, global_game_variables_t *gvar)\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
+               if (gvar->mm.mmrover->useptr == baseptr)\r
                        break;\r
 \r
                gvar->mm.mmrover = gvar->mm.mmrover->next;\r
 \r
-               if(!gvar->mm.mmrover)\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
+               else if (gvar->mm.mmrover == start)\r
+                       Quit (gvar, "MM_SetLock: Block not found!");\r
 \r
        } while(1);\r
 \r
@@ -1167,12 +1237,11 @@ void MM_SetLock(memptr *baseptr, boolean locked, global_game_variables_t *gvar)
 =====================\r
 */\r
 \r
-void MM_SortMem(global_game_variables_t *gvar)\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
+       //++++int                       playing;\r
 \r
        //\r
        // lock down a currently playing sound\r
@@ -1189,24 +1258,26 @@ void MM_SortMem(global_game_variables_t *gvar)
                        playing += STARTADLIBSOUNDS;\r
                        break;\r
                }\r
-               MM_SetLock(&(memptr)audiosegs[playing],true);\r
+               MM_SetLock(MEMPTRCONV audiosegs[playing],true);\r
        }\r
 \r
 \r
        SD_StopSound();*/\r
-//     oldborder = bordercolor;\r
-//     VW_ColorBorder (15);\r
+#ifdef __WATCOMC__\r
+       oldborder = gvar->video.bordercolor;\r
+       gvar->video.bordercolor = VL_modexPalOverscan(gvar->video.palette, 4);\r
+#endif\r
 \r
-       if(beforesort)\r
+       if (beforesort)\r
                beforesort();\r
 \r
        scan = gvar->mm.mmhead;\r
 \r
        last = NULL;            // shut up compiler warning\r
 \r
-       while(scan)\r
+       while (scan)\r
        {\r
-               if(scan->attributes & LOCKBIT)\r
+               if (scan->attributes & LOCKBIT)\r
                {\r
                //\r
                // block is locked, so try to pile later blocks right after it\r
@@ -1215,14 +1286,13 @@ void MM_SortMem(global_game_variables_t *gvar)
                }\r
                else\r
                {\r
-                       if(scan->attributes & PURGEBITS)\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
+                               FREEBLOCK(scan); //MM_FreeBlock(scan, gvar);\r
                                last->next = next;\r
                                scan = next;\r
                                continue;\r
@@ -1232,12 +1302,12 @@ void MM_SortMem(global_game_variables_t *gvar)
                        //\r
                        // push the non purgable block on top of the last moved block\r
                        //\r
-                               if(scan->start != start)\r
+                               if (scan->start != start)\r
                                {\r
                                        length = scan->length;\r
                                        source = scan->start;\r
                                        dest = start;\r
-                                       while(length > 0xf00)\r
+                                       while (length > 0xf00)\r
                                        {\r
                                                movedata(source,0,dest,0,0xf00*16);\r
                                                length -= 0xf00;\r
@@ -1259,17 +1329,26 @@ void MM_SortMem(global_game_variables_t *gvar)
 \r
        gvar->mm.mmrover = gvar->mm.mmhead;\r
 \r
-       if(aftersort)\r
+       if (aftersort)\r
                aftersort();\r
 \r
-//     VW_ColorBorder (oldborder);\r
+       VL_ColorBorder (oldborder, &gvar->video);\r
 \r
 /*++++ if(playing)\r
-               MM_SetLock(&(memptr)audiosegs[playing],false);*/\r
+               MM_SetLock((memptr *)&audiosegs[playing],false);*/\r
 }\r
 \r
 //==========================================================================\r
 \r
+#ifdef __BORLANDC__\r
+extern char global_temp_status_text[512];\r
+extern char global_temp_status_text2[512];\r
+#endif\r
+#ifdef __WATCOMC__\r
+//#define MMSMPANVID\r
+#define MMSMSCANINFO\r
+#endif\r
+\r
 /*\r
 =====================\r
 =\r
@@ -1278,91 +1357,111 @@ void MM_SortMem(global_game_variables_t *gvar)
 =====================\r
 */\r
 \r
-void MM_ShowMemory(global_game_variables_t *gvar)\r
+\r
+void MM_ShowMemory (global_game_variables_t *gvar)\r
 {\r
-       //huge mmblocktype huge *scan;\r
        mmblocktype far *scan;\r
-       word temp;\r
+       unsigned color,temp,x,y         ,w,width,sw;\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
+       byte            scratch[160],scratch0[4096],str[16];\r
+#ifdef MMSMSCANINFO\r
+       mmshowmemoryinfo_t scaninfo[MAXBLOCKS];\r
+       byte scratch1[4];\r
+       unsigned                xpos,ypos, oldq,q,maxq;\r
+       boolean         done,restarted,mmsmscaninfoxyposinew;\r
+       ScanCode                scancode;\r
+#endif\r
+\r
+       if(!gvar->video.page[0].width) gvar->video.page[0].sw = gvar->video.page[0].width = 320;        //to prevent division by 0\r
+//--   VL_SetLineWidth(40, gvar);\r
+       //temp = gvar->video.ofs.bufferofs;\r
+       //gvar->video.ofs.bufferofs = gvar->video.ofs.displayofs;\r
+       temp = BDOFSCONV gvar->video.BOFS;\r
+       gvar->video.BOFS = gvar->video.DOFS;\r
+#ifdef MMSMSCANINFO\r
+       oldq = 0; restarted = false; mmsmscaninfoxyposinew = false;\r
+reset:\r
+       q = 0;\r
+#endif\r
        scan = gvar->mm.mmhead;\r
-       end = -1;\r
+\r
+       end = -1; w = 0;\r
+\r
+       width = gvar->video.page[0].width; sw = gvar->video.page[0].sw;\r
 \r
        CA_OpenDebug (gvar);\r
-       w=0;\r
-       while(scan)\r
+       while (scan)\r
        {\r
+#ifdef MMSMSCANINFO\r
+               scaninfo[q].scan = scan;\r
+#endif\r
                strcpy(scratch, AARESET);\r
                if(scan->attributes & PURGEBITS)\r
+               {\r
+                       color = 6;              // dark purple = purgable\r
                        strcpy(scratch0, AAMAGENTA);            // dark purple = purgable\r
-               else\r
+               }else{\r
+                       color = 2;              // medium blue = non purgable\r
                        strcpy(scratch0, AABLUE);               // medium blue = non purgable\r
+               }\r
                if(scan->attributes & LOCKBIT)\r
+               {\r
+                       color = 1;              // red = locked\r
                        strcpy(scratch0, AARED);                // red = locked\r
-               if(scan->start<=end)\r
+               }\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
+                       strcat(scratch, "End's Size: ");        ultoa (end,str,10);     strcat (scratch,str);\r
+                       strcat(scratch, "\nscan->start's Size: ");      ultoa (scan->start,str,10);     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
+                       Quit (gvar, "MM_ShowMemory: Memory block order currupted!");\r
+               }\r
+               end = scan->length-1;\r
+               y = gvar->video.page[0].dx+(scan->start/sw);\r
+               x = gvar->video.page[0].dy+(scan->start%sw);\r
+#if 0\r
+//def MMSMSCANINFO\r
+               if(restarted){\r
+                       y += gvar->video.page[0].dy;\r
+                       x += gvar->video.page[0].dx;\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
+#if 0\r
+               else{\r
+                       scaninfo[q].y = y;\r
+                       scaninfo[q].x = x;\r
+               }\r
+#endif\r
+#endif\r
+               VW_Hlin(x,x+end,y,color,gvar);\r
+               VL_Plot(x,y,5,gvar);\r
+//++==++==optional                     strcat(scratch0, AARESET); strcat(scratch0, AAGREY); strcat(scratch0,"_");\r
                for(w=(scan->start)/80;w<=end/80;w++)\r
                {\r
-                       //printf("+     %u      %lu\n", w, scan->length);\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
+               if (scan->next && scan->next->start > end+1)\r
                {\r
+                       VW_Hlin(x+end+1,x+(scan->next->start-scan->start),y,3,gvar);    // black = free//now green\r
                        strcat(scratch0, AARESET);\r
-                       //++==++==optional strcat(scratch0, "\n");\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
+//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("w=%u  start=%04x      next=%04x       end=%lu\n", w/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
+               }\r
+#if 0\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
@@ -1372,29 +1471,21 @@ void MM_ShowMemory(global_game_variables_t *gvar)
                                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("w=%x    start=%x        next=%x end=%u\n", w, scan->start, (scan->next->start), end+1);\r
                        printf("================\n");\r
                        getch();\r
-               }*/\r
+               }\r
+#endif\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, AABLACK); strcat(scratch,"\t"); strcat(scratch, AARESET);\r
                strcat (scratch,"\tSize:");\r
                ultoa ((unsigned)scan->length,str,10);\r
                strcat (scratch,str);\r
+//             strcat(scratch, AABLACK); strcat(scratch,"\t"); strcat(scratch, AARESET);\r
                strcat (scratch,"\tOwner:0x");\r
                owner = (unsigned)scan->useptr;\r
                ultoa (owner,str,16);\r
@@ -1402,37 +1493,206 @@ void MM_ShowMemory(global_game_variables_t *gvar)
                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
+//0000fprintf(stdout, "\n[%s]", scratch);\r
+//0000fprintf(stdout, "[\n%s\n]", scratch0);\r
+//0000fprintf(stdout, "[%u]\n", q);\r
 \r
                scan = scan->next;\r
+#ifdef MMSMSCANINFO\r
+               q++;\r
+#endif\r
+//0000if(q==1 && gvar->video.VL_Started && color!=6) IN_Ack(gvar);\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
+#ifdef MMSMPANVID\r
+       {\r
+               int dx,dy,odx,ody;\r
+               odx = gvar->video.page[0].dx;\r
+               ody = gvar->video.page[0].dy;\r
+               dx = dy = 0;\r
+               while(!gvar->in.inst->Keyboard[sc_Escape] && !gvar->in.inst->Keyboard[sc_Space])\r
+               {\r
+                       if(gvar->in.inst->Keyboard[sc_UpArrow])\r
+                       {\r
+                               if(dy>0)\r
+                                       dy--;\r
+                       }\r
+                       else if(gvar->in.inst->Keyboard[sc_DownArrow])\r
+                       {\r
+                               if(dy<gvar->video.page[0].height-gvar->video.page[0].sh)\r
+                                       dy++;\r
+                       }\r
+                       if(gvar->in.inst->Keyboard[sc_LeftArrow])\r
+                       {\r
+                               if(dx>0)\r
+                                       dx--;\r
+                       }\r
+                       else if(gvar->in.inst->Keyboard[sc_RightArrow])\r
+                       {\r
+                               if(dx<gvar->video.page[0].width-gvar->video.page[0].sw)\r
+                                       dx++;\r
+                       }\r
+\r
+                       modexPanPage(&gvar->video.page[0], dx, dy);\r
+                       VL_ShowPage(&gvar->video.page[0], 1, 1);\r
+               }\r
+\r
+               gvar->video.page[0].dx = odx;\r
+               gvar->video.page[0].dy = ody;\r
+       }\r
+#endif\r
+#ifdef MMSMSCANINFO\r
+       maxq = q;\r
+       if(restarted) q = oldq;\r
+       else q = 0;\r
+       restarted = false;\r
+\r
+       IN_Ack(gvar);\r
+//     VL_ClearVideo (8);\r
+       for (done = false;!done;)\r
+       {\r
+               if(scaninfo[q].scan->attributes & PURGEBITS)\r
+               {\r
+                       color = 6;              // dark purple = purgable\r
+                       strcpy(scratch1, AAMAGENTA);            // dark purple = purgable\r
+                       //printf("%s", AAMAGENTA);\r
+               }else{\r
+                       color = 2;              // medium blue = non purgable\r
+                       strcpy(scratch1, AABLUE);               // medium blue = non purgable\r
+                       //printf("%s", AABLUE);\r
+               }\r
+               if(scaninfo[q].scan->attributes & LOCKBIT)\r
+               {\r
+                       color = 1;              // red = locked\r
+                       strcpy(scratch1, AARED);                // red = locked\r
+                       //printf("%s", AARED);\r
+               }\r
+               end = scaninfo[q].scan->length-1;\r
+//modexprint(page, x, y, t, tlsw, color, bgcolor, vidsw, const byte *str);\r
+#define MMSMPRINTMEMINFO modexprint(&(gvar->video.page[0]), xpos, ypos, 1, 1, color, 8, gvar->video.VL_Started, global_temp_status_text); ypos+=8;\r
+#ifdef __WATCOMC__\r
+               if(gvar->video.VL_Started)\r
+               {\r
+                       VL_ShowPage(&gvar->video.page[0], 1, 0);\r
+                       modexClearRegion(&gvar->video.page[0], gvar->video.page[0].dx, gvar->video.page[0].dy, gvar->video.page[0].sw, gvar->video.page[0].sh, 8);\r
+               }else\r
+#endif\r
+                       clrscr();\r
+               sprintf(global_temp_status_text, "block #%04u", q); MMSMPRINTMEMINFO\r
+//             sprintf(global_temp_status_text, "%Fp", scaninfo[q].scan->useptr); MMSMPRINTMEMINFO\r
+               sprintf(global_temp_status_text, "start:  %04x", (unsigned)scaninfo[q].scan->start); MMSMPRINTMEMINFO\r
+               sprintf(global_temp_status_text, "useptr: %04x", (unsigned)scaninfo[q].scan->useptr); MMSMPRINTMEMINFO\r
+               sprintf(global_temp_status_text, "size: %05u", (unsigned)scaninfo[q].scan->length); MMSMPRINTMEMINFO\r
+               if (scaninfo[q].scan->next && scaninfo[q].scan->next->start > end+1)\r
+               {\r
+                       sprintf(global_temp_status_text, "free: %05u", (unsigned)(scaninfo[q].scan->next->start-scaninfo[q].scan->start)); MMSMPRINTMEMINFO\r
+               }else   ypos+=8;\r
+               if(gvar->video.VL_Started)\r
+               {\r
+                       y = scaninfo[q].scan->start/sw;\r
+                       x = scaninfo[q].scan->start%sw;\r
+                       if(!mmsmscaninfoxyposinew)\r
+                       {\r
+                               y = ypos;\r
+                               x = xpos;\r
+                       }else{\r
+                               //y = scaninfo[q].y;\r
+                               //x = scaninfo[q].x;\r
+                               y += gvar->video.page[0].dy;\r
+                               x += gvar->video.page[0].dx;\r
+                       }\r
+                       VW_Hlin(x,x+end,y,color,gvar);\r
+                       VL_Plot(x,y,5,gvar);\r
+               }\r
+               else\r
+               {\r
+                       printf("%s", scratch1);\r
+                       printf("%s", AAGREY); printf("_");\r
+                       for(w=(scaninfo[q].scan->start)/80;w<=end/80;w++)\r
+                       {\r
+                               //strcat(scratch1, "+");\r
+                               printf("+");\r
+                       }\r
+               }\r
+\r
+\r
+               if (scaninfo[q].scan->next && scaninfo[q].scan->next->start > end+1) if(!gvar->video.VL_Started)\r
+               {\r
+                       //strcat(scratch1, AARESET);\r
+                       printf("%s", AARESET);\r
+                       //strcat(scratch1,AAGREEN);\r
+                       printf("%s", AAGREEN);\r
+                       for(w=(end+1)/80;w<=((scaninfo[q].scan->next->start-scaninfo[q].scan->start)/80);w++)\r
+                       {\r
+                               //strcat(scratch1,"0");\r
+                               printf("0");\r
+                       }\r
+               }else VW_Hlin(x+end+1,x+(scaninfo[q].scan->next->start-scaninfo[q].scan->start),y,3,gvar);      // black = free//now green\r
+\r
+\r
+               if(gvar->video.VL_Started)\r
+               {\r
+                       //if (scan->next && scan->next->start > end+1) free\r
+                       xpos = gvar->video.page[0].dx;\r
+                       ypos = gvar->video.page[0].dy;\r
+               }\r
+               else\r
+               {\r
+                       //printf("%s\n", scratch1);\r
+                       printf("%s", AARESET);\r
+                       printf("\n");\r
+               }\r
+\r
+\r
+               while (!(scancode = gvar->in.inst->LastScan)){}\r
+\r
+               IN_ClearKey(scancode);\r
+               switch (scancode)\r
+               {\r
+                       case sc_Enter:\r
+                               if(!mmsmscaninfoxyposinew) mmsmscaninfoxyposinew = true;\r
+                               else mmsmscaninfoxyposinew = false;\r
+                               //mmsmscaninfoxyposinew!=mmsmscaninfoxyposinew;\r
+                       break;\r
+                       case sc_LeftArrow:\r
+                               if(q>0) q--;\r
+                               else    q = maxq;\r
+                       break;\r
+                       case sc_RightArrow:\r
+                               if(q<maxq) q++;\r
+                               else q = 0;\r
+                       break;\r
+                       case sc_UpArrow:\r
+                               if(q>9) q-=10;\r
+                               else    q = maxq;\r
+                       break;\r
+                       case sc_DownArrow:\r
+                               if(q<maxq-9) q+=10;\r
+                               else q = 0;\r
+                       break;\r
+                       case sc_Space:\r
+                               oldq = q;\r
+                               restarted = true;\r
+                               modexClearRegion(&gvar->video.page[0], gvar->video.page[0].dx, gvar->video.page[0].dy, gvar->video.page[0].sw, gvar->video.page[0].sh, 8);\r
+                               goto reset;\r
+                       break;\r
+                       case sc_Escape:\r
+                               done = true;\r
+                       break;\r
+               }\r
+       }\r
+#else\r
+       if(gvar->video.VL_Started) IN_Ack(gvar);\r
+#endif\r
+\r
+       gvar->video.BOFS = (byte __far *)temp;\r
 }\r
 \r
 //==========================================================================\r
 \r
+\r
 /*\r
 =====================\r
 =\r
@@ -1441,26 +1701,18 @@ void MM_ShowMemory(global_game_variables_t *gvar)
 =====================\r
 */\r
 \r
-void MM_DumpData(global_game_variables_t *gvar)\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
+       unsigned        owner;\r
+       char    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
+       _nfree(gvar->mm.nearheap);\r
+       dumpfile = fopen (gvar->handle.datadumpfilename, "w");\r
+       if (!dumpfile)\r
+               Quit (gvar, "MM_DumpData: Couldn't open MMDUMP.16!\n");\r
 \r
        lowest = -1;\r
        do\r
@@ -1498,8 +1750,16 @@ void MM_DumpData(global_game_variables_t *gvar)
 \r
        } while (lowest != 0xffff);\r
 \r
-       fclose(dumpfile);\r
-       printf("MMDUMP.16 created.\n");\r
+       fclose (dumpfile);\r
+\r
+       //reset filename\r
+#ifdef __BORLANDC__\r
+       strcpy(gvar->handle.datadumpfilename, "mmdump.16b");\r
+#endif\r
+#ifdef __WATCOMC__\r
+       strcpy(gvar->handle.datadumpfilename, "mmdump.16w");\r
+#endif\r
+//00   printf ("MMDUMP.16 created.\n");\r
 }\r
 \r
 //==========================================================================\r
@@ -1515,10 +1775,9 @@ void MM_DumpData(global_game_variables_t *gvar)
 ======================\r
 */\r
 \r
-dword MM_UnusedMemory(global_game_variables_t *gvar)\r
+dword MM_UnusedMemory (global_game_variables_t *gvar)\r
 {\r
-       dword free;\r
-       //huge mmblocktype huge *scan;\r
+       unsigned free;\r
        mmblocktype far *scan;\r
 \r
        free = 0;\r
@@ -1531,7 +1790,6 @@ dword MM_UnusedMemory(global_game_variables_t *gvar)
        }\r
 \r
        return free*16lu;\r
-//     return free;\r
 }\r
 \r
 //==========================================================================\r
@@ -1547,10 +1805,9 @@ dword MM_UnusedMemory(global_game_variables_t *gvar)
 ======================\r
 */\r
 \r
-dword MM_TotalFree(global_game_variables_t *gvar)\r
+dword MM_TotalFree (global_game_variables_t *gvar)\r
 {\r
-       dword free;\r
-       //huge mmblocktype huge *scan;\r
+       unsigned free;\r
        mmblocktype far *scan;\r
 \r
        free = 0;\r
@@ -1565,7 +1822,6 @@ dword MM_TotalFree(global_game_variables_t *gvar)
        }\r
 \r
        return free*16lu;\r
-//     return free;\r
 }\r
 \r
 //==========================================================================\r
@@ -1578,28 +1834,32 @@ dword MM_TotalFree(global_game_variables_t *gvar)
 =====================\r
 */\r
 \r
-void MM_Report_(global_game_variables_t *gvar)\r
+void MM_Report_ (global_game_variables_t *gvar)\r
 {\r
        printf("========================================\n");\r
-       printf("                MM_Report\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
+               printf("        %cLIMEMS        %u\n", 0xC9, gvar->pm.emm.EMSPresent);\r
+               printf("        %c%cEMM v%x.%x available\n", 0xC7, 0xC4, gvar->pm.emm.EMSVer>>4,gvar->pm.emm.EMSVer&0x0F);\r
+               printf("        %c%ctotalEMSpages:      %u      ", 0xC7, 0xC4, gvar->pm.emm.totalEMSpages); printf("freeEMSpages:       %u\n", gvar->pm.emm.freeEMSpages);\r
+               printf("        %c%cEMSPageFrame:       %04x\n", 0xC7, 0xC4, gvar->pm.emm.EMSPageFrame);\r
+               printf("        %c%cEMSmem:     %lu\n", 0xD3, 0xC4, gvar->mmi.EMSmem);\r
        }\r
-       if(MML_CheckForXMS(gvar))\r
+       if(MML_CheckForXMS())\r
        {\r
-               printf("        XMS\n");\r
-               printf("                XMSaddr:        %X\n", *XMSaddr);\r
+               printf("        %cXMS   %u\n", 0xC9, gvar->pm.xmm.XMSPresent);\r
+               printf("        %c%cXMS v%x.%x available\n", 0xC7, 0xC4, XMSVer>>8,XMSVer&0x0F);\r
+               printf("        %c%cXMSDriver:  %Fp\n", 0xC7, 0xC4, XMSDriver);\r
+               printf("        %c%cXMSHandle:  %04x\n", 0xC7, 0xC4, gvar->pm.xmm.XMSHandle);\r
+               printf("        %c%cXMSmem:     %lu\n", 0xD3, 0xC4, gvar->mmi.XMSmem);\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("        %cConv. %u\n", 0xC9, gvar->pm.mm.MainPresent); DebugMemory_(gvar, 0);\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
+       //printf("Total convmem:        %lu     ", gvar->mmi.mainmem); printf("TotalFree:       %lu     ", MM_TotalFree(gvar)+gvar->mmi.EMSmem+gvar->mmi.XMSmem+gvar->mmi.XMSmem); printf("TotalUsed:   %lu\n", gvar->mmi.mainmem);\r
+       //printf("                      UnusedMemory:   %lu\n", MM_UnusedMemory(gvar));\r
+       printf("nearheap:       %lu             ", gvar->mmi.nearheap); printf("farheap:        %lu\n", gvar->mmi.farheap);\r
 }\r
 \r
 //==========================================================================\r
@@ -1743,12 +2003,13 @@ void MM_EMSerr(byte *stri, byte err)
 =====================\r
 */\r
 \r
-void MM_BombOnError(boolean bomb, global_game_variables_t *gvar)\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
+#if 0\r
+void MM_GetNewBlock(global_game_variables_t *gvar)\r
 {\r
        if(!gvar->mm.mmfree)\r
                MML_ClearBlock(gvar);\r
@@ -1767,15 +2028,15 @@ void MM_FreeBlock(mmblocktype *x, global_game_variables_t *gvar)
        x->useptr=NULL;\r
        x->next=gvar->mm.mmfree;\r
        gvar->mm.mmfree=x;\r
-}*/\r
+}\r
+#endif\r
 \r
-void   XMS_CALL(byte v, global_game_variables_t *gvar)\r
+void xms_call(byte v, global_game_variables_t *gvar)\r
 {\r
-       XMSD;\r
-       //XMSDriver=gvar->pm.xmm.XMSDriver;\r
+       dword XMSDriver = gvar->pm.xmm.XMSDriver;\r
        __asm {\r
-               mov v,ah\r
-               call [WORD PTR XMSDriver]\r
+               mov     ah,[v]\r
+               call [DWORD PTR XMSDriver]\r
        }\r
 }\r
 \r