]> 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
old mode 100644 (file)
new mode 100755 (executable)
index 111b696..18c02bb
@@ -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
@@ -41,9 +45,50 @@ EMS / XMS unmanaged routines
 \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
+#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
@@ -52,9 +97,9 @@ EMS / XMS unmanaged routines
 =============================================================================\r
 */\r
 \r
-mminfotype     mminfo;\r
+/*mminfotype   mminfo;\r
 memptr         bufferseg;\r
-boolean                mmerror;\r
+boolean                mmerror;*/\r
 \r
 void           (* beforesort) (void);\r
 void           (* aftersort) (void);\r
@@ -67,7 +112,7 @@ void         (* aftersort) (void);
 =============================================================================\r
 */\r
 \r
-boolean                mmstarted;\r
+/*boolean              mmstarted;\r
 \r
 void far       *farheap;\r
 void           *nearheap;\r
@@ -75,17 +120,34 @@ void               *nearheap;
 mmblocktype    far mmblocks[MAXBLOCKS]\r
                        ,far *mmhead,far *mmfree,far *mmrover,far *mmnew;\r
 \r
-boolean                bombonerror;\r
+boolean                bombonerror;*/\r
 \r
-unsigned       totalEMSpages,freeEMSpages,EMSpageframe,EMSpagesmapped,EMShandle;
-unsigned int EMSVer;\r
+//unsigned     totalEMSpages,freeEMSpages,EMSpageframe,EMSpagesmapped,EMShandle;\r
 \r
 void           (* XMSaddr) (void);             // far pointer to XMS driver\r
 \r
-unsigned       numUMBs,UMBbase[MAXUMBS];
-
-static char *ParmStringsexmm[] = {"noems","noxms",""};
+/*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
@@ -96,21 +158,22 @@ static     char *ParmStringsexmm[] = {"noems","noxms",""};
 =======================\r
 */\r
 \r
