]> 4ch.mooo.com Git - 16.git/commitdiff
deleted: src/lib/exmm/EMM.EXE
authorsparky4 <sparky4@cock.li>
Thu, 12 Feb 2015 21:09:52 +0000 (15:09 -0600)
committersparky4 <sparky4@cock.li>
Thu, 12 Feb 2015 21:09:52 +0000 (15:09 -0600)
new file:   src/lib/exmm/EMM_ALL.TXT
new file:   src/lib/exmm/XMEM.ALL
modified:   src/lib/exmm/emm.c
modified:   src/lib/exmm/memory.c
modified:   src/lib/exmm/x.bat
modified:   src/lib/exmm/xmem.c
deleted:    src/lib/exmm/xmemc.c

src/lib/exmm/EMM.EXE [deleted file]
src/lib/exmm/EMM_ALL.TXT [new file with mode: 0644]
src/lib/exmm/XMEM.ALL [new file with mode: 0644]
src/lib/exmm/emm.c
src/lib/exmm/memory.c
src/lib/exmm/x.bat
src/lib/exmm/xmem.c
src/lib/exmm/xmemc.c [deleted file]

diff --git a/src/lib/exmm/EMM.EXE b/src/lib/exmm/EMM.EXE
deleted file mode 100644 (file)
index a084353..0000000
Binary files a/src/lib/exmm/EMM.EXE and /dev/null differ
diff --git a/src/lib/exmm/EMM_ALL.TXT b/src/lib/exmm/EMM_ALL.TXT
new file mode 100644 (file)
index 0000000..9291eb6
--- /dev/null
@@ -0,0 +1,891 @@
+//      Author:  Chris Somers\r
+\r
+AJR:\r
+  This file contains 3 .h files and two .c files, and some notes\r
+  all glued together. you'll have to cut them apart to compile.\r
+\r
+//      Author:  Chris Somers\r
+\r
+To use memory.c, a few notes are in order. This file was originally used\r
+in an event-driven windowing environment, so there are several headers you\r
+won't need (so I didn't include 'em).\r
+\r
+AJR - I nuked all uneeded references from the code\r
+\r
+This code was written for Borland C/C++ v3.1 and has _not_ been tested\r
+under any other version. The first set of conventional memory calls\r
+(those flanked by #ifndef USEBORLIB) are to replace Borland's malloc\r
+library when using 3rd party libraries or APIs which called DOS's malloc.\r
+Add a -DUSEBORLIB to the compile command line to remove this code.\r
+\r
+The file, tasks.h (application specific - not included), optionally\r
+#define'd EMM_SUPPORT and TCPCOM. #define the first and not the second.\r
+\r
+AJR - I modified these sources so this isn't neccessary - all\r
+      references to TCPCOM have been deleted.\r
+\r
+Add memory.p to your application to have access to the EMM calls. Don't\r
+include memory.h - it's got static calls and variables you don't want\r
+direct access to.\r
+\r
+AJR - I added memory.p to memory.c, and cleaned up memory.h so it can\r
+      be included.\r
+\r
+      Please see emm.c for an example.\r
+\r
+returns.h and sizes.h just have the #defines for (duh!) return codes\r
+and size constants. Unfortunately, the values used for some of the\r
+return codes may not be safely changed. If they clash with codes in your\r
+program, it might be safer to rename them than to change their values\r
+and try to see where the EMM code got broken.\r
+\r
+AJR: I renamed returns.h to emmret.h and sizes.h to emmsize.h\r
+     to avoid file name clashes.\r
+\r
+Here are some notes on the calls:\r
+\r
+OpenEMM()  - call this first, period.\r
+CloseEMM() - call this last. It'll even free any EMS you forgot to free\r
+             in your program (this isn't like conventional memory, y'know)\r
+EMMInstalled() - returns TRUE or FALSE. Use only after OpenEMM() is called.\r
+EMMalloc() - returns a pointer to the first EMM page (EMMSeg:0000 hex).\r
+             Also stuffs a new handle into *Handle (*Handle == NULL is not\r
+             checked for, so be careful or fix the code). You gotta supply\r
+             Pages (i.e. number of 16K blocks).\r
+EMMRealloc() - increases/decreases number of pages allocated to your handle.\r
+EMMFree()  - frees all the pages and voids the handle.\r
+MapEMM()   - places 1 to 4 Pages into the page frame starting with page, Start.\r
+UnmapEMM() - removes the pages from the page frame so nothing else trashes\r
+             your data.\r
+UseEMM()   - same as MapEMM() but saves the frame state before mapping.\r
+SaveEMM()  - same as UnmapEMM() but restores a saved frame state after unmapping.\r
+EMMCoreLeft() - returns the number of bytes of EMM left to allocate.\r
+\r
+The comments in the MapEMM() and UseEMM() (and UnmapEMM() and SaveEMM()) speak\r
+of 'applications' and 'devices'. These refer to layers in the development\r
+environment using this .c file. The application layer could use EMS as long\r
+as it kept track of it's own usage. So it wouldn't have to keep track of the\r
+environment's usage, 'devices' (i.e. lower layers) saved the page frame\r
+state to use EMS themselves, so as not to trash the application layer's data,\r
+and restored the original state upon returning.\r
+\r
+\r
+\r
+More notes:\r
+Alexander J Russell wrote:\r
+\r
+>How do you USE emm memory?\r
+>With xms it is obvious - you copy mem back and forth.\r
+>What the parameters for mapemm() etc... mean isn't documented well enough\r
+>for a newbie to use it.\r
+\r
+EMM is alot like XMS except that the EMM driver does the copying for you,\r
+without really copying (the 386's LDTs are used to point to appropriate\r
+parts of physical memory when mapping EMM). Here's how it works.\r
+EMM has a 64K (typically) page frame in conventional memory, often at\r
+E000-EFFF. The page frame consists of four 16K pages. When you call\r
+EMMalloc(), you supply the number of 16K pages you need and it\r
+returns 1) a handle, and 2) a pointer to the page frame (i.e. E000:0000).\r
+This memory is allocated somewhere in extended memory but still\r
+unavailable. To use it, you must 'map' it into the page frame so\r
+conventional memory pointers can access it. The MapEMM() function\r
+maps the pages you need (up to four) associated with that handle \r
+into the page frame. You can now use your alloc'd memory at E000.\r
+When you're finished accessing the memory, you can unmap it using\r
+UnmapEMM(). This removes the mapping from the page frame so you can\r
+map other allocations or just protect what you've already written\r
+(i.e. writing to the page frame segment won't touch your data).\r
+N.B. You never *have to* unmap your pages. Mapping new pages\r
+automagically unmaps existing mappings - but it's good practice\r
+to unmap when you're finished.\r
+\r
+Another way to look at EMS is to consider the page frame as a window\r
+over the extended memory area. Mapping is like moving the window to\r
+some area of XMS and making it available with a conventional memory\r
+pointer - at the page frame address, which never changes. \r
+In other words, EMS 'bank switches' segments of XMS memory into\r
+conventional memory.\r
+\r
+>I think I call openemm() the use map and unmap to utilize the mem.\r
+>what does map do, what do the parms mean? Once mapped how is the mem used.\r
+\r
+Pretty close. OpenEMM() makes sure the driver is loaded and gets the\r
+page frame address (EMMSeg:0000). Then EMMalloc() reserves the specified\r
+number of 16K pages, associates them to a handle, and gives your app the\r
+page frame address. Then MapEMM() lets you use up to four pages at a time\r
+(at the address returned by EMMalloc()). The parameters for MapEMM() are:\r
+- the handle you got from EMMalloc()\r
+- the memory page # to map to the first page frame page.\r
+- the number of pages to map to the page frame (max. of 4)\r
+BTW, all numbering is zero-based.\r
+\r
+>Could you send a quick overview of how you actually use emm mem in a dos\r
+>program.\r
+\r
+ -------------------- see emm.c for example ---------------\r
+\r
+\r
+>Can I re-post your code and notes on my page?\r
+Yup. Leaving my name in the comments at the top would be much appreciated.\r
+\r
+I learnt most of this from DOS Programmer's Reference by Terry Dettmann\r
+from Que publishing (it's (C)1989 and I *still* use it!). You can check out\r
+other references dealing with int67h (the EMS API) too.\r
+\r
+Hope I didn't leave anything out. Email me again if any points aren't clear.\r
+\r
+Chris S.\r
+\r
+AJR adds:\r
+\r
+memory.c, and the h files all you need to use emm!\r
+emm.c is just a test program to show how it is used.\r
+\r
+\r
+/*\r
+   *********************************************************************\r
+   *********************************************************************\r
+\r
+                               next file\r
+\r
+   *********************************************************************\r
+   *********************************************************************\r
+*/\r
+\r
+// Cut this out as emmsize.h\r
+\r
+/*      File:       EmmSize.h\r
+ *      Module:     All Modules\r
+ *      Author(s):  Chris Somers\r
+ *      Date:       May 8, 1992\r
+ *      Version:    V.1.0\r
+ */\r
+\r
+#ifndef _EMMSIZES_DEF\r
+#define _EMMSIZES_DEF 1\r
+\r
+\r
+/* Module size constants */\r
+\r
+#define     MAXACTIONS          29\r
+#define     MAXCHANNELS          4\r
+#define     MAXFOCUS             3\r
+#define     MAXBUFTYPES         64\r
+#define     MAXEMHANDLES        64      /* up to a max of 255 */\r
+#define     MAXTIMERS           32\r
+#define     MAXTITEMS          128\r
+#define     MAXQUEUES           24\r
+#ifdef PRINTER\r
+#define     MAXPRNS              4\r
+#else\r
+#define     MAXPRNS              0\r
+#endif\r
+#ifdef UTSCOM\r
+#define     MAXUTSSCRNS          2\r
+#else\r
+#define     MAXUTSSCRNS          0\r
+#endif\r
+#ifdef CAPTURE\r
+#define     MAXCAPTURE           1\r
+#else\r
+#define     MAXCAPTURE           0\r
+#endif\r
+#define     MAXIRQS             10\r
+#define     MAXTCPDSCPTITEMS    16     /*max # of TCP connections*/\r
+\r
+#define FREEBUFF        1   /* CallIODevice flag for BuffSize arrays */\r
+#define DSCONLY         2   /* allocate a BufDscpt, only - no buffer */\r
+\r
+#define     EMMPAGESIZE     0x4000     /* 16K EMM page size */\r
+#define     SETUPLEN            32\r
+#define     NAMELEN             40\r
+#define     UNIXLEN             32\r
+#define     ADDRLEN             16\r
+#define     TITLELEN           128\r
+#define     TSLEN               80\r
+#define     COMMENTLEN          65\r
+#define     PALSIZE            768\r
+#define     QSTRLEN            254\r
+#define     PRNBUFSIZ         2048\r
+#define     TXTSCRNSIZE       4096\r
+#define     UTSBUFSIZ         4096\r
+#define     UTSSCRNSIZ        1920\r
+#define     QMEMSIZE            15\r
+#define     KBUFLEN             16\r
+#define     GXBUFFSIZE      0x4000\r
+#define     TCPNDBUFFSIZE   0x1000      /*router auto-allocation buff size*/\r
+                                        /* graphics printing scale values */\r
+#define     SCALE_HALF           1      /* value must not change */\r
+#define     SCALE_ONE            2\r
+#define     SCALE_QUART          3      /* value must not change */\r
+\r
+#define     SIXTH_SECOND         3L     /* shade over 1/6 of a second*/\r
+#define     HALF_SECOND          9L\r
+#define     ONE_SECOND          18L\r
+#define     TWO_SECONDS         36L\r
+#define     FIVE_SECONDS        91L\r
+#define     TEN_SECONDS        182L\r
+#define     HALF_MINUTE      182*3L     /* same as 18.2*30, right? */\r
+#define     ONE_MINUTE       182*6L     /* same as 18.2*60, right? */\r
+#define     TWO_MINUTES     182*12L     /* same as 18.2*120, right? */\r
+#define     FIVE_MINUTES    182*30L     /* same as 18.2*300, right? */\r
+#define     TEN_MINUTES     182*60L     /* same as 18.2*600, right? */\r
+#define     HALF_HOUR      182*180L     /* same as 18.2*1800, right? */\r
+#define     ONE_HOUR       182*360L     /* same as 18.2*3600, right? */\r
+\r
+#define MAXROUTMOVES            24      /*max # of routing moves at one time*/\r
+                                        /*also max # of Move Complete Events*/\r
+/* Event Channel Defines */\r
+\r
+#define MAXRECALLEVENTS    1   /*max nm of Recall Event Channels*/\r
+#define MAXKBDEVENTS       1   /*max nm of Kbd Event Channels*/\r
+#define MAXPRNEVENTS       4   /*max nm of Prt Prog & Prt Cmplte Event Chan*/\r
+#define MAXUTSRCVEVENTS    MAXUTSSCRNS       /*max nm of Uts Rx Event Chans*/\r
+#define MAXUTSXMTEVENTS    MAXUTSSCRNS       /*max nm of Uts Tx Event Chans*/\r
+#define MAXCAPEVENTS       2   /* max number of capture event channels */\r
+#define MAXOP1CMPLTEVENTS  1   /*max nm of Operation 1 Cmplt Event Channels*/\r
+#define MAXOP2CMPLTEVENTS  1   /*max nm of Operation 2 Cmplt Event Channels*/\r
+#define MAXOP3CMPLTEVENTS  MAXTCPDSCPTITEMS  /*max nm of Op 3 Event Chans*/\r
+#define MAXTCPEVENTS       MAXTCPDSCPTITEMS  /* max nm of TCP Event types */\r
+\r
+#endif\r
+\r
+/*\r
+   *********************************************************************\r
+   *********************************************************************\r
+\r
+                               next file\r
+\r
+   *********************************************************************\r
+   *********************************************************************\r
+*/\r
+\r
+// AJR notes: some of these are not used by the emm code\r
+\r
+// Cut this out as emmret.h\r
+\r
+/*      File:       EmmRet.h\r
+ *      Module:     All Modules\r
+ *      Author(s):  Chris Somers\r
+ *      Date:       May 8, 1992\r
+ *      Version:    V.1.0\r
+ */\r
+\r
+#ifndef _EMM_RETURNS_DEF\r
+#define _EMM_RETURNS_DEF 1\r
+\r
+/* Module return values */\r
+\r
+/* Return Values */\r
+\r
+#define     START                8\r
+#define     END                  7\r
+#define     MOVABORT             6\r
+#define     PRN_COMPLETE         5\r
+#define     PRN_PROGRESS         4\r
+#define     INCOMPLETE           3\r
+#define     HAVEROOM             2\r
+#define     SUCCESS              1\r
+#define     TRUE                 1\r
+#define     YES                  1\r
+#define     FALSE                0\r
+#define     NO                   0\r
+#define     NOTREADY             0\r
+#define     NO_DATA              0\r
+#define     NONE                -1\r
+\r
+/* Start of Recoverable error codes */\r
+\r
+#define     NO_SPACE            -1001\r
+#define     NOTPOLLING          -1002\r
+#define     ALREADYDONE         -1003\r
+#define     NO_PRN_DEV          -1004\r
+#define     OUTF_PAPER          -1005\r
+#define     NO_VIDEO            -1006\r
+#define     TIMEOUT             -1007\r
+#define     FILENOPEN           -1008\r
+#define     ABORT_REQ           -1009\r
+#define     DEV_IOERR           -1010\r
+\r
+#define     MAXRERR                10\r
+#define     RECOVERABLE         -1999   /* all above errors are recoverable */\r
+\r
+/* Start of Threadfatal error codes */\r
+\r
+#define     NOT_OPEN            -2001\r
+#define     NOT_ATTACHED        -2002\r
+#define     NO_CONNECTION       -2003\r
+#define     INSUFF_MEM          -2004\r
+#define     NR_TIMEOUT          -2005\r
+\r
+#define     MAXTERR                 5\r
+#define     THREADFATAL         -2999   /* above errors force task to cancel */\r
+\r
+/* Start of Systemfatal error codes */\r
+\r
+#define     BAD_TASKNUM         -3001\r
+#define     BAD_HANDLE          -3002\r
+#define     BAD_HARDWARE        -3003\r
+#define     INVALIDACTION       -3004\r
+#define     NOFREEITEMS         -3005\r
+#define     NO_MEMORY           -3006\r
+#define     NO_EMS              -3007\r
+#define     VALUE_OUTF_RANGE    -3008\r
+#define     BAD_MODE            -3009\r
+#define     NO_PALETTE          -3010\r
+#define     BAD_DISPPAGE        -3011\r
+#define     NO_TSR              -3012\r
+#define     BUFTOOSMALL         -3013\r
+#define     BAD_NAME            -3014\r
+#define     BAD_DISPHW          -3015\r
+#define     NO_FLOPPY           -3016\r
+\r
+#define     MAXSERR                16\r
+#define     SYSTEMFATAL         -3999   /* above errors are fatal to system */\r
+\r
+#endif\r
+\r
+/*\r
+   *********************************************************************\r
+   *********************************************************************\r
+\r
+                               next file\r
+\r
+   *********************************************************************\r
+   *********************************************************************\r
+*/\r
+\r
+// Cut this out as memory.h\r
+\r
+/*      File:       Memory.h\r
+ *      Module:     All Modules\r
+ *      Author(s):  Chris Somers\r
+ *      Date:       August 5, 1993\r
+ *      Version:    V.1.1\r
+\r
+        modified by Alex Russell to simplify.\r
+ */\r
+\r
+\r
+#ifndef _MEMORY_DEF\r
+#define _MEMORY_DEF 1\r
+\r
+#include "emmret.h"\r
+#include "emmsize.h"\r
+\r
+#define     CMM                  0\r
+#define     EMM                  1\r
+\r
+extern int      OpenEMM(void);\r
+extern void     CloseEMM(void);\r
+extern int      EMMInstalled(void);\r
+extern void far *EMMalloc(int *Handle, int Pages);\r
+extern int      EMMRealloc(int Handle, int Pages);\r
+extern void     EMMFree(int Handle);\r
+extern int      MapEMM(int Handle, int Start, int Pages);\r
+extern void     UnmapEMM(int Handle, int Start, int Pages);\r
+extern int      UseEMM(int Handle, int Start, int Pages);\r
+extern void     SaveEMM(int Handle, int Start, int Pages);\r
+extern unsigned long EMMCoreLeft(void);\r
+\r
+#endif\r
+\r
+/*\r
+   *********************************************************************\r
+   *********************************************************************\r
+\r
+                               next file\r
+\r
+   *********************************************************************\r
+   *********************************************************************\r
+*/\r
+\r
+\r
+/*      File:       Memory.c\r
+ *      Module:     All Modules\r
+ *      Author(s):  Chris Somers\r
+ *      Date:       December 1, 1992\r
+ *      Version:    V.1.1\r
+\r
+        minor mods by Alex Russell to simplify\r
+\r
+        Must use memory model with FAR code\r
+\r
+ */\r
+\r
+\r
+\r
+#if !defined(__LARGE__) && !defined(__COMPACT__) && !defined(__HUGE__)\r
+#error Invalid memory model for compiling MEMORY.C\r
+#endif\r
+\r
+#include <stdio.h>\r
+#include <dos.h>\r
+#include <mem.h>\r
+\r
+#include "memory.h"\r
+\r
+// static globals --------------------------------\r
+\r
+static int  ActiveEMList[MAXEMHANDLES];\r
+static unsigned int  EMMSeg;\r
+\r
+// forward declarations ---------------------------------\r
+\r
+static int  EMPresent(void);\r
+static int  EMReady(void);\r
+static unsigned int  GetEMMSeg(void);\r
+static int  GetEMHandle(int NumPages);\r
+static int  EMMap(int Handle, int LogPg, int PhyPg);\r
+static int  FreeEMHandle(int Handle);\r
+static int  GetNumPages(int Handle);\r
+static int  EMStateSave(int Handle);\r
+static void EMStateRestore(int Handle);\r
+\r
+\r
+/********************************************************************/\r
+int\r
+OpenEMM(void)\r
+{\r
+    if (!EMPresent() || !EMReady()) return(NOTREADY);\r
+    if (!(EMMSeg = GetEMMSeg())) return(NOTREADY);  /*lint !e720 */\r
+    return(SUCCESS);\r
+}               /* End of OpenEMM() */\r
+\r
+/********************************************************************/\r
+\r
+void\r
+CloseEMM(void)\r
+{\r
+    int     i;\r
+\r
+    if (!EMMSeg) return;\r
+    for (i = 0; i < MAXEMHANDLES; i++) {\r
+        if (ActiveEMList[i]) {\r
+            FreeEMHandle(ActiveEMList[i]);\r
+            ActiveEMList[i] = 0;\r
+        }\r
+    }\r
+    EMMSeg = 0;\r
+}               /* End of CloseEMM() */\r
+\r
+/********************************************************************/\r
+\r
+int\r
+EMMInstalled(void)\r
+{\r
+    return((EMMSeg) ? TRUE : FALSE);        /* successfully opened? */\r
+}               /* End of EMMInstalled() */\r
+\r
+/********************************************************************/\r
+\r
+unsigned long\r
+EMMCoreLeft(void)\r
+{\r
+    unsigned      Pages;\r
+    unsigned long RtnVal = 0UL;\r
+\r
+    _asm {\r
+        mov     ah,0x42             /* get EMM free page count */\r
+        int     0x67\r
+        or      ah,ah\r
+        js      InternalError       /* returns 80, 81, or 84 hex on error */\r
+        mov     Pages,bx            /* number of unallocated 16K pages */\r
+    }\r
+    RtnVal = ((unsigned long)Pages << 14);  /* Pages * 16K rtns bytes*/\r
+\r
+InternalError:\r
+\r
+    return(RtnVal);\r
+}               /* End of EMMCoreLeft() */\r
+\r
+/********************************************************************/\r
+\r
+void far *\r
+EMMalloc(int *Handle, int Pages)\r
+{\r
+    int     i;\r
+    char    *RtnPtr = NULL;\r
+\r
+    if (!EMMSeg) {\r
+        *Handle = NOTREADY;\r
+        return(NULL);\r
+    }\r
+    if ((Pages < 1) || (Pages > 1020)) {\r
+        *Handle = VALUE_OUTF_RANGE;\r
+        return (NULL);\r
+    }\r
+    for (i = 0; (i < MAXEMHANDLES) && (ActiveEMList[i]); i++) ;\r
+    if (i == MAXEMHANDLES) {\r
+        *Handle = NOFREEITEMS;\r
+        return (NULL);\r
+    }\r
+    if ((ActiveEMList[i] = GetEMHandle(Pages)) > 0) {\r
+        RtnPtr = MK_FP(EMMSeg, 0);\r
+    }\r
+    *Handle = ActiveEMList[i];\r
+    return((void far *)RtnPtr);\r
+}               /* End of EMMalloc() */\r
+\r
+/********************************************************************/\r
+\r
+int\r
+EMMRealloc(int Handle, int Pages)\r
+{\r
+    int     RtnCode = FALSE;\r
+\r
+    if (!EMMSeg || (Pages < 0) || (Pages > 1020)) {\r
+        return (FALSE);\r
+    }\r
+    _asm {\r
+        mov     ah,0x51             /* change # of pages */\r
+        mov     bx,Pages\r
+        mov     dx,Handle\r
+        int     0x67\r
+        or      ah,ah\r
+        js      NoGo                /* returns 80 to 88 hex on error */\r
+    }\r
+    RtnCode = TRUE;\r
+\r
+NoGo:\r
+\r
+    return(RtnCode);\r
+}               /* End of EMMRealloc() */\r
+\r
+/********************************************************************/\r
+\r
+void\r
+EMMFree(int Handle)\r
+{\r
+    int     i, j;\r
+\r
+    if (!EMMSeg) return;\r
+    for (i = 0; (i < MAXEMHANDLES) && (ActiveEMList[i] != Handle); i++) ;\r
+    if (i >= MAXEMHANDLES) return;\r
+    j = 16;\r
+    while (j--) {\r
+        if (FreeEMHandle(ActiveEMList[i])) break;\r
+    }\r
+    ActiveEMList[i] = 0;\r
+}               /* End of EMMFree() */\r
+\r
+/********************************************************************/\r
+\r
+int                                         /* EMM map for application */\r
+MapEMM(int Handle, int Start, int Pages)\r
+{\r
+    int     i;\r
+\r
+    if (!EMMSeg) return(NOTREADY);\r
+    for (i = 0; (i < MAXEMHANDLES) && (ActiveEMList[i] != Handle); i++) ;\r
+    if (i == MAXEMHANDLES) return (NO_DATA);\r
+    if ((GetNumPages(Handle) < Pages) || (Pages < 1) || (Pages > 4)) {\r
+        return (VALUE_OUTF_RANGE);\r
+    }\r
+    for (i = Start; i < Start + Pages; i++) {\r
+        if (!EMMap(Handle, i, i - Start)) return(NO_DATA);\r
+    }\r
+    return(SUCCESS);\r
+}               /* End of MapEMM() */\r
+\r
+/********************************************************************/\r
+\r
+void                                        /* EMM unmap for application */\r
+UnmapEMM(int Handle, int Start, int Pages)\r
+{\r
+    int     i, j;\r
+\r
+    if (!EMMSeg) return;\r
+    for (i = 0; (i < MAXEMHANDLES) && (ActiveEMList[i] != Handle); i++) ;\r
+    if (i == MAXEMHANDLES) return;\r
+    j = Start + Pages;\r
+    if ((Pages < 1) || (j > 4)) return;\r
+\r
+    for (i = Start; i < j; i++) {\r
+        EMMap(Handle, NONE, i);\r
+    }\r
+}               /* End of UnmapEMM() */\r
+\r
+/********************************************************************/\r
+\r
+int                     /* EMM map for devices - saves EMM state */\r
+UseEMM(int Handle, int Start, int Pages)\r
+{\r
+    EMStateSave(Handle);\r
+    return(MapEMM(Handle, Start, Pages));\r
+}               /* End of UseEMM() */\r
+\r
+/********************************************************************/\r
+\r
+void                    /* EMM unmap for devices - restores EMM state */\r
+SaveEMM(int Handle, int Start, int Pages)\r
+{\r
+    UnmapEMM(Handle, Start, Pages);\r
+    EMStateRestore(Handle);\r
+}               /* End of SaveEMM() */\r
+\r
+/********************************************************************/\r
+\r
+static int\r
+EMPresent(void)\r
+{\r
+    int     i, Segment;\r
+    char    EMName[] = "EMMXXXX0";\r
+    char    *s, *t;\r
+\r
+    _asm {                      /* can be replaced with getvect() */\r
+        push    es\r
+        mov     ax,0x3567       /* get vector for int 67h */\r
+        int     0x21\r
+        mov     ax,es\r
+        mov     Segment,ax\r
+        pop     es\r
+    }\r
+    t = MK_FP(Segment, 0x0A);   /* point to driver name */\r
+    s = EMName;\r
+    for (i = 0; (i < 8) && (*s++ == *t++); i++) ;   /* strncmp equivalent */\r
+\r
+    if (i == 8) return(TRUE);\r
+    return(FALSE);\r
+}               /*End of EMPresent() */\r
+\r
+/********************************************************************/\r
+\r
+static int\r
+EMReady(void)\r
+{\r
+    _asm {\r
+        mov     ah,0x40             /* get EM Manager Status */\r
+        int     0x67\r
+        or      ah,ah\r
+        jns     Ready               /* returns 80, 81, or 84 hex on error */\r
+    }\r
+    return(FALSE);\r
+\r
+Ready:\r
+    return(TRUE);\r
+}               /* End of EMReady() */\r
+\r
+/********************************************************************/\r
+\r
+static unsigned int\r
+GetEMMSeg(void)\r
+{\r
+    unsigned int     EMSegment;\r
+\r
+    _asm {\r
+        mov     ah,0x41             /* get EMM page frame segment */\r
+        int     0x67\r
+        or      ah,ah\r
+        js      NotReady            /* returns 80, 81, or 84 hex on error */\r
+        mov     EMSegment,bx\r
+    }\r
+    return(EMSegment);              /*lint !e530 */\r
+\r
+NotReady:\r
+    return(NOTREADY);\r
+}               /* End of GetEMMSeg() */\r
+\r
+/********************************************************************/\r
+\r
+static int\r
+GetEMHandle(int NumPages)\r
+{\r
+    int     NewHandle;\r
+\r
+    _asm {\r
+        mov     ah,0x43             /* get handle and allocate EM */\r
+        mov     bx,NumPages         /* number of 16K pages to allocate */\r
+        int     0x67\r
+        or      ah,ah               /* returns 80 to 89 hex on error */\r
+        js      NoHandle\r
+        mov     NewHandle,dx        /* retrieve handle */\r
+    }\r
+    return(NewHandle);\r
+\r
+NoHandle:\r
+    return(NO_DATA);\r
+}               /* End of GetEMHandle() */\r
+\r
+/********************************************************************/\r
+\r
+static int\r
+EMMap(int Handle, int LogPg, int PhyPg)\r
+{\r
+    int     RtnCode = NO_DATA;\r
+\r
+    _asm {\r
+        mov     ax,PhyPg            /* physical page: 0 - 3 in AL only */\r
+        mov     ah,0x44             /* map logical to physical page */\r
+        mov     bx,LogPg            /* logical page: 0 - 1020 */\r
+        mov     dx,Handle\r
+        int     0x67\r
+        or      ah,ah               /* returns 80 to 8B hex on error */\r
+        js      NoMapping\r
+    }\r
+    RtnCode = SUCCESS;\r
+\r
+NoMapping:\r
+    return(RtnCode);\r
+}               /* End of EMMap() */\r
+\r
+/********************************************************************/\r
+\r
+static int\r
+FreeEMHandle(int Handle)\r
+{\r
+    _asm {\r
+        mov     ah,0x45             /* free handle and deallocate EM */\r
+        mov     dx,Handle\r
+        int     0x67\r
+        or      ah,ah               /* returns 80 to 86 hex on error */\r
+        js      NotFreed\r
+    }\r
+    return(SUCCESS);\r
+\r
+NotFreed:                           /* must retry if unsuccessful */\r
+    return(NO_DATA);\r
+}               /* End of FreeEMHandle() */\r
+\r
+/********************************************************************/\r
+\r
+static int\r
+GetNumPages(int Handle)\r
+{\r
+    int     NumPages = 0;\r
+\r
+    _asm {\r
+        mov     ah,0x4C             /* get allocated pages for Handle */\r
+        mov     dx,Handle\r
+        int     0x67\r
+        or      ah,ah               /* returns 80 to 84 hex on error */\r
+        js      BadHandle\r
+        mov     NumPages,bx\r
+    }\r
+BadHandle:\r
+\r
+    return(NumPages);\r
+}               /* End of GetNumPages() */\r
+\r
+/********************************************************************/\r
+\r
+static int\r
+EMStateSave(int Handle)\r
+{\r
+    int     RtnCode = NO_MEMORY;\r
+    _asm {\r
+        mov     ah,0x47             /* save page map under Handle */\r
+        mov     dx,Handle\r
+        int     0x67\r
+        or      ah,ah\r
+        js      Unsaved             /* out of save space error */\r
+    }\r
+    RtnCode = SUCCESS;\r
+\r
+Unsaved:\r
+    return(RtnCode);\r
+}               /* End of EMStateSave() */\r
+\r
+/********************************************************************/\r
+\r
+static void\r
+EMStateRestore(int Handle)\r
+{\r
+    _asm {\r
+        mov     ah,0x48             /* restore page map for Handle */\r
+        mov     dx,Handle\r
+        int     0x67                /* ignore error */\r
+    }\r
+}               /* End of EMStateRestore() */\r
+\r
+/********************************************************************/\r
+\r
+/*\r
+   *********************************************************************\r
+   *********************************************************************\r
+\r
+                               next file\r
+\r
+   *********************************************************************\r
+   *********************************************************************\r
+*/\r
+\r
+// Cut this out as emm.c\r
+\r
+/*      File:       emm.c\r
+ *      Module:     All Modules\r
+ *      Author(s):  Chris Somers\r
+ *      Date:       December 1, 1992\r
+ *      Version:    V.1.1\r
+\r
+        minor mods by Alex Russell to simplify\r
+\r
+        Must use memory model with FAR code\r
+\r
+ */\r
+\r
+\r
+#include <stdio.h>\r
+#include <stdlib.h>\r
+#include <mem.h>\r
+\r
+#include "memory.h"\r
+\r
+void TransformData(char *pEmmData, unsigned int len)\r
+{\r
+   while ( len )\r
+      {\r
+      (*pEmmData)++;\r
+      pEmmData++;\r
+\r
+      len--;\r
+      }\r
+}\r
+\r
+void main(void)\r
+{\r
+   char    *pEmmData;\r
+   int     hEData;\r
+\r
+   if ( OpenEMM() != SUCCESS )\r
+      {     // make sure we got EMM\r
+      printf("EMM unavailable.\n");\r
+      exit(1);\r
+      }\r
+   else\r
+      printf("Emm available\n");\r
+\r
+   pEmmData = EMMalloc(&hEData, 6);  // get 6 * 16K bytes - 96K\r
+   if ( pEmmData == NULL )\r
+      {\r
+      printf("Not enough EMM or out of handles.\n");\r
+      exit(2);\r
+      }\r
+   else\r
+      printf("emm alloced OK\n");\r
+\r
+\r
+   printf("Map 1st 4 pages\n");\r
+   MapEMM(hEData, 0, 4);   // load 1st 4 pages into page frame: 0-3\r
+\r
+   memset(pEmmData, 0x0e, 64000u);\r
+   UnmapEMM(hEData, 0, 4);          // not absolutely necessary\r
+   \r
+   printf("Map next 2 pages\n");\r
+   MapEMM(hEData, 4, 2);            // map last 2 pages: 4-5\r
+   memset(pEmmData, 0x0e, 32768u);\r
+\r
+   MapEMM(hEData, 0, 4);\r
+   // do some stuff with the first 64K of file data.\r
+   printf("Transform data\n");\r
+   TransformData(pEmmData, 64000UL);\r
+   MapEMM(hEData, 4, 2);  // only unmaps 1st two pages of prior 64k mapping\r
+   // do stuff with remaining 32K of data\r
+   TransformData(pEmmData, 32768UL);\r
+   UnmapEMM(hEData, 0, 4);  // should unmap before freeing\r
+\r
+   printf("Close emm\n");\r
+   EMMFree(hEData);     // finished with the file data\r
+   CloseEMM();\r
+}\r
+\r
diff --git a/src/lib/exmm/XMEM.ALL b/src/lib/exmm/XMEM.ALL
new file mode 100644 (file)
index 0000000..3e504e5
--- /dev/null
@@ -0,0 +1,1140 @@
+This file contains 3 files:\r
+xmem.h   : c include file\r
+xmem.asm : low level basic XMS acess\r
+xmemc.c  : super easy C access via functions like fopen, fread, fwrite\r
+           xopen, xread, xwrite, xseek etc...\r
+\r
+FOR DOS REAL mode programs, requires HIMEM.SYS to be loaded in\r
+config.sys.\r
+\r
+XMEM.H ------------- START --------------------------------------------------\r
+#if !defined(_XMEM_H)\r
+#define _XMEM_H\r
+\r
+typedef struct xms_node\r
+   {\r
+   long start, size, off;\r
+   short used;\r
+   struct xms_node *next;\r
+   }\r
+xms_node_t;\r
+\r
+typedef struct\r
+   {\r
+   int handle;\r
+   unsigned long total;\r
+   unsigned long avail;\r
+   unsigned long next_off;\r
+   xms_node_t *next;\r
+   }\r
+xms_head_t;\r
+\r
+#define XMSBLOCK 16384u\r
+#define XMSBLOCKSHIFT 14\r
+\r
+extern void LSHL( unsigned long far *SHLnumber, unsigned short n );\r
+\r
+extern unsigned short XMS_available( void );\r
+\r
+extern unsigned short XMSblk_available( void );\r
+\r
+extern short XMS_alloc(unsigned short rsrvd,\r
+                       unsigned short far *size\r
+                      );\r
+extern short XMS_dealloc(unsigned short Hdl );\r
+extern short XMStoMem(unsigned short Handle,   // XMS handle returned by XMS_alloc()\r
+                      unsigned short blk,      // which 16k block to copy to\r
+                      unsigned short blkAdr,   // offset within 16k block\r
+                      unsigned short Bytes,    // bytes to copy\r
+                      void   far *memAdr\r
+                     );\r
+extern short MemToXMS(unsigned short Handle,\r
+                      unsigned short blk,\r
+                      unsigned short blkAdr,\r
+                      unsigned short Bytes,\r
+                      void   far *memAdr\r
+                     );\r
+\r
+// call these for ease\r
+short alloc_xms(unsigned short far *size);  // size in 16k blocks\r
+// NOTE size is changed to the amount block size was altered by!\r
+// normaly this is zero\r
+\r
+short xms_to_mem(unsigned short handle, void far *p, unsigned long off, unsigned short n);\r
+short mem_to_xms(unsigned short handle, void far *p, unsigned long off, unsigned short n);\r
+void deinit_xms(void);\r
+short init_xms(unsigned short min_blocks);\r
+void qfree_xms(xms_node_t *node);\r
+xms_node_t *qalloc_xms(unsigned long size);\r
+xms_node_t *xms_open(char *file);\r
+short xms_read(void far *buffer, unsigned short n, xms_node_t *node);\r
+short xms_write(void far *buffer, unsigned short n, xms_node_t *node);\r
+long xms_tell(xms_node_t *node);\r
+short xms_seek(xms_node_t *node, long off, short whence);\r
+void xms_close(xms_node_t *node);\r
+\r
+extern xms_head_t xms_head;\r
+\r
+#endif\r
+/* ---------------------------------- end of file --------------------- */\r
+\r
+XMEM.H ------------- END --------------------------------------------------\r
+\r
+xmem.asm --------------------- START --------------------------------------\r
+;-----------------------------------------------------------------------\r
+;\r
+.MODEL MEDIUM\r
+\r
+        EXTmemError     EQU     7\r
+        XMSmemError     EQU     8\r
+\r
+\r
+        ShortAdr        EQU     0\r
+        LongAdr         EQU     1\r
+\r
+procname        MACRO  Pnam\r
+        PUBLIC  _&Pnam&\r
+_&Pnam&  PROC    FAR\r
+ENDM\r
+\r
+endproc         MACRO  Pnam\r
+\r
+_&Pnam&  ENDP\r
+\r
+ENDM\r
+\r
+pwrlolvl_TEXT   SEGMENT WORD PUBLIC 'CODE'\r
+\r
+        ASSUME  CS:pwrlolvl_TEXT, DS:pwrlolvl_TEXT, ES:pwrlolvl_TEXT\r
+\r
+SUBTTL  (Local Procedure) XMS_setup - find a XMS driver.\r
+PAGE+\r
+\r
+                EVEN\r
+XMSwordByte     LABEL BYTE\r
+XMSword         DW      0\r
+\r
+XMSmoveSTRUC    STRUC\r
+\r
+Length          DW      0\r
+LengthX         DW      0\r
+SrcHandle       DW      0\r
+SrcOffset       DW      0\r
+SrcOffsetX      DW      0\r
+DestHandle      DW      0\r
+DestOffset      DW      0\r
+DestOffsetX     DW      0\r
+\r
+XMSmoveSTRUC    ENDS\r
+\r
+XMSmainGET      XMSmoveSTRUC  <>\r
+XMSmainPUT      XMSmoveSTRUC  <>\r
+XMSwordGET      XMSmoveSTRUC  <2,,,,,,OFFSET XMSword>\r
+XMSwordPUT      XMSmoveSTRUC  <2,,,OFFSET XMSword>\r
+\r
+XMSfunctAdr     DW      0, 0\r
+\r
+; Don't try to call this from your programs\r
+\r
+XMS_setup               PROC NEAR\r
+\r
+        PUSH    DS\r
+        PUSH    ES\r
+        PUSH    BX\r
+\r
+        MOV     AX,CS                   ; Set Data segment to the code segment.\r
+        MOV     DS,AX                   ;\r
+        MOV     [XMSwordGET.DestOffsetX],AX  ; Set up the move data structures.\r
+        MOV     [XMSwordPUT.SrcOffsetX],AX   ;\r
+\r
+        MOV     AX,4300H                ; See if a XMS Driver Exists.\r
+        INT     2FH                     ;\r
+        CMP     AL,80H                  ;\r
+        MOV     AX,0                    ;\r
+        JNE     XMS_setup01             ; Return 0 if not.\r
+\r
+        MOV     AX,4310H                ; If so, set the driver's function\r
+        INT     2FH                     ;  address.\r
+        MOV     [XMSfunctAdr],BX        ;\r
+        MOV     [XMSfunctAdr+2],ES      ;\r
+\r
+        MOV     AX,1                    ; Return 1.\r
+\r
+  XMS_setup01:\r
+        POP     BX\r
+        POP     ES\r
+        POP     DS\r
+\r
+        RET\r
+\r
+XMS_setup               ENDP\r
+\r
+SUBTTL  LSHL - Shift an unsigned long left\r
+PAGE+\r
+\r
+ ;****************************************************************************\r
+ ;* \r
+ ;* Shift an unsigned long integer left n number of bits.\r
+ ;*\r
+ ;****************************************************************************\r
+\r
+ ;\r
+ ; Stack frame definition for void LSHL( unsigned long *SHLnumber, unsigned n );\r
+ ;\r
+\r
+LSHLparms STRUC\r
+\r
+        DW      0, 0\r
+        DW      0\r
+SHLadr   DD      ?\r
+SHLn     DW      ?\r
+\r
+LSHLparms ENDS\r
+\r
+procname  LSHL\r
+\r
+        PUSH    BP\r
+        MOV     BP,SP\r
+\r
+        PUSH    BX\r
+        PUSH    CX\r
+        PUSH    DX\r
+\r
+        PUSH    DS\r
+        LDS     BX,SHLadr[BP]\r
+        MOV     CX,SHLn[BP]\r
+\r
+        MOV     AX,[BX]                 ; Get the long integer.\r
+        MOV     DX,[BX+2]               ; \r
+\r
+ LSHL_01:\r
+        SHL     AX,1                    ; Do the long shift.\r
+        RCL     DX,1                    ; \r
+        LOOP    LSHL_01                 ; \r
+\r
+        MOV     [BX],AX                 ; Replace the addressed number.\r
+        MOV     [BX+2],DX               ; \r
+\r
+        POP     DS\r
+        POP     DX\r
+        POP     CX\r
+        POP     BX\r
+\r
+        POP     BP\r
+        RET                             ; Exit\r
+\r
+endproc   LSHL\r
+\r
+\r
+SUBTTL  Extended Memory - Stack template for EXTget, EXTput\r
+PAGE+\r
+\r
+EXTgpparms STRUC\r
+\r
+        DW      0, 0\r
+        DW      0\r
+extgpBase    DW      ?\r
+extgpblk     DW      ?\r
+extgpblkAdr  DW      ?\r
+extgpBytes   DW      ?\r
+extgpmemAdr  DW      ?\r
+             DW      ?\r
+\r
+EXTgpparms ENDS\r
+\r
+\r
+\r
+SUBTTL  Extended Memory - XMS - Return total XMS memory.\r
+PAGE+\r
+\r
+ ; Use this function to detect wether or not XMS driver installed\r
+ ;\r
+ ; Stack frame definition for unsigned XMS_available( void );\r
+ ;\r
+ ;  The total XMS memory available (in 16k blocks) is returned.\r
+ ;\r
+procname  XMS_available\r
+\r
+        PUSH    BX\r
+        PUSH    CX\r
+        PUSH    DX\r
+\r
+        CALL    XMS_setup               ; Ensure XMS memory is set.\r
+        TEST    AX,AX                   ;\r
+        JZ      XMS_available01         ; Return zero if not.\r
+\r
+        MOV     AH,08H                  ; Set the size function code.\r
+        CALL    DWORD PTR CS:[XMSfunctAdr] ; Get the size.\r
+        TEST    AX,AX                   ;\r
+        JZ      XMS_available01         ;\r
+\r
+        MOV     AX,DX                   ; Set available Kbytes.\r
+        SUB     AX,64                   ; Subtract out the HMA (HIMEM.SYS bug).\r
+        JNC     XMS_available01         ;\r
+        XOR     AX,AX                   ; Set zero if underflow.\r
+\r
+  XMS_available01:\r
+        MOV     CL,4                    ; Divide Kbytes by 16 for blocks.\r
+        SHR     AX,CL                   ;\r
+\r
+        POP     DX\r
+        POP     CX\r
+        POP     BX\r
+\r
+        RET                             ; Exit\r
+\r
+endproc   XMS_available\r
+\r
+SUBTTL  Extended Memory - XMS - Return largest block XMS mem.\r
+PAGE+\r
+\r
+ ;\r
+ ; Stack frame definition for unsigned XMSblk_available( void );\r
+ ;\r
+ ;  The size of the largest block of XMS memory available,\r
+ ;  (in 16Kbyte blocks) is returned.\r
+ ;\r
+procname  XMSblk_available\r
+\r
+        PUSH    BX\r
+        PUSH    CX\r
+        PUSH    DX\r
+\r
+        CALL    XMS_setup               ; Ensure XMS memory is set.\r
+        TEST    AX,AX                   ;\r
+        JZ      XMSblk_available01      ; Return zero if not.\r
+\r
+        MOV     AH,08H                  ; Set the size function code.\r
+        CALL    DWORD PTR CS:[XMSfunctAdr] ; Get the size.\r
+        TEST    AX,AX                   ;\r
+        JZ      XMSblk_available01      ;\r
+\r
+        SUB     DX,64                   ; Subtract out the HMA (HIMEM.SYS bug).\r
+        JNC     XMSblk_available0X      ;\r
+        XOR     DX,DX                   ; Set zero if underflow.\r
+\r
+ XMSblk_available0X:\r
+        CMP     AX,DX                   ;\r
+        JBE     XMSblk_available01      ;\r
+        MOV     AX,DX                   ; Set available Kbytes.\r
+\r
+  XMSblk_available01:\r
+        MOV     CL,4                    ; Divide Kbytes by 16 for blocks.\r
+        SHR     AX,CL                   ;\r
+\r
+        POP     DX\r
+        POP     CX\r
+        POP     BX\r
+\r
+        RET                             ; Exit\r
+\r
+endproc   XMSblk_available\r
+\r
+SUBTTL  Extended Memory - XMS De-allocate a memory block.\r
+PAGE+\r
+\r
+ ;\r
+ ; Stack frame definition for int XMS_dealloc( int Hdl );\r
+ ;\r
+ ; Zero is returned if the operation fails, non-zero if success.\r
+ ;\r
+ ; its really important to do this, only other way to recover\r
+ ; XMS blocks is to re-boot\r
+\r
+XMSdealparms STRUC\r
+\r
+        DW      0, 0\r
+        DW      0\r
+xmsdealHdl  DW      ?\r
+\r
+XMSdealparms ENDS\r
+\r
+\r
+procname  XMS_dealloc\r
+\r
+        PUSH    BP\r
+        MOV     BP,SP\r
+\r
+        PUSH    BX\r
+        PUSH    DX\r
+\r
+;        CALL    XMS_setup               ; Ensure XMS memory is set.\r
+;        TEST    AX,AX                   ;\r
+;        JZ      XMS_dealloc01           ; Return zero if not.\r
+\r
+        MOV     DX,xmsdealHdl[BP]       ; Get the handle to de-allocate.\r
+        MOV     AH,0AH                  ;\r
+\r
+        CALL    DWORD PTR CS:[XMSfunctAdr] ; De-allocate it.\r
+\r
+  XMS_dealloc01:\r
+        POP     DX\r
+        POP     BX\r
+\r
+        POP     BP\r
+        RET                             ; Exit\r
+\r
+endproc   XMS_dealloc\r
+\r
+SUBTTL  Extended Memory - XMS Allocate a memory block.\r
+PAGE+\r
+\r
+ ;\r
+ ; Stack frame definition for int XMS_alloc( unsigned rsrvd, *size );\r
+ ;\r
+ ;     rsrved and size are in 16K byte blocks.\r
+ ;     rsrved is mem set aside for EMS, generaly zero\r
+ ;\r
+ ;  Zero is returned if the operation fails.\r
+ ;  Block (XMS) handle is returned if success.\r
+ ;\r
+ ;  size - is reduced by the amount of XMS memory actually allocated.\r
+ ;\r
+\r
+XMSalparms STRUC\r
+\r
+        DW      0, 0\r
+        DW      0\r
+xmsalrsrvd DW      ?\r
+xmsalsize  DD      ?\r
+\r
+XMSalparms ENDS\r
+\r
+procname  XMS_alloc\r
+\r
+        PUSH    BP\r
+        MOV     BP,SP\r
+\r
+        PUSH    BX\r
+        PUSH    CX\r
+        PUSH    DX\r
+        PUSH    DI\r
+        PUSH    ES\r
+        PUSH    DS\r
+\r
+        MOV     AX,CS                   ; Set the data segment to the code\r
+        MOV     DS,AX                   ;  segment.\r
+\r
+        MOV     CX,4                    ;\r
+        ADD     xmsalrsrvd[BP],CX       ; Subtract out the HMA (HIMEM.SYS bug).\r
+        SHL     xmsalrsrvd[BP],CL       ; Convert reserved blocks to K-bytes.\r
+\r
+        LES     DI,xmsalsize[BP]        ; Load size address.\r
+        XOR     AX,AX                   ;\r
+        MOV     BX,ES:[DI]              ; Get the requested size in blocks.\r
+\r
+        TEST    BX,0F000H               ; Check for more than 64 Megabytes.\r
+        JZ      XMS_alloc01             ;\r
+        MOV     BX,00FFFH               ;\r
+\r
+  XMS_alloc01:\r
+        MOV     CL,4                    ;\r
+        SHL     BX,CL                   ; Convert to K-Bytes.\r
+        MOV     CX,BX                   ; In CX.\r
+        JZ      XMS_alloc05             ; Return zero if no size requested.\r
+\r
+;        CALL    XMS_setup               ; Ensure XMS memory is set.\r
+;        TEST    AX,AX                   ;\r
+;        JZ      XMS_alloc05             ; Return zero if not.\r
+\r
+        XOR     BX,BX                   ;\r
+        MOV     AH,08H                  ; Set to Query Free XMS Memory.\r
+        CALL    DWORD PTR [XMSfunctAdr] ;\r
+\r
+        SUB     DX,xmsalrsrvd[BP]       ; Subtract out reserved blocks.\r
+        JB      XMS_alloc03             ; Ensure no borrow.\r
+        CMP     AX,DX                   ;\r
+        JBE     XMS_alloc02             ;\r
+        MOV     AX,DX                   ;\r
+\r
+  XMS_alloc02:\r
+        MOV     DX,AX                   ;\r
+        CMP     AX,68                   ; Ensure enough memory to allocate.\r
+\r
+  XMS_alloc03:\r
+        MOV     AX,0                    ;\r
+        JB      XMS_alloc05             ; Exit if not.\r
+\r
+        CMP     BL,80H                  ; Check for errors.\r
+        JE      XMS_alloc05             ;\r
+        CMP     BL,81H                  ;\r
+        JE      XMS_alloc05             ;\r
+\r
+        CMP     CX,DX                   ; Check actual against requested size.\r
+        JBE     XMS_alloc04             ;\r
+        MOV     CX,DX                   ; Set if actual < requested.\r
+\r
+  XMS_alloc04:\r
+        MOV     DX,CX                   ; Set requested size.\r
+        MOV     AH,09H                  ;\r
+        CALL    DWORD PTR [XMSfunctAdr] ; Allocate it.\r
+        DEC     AX                      ; Check for errors.\r
+        MOV     AX,0                    ;\r
+        JNZ     XMS_alloc05             ;\r
+\r
+\r
+        MOV     AX,CX                   ; Convert allocated size in KBytes\r
+        MOV     CL,4                    ; to allocated blocks.\r
+        SHR     AX,CL                   ;\r
+\r
+        SUB     ES:[DI],AX              ; Subtract the blocks allocated.\r
+        MOV     AX,DX                   ; Set to return the handle.\r
+\r
+  XMS_alloc05:\r
+        POP     DS\r
+        POP     ES\r
+        POP     DI\r
+        POP     DX\r
+        POP     CX\r
+        POP     BX\r
+\r
+        POP     BP\r
+        RET                             ; Exit\r
+\r
+endproc  XMS_alloc\r
+\r
+SUBTTL  Extended Memory - XMS get, put Stack Frame definition\r
+PAGE+\r
+\r
+\r
+XMSgpparms STRUC\r
+\r
+        DW      0, 0\r
+        DW      0\r
+xmsgpHdl     DW      ?\r
+xmsgpblk     DW      ?\r
+xmsgpblkAdr  DW      ?\r
+xmsgpBytes   DW      ?\r
+xmsgpmemAdr  DD      ?\r
+\r
+XMSgpparms ENDS\r
+\r
+SUBTTL  Extended Memory - XMStoMem\r
+PAGE+\r
+\r
+\r
+ ;\r
+ ; Stack frame definition for int XMStoMem( unsigned Handle,\r
+ ;                                          unsigned blk,\r
+ ;                                          unsigned blkAdr,\r
+ ;                                          unsigned Bytes,\r
+ ;                                          char     *memAdr\r
+ ;                                        );\r
+ ;\r
+ ;  XMSmemError is returned if the operation fails, Zero if success.\r
+ ;\r
+\r
+procname  XMStoMem\r
+\r
+        PUSH    BP\r
+        MOV     BP,SP\r
+\r
+        PUSH    BX\r
+        PUSH    CX\r
+        PUSH    DX\r
+        PUSH    SI\r
+        PUSH    DI\r
+        PUSH    ES\r
+        PUSH    DS\r
+\r
+        MOV     AX,CS                   ; Set Data Segment to Code Segment.\r
+        MOV     DS,AX                   ;\r
+\r
+        MOV     CX,xmsgpBytes[BP]       ; Get the number of bytes to transfer.\r
+        LES     BX,xmsgpmemAdr[BP]      ; Get the memory address.\r
+        MOV     DX,xmsgpHdl[BP]         ; Get the XMS handle.\r
+        MOV     [XMSmainGET.SrcHandle],DX ; Set it in the move structures.\r
+        MOV     [XMSwordGET.SrcHandle],DX ;\r
+\r
+        XOR     DX,DX                   ;\r
+        MOV     DI,xmsgpblk[BP]         ; Get the block number.\r
+        SHR     DI,1                    ; Form the 32 bit XMS address in\r
+        RCR     DX,1                    ;  DI:DX.\r
+        SHR     DI,1                    ;\r
+        RCR     DX,1                    ;\r
+        ADD     DX,xmsgpblkAdr[BP]      ;\r
+\r
+        TEST    CX,1                    ; Check for an odd number of bytes\r
+        JZ      XMStoMem02              ;  to transfer.\r
+\r
+        DEC     CX                      ; Decrement to an even number of bytes.\r
+\r
+        TEST    DX,1                    ; Check for an odd XMS address.\r
+        JZ      XMStoMem01              ;\r
+\r
+                                        ; XMS address is odd.\r
+                                        ; -------------------\r
+        DEC     DX                      ;\r
+        MOV     [XMSwordGET.SrcOffset],DX   ; Set the XMS address.\r
+        MOV     [XMSwordGET.SrcOffsetX],DI  ;\r
+\r
+        MOV     AH,0BH                  ; Set the XMS move, function code.\r
+        MOV     SI,OFFSET XMSwordGET    ; Set address of the move structure.\r
+\r
+        PUSH    BX                      ;\r
+        CALL    DWORD PTR [XMSfunctAdr] ; Call the XMS handler.\r
+        POP     BX                      ;\r
+        DEC     AX                      ; Check for errors.\r
+        JNZ     XMStoMem03              ; Error out if error.\r
+\r
+        MOV     AX,[XMSword]            ; Get the moved word.\r
+\r
+        MOV     ES:[BX],AH              ; Move the odd byte to memory.\r
+\r
+        INC     BX                      ; Reset the memory address.\r
+        ADD     DX,2                    ; And the XMS address.\r
+\r
+        JMP     XMStoMem02              ; Move the block.\r
+\r
+\r
+  XMStoMem01:\r
+                                        ; XMS address is even.\r
+                                        ; --------------------\r
+        ADD     DX,CX                   ;\r
+        MOV     [XMSwordGET.SrcOffset],DX   ; Set the XMS address.\r
+        SUB     DX,CX                       ;\r
+        MOV     [XMSwordGET.SrcOffsetX],DI  ;\r
+\r
+        MOV     AH,0BH                  ; Set the XMS move, function code.\r
+        MOV     SI,OFFSET XMSwordGET    ; Set address of the move structure.\r
+\r
+        PUSH    BX                      ;\r
+        CALL    DWORD PTR [XMSfunctAdr] ; Call the XMS handler.\r
+        POP     BX                      ;\r
+        DEC     AX                      ; Check for errors.\r
+        JNZ     XMStoMem03              ; Error out if error.\r
+\r
+        MOV     AX,[XMSword]            ; Get the moved word.\r
+\r
+        XCHG    DI,CX                   ;\r
+        MOV     ES:[BX+DI],AL           ; Move the odd byte to memory.\r
+        XCHG    DI,CX                   ;\r
+\r
+  XMStoMem02:\r
+        JCXZ    XMStoMem04              ; Avoid a zero byte move.\r
+\r
+        MOV     XMSmainGET.Length,CX    ; Set length for the move.\r
+\r
+        MOV     XMSmainGET.DestOffset,BX   ; Set Memory address.\r
+        MOV     XMSmainGET.DestOffsetX,ES  ;\r
+\r
+        MOV     XMSmainGET.SrcOffset,DX    ; Set XMS address.\r
+        MOV     XMSmainGET.SrcOffsetX,DI   ;\r
+\r
+        MOV     AH,0BH                  ; Set the XMS move, function code.\r
+        MOV     SI,OFFSET XMSmainGET    ; Set address of the move structure.\r
+\r
+        CALL    DWORD PTR [XMSfunctAdr] ; Call the XMS handler.\r
+        DEC     AX                      ; Check for errors.\r
+        JZ      XMStoMem05\r
+\r
+  XMStoMem03:\r
+        MOV     AX,XMSmemError          ; Set error code if error.\r
+        JMP     XMStoMem05              ;\r
+\r
+  XMStoMem04:\r
+        XOR     AX,AX                   ;\r
+\r
+  XMStoMem05:\r
+        POP     DS\r
+        POP     ES\r
+        POP     DI\r
+        POP     SI\r
+        POP     DX\r
+        POP     CX\r
+        POP     BX\r
+\r
+        POP     BP\r
+        RET                             ; Exit\r
+\r
+endproc  XMStoMem\r
+\r
+SUBTTL  Extended Memory - MemToXMS\r
+PAGE+\r
+\r
+\r
+ ;\r
+ ; Stack frame definition for int MemToXMS( unsigned Handle,\r
+ ;                                        unsigned blk,\r
+ ;                                        unsigned blkAdr,\r
+ ;                                        unsigned Bytes,\r
+ ;                                        char     *memAdr\r
+ ;                                       );\r
+ ;\r
+ ;  XMSmemError is returned if the operation fails, Zero if success.\r
+ ;\r
+\r
+procname  MemToXMS\r
+\r
+        PUSH    BP\r
+        MOV     BP,SP\r
+\r
+        PUSH    BX\r
+        PUSH    CX\r
+        PUSH    DX\r
+        PUSH    SI\r
+        PUSH    DI\r
+        PUSH    ES\r
+        PUSH    DS\r
+\r
+        MOV     AX,CS                   ;\r
+        MOV     DS,AX                   ;\r
+\r
+        MOV     CX,xmsgpBytes[BP]       ; Get the number of bytes to transfer.\r
+        LES     BX,xmsgpmemAdr[BP]      ; Get the memory address.\r
+        MOV     DX,xmsgpHdl[BP]         ; Get the XMS handle.\r
+        MOV     [XMSmainPUT.DestHandle],DX ; Set it in the move structures.\r
+        MOV     [XMSwordPUT.DestHandle],DX ;\r
+        MOV     [XMSwordGET.SrcHandle],DX  ;\r
+\r
+        XOR     DX,DX                   ;\r
+        MOV     DI,xmsgpblk[BP]         ; Get the block number.\r
+        SHR     DI,1                    ; Form the 32 bit XMS address in\r
+        RCR     DX,1                    ;  DI:DX.\r
+        SHR     DI,1                    ;\r
+        RCR     DX,1                    ;\r
+        ADD     DX,xmsgpblkAdr[BP]      ;\r
+\r
+        TEST    CX,1                    ; Check for an odd number of bytes\r
+        JZ      MemToXMS02              ;  to transfer.\r
+\r
+        DEC     CX                      ; Decrement to an even number of bytes.\r
+\r
+        TEST    DX,1                    ; Check for an odd XMS address.\r
+        JZ      MemToXMS01              ;\r
+\r
+                                        ; XMS address is odd.\r
+                                        ; -------------------\r
+        DEC     DX                      ;\r
+        MOV     [XMSwordGET.SrcOffset],DX   ; Set the XMS address.\r
+        MOV     [XMSwordGET.SrcOffsetX],DI  ;\r
+        MOV     [XMSwordPUT.DestOffset],DX  ;\r
+        MOV     [XMSwordPUT.DestOffsetX],DI ;\r
+\r
+        MOV     AH,0BH                  ; Set the XMS move, function code.\r
+        MOV     SI,OFFSET XMSwordGET    ; Set address of the move structure.\r
+\r
+        PUSH    BX                      ;\r
+        CALL    DWORD PTR [XMSfunctAdr] ; Call the XMS handler.\r
+        POP     BX                      ;\r
+        DEC     AX                      ; Check for errors.\r
+        JNZ     MemToXMS03              ; Error out if error.\r
+\r
+        MOV     AH,ES:[BX]              ; Get the odd memory byte.\r
+\r
+        MOV     [XMSwordByte+1],AH      ; Put it in the moved word.\r
+\r
+        MOV     AH,0BH                  ; Set the XMS move, function code.\r
+        MOV     SI,OFFSET XMSwordPUT    ; Set address of the move structure.\r
+\r
+        PUSH    BX                      ;\r
+        CALL    DWORD PTR [XMSfunctAdr] ; Call the XMS handler.\r
+        POP     BX                      ;\r
+        DEC     AX                      ; Check for errors.\r
+        JNZ     MemToXMS03              ; Error out if error.\r
+\r
+        INC     BX                      ; Reset the memory address.\r
+        ADD     DX,2                    ; And the XMS address.\r
+\r
+        JMP     MemToXMS02              ; Move the block.\r
+\r
+  MemToXMS01:\r
+                                        ; XMS address is even.\r
+                                        ; --------------------\r
+        ADD     DX,CX                   ;\r
+        MOV     [XMSwordGET.SrcOffset],DX   ; Set the XMS address.\r
+        MOV     [XMSwordPUT.DestOffset],DX  ;\r
+        SUB     DX,CX                       ;\r
+        MOV     [XMSwordGET.SrcOffsetX],DI  ;\r
+        MOV     [XMSwordPUT.DestOffsetX],DI ;\r
+\r
+        MOV     AH,0BH                  ; Set the XMS move, function code.\r
+        MOV     SI,OFFSET XMSwordGET    ; Set address of the move structure.\r
+\r
+        PUSH    BX                      ;\r
+        CALL    DWORD PTR [XMSfunctAdr] ; Call the XMS handler.\r
+        POP     BX                      ;\r
+        DEC     AX                      ; Check for errors.\r
+        JNZ     MemToXMS03              ; Error out if error.\r
+\r
+        XCHG    DI,CX                   ;\r
+        MOV     AL,ES:[BX+DI]           ; Get the odd memory byte.\r
+        XCHG    DI,CX                   ;\r
+\r
+        MOV     [XMSwordByte],AL        ; Set the moved word.\r
+\r
+        MOV     AH,0BH                  ; Set the XMS move, function code.\r
+        MOV     SI,OFFSET XMSwordPUT    ; Set address of the move structure.\r
+\r
+        PUSH    BX                      ;\r
+        CALL    DWORD PTR [XMSfunctAdr] ; Call the XMS handler.\r
+        POP     BX                      ;\r
+        DEC     AX                      ; Check for errors.\r
+        JNZ     MemToXMS03              ; Error out if error.\r
+\r
+  MemToXMS02:\r
+        JCXZ    MemToXMS04              ; Avoid a zero byte move.\r
+\r
+        MOV     XMSmainPUT.Length,CX    ; Set length for the move.\r
+\r
+        MOV     XMSmainPUT.SrcOffset,BX    ; Set Memory address.\r
+        MOV     XMSmainPUT.SrcOffsetX,ES   ;\r
+\r
+        MOV     XMSmainPUT.DestOffset,DX   ; Set XMS address.\r
+        MOV     XMSmainPUT.DestOffsetX,DI  ;\r
+\r
+        MOV     AH,0BH                  ; Set the XMS move, function code.\r
+        MOV     SI,OFFSET XMSmainPUT    ; Set address of the move structure.\r
+\r
+        CALL    DWORD PTR [XMSfunctAdr] ; Call the XMS handler.\r
+        DEC     AX                      ; Check for errors.\r
+        JZ      MemToXMS05\r
+\r
+  MemToXMS03:\r
+        MOV     AX,XMSmemError          ; Set error code if error.\r
+        JMP     MemToXMS05              ;\r
+\r
+  MemToXMS04:\r
+        XOR     AX,AX                   ;\r
+\r
+  MemToXMS05:\r
+        POP     DS\r
+        POP     ES\r
+        POP     DI\r
+        POP     SI\r
+        POP     DX\r
+        POP     CX\r
+        POP     BX\r
+\r
+        POP     BP\r
+        RET                             ; Exit\r
+\r
+endproc  MemToXMS\r
+\r
+\r
+SUBTTL  Last Page\r
+PAGE+\r
+\r
+pwrlolvl_TEXT   ENDS\r
+\r
+        END\r
+\r
+\r
+xmem.asm --------------------- END --------------------------------------\r
+\r
+xmemc.c ---------------------------- START -------------------------\r
+\r
+/*\r
+\r
+   Copyright 1994 Alec Russell, ALL rights reserved\r
+        Permission granted to use as you wish.\r
+\r
+   Slightly higher level xms calls than xmem.asm\r
+\r
+*/\r
+\r
+#include <stdio.h>\r
+#include <io.h>\r
+#include <string.h>\r
+#include <malloc.h>\r
+\r
+#include <xmem.h>\r
+\r
+xms_head_t xms_head={0};  // set handle to zero\r
+\r
+\r
+/* ---------------------- alloc_xms() ----------------- February 19,1994 */\r
+short alloc_xms(unsigned short far *size)  // size in 16k blocks\r
+{\r
+   return(XMS_alloc(0, size));\r
+}\r
+\r
+/* ---------------------- xms_to_mem() ---------------- February 19,1994 */\r
+short xms_to_mem(unsigned short handle, void far *p, unsigned long off, unsigned short n)\r
+{\r
+   unsigned short block, boff;\r
+\r
+   block=off >> XMSBLOCKSHIFT;\r
+   boff=off - (block << XMSBLOCKSHIFT);\r
+\r
+   return(XMStoMem(handle, block, boff, n, p));\r
+}\r
+\r
+/* ---------------------- mem_to_xms() ---------------- February 19,1994 */\r
+short mem_to_xms(unsigned short handle, void far *p, unsigned long off, unsigned short n)\r
+{\r
+   unsigned short block, boff;\r
+\r
+   block=off >> XMSBLOCKSHIFT;\r
+   boff=off - (block << XMSBLOCKSHIFT);\r
+\r
+   return(MemToXMS(handle, block, boff, n, p));\r
+}\r
+\r
+/* ---------------------- qalloc_xms() -------------------- March 8,1994 */\r
+xms_node_t *qalloc_xms(unsigned long size)\r
+{\r
+   xms_node_t *node=NULL;\r
+   xms_node_t *t1;\r
+\r
+   if ( size <= xms_head.avail )\r
+      {\r
+      // look for existing node\r
+      t1=xms_head.next;\r
+      while ( t1 )\r
+         {\r
+         if ( t1->used == 0 && t1->size >= size )\r
+            {\r
+            t1->off=0;\r
+            t1->used=1;\r
+            node=t1;\r
+            break;\r
+            }\r
+         else\r
+            t1=t1->next;\r
+         }\r
+\r
+      if ( node == NULL ) // didn't find existing node\r
+         {\r
+         node=malloc(sizeof(xms_node_t));\r
+         if ( node )\r
+            {\r
+            node->off=0;\r
+            node->used=1;\r
+            node->size=size;\r
+            node->next=NULL;\r
+            node->start=xms_head.next_off;\r
+            xms_head.avail-=size;\r
+            xms_head.next_off+=size;\r
+            if ( xms_head.next == NULL )\r
+               {\r
+               xms_head.next=node;\r
+               }\r
+            else\r
+               {\r
+               t1=xms_head.next;\r
+               while ( t1->next )\r
+                  t1=t1->next;\r
+               t1->next=node;\r
+               }\r
+            }\r
+         else\r
+            pr2("out of near mem in qalloc_xms");\r
+         }\r
+      }\r
+   else\r
+      pr2("out of xms mem in qalloc size %lu avail %lu", size, xms_head.avail);\r
+\r
+   return(node);\r
+}\r
+\r
+/* ---------------------- qfree_xms() --------------------- March 8,1994 */\r
+void qfree_xms(xms_node_t *node)\r
+{\r
+   xms_node_t *t1;\r
+\r
+   if ( xms_head.next )\r
+      {\r
+      t1=xms_head.next;\r
+      while ( t1 != node && t1 )\r
+         t1=t1->next;\r
+\r
+      if ( t1 )\r
+         {\r
+         t1->used=0;\r
+         }\r
+      else\r
+         pr2("ERROR didn't find node qfree");\r
+      }\r
+   else\r
+      {\r
+      pr2("ATTEMPTED to qfree empty list");\r
+      }\r
+}\r
+\r
+/* ---------------------- xms_open() ---------------------- March 8,1994 */\r
+xms_node_t *xms_open(char *file)\r
+{\r
+   int i;\r
+   xms_node_t *node=NULL;\r
+   FILE *fp;\r
+   char *buffer;\r
+   unsigned long off;\r
+\r
+   fp=fopen(file, "rb");\r
+   if ( fp )\r
+      {\r
+      node=qalloc_xms(filelength(fileno(fp)));\r
+      if ( node )\r
+         {\r
+         buffer=malloc(4096);\r
+         if ( buffer )\r
+            {\r
+            off=0l;\r
+            while ( (i=fread(buffer, 1, 4096, fp)) )\r
+               {\r
+               mem_to_xms(xms_head.handle, (char far *)buffer, off+node->start, i);\r
+               off+=i;\r
+               }\r
+\r
+            free(buffer);\r
+            }\r
+         else\r
+            pr2("out of mem in xms_open 1");\r
+         }\r
+\r
+      fclose(fp);\r
+      }\r
+   else\r
+      pr2("ERROR opening %s in xms_open", file);\r
+\r
+   return(node);\r
+}\r
+\r
+/* ---------------------- xms_read() ---------------------- March 8,1994 */\r
+short xms_read(void far *buffer, unsigned short n, xms_node_t *node)\r
+{\r
+\r
+   if ( node->off >= node->size )\r
+      return 0;\r
+\r
+   if ( n+node->off > node->size )\r
+      n=node->size - node->off;\r
+\r
+   xms_to_mem(xms_head.handle, buffer, node->start+node->off, n);\r
+   node->off+=n;\r
+\r
+   return(n);\r
+}\r
+\r
+/* ---------------------- xms_write() ---------------------- March 8,1994 */\r
+short xms_write(void far *buffer, unsigned short n, xms_node_t *node)\r
+{\r
+\r
+   if ( node->off >= node->size )\r
+      return 0;\r
+\r
+   if ( n+node->off > node->size )\r
+      n=node->size - node->off;\r
+\r
+   mem_to_xms(xms_head.handle, buffer, node->start+node->off, n);\r
+   node->off+=n;\r
+\r
+   return(n);\r
+}\r
+\r
+\r
+/* ---------------------- xms_tell() ---------------------- March 8,1994 */\r
+long xms_tell(xms_node_t *node)\r
+{\r
+   return node->off;\r
+}\r
+\r
+/* ---------------------- xms_seek() ---------------------- March 8,1994 */\r
+short xms_seek(xms_node_t *node, long off, short whence)\r
+{\r
+   short err=0;\r
+\r
+   switch ( whence )\r
+      {\r
+      case SEEK_SET:\r
+         if ( off < 0l || off > node->size )\r
+            err=1;\r
+         else\r
+            node->off=off;\r
+         break;\r
+\r
+      case SEEK_END:\r
+         if ( off > 0l || (node->size + off) < 0l )\r
+            err=1;\r
+         else\r
+            node->off=node->size + off;\r
+         break;\r
+\r
+      case SEEK_CUR:\r
+         if ( node->off + off < 0l || node->off + off > node->size )\r
+            err=1;\r
+         else\r
+            node->off+=off;\r
+         break;\r
+      }\r
+\r
+   return(err);\r
+}\r
+\r
+/* ---------------------- xms_close() --------------------- March 8,1994 */\r
+void xms_close(xms_node_t *node)\r
+{\r
+   qfree_xms(node);\r
+}\r
+\r
+/* ---------------------- init_xms() ---------------------- March 8,1994 */\r
+short init_xms(unsigned short min_blocks)\r
+{\r
+   unsigned short blocks;\r
+\r
+   blocks=XMSblk_available();\r
+   if ( blocks >= min_blocks )\r
+      {\r
+      memset(&xms_head, 0, sizeof(xms_head_t));\r
+      if ( (xms_head.handle=alloc_xms(&blocks)) )\r
+         {\r
+         pr2("blocks minus by = %u", blocks);\r
+         min_blocks-=blocks;\r
+         xms_head.avail=xms_head.total=(unsigned long)min_blocks*XMSBLOCK;\r
+         blocks=min_blocks;\r
+         }\r
+      else\r
+         blocks=0;\r
+      }\r
+   else\r
+      blocks=0;\r
+\r
+   return(blocks);\r
+}\r
+\r
+/* ---------------------- deinit_xms() -------------------- March 8,1994 */\r
+void deinit_xms(void)\r
+{\r
+   xms_node_t *t1, *t2;\r
+\r
+   if ( xms_head.handle )\r
+      {\r
+      XMS_dealloc(xms_head.handle);\r
+      if ( xms_head.next )\r
+         {\r
+         t1=xms_head.next;\r
+         t2=t1->next;\r
+         while ( t1 )\r
+            {\r
+            free(t1);\r
+            t1=t2;\r
+            t2=t1->next;\r
+            }\r
+         }\r
+\r
+      memset(&xms_head, 0, sizeof(xms_head_t));\r
+      }\r
+}\r
+/* --------------------------- end of file ------------------------- */\r
+\r
+/*\r
+\r
+Not sure how to use this?\r
+\r
+call init_xms(x) to allocate a big chunk of xms.\r
+x is in 'blocks' of 16Kb. Pick X big enough to buffer all the files\r
+you want to place in xms.\r
+\r
+call xms_open("filename); for each file to be buffered. This copies the file\r
+int xms.\r
+\r
+then use xms_read(), xms_write(), and xms_seek() to read the file from\r
+xms instead of disk.\r
+\r
+call deinit_xms() just before exit to clean up.\r
+\r
+You can also use the lower level calls directly.\r
+\r
+*/\r
+xmemc.c ---------------------------- END -------------------------\r
index f642fada1f2aa8465c4257536c077e202ac1e48f..f76a59e1bcb74592ad40a7be6b8f9a78fc6a2e01 100644 (file)
@@ -17,7 +17,7 @@
 #include <stdlib.h>\r
 #include <mem.h>\r
 \r
-#include "memory.c"\r
+#include "memory.h"\r
 \r
 void TransformData(char *pEmmData, unsigned int len)\r
 {\r
index ce58c3e4a6cbfdbd10019dafad5c9d1d8fe3887e..519ec6cb2812d7478ff9665619a51837c011c074 100644 (file)
 \r
 #include "memory.h"\r
 \r
-// static globals --------------------------------\r
+ //static globals --------------------------------\r
 \r
 static int  ActiveEMList[MAXEMHANDLES];\r
 static unsigned int  EMMSeg;\r
 \r
-// forward declarations ---------------------------------\r
+ //forward declarations ---------------------------------\r
 \r
 static int  EMPresent(void);\r
 static int  EMReady(void);\r
@@ -87,13 +87,12 @@ EMMCoreLeft(void)
         mov     ah,0x42             /* get EMM free page count */\r
         int     0x67\r
         or      ah,ah\r
-        //js      InternalError       /* returns 80, 81, or 84 hex on error */\r
+        js      InternalError       /* returns 80, 81, or 84 hex on error */\r
         mov     Pages,bx            /* number of unallocated 16K pages */\r
     }\r
     RtnVal = ((unsigned long)Pages << 14);  /* Pages * 16K rtns bytes*/\r
 \r
-//InternalError:\r
-\r
+InternalError:\r
     return(RtnVal);\r
 }               /* End of EMMCoreLeft() */\r
 \r
@@ -141,11 +140,11 @@ EMMRealloc(int Handle, int Pages)
         mov     dx,Handle\r
         int     0x67\r
         or      ah,ah\r
-        //js      NoGo                /* returns 80 to 88 hex on error */\r
+        js      NoGo                /* returns 80 to 88 hex on error */\r
     }\r
     RtnCode = TRUE;\r
 \r
-//NoGo:\r
+NoGo:\r
 \r
     return(RtnCode);\r
 }               /* End of EMMRealloc() */\r
@@ -256,11 +255,11 @@ EMReady(void)
         mov     ah,0x40             /* get EM Manager Status */\r
         int     0x67\r
         or      ah,ah\r
-        //jns     Ready               /* returns 80, 81, or 84 hex on error */\r
+        jns     Ready               /* returns 80, 81, or 84 hex on error */\r
     }\r
     return(FALSE);\r
 \r
-//Ready:\r
+Ready:\r
     return(TRUE);\r
 }               /* End of EMReady() */\r
 \r
@@ -275,12 +274,12 @@ GetEMMSeg(void)
         mov     ah,0x41             /* get EMM page frame segment */\r
         int     0x67\r
         or      ah,ah\r
-        //js      NotReady            /* returns 80, 81, or 84 hex on error */\r
+        js      NotReady            /* returns 80, 81, or 84 hex on error */\r
         mov     EMSegment,bx\r
     }\r
     return(EMSegment);              /*lint !e530 */\r
 \r
-//NotReady:\r
+NotReady:\r
     return(NOTREADY);\r
 }               /* End of GetEMMSeg() */\r
 \r
@@ -296,12 +295,12 @@ GetEMHandle(int NumPages)
         mov     bx,NumPages         /* number of 16K pages to allocate */\r
         int     0x67\r
         or      ah,ah               /* returns 80 to 89 hex on error */\r