-boolean MML_CheckForEMS (void)\r
+boolean MML_CheckForEMS(void)\r
 {\r
-       boolean emmcfems;\r
-       char    emmname[] = "EMMXXXX0";\r
-//             mov     dx,OFFSET emmname\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
-               LEA     DX, emmname     //fix by andrius4669\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
@@ -118,30 +181,70 @@ 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
                error:\r
+#ifdef __BORLANDC__\r
+       __asm {\r
+#endif\r
                //\r
                // EMS is bad\r
                //\r
-               mov     emmcfems,0\r
+               mov     err,ah\r
+               mov     emmcfems,0\r
+#ifdef __BORLANDC__\r
+       }\r
+#endif\r
                End:\r
+#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
@@ -150,21 +253,22 @@ boolean MML_CheckForEMS (void)
 =======================\r
 */\r
 \r
-unsigned MML_SetupEMS (void)\r
+byte MML_SetupEMS(global_game_variables_t *gvar)\r
 {\r
-       char    str[80],str2[10];\r
-       unsigned        err;\r
+       byte    str[160];\r
+       byte    err;\r
        boolean errorflag=false;\r
-       union REGS CPURegs;\r
 \r
-       EMSVer = 0;\r
-       totalEMSpages = freeEMSpages = EMSpageframe = EMSpagesmapped = 0;\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
-               {\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
@@ -179,7 +283,7 @@ unsigned MML_SetupEMS (void)
                int     EMS_INT                                         // find the page frame address\r
                or      ah,ah\r
                jnz     error\r
-               mov     [EMSpageframe],bx\r
+               mov     [EMSPageFrame],bx\r
 \r
                mov     ah,EMS_GETPAGES\r
                int     EMS_INT                                         // find out how much EMS is there\r
@@ -189,34 +293,68 @@ unsigned MML_SetupEMS (void)
                mov     [freeEMSpages],bx\r
                or      bx,bx\r
                jz      noEMS                                           // no EMS at all to allocate\r
-\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
-\r
-getpages:\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
+               mov     [EMSHandle],dx\r
                jmp End\r
-error:\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
-               err = CPURegs.h.ah;\r
-               strcpy(str,"MML_SetupEMS: EMS error 0x");\r
-               itoa(err,str2,16);\r
-               strcpy(str,str2);\r
-               printf("%s\n",str);
+               strcpy(str,"MM_SetupEMS: EMS error ");\r
+               MM_EMSerr(str, err);\r
+               printf("%s\n",str);\r
                return err;\r
-       }
+       }\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
@@ -229,22 +367,29 @@ End:
 =======================\r
 */\r
 \r
-void MML_ShutdownEMS (void)\r
+void MML_ShutdownEMS(global_game_variables_t *gvar)\r
 {\r
        boolean errorflag=false;\r
-       if (!EMShandle)\r
+       unsigned EMSHandle=gvar->mm.EMSHandle;\r
+\r
+       if(!EMSHandle)\r
                return;\r
-       __asm\r
-       {\r
+       __asm {\r
                mov     ah,EMS_FREEPAGES\r
-               mov     dx,[EMShandle]\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
-       if(errorflag==true) printf("MML_ShutdownEMS: Error freeing EMS!");      //++++ add something\r
+#endif\r
+       if(errorflag==true)\r
+               Quit (gvar, "MML_ShutdownEMS: Error freeing EMS!\n");   //++++ add something\r
 }\r
 \r
 /*\r
@@ -259,43 +404,132 @@ void MML_ShutdownEMS (void)
 ====================\r
 */\r
 \r
-unsigned MM_MapEMS (void)\r
+byte MM_MapEMS(global_game_variables_t *gvar)\r
 {\r
-       char    str[80],str2[10];\r
-       unsigned        err;\r
+       byte    str[160];\r
+       unsigned        EMSHandle;\r
+       byte err;\r
        boolean errorflag=false;\r
        int     i;\r
-       union REGS CPURegs;\r
+       EMSHandle=gvar->mm.EMSHandle;\r
 \r
-       for (i=0;i<EMSpagesmapped;i++)\r
+       for (i=0;i<4/*MAPPAGES*/;i++)\r
        {\r
-               __asm\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
+                       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
-                       err = CPURegs.h.ah;\r
-                       strcpy(str,"MM_MapEMS: EMS error 0x");\r
-                       itoa(err,str2,16);\r
-                       strcpy(str,str2);\r
-                       printf("%s\n",str);
+                       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
        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->mm.EMSHandle;\r
+\r
+       if(gvar->mm.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
+#endif\r
+#endif\r
 //==========================================================================\r
 \r
 /*\r
@@ -308,25 +542,30 @@ unsigned MM_MapEMS (void)
 =======================\r
 */\r
 \r
-boolean MML_CheckForXMS (void)\r
+boolean MML_CheckForXMS(void)\r
 {\r
+       //numUMBs = 0;\r
        boolean errorflag=false;\r
-       numUMBs = 0;\r
 \r
-       __asm\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
+#ifndef __16_PM__\r
+#if 0\r
 /*\r
 ======================\r
 =\r
@@ -337,22 +576,22 @@ boolean MML_CheckForXMS (void)
 =======================\r
 */\r
 \r
-void MML_SetupXMS (void)\r
+void MML_SetupXMS(global_game_variables_t *gvar)\r
 {\r
-       unsigned        base,size;\r
+       word    base,size;\r
 \r
-       __asm\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
-       {\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
@@ -364,17 +603,28 @@ getmemory:
                call    [DWORD PTR XMSaddr]             // DX holds largest available UMB\r
                or      ax,ax\r
                jz      done                                            // another error...\r
-\r
-gotone:\r
+#ifdef __BORLANDC__\r
+       }\r
+#endif\r
+               gotone:\r
+#ifdef __BORLANDC__\r
+       __asm {\r
+#endif\r
                mov     [base],bx\r
                mov     [size],dx\r
-done:\r
+#ifdef __BORLANDC__\r
        }\r
-       MML_UseSpace (base,size);\r
-       mminfo.XMSmem += size*16;\r
-       UMBbase[numUMBs] = base;\r
-       numUMBs++;\r
-       if (numUMBs < MAXUMBS)\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
@@ -387,23 +637,23 @@ done:
 ======================\r
 */\r
 \r
-void MML_ShutdownXMS (void)\r
+void MML_ShutdownXMS(global_game_variables_t *gvar)\r
 {\r
        int     i;\r
        unsigned        base;\r
 \r
-       for (i=0;i<numUMBs;i++)\r
+       for (i=0;i<gvar->mm.numUMBs;i++)\r
        {\r
-               base = UMBbase[i];\r
-               __asm\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
+#endif\r
+#endif\r
 //==========================================================================\r
 \r
 /*\r
@@ -418,14 +668,41 @@ void MML_ShutdownXMS (void)
 ======================\r
 */\r
 \r
-void MML_UseSpace (unsigned segstart, unsigned seglength)\r
+/*\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
+*/\r
+void MML_UseSpace (unsigned segstart, unsigned seglength, global_game_variables_t *gvar)\r
 {\r
        mmblocktype far *scan,far *last;\r
        unsigned        oldend;\r
-       long            extra;\r
+       sdword          extra;\r
+       //word segm=1;\r
 \r
-       scan = last = mmhead;\r
-       mmrover = mmhead;               // reset rover to start of memory\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
@@ -436,17 +713,38 @@ void MML_UseSpace (unsigned segstart, unsigned seglength)
                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+seglength);\r
        if (extra < 0)\r
+#ifdef __DEBUG_MM__\r
        {\r
-               printf("MML_UseSpace: Segment spans two blocks!");\r
-               return;\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
+#else\r
+               Quit (gvar, "MML_UseSpace: Segment spans two blocks!");\r
+#endif\r
 \r
        if (segstart == scan->start)\r
        {\r
@@ -460,12 +758,14 @@ void MML_UseSpace (unsigned segstart, unsigned seglength)
        if (extra > 0)\r
        {\r
                GETNEWBLOCK;\r
-               mmnew->next = scan->next;\r
-               scan->next = mmnew;\r
-               mmnew->start = segstart+seglength;\r
-               mmnew->length = extra;\r
-               mmnew->attributes = LOCKBIT;\r
-       }\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
 \r
@@ -481,23 +781,55 @@ void MML_UseSpace (unsigned segstart, unsigned seglength)
 ====================\r
 */\r
 \r
-void MML_ClearBlock (void)\r
+void MML_ClearBlock (global_game_variables_t *gvar)\r
 {\r
-       mmblocktype far *scan,far *last;\r
+       mmblocktype far *scan;//,far *last;\r
 \r
-       scan = mmhead->next;\r
+       scan = gvar->mm.mmhead->next;\r
 \r
-       while (scan)\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);\r
+                       MM_FreePtr (scan->useptr, gvar);\r
                        return;\r
                }\r
                scan = scan->next;\r
        }\r
 \r
-       printf("MM_ClearBlock: No purgable blocks!");\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
@@ -514,117 +846,116 @@ void MML_ClearBlock (void)
 ===================\r
 */\r
 \r
-void MM_Startup (void)\r
+void MM_Startup (global_game_variables_t *gvar)\r
 {\r
        int i;\r
-       dword length;\r
-       void far        *start;\r
-       unsigned        segstart,seglength,endfree;\r
+       unsigned        long length;\r
+       void far        *start;\r
+       unsigned        segstart,seglength;//,endfree;\r
 \r
-       if (mminfo.mmstarted)\r
-               MM_Shutdown ();\r
+       if(gvar->mm.mmstarted)\r
+               MM_Shutdown (gvar);\r
 \r
-\r
-       mminfo.mmstarted = true;\r
-       mminfo.bombonerror = true;\r
+       MM_Reset (gvar);\r
+       gvar->mm.mmstarted = true;\r
+       gvar->mm.bombonerror = true;\r
 //\r
 // set up the linked list (everything in the free list;\r
 //\r
-       mmhead = NULL;\r
-       mmfree = &mmblocks[0];\r
+       gvar->mm.mmhead = NULL;\r
+       gvar->mm.mmfree = &(gvar->mm.mmblocks[0]);\r
        for (i=0;i<MAXBLOCKS-1;i++)\r
-               mmblocks[i].next = &mmblocks[i+1];\r
-       mmblocks[i].next = NULL;\r
+               gvar->mm.mmblocks[i].next = &(gvar->mm.mmblocks[i+1]);\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
-       mmhead = mmnew;                         // this will allways be the first node\r
-       mmnew->start = 0;\r
-       mmnew->length = 0xffff;\r
-       mmnew->attributes = LOCKBIT;\r
-       mmnew->next = NULL;\r
-       mmrover = mmhead;\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.mmrover = gvar->mm.mmhead;\r
 \r
 \r
 //\r
 // get all available near conventional memory segments\r
 //\r
-//---- length=coreleft();\r
-       _nheapgrow();\r
-       length=_memavl();\r
-       start = (void far *)(nearheap = malloc(length));\r
+       length=(word)coreleft();\r
+       start = (void far *)(gvar->mm.nearheap = _nmalloc(length));\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);\r
-       mminfo.nearheap = length;\r
-\r
+       MML_UseSpace (segstart,seglength, gvar);\r
+       gvar->mmi.nearheap = length;\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
-//---- length=farcoreleft();\r
-       _fheapgrow();\r
-       length=_memavl();\r
-       start = farheap = _fmalloc(length);\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);\r
-       mminfo.farheap = length;\r
-       mminfo.mainmem = mminfo.nearheap + mminfo.farheap;\r
-\r
-\r
+       MML_UseSpace (segstart,seglength, gvar);\r
+       gvar->mmi.farheap = length;\r
+       gvar->mmi.mainmem = gvar->mmi.nearheap + gvar->mmi.farheap;\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
-       mminfo.EMSmem = 0;\r
-       for (i = 1;i < __argc;i++)\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
+               if(US_CheckParm(_argv[i],ParmStringsexmm) == 0)\r
                        goto emsskip;                           // param NOEMS\r
        }\r
-\r
-       if (MML_CheckForEMS())\r
+       if(MML_CheckForEMS())\r
        {\r
-               //printf("EMS1\n");\r
-               MML_SetupEMS();                                 // allocate space\r
-               //printf("EMS2\n");\r
-               MML_UseSpace (EMSpageframe,EMSpagesmapped*0x400);\r
-               //printf("EMS3\n");\r
-               MM_MapEMS();                                    // map in used pages\r
-               //printf("EMS4\n");\r
-               mminfo.EMSmem = EMSpagesmapped*0x4000l;\r
+               MML_SetupEMS(gvar);                                     // allocate space\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
+                       //MM_MapXEMS(gvar);                                     // map in used pages\r
        }\r
 \r
 //\r
 // detect XMS and get upper memory blocks\r
 //\r
 emsskip:\r
-       mminfo.XMSmem = 0;\r
-       for (i = 1;i < __argc;i++)\r
+       gvar->mmi.XMSmem = 0;\r
+goto xmsskip;//0000\r
+       for(i = 1;i < _argc;i++)\r
        {\r
-               if ( US_CheckParm(__argv[i],ParmStringsexmm) == 0)\r
+               if(US_CheckParm( _argv[i],ParmStringsexmm) == 0)\r
                        goto xmsskip;                           // param NOXMS\r
        }\r
-\r
-       if (MML_CheckForXMS())\r
+       if(MML_CheckForXMS())\r
        {\r
-//             printf("XMS!\n");\r
-//++++         MML_SetupXMS();                                 // allocate as many UMBs as possible\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
-       mmrover = mmhead;               // start looking for space after low block\r
+       gvar->mm.mmrover = gvar->mm.mmhead;             // start looking for space after low block\r
 \r
-       MM_GetPtr (&bufferseg,BUFFERSIZE);\r
+       MM_GetPtr (&(gvar->mm.bufferseg),BUFFERSIZE, gvar);\r
 }\r
 \r
 //==========================================================================\r
@@ -639,21 +970,25 @@ xmsskip:
 ====================\r
 */\r
 \r
-void MM_Shutdown (void)\r
+void MM_Shutdown (global_game_variables_t *gvar)\r
 {\r
-  if (!mminfo.mmstarted)\r
-       return;\r
-\r
-  _ffree (farheap);
-  printf("far freed\n");\r
-  free (nearheap);
-  printf("near freed\n");\r
-  //hfree(hugeheap);
-  printf("huge freed\n");\r
-  MML_ShutdownEMS ();
-  printf("EMS freed\n");\r
-//++++  MML_ShutdownXMS ();
-  printf("XMS freed\n");\r
+       if(!(gvar->mm.mmstarted))\r
+               return;\r
+\r
+       _ffree(gvar->mm.farheap);//     printf("                far freed\n");\r
+       _nfree(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()){ MML_ShutdownXMS(gvar); }//printf("               XMS freed\n"); }\r
+#ifdef __DEBUG__\r
+       }\r
+#endif\r
+#endif\r
+#endif\r
 }\r
 \r
 //==========================================================================\r
@@ -668,7 +1003,7 @@ void MM_Shutdown (void)
 ====================\r
 */\r
 \r
-void MM_GetPtr (memptr *baseptr,dword size)\r
+void MM_GetPtr (memptr *baseptr,dword size, global_game_variables_t *gvar)\r
 {\r
        mmblocktype far *scan,far *lastscan,far *endscan\r
                                ,far *purge,far *next;\r
@@ -678,35 +1013,55 @@ void MM_GetPtr (memptr *baseptr,dword size)
        needed = (size+15)/16;          // convert size from bytes to paragraphs\r
 \r
        GETNEWBLOCK;                            // fill in start and next after a spot is found\r
-       mmnew->length = needed;\r
-       mmnew->useptr = baseptr;\r
-       mmnew->attributes = BASEATTRIBUTES;\r
+       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_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
+       //Quit (gvar, "gvar->mm.mmnew->useptr==NULL"); }\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 && mmrover == mmhead)\r
+               if (search == 1 && gvar->mm.mmrover == gvar->mm.mmhead)\r
                        search++;\r
 \r
                switch (search)\r
                {\r
                case 0:\r
-                       lastscan = mmrover;\r
-                       scan = mmrover->next;\r
+                       lastscan = gvar->mm.mmrover;\r
+                       scan = gvar->mm.mmrover->next;\r
                        endscan = NULL;\r
                        break;\r
                case 1:\r
-                       lastscan = mmhead;\r
-                       scan = mmhead->next;\r
-                       endscan = mmrover;\r
+                       lastscan = gvar->mm.mmhead;\r
+                       scan = gvar->mm.mmhead->next;\r
+                       endscan = gvar->mm.mmrover;\r
                        break;\r
                case 2:\r
-                       MM_SortMem ();\r
-                       lastscan = mmhead;\r
-                       scan = mmhead->next;\r
+                       MM_SortMem (gvar);\r
+                       lastscan = gvar->mm.mmhead;\r
+                       scan = gvar->mm.mmhead->next;\r
                        endscan = NULL;\r
                        break;\r
                }\r
@@ -723,16 +1078,16 @@ void MM_GetPtr (memptr *baseptr,dword size)
                        // and allocate the new block\r
                        //\r
                                purge = lastscan->next;\r
-                               lastscan->next = mmnew;\r
-                               mmnew->start = *(unsigned *)baseptr = startseg;\r
-                               mmnew->next = scan;\r
+                               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
-                               mmrover = mmnew;\r
+                               gvar->mm.mmrover = gvar->mm.mmnew;\r
                                return; // good allocation!\r
                        }\r
 \r
@@ -751,10 +1106,16 @@ void MM_GetPtr (memptr *baseptr,dword size)
                }\r
        }\r
 \r
-       if (mminfo.bombonerror)\r
-               printf(OUT_OF_MEM_MSG,(size-mminfo.nearheap));\r
+       if (gvar->mm.bombonerror)\r
+       {\r
+#ifdef __WATCOMC__\r
+               //heapdump();\r
+#endif\r
+               printf(OUT_OF_MEM_MSG,(size-gvar->mmi.nearheap));\r
+               Quit (gvar, "for stability reasons the program will shut down! wwww\n");\r
+       }\r
        else\r
-               mminfo.mmerror = true;\r
+               gvar->mm.mmerror = true;\r
 }\r
 \r
 //==========================================================================\r
@@ -764,20 +1125,20 @@ void MM_GetPtr (memptr *baseptr,dword size)
 =\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)\r
+void MM_FreePtr (memptr *baseptr, global_game_variables_t *gvar)\r
 {\r
        mmblocktype far *scan,far *last;\r
 \r
-       last = mmhead;\r
+       last = gvar->mm.mmhead;\r
        scan = last->next;\r
 \r
-       if (baseptr == mmrover->useptr) // removed the last allocated block\r
-               mmrover = mmhead;\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
@@ -786,10 +1147,7 @@ void MM_FreePtr (memptr *baseptr)
        }\r
 \r
        if (!scan)\r
-       {\r
-               printf("MM_FreePtr: Block not found!");\r
-               return;\r
-       }\r
+               Quit (gvar, "MM_FreePtr: Block not found!");\r
 \r
        last->next = scan->next;\r
 \r
@@ -807,31 +1165,28 @@ void MM_FreePtr (memptr *baseptr)
 =====================\r
 */\r
 \r
-void MM_SetPurge (memptr *baseptr, int purge)\r
+void MM_SetPurge (memptr *baseptr, int purge, global_game_variables_t *gvar)\r
 {\r
        mmblocktype far *start;\r
 \r
-       start = mmrover;\r
+       start = gvar->mm.mmrover;\r
 \r
        do\r
        {\r
-               if (mmrover->useptr == baseptr)\r
+               if (gvar->mm.mmrover->useptr == baseptr)\r
                        break;\r
 \r
-               mmrover = mmrover->next;\r
+               gvar->mm.mmrover = gvar->mm.mmrover->next;\r
 \r
-               if (!mmrover)\r
-                       mmrover = mmhead;\r
-               else if (mmrover == start)\r
-               {\r
-                       printf("MM_SetPurge: Block not found!");\r
-                       return;\r
-               }\r
+               if (!gvar->mm.mmrover)\r
+                       gvar->mm.mmrover = gvar->mm.mmhead;\r
+               else if (gvar->mm.mmrover == start)\r
+                       Quit (gvar, "MM_SetPurge: Block not found!");\r
 \r
        } while (1);\r
 \r
-       mmrover->attributes &= ~PURGEBITS;\r
-       mmrover->attributes |= purge;\r
+       gvar->mm.mmrover->attributes &= ~PURGEBITS;\r
+       gvar->mm.mmrover->attributes |= purge;\r
 }\r
 \r
 //==========================================================================\r
@@ -846,31 +1201,28 @@ void MM_SetPurge (memptr *baseptr, int purge)
 =====================\r
 */\r
 \r
-void MM_SetLock (memptr *baseptr, boolean locked)\r
+void MM_SetLock (memptr *baseptr, boolean locked, global_game_variables_t *gvar)\r
 {\r
        mmblocktype far *start;\r
 \r
-       start = mmrover;\r
+       start = gvar->mm.mmrover;\r
 \r
        do\r
        {\r
-               if (mmrover->useptr == baseptr)\r
+               if (gvar->mm.mmrover->useptr == baseptr)\r
                        break;\r
 \r
-               mmrover = mmrover->next;\r
+               gvar->mm.mmrover = gvar->mm.mmrover->next;\r
 \r
-               if (!mmrover)\r
-                       mmrover = mmhead;\r
-               else if (mmrover == start)\r
-               {\r
-                       printf("MM_SetLock: Block not found!");\r
-                       return;\r
-               }\r
+               if (!gvar->mm.mmrover)\r
+                       gvar->mm.mmrover = gvar->mm.mmhead;\r
+               else if (gvar->mm.mmrover == start)\r
+                       Quit (gvar, "MM_SetLock: Block not found!");\r
 \r
-       } while (1);\r
+       } while(1);\r
 \r
-       mmrover->attributes &= ~LOCKBIT;\r
-       mmrover->attributes |= locked*LOCKBIT;\r
+       gvar->mm.mmrover->attributes &= ~LOCKBIT;\r
+       gvar->mm.mmrover->attributes |= locked*LOCKBIT;\r
 }\r
 \r
 //==========================================================================\r
@@ -885,17 +1237,17 @@ void MM_SetLock (memptr *baseptr, boolean locked)
 =====================\r
 */\r
 \r
-void MM_SortMem (void)\r
+void MM_SortMem (global_game_variables_t *gvar)\r
 {\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
        //\r
 /*++++ playing = SD_SoundPlaying ();\r
-       if (playing)\r
+       if(playing)\r
        {\r
                switch (SoundMode)\r
                {\r
@@ -906,18 +1258,20 @@ void MM_SortMem (void)
                        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
                beforesort();\r
 \r
-       scan = mmhead;\r
+       scan = gvar->mm.mmhead;\r
 \r
        last = NULL;            // shut up compiler warning\r
 \r
@@ -938,7 +1292,7 @@ void MM_SortMem (void)
                        // throw out the purgable block\r
                        //\r
                                next = scan->next;\r
-                               FREEBLOCK(scan);\r
+                               FREEBLOCK(scan); //MM_FreeBlock(scan, gvar);\r
                                last->next = next;\r
                                scan = next;\r
                                continue;\r
@@ -973,21 +1327,28 @@ void MM_SortMem (void)
                scan = scan->next;              // go to next block\r
        }\r
 \r
-       mmrover = mmhead;\r
+       gvar->mm.mmrover = gvar->mm.mmhead;\r
 \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
+/*++++ if(playing)\r
+               MM_SetLock((memptr *)&audiosegs[playing],false);*/\r
 }\r
 \r
-\r
 //==========================================================================\r
 \r
-//****#if 0\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
@@ -996,69 +1357,410 @@ void MM_SortMem (void)
 =====================\r
 */\r
 \r
-void MM_ShowMemory (void)\r
+\r
+void MM_ShowMemory (global_game_variables_t *gvar)\r
 {\r
        mmblocktype far *scan;\r
-       unsigned color,temp;//, i;\r
-       long    end,owner;\r
-       char    scratch[80],str[10];\r
+       unsigned color,temp,x,y         ,w,width,sw;\r
+       sdword  end,owner;\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
+\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
+       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
+                       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
+               }\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: ");        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
+                       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
+#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
+                       strcat(scratch0, "+");\r
+               }\r
 \r
-//**** VW_SetDefaultColors();\r
-//**** VW_SetLineWidth(40);\r
-//++++mh       temp = bufferofs;\r
-//++++mh       bufferofs = 0;\r
-//**** VW_SetScreen (0,0);\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
+                       strcat(scratch0,AAGREEN);\r
+                       for(w=(end+1)/80;w<=((scan->next->start-scan->start)/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  start=%04x      next=%04x       end=%lu\n", w/80, scan->start, (scan->next->start), end+1);\r
+                       //printf("==================\n");\r
+                       strcat(scratch0, "\n");\r
+               }\r
+#if 0\r
+               else {//if(scan->next->start <= scan->start){\r
+                       scan->next->start=scan->start+0x1000;\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\n", w, scan->start, (scan->next->start), end+1);\r
+                       printf("================\n");\r
+                       getch();\r
+               }\r
+#endif\r
+               strcat(scratch0, AARESET);\r
+               //strcat(scratch0,"\n");\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
+               strcat (scratch,str);\r
+               strcat (scratch,"\n");\r
+               write(gvar->handle.debughandle,scratch,strlen(scratch));\r
+               write(gvar->handle.debughandle,scratch0,strlen(scratch0));\r
+//0000fprintf(stdout, "\n[%s]", scratch);\r
+//0000fprintf(stdout, "[\n%s\n]", scratch0);\r
+//0000fprintf(stdout, "[%u]\n", q);\r
 \r
-       scan = mmhead;\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
 \r
-       end = -1;\r
+       CA_CloseDebug (gvar);\r
 \r
-//CA_OpenDebug ();\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
-       while (scan)\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 (scan->attributes & PURGEBITS)\r
-                       color = 5;              // dark purple = purgable\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
-                       color = 9;              // medium blue = non purgable\r
-               if (scan->attributes & LOCKBIT)\r
-                       color = 12;             // red = locked\r
-               if (scan->start<=end)\r
                {\r
-                       printf("MM_ShowMemory: Memory block order currupted!");\r
-                       return;\r
+                       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
-               end = scan->start+scan->length-1;\r
-//++++         VW_Hlin(scan->start,(unsigned)end,0,color);\r
-//++++         VW_Plot(scan->start,0,15);\r
-               if (scan->next->start > end+1)\r
-//++++                 VW_Hlin(end+1,scan->next->start,0,0);   // black = free\r
-\r
-//****#if 0\r
-printf("Location:");\r
-printf("%Fp\t", scan->start);\r
-strcpy (scratch,"Size:");\r
-ltoa ((long)scan->length*16,str,10);\r
-strcat (scratch,str);\r
-strcat (scratch,"\tOwner:0x");\r
-owner = (unsigned)scan->useptr;\r
-ultoa (owner,str,16);\r
-strcat (scratch,str);\r
-strcat (scratch,"\n");\r
-//++++write (debughandle,scratch,strlen(scratch));\r
-fprintf(stdout, "%s", scratch);\r
-//****#endif\r
 \r
-               scan = scan->next;\r
+\r
+               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
+= MM_DumpData\r
+=\r
+=====================\r
+*/\r
+\r
+void MM_DumpData (global_game_variables_t *gvar)\r
+{\r
+       mmblocktype far *scan,far *best;\r
+       long    lowest,oldlowest;\r
+       unsigned        owner;\r
+       char    lock,purge;\r
+       FILE    *dumpfile;\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
+       {\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
-//CA_CloseDebug ();\r
+       } while (lowest != 0xffff);\r
 \r
-//++++mh       IN_Ack();\r
-//**** VW_SetLineWidth(64);\r
-//++++mh       bufferofs = temp;\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
-//****#endif\r
 \r
 //==========================================================================\r
 \r
@@ -1073,22 +1775,21 @@ fprintf(stdout, "%s", scratch);
 ======================\r
 */\r
 \r
-dword MM_UnusedMemory (void)\r
+dword MM_UnusedMemory (global_game_variables_t *gvar)\r
 {\r
        unsigned free;\r
        mmblocktype far *scan;\r
 \r
        free = 0;\r
-       scan = mmhead;\r
+       scan = gvar->mm.mmhead;\r
 \r
-       while (scan->next)\r
+       while(scan->next)\r
        {\r
                free += scan->next->start - (scan->start + scan->length);\r
                scan = scan->next;\r
        }\r
 \r
-       return free*16l;\r
-//     return free;\r
+       return free*16lu;\r
 }\r
 \r
 //==========================================================================\r
@@ -1104,24 +1805,23 @@ dword MM_UnusedMemory (void)
 ======================\r
 */\r
 \r
-dword MM_TotalFree (void)\r
+dword MM_TotalFree (global_game_variables_t *gvar)\r
 {\r
        unsigned free;\r
        mmblocktype far *scan;\r
 \r
        free = 0;\r
-       scan = mmhead;\r
+       scan = gvar->mm.mmhead;\r
 \r
-       while (scan->next)\r
+       while(scan->next)\r
        {\r
-               if ((scan->attributes&PURGEBITS) && !(scan->attributes&LOCKBIT))\r
+               if((scan->attributes&PURGEBITS) && !(scan->attributes&LOCKBIT))\r
                        free += scan->length;\r
                free += scan->next->start - (scan->start + scan->length);\r
                scan = scan->next;\r
        }\r
 \r
-       return free*16l;\r
-//     return free;\r
+       return free*16lu;\r
 }\r
 \r
 //==========================================================================\r
@@ -1134,22 +1834,32 @@ dword MM_TotalFree (void)
 =====================\r
 */\r
 \r
-void MM_Report(void)\r
+void MM_Report_ (global_game_variables_t *gvar)\r
 {\r
-       printf("EMM %x available\n", EMSVer);\r
-       printf("totalEMSpages=%u\n", totalEMSpages);\r
-       printf("freeEMSpages=%u\n", freeEMSpages);\r
-       printf("EMSpageframe=%Fp\n", EMSpageframe);\r
-       printf("near=%lu\n", mminfo.nearheap);\r
-       printf("far=%lu\n", mminfo.farheap);\r
-       printf("EMSmem=%lu\n", mminfo.EMSmem);\r
-       printf("XMSmem=%lu\n", mminfo.XMSmem);\r
-       printf("mainmem=%lu\n", mminfo.mainmem);\r
-       printf("UnusedMemory=%lu\n", MM_UnusedMemory());\r
-       printf("TotalFree=%lu\n", MM_TotalFree());\r
-//     printf("\n");\r
-//     printf("UnusedMemory=%lu kb\n", MM_UnusedMemory()/10248);\r
-//     printf("TotalFree=%lu kb\n", MM_TotalFree()/10248);\r
+       printf("========================================\n");\r
+       printf("                MM_Report_\n");\r
+       printf("========================================\n");\r
+       if(MML_CheckForEMS())\r
+       {\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())\r
+       {\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("        %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)+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
@@ -1157,22 +1867,131 @@ void MM_Report(void)
 /*\r
 =====================\r
 =\r
-= MM_EMSVer\r
+= MM_EMSerr\r
 =\r
 =====================\r
+*/\r
 \r
-\r
-int MM_EMSVer(void)\r
+void MM_EMSerr(byte *stri, byte err)\r
 {\r
-       int EMSver;\r
-       __asm\r
+       //Returns a text string describing the error code in EMS.Error.\r
+       switch(err)\r
        {\r
-               mov             ah,EMS_VERSION\r
-               int             EMS_INT\r
-               mov             EMSver,ax\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
-       return(EMSver);\r
-}*/\r
+}\r
 \r
 //==========================================================================\r
 \r
@@ -1184,7 +2003,67 @@ int MM_EMSVer(void)
 =====================\r
 */\r
 \r
-void MM_BombOnError (boolean bomb)\r
+void MM_BombOnError (boolean bomb, global_game_variables_t *gvar)\r
+{\r
+       gvar->mm.bombonerror = bomb;\r
+}\r
+\r
+#if 0\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
+#endif\r
+\r
+void xms_call(byte v, global_game_variables_t *gvar)\r
+{\r
+       dword XMSDriver = gvar->pm.xmm.XMSDriver;\r
+       __asm {\r
+               mov     ah,[v]\r
+               call [DWORD PTR XMSDriver]\r
+       }\r
+}\r
+\r
+/*void MM_seguin(void)\r
 {\r
-       mminfo.bombonerror = bomb;\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