-        //js      NoHandle\r
+        js      NoHandle\r
         mov     NewHandle,dx        /* retrieve handle */\r
     }\r
     return(NewHandle);\r
 \r
-//NoHandle:\r
+NoHandle:\r
     return(NO_DATA);\r
 }               /* End of GetEMHandle() */\r
 \r
@@ -319,11 +318,11 @@ EMMap(int Handle, int LogPg, int PhyPg)
         mov     dx,Handle\r
         int     0x67\r
         or      ah,ah               /* returns 80 to 8B hex on error */\r
-        //js      NoMapping\r
+        js      NoMapping\r
     }\r
     RtnCode = SUCCESS;\r
 \r
-//NoMapping:\r
+NoMapping:\r
     return(RtnCode);\r
 }               /* End of EMMap() */\r
 \r
@@ -337,11 +336,11 @@ FreeEMHandle(int Handle)
         mov     dx,Handle\r
         int     0x67\r
         or      ah,ah               /* returns 80 to 86 hex on error */\r
-        //js      NotFreed\r
+        js      NotFreed\r
     }\r
     return(SUCCESS);\r
 \r
-//NotFreed:                           /* must retry if unsuccessful */\r
+NotFreed:                           /* must retry if unsuccessful */\r
     return(NO_DATA);\r
 }               /* End of FreeEMHandle() */\r
 \r
@@ -357,10 +356,10 @@ GetNumPages(int Handle)
         mov     dx,Handle\r
         int     0x67\r
         or      ah,ah               /* returns 80 to 84 hex on error */\r
-        //js      BadHandle\r
+        js      BadHandle\r
         mov     NumPages,bx\r
     }\r
-//BadHandle:\r
+BadHandle:\r
 \r
     return(NumPages);\r
 }               /* End of GetNumPages() */\r
@@ -376,11 +375,11 @@ EMStateSave(int Handle)
         mov     dx,Handle\r
         int     0x67\r
         or      ah,ah\r
-        //js      Unsaved             /* out of save space error */\r
+        js      Unsaved             /* out of save space error */\r
     }\r
     RtnCode = SUCCESS;\r
 \r
-//Unsaved:\r
+Unsaved:\r
     return(RtnCode);\r
 }               /* End of EMStateSave() */\r
 \r
index 5e8a8bfae97e89250680794533b7f783d1e7079c..e17517021a4562feea73b4952f78c31e29fbde89 100644 (file)
@@ -1 +1 @@
-"wcp -mh emm.c"  at\r
+wcp -mh emm.c\r
index ff15d1ec614029f6395e223b6fa6b23f8f03e51a..d5e7d549e6c95fb42a189ea87e885fba7043a9b6 100644 (file)
@@ -1,57 +1,62 @@
-
 /*
-
-   Copyright 1994 Alec Russell, ALL rights reserved
-        Permission granted to use as you wish.
-
+   Written by Alexander J. Russell 1994
+   Placed in the public Domain by Alec Russell, March 1995
    Slightly higher level xms calls than xmem.asm
-
 */
-
 #include <stdio.h>
 #include <io.h>
 #include <string.h>
 #include <malloc.h>
-
-#include <xmem.h>
-
+#include "src\lib\exmm\xmem.h"
 xms_head_t xms_head={0};  // set handle to zero
-
-
 /* ---------------------- alloc_xms() ----------------- February 19,1994 */
 short alloc_xms(unsigned short far *size)  // size in 16k blocks
 {
    return(XMS_alloc(0, size));
 }
-
 /* ---------------------- xms_to_mem() ---------------- February 19,1994 */
-short xms_to_mem(unsigned short handle, void far *p, unsigned long off, unsigned short n)
+short xms_to_mem(unsigned short handle, void far *p, unsigned long off,
+unsigned short n)
 {
    unsigned short block, boff;
-
    block=off >> XMSBLOCKSHIFT;
    boff=off - (block << XMSBLOCKSHIFT);
-
    return(XMStoMem(handle, block, boff, n, p));
 }
-
 /* ---------------------- mem_to_xms() ---------------- February 19,1994 */
-short mem_to_xms(unsigned short handle, void far *p, unsigned long off, unsigned short n)
+short mem_to_xms(unsigned short handle, void far *p, unsigned long off,
+unsigned short n)
 {
    unsigned short block, boff;
-
    block=off >> XMSBLOCKSHIFT;
    boff=off - (block << XMSBLOCKSHIFT);
-
    return(MemToXMS(handle, block, boff, n, p));
 }
-
 /* ---------------------- qalloc_xms() -------------------- March 8,1994 */
 xms_node_t *qalloc_xms(unsigned long size)
 {
    xms_node_t *node=NULL;
    xms_node_t *t1;
-
    if ( size <= xms_head.avail )
       {
       // look for existing node
@@ -68,7 +73,7 @@ xms_node_t *qalloc_xms(unsigned long size)
          else
             t1=t1->next;
          }
-
       if ( node == NULL ) // didn't find existing node
          {
          node=malloc(sizeof(xms_node_t));
@@ -94,39 +99,43 @@ xms_node_t *qalloc_xms(unsigned long size)
                }
             }
          else
-            pr2("out of near mem in qalloc_xms");
+            printf("out of near mem in qalloc_xms");
          }
       }
    else
-      pr2("out of xms mem in qalloc size %lu avail %lu", size, xms_head.avail);
-
+      printf("out of xms mem in qalloc size %lu avail %lu", size,
+xms_head.avail);
    return(node);
 }
-
 /* ---------------------- qfree_xms() --------------------- March 8,1994 */
 void qfree_xms(xms_node_t *node)
 {
    xms_node_t *t1;
-
    if ( xms_head.next )
       {
       t1=xms_head.next;
       while ( t1 != node && t1 )
          t1=t1->next;
-
       if ( t1 )
          {
          t1->used=0;
          }
       else
-         pr2("ERROR didn't find node qfree");
+         printf("ERROR didn't find node qfree");
       }
    else
       {
-      pr2("ATTEMPTED to qfree empty list");
+      printf("ATTEMPTED to qfree empty list");
       }
 }
-
 /* ---------------------- xms_open() ---------------------- March 8,1994 */
 xms_node_t *xms_open(char *file)
 {
@@ -135,7 +144,7 @@ xms_node_t *xms_open(char *file)
    FILE *fp;
    char *buffer;
    unsigned long off;
-
    fp=fopen(file, "rb");
    if ( fp )
       {
@@ -148,68 +157,73 @@ xms_node_t *xms_open(char *file)
             off=0l;
             while ( (i=fread(buffer, 1, 4096, fp)) )
                {
-               mem_to_xms(xms_head.handle, (char far *)buffer, off+node->start, i);
+               mem_to_xms(xms_head.handle, (char far *)buffer,
+off+node->start, i);
                off+=i;
                }
-
             free(buffer);
             }
          else
-            pr2("out of mem in xms_open 1");
+            printf("out of mem in xms_open 1");
          }
-
       fclose(fp);
       }
    else
-      pr2("ERROR opening %s in xms_open", file);
-
+      printf("ERROR opening %s in xms_open", file);
    return(node);
 }
-
 /* ---------------------- xms_read() ---------------------- March 8,1994 */
 short xms_read(void far *buffer, unsigned short n, xms_node_t *node)
 {
-
    if ( node->off >= node->size )
       return 0;
-
    if ( n+node->off > node->size )
       n=node->size - node->off;
-
    xms_to_mem(xms_head.handle, buffer, node->start+node->off, n);
    node->off+=n;
-
    return(n);
 }
-
 /* ---------------------- xms_write() ---------------------- March 8,1994 */
 short xms_write(void far *buffer, unsigned short n, xms_node_t *node)
 {
-
    if ( node->off >= node->size )
       return 0;
-
    if ( n+node->off > node->size )
       n=node->size - node->off;
-
    mem_to_xms(xms_head.handle, buffer, node->start+node->off, n);
    node->off+=n;
-
    return(n);
 }
-
-
 /* ---------------------- xms_tell() ---------------------- March 8,1994 */
 long xms_tell(xms_node_t *node)
 {
    return node->off;
 }
-
 /* ---------------------- xms_seek() ---------------------- March 8,1994 */
 short xms_seek(xms_node_t *node, long off, short whence)
 {
    short err=0;
-
    switch ( whence )
       {
       case SEEK_SET:
@@ -218,14 +232,14 @@ short xms_seek(xms_node_t *node, long off, short whence)
          else
             node->off=off;
          break;
-
       case SEEK_END:
          if ( off > 0l || (node->size + off) < 0l )
             err=1;
          else
             node->off=node->size + off;
          break;
-
       case SEEK_CUR:
          if ( node->off + off < 0l || node->off + off > node->size )
             err=1;
@@ -233,28 +247,32 @@ short xms_seek(xms_node_t *node, long off, short whence)
             node->off+=off;
          break;
       }
-
    return(err);
 }
-
 /* ---------------------- xms_close() --------------------- March 8,1994 */
 void xms_close(xms_node_t *node)
 {
    qfree_xms(node);
 }
-
 /* ---------------------- init_xms() ---------------------- March 8,1994 */
 short init_xms(unsigned short min_blocks)
 {
    unsigned short blocks;
-
    blocks=XMSblk_available();
    if ( blocks >= min_blocks )
       {
       memset(&xms_head, 0, sizeof(xms_head_t));
       if ( (xms_head.handle=alloc_xms(&blocks)) )
          {
-         pr2("blocks minus by = %u", blocks);
+         printf("blocks minus by = %u", blocks);
          min_blocks-=blocks;
          xms_head.avail=xms_head.total=(unsigned long)min_blocks*XMSBLOCK;
          blocks=min_blocks;
@@ -264,15 +282,16 @@ short init_xms(unsigned short min_blocks)
       }
    else
       blocks=0;
-
    return(blocks);
 }
-
 /* ---------------------- deinit_xms() -------------------- March 8,1994 */
 void deinit_xms(void)
 {
    xms_node_t *t1, *t2;
-
    if ( xms_head.handle )
       {
       XMS_dealloc(xms_head.handle);
@@ -287,28 +306,31 @@ void deinit_xms(void)
             t2=t1->next;
             }
          }
-
       memset(&xms_head, 0, sizeof(xms_head_t));
       }
 }
 /* --------------------------- end of file ------------------------- */
 
-/*
-
-Not sure how to use this?
-
-call init_xms(x) to allocate a big chunk of xms.
-x is in 'blocks' of 16Kb. Pick X big enough to buffer all the files
-you want to place in xms.
-
-call xms_open("filename); for each file to be buffered. This copies the file
-int xms.
-
-then use xms_read(), xms_write(), and xms_seek() to read the file from
-xms instead of disk.
-
-call deinit_xms() just before exit to clean up.
-
-You can also use the lower level calls directly.
-
+/*\r
+\r
+Not sure how to use this?\r
+\r
+call init_xms(x) to allocate a big chunk of xms.\r
+x is in 'blocks' of 16Kb. Pick X big enough to buffer all the files\r
+you want to place in xms.\r
+\r
+call xms_open("filename); for each file to be buffered. This copies the file\r
+int xms.\r
+\r
+then use xms_read(), xms_write(), and xms_seek() to read the file from\r
+xms instead of disk.\r
+\r
+call deinit_xms() just before exit to clean up.\r
+\r
+You can also use the lower level calls directly.\r
+\r
 */
diff --git a/src/lib/exmm/xmemc.c b/src/lib/exmm/xmemc.c
deleted file mode 100644 (file)
index 0ab1de3..0000000
+++ /dev/null
@@ -1,316 +0,0 @@
-/*
-   Written by Alexander J. Russell 1994
-   Placed in the public Domain by Alec Russell, March 1995
-   Slightly higher level xms calls than xmem.asm
-*/
-#include <stdio.h>
-#include <io.h>
-#include <string.h>
-#include <malloc.h>
-#include "src\lib\xmem\xmem.h"
-xms_head_t xms_head={0};  // set handle to zero
-/* ---------------------- alloc_xms() ----------------- February 19,1994 */
-short alloc_xms(unsigned short far *size)  // size in 16k blocks
-{
-   return(XMS_alloc(0, size));
-}
-/* ---------------------- xms_to_mem() ---------------- February 19,1994 */
-short xms_to_mem(unsigned short handle, void far *p, unsigned long off,
-unsigned short n)
-{
-   unsigned short block, boff;
-   block=off >> XMSBLOCKSHIFT;
-   boff=off - (block << XMSBLOCKSHIFT);
-   return(XMStoMem(handle, block, boff, n, p));
-}
-/* ---------------------- mem_to_xms() ---------------- February 19,1994 */
-short mem_to_xms(unsigned short handle, void far *p, unsigned long off,
-unsigned short n)
-{
-   unsigned short block, boff;
-   block=off >> XMSBLOCKSHIFT;
-   boff=off - (block << XMSBLOCKSHIFT);
-   return(MemToXMS(handle, block, boff, n, p));
-}
-/* ---------------------- qalloc_xms() -------------------- March 8,1994 */
-xms_node_t *qalloc_xms(unsigned long size)
-{
-   xms_node_t *node=NULL;
-   xms_node_t *t1;
-   if ( size <= xms_head.avail )
-      {
-      // look for existing node
-      t1=xms_head.next;
-      while ( t1 )
-         {
-         if ( t1->used == 0 && t1->size >= size )
-            {
-            t1->off=0;
-            t1->used=1;
-            node=t1;
-            break;
-            }
-         else
-            t1=t1->next;
-         }
-      if ( node == NULL ) // didn't find existing node
-         {
-         node=malloc(sizeof(xms_node_t));
-         if ( node )
-            {
-            node->off=0;
-            node->used=1;
-            node->size=size;
-            node->next=NULL;
-            node->start=xms_head.next_off;
-            xms_head.avail-=size;
-            xms_head.next_off+=size;
-            if ( xms_head.next == NULL )
-               {
-               xms_head.next=node;
-               }
-            else
-               {
-               t1=xms_head.next;
-               while ( t1->next )
-                  t1=t1->next;
-               t1->next=node;
-               }
-            }
-         else
-            printf("out of near mem in qalloc_xms");
-         }
-      }
-   else
-      printf("out of xms mem in qalloc size %lu avail %lu", size,
-xms_head.avail);
-   return(node);
-}
-/* ---------------------- qfree_xms() --------------------- March 8,1994 */
-void qfree_xms(xms_node_t *node)
-{
-   xms_node_t *t1;
-   if ( xms_head.next )
-      {
-      t1=xms_head.next;
-      while ( t1 != node && t1 )
-         t1=t1->next;
-      if ( t1 )
-         {
-         t1->used=0;
-         }
-      else
-         printf("ERROR didn't find node qfree");
-      }
-   else
-      {
-      printf("ATTEMPTED to qfree empty list");
-      }
-}
-/* ---------------------- xms_open() ---------------------- March 8,1994 */
-xms_node_t *xms_open(char *file)
-{
-   int i;
-   xms_node_t *node=NULL;
-   FILE *fp;
-   char *buffer;
-   unsigned long off;
-   fp=fopen(file, "rb");
-   if ( fp )
-      {
-      node=qalloc_xms(filelength(fileno(fp)));
-      if ( node )
-         {
-         buffer=malloc(4096);
-         if ( buffer )
-            {
-            off=0l;
-            while ( (i=fread(buffer, 1, 4096, fp)) )
-               {
-               mem_to_xms(xms_head.handle, (char far *)buffer,
-off+node->start, i);
-               off+=i;
-               }
-            free(buffer);
-            }
-         else
-            printf("out of mem in xms_open 1");
-         }
-      fclose(fp);
-      }
-   else
-      printf("ERROR opening %s in xms_open", file);
-   return(node);
-}
-/* ---------------------- xms_read() ---------------------- March 8,1994 */
-short xms_read(void far *buffer, unsigned short n, xms_node_t *node)
-{
-   if ( node->off >= node->size )
-      return 0;
-   if ( n+node->off > node->size )
-      n=node->size - node->off;
-   xms_to_mem(xms_head.handle, buffer, node->start+node->off, n);
-   node->off+=n;
-   return(n);
-}
-/* ---------------------- xms_write() ---------------------- March 8,1994 */
-short xms_write(void far *buffer, unsigned short n, xms_node_t *node)
-{
-   if ( node->off >= node->size )
-      return 0;
-   if ( n+node->off > node->size )
-      n=node->size - node->off;
-   mem_to_xms(xms_head.handle, buffer, node->start+node->off, n);
-   node->off+=n;
-   return(n);
-}
-/* ---------------------- xms_tell() ---------------------- March 8,1994 */
-long xms_tell(xms_node_t *node)
-{
-   return node->off;
-}
-/* ---------------------- xms_seek() ---------------------- March 8,1994 */
-short xms_seek(xms_node_t *node, long off, short whence)
-{
-   short err=0;
-   switch ( whence )
-      {
-      case SEEK_SET:
-         if ( off < 0l || off > node->size )
-            err=1;
-         else
-            node->off=off;
-         break;
-      case SEEK_END:
-         if ( off > 0l || (node->size + off) < 0l )
-            err=1;
-         else
-            node->off=node->size + off;
-         break;
-      case SEEK_CUR:
-         if ( node->off + off < 0l || node->off + off > node->size )
-            err=1;
-         else
-            node->off+=off;
-         break;
-      }
-   return(err);
-}
-/* ---------------------- xms_close() --------------------- March 8,1994 */
-void xms_close(xms_node_t *node)
-{
-   qfree_xms(node);
-}
-/* ---------------------- init_xms() ---------------------- March 8,1994 */
-short init_xms(unsigned short min_blocks)
-{
-   unsigned short blocks;
-   blocks=XMSblk_available();
-   if ( blocks >= min_blocks )
-      {
-      memset(&xms_head, 0, sizeof(xms_head_t));
-      if ( (xms_head.handle=alloc_xms(&blocks)) )
-         {
-         printf("blocks minus by = %u", blocks);
-         min_blocks-=blocks;
-         xms_head.avail=xms_head.total=(unsigned long)min_blocks*XMSBLOCK;
-         blocks=min_blocks;
-         }
-      else
-         blocks=0;
-      }
-   else
-      blocks=0;
-   return(blocks);
-}
-/* ---------------------- deinit_xms() -------------------- March 8,1994 */
-void deinit_xms(void)
-{
-   xms_node_t *t1, *t2;
-   if ( xms_head.handle )
-      {
-      XMS_dealloc(xms_head.handle);
-      if ( xms_head.next )
-         {
-         t1=xms_head.next;
-         t2=t1->next;
-         while ( t1 )
-            {
-            free(t1);
-            t1=t2;
-            t2=t1->next;
-            }
-         }
-      memset(&xms_head, 0, sizeof(xms_head_t));
-      }
-}
-/* --------------------------- end of file ------------------------- */