From b2069fd60625ac26ec21a5c35568b99f331c6d34 Mon Sep 17 00:00:00 2001
From: sparky4 <sparky4@lappy4.4ch.mooo.com>
Date: Wed, 10 Dec 2014 01:44:46 -0600
Subject: [PATCH] 	modified:   scroll.exe 	new file:  
 src/lib/xmem/xmem.asm 	new file:   src/lib/xmem/xmem.h 	new file:  
 src/lib/xmem/xmem.txt 	new file:   src/lib/xmem/xmemc.c 	modified:  
 src/scroll.c

---
 scroll.exe            | Bin 52118 -> 52118 bytes
 src/lib/xmem/xmem.asm | 753 ++++++++++++++++++++++++++++++++++++++++++
 src/lib/xmem/xmem.h   |  79 +++++
 src/lib/xmem/xmem.txt |  33 ++
 src/lib/xmem/xmemc.c  | 316 ++++++++++++++++++
 src/scroll.c          |   8 +-
 6 files changed, 1185 insertions(+), 4 deletions(-)
 create mode 100644 src/lib/xmem/xmem.asm
 create mode 100644 src/lib/xmem/xmem.h
 create mode 100644 src/lib/xmem/xmem.txt
 create mode 100644 src/lib/xmem/xmemc.c

diff --git a/scroll.exe b/scroll.exe
index 8912afb4be416bc624556647bd611d1efe2c8da9..b34a5be59dbc8c0eec6409340fc0a19ca36b3428 100644
GIT binary patch
delta 4818
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
K-4W;N#s327p}>^@

delta 4771
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

diff --git a/src/lib/xmem/xmem.asm b/src/lib/xmem/xmem.asm
new file mode 100644
index 00000000..3453e080
--- /dev/null
+++ b/src/lib/xmem/xmem.asm
@@ -0,0 +1,753 @@
+;-----------------------------------------------------------------------
+;Can't take credit for the ASM code here, found it on a local BBS.
+;The author has beem lost in the mists of time.
+; 
+;
+.MODEL MEDIUM
+ 
+ 
+        EXTmemError     EQU     7
+        XMSmemError     EQU     8
+ 
+ 
+        ShortAdr        EQU     0
+        LongAdr         EQU     1
+ 
+ 
+procname        MACRO  Pnam
+        PUBLIC  _&Pnam&
+_&Pnam&  PROC    FAR
+ENDM
+ 
+endproc         MACRO  Pnam
+ 
+_&Pnam&  ENDP
+ 
+ENDM
+ 
+pwrlolvl_TEXT   SEGMENT WORD PUBLIC 'CODE'
+ 
+        ASSUME  CS:pwrlolvl_TEXT, DS:pwrlolvl_TEXT, ES:pwrlolvl_TEXT
+ 
+SUBTTL  (Local Procedure) XMS_setup - find a XMS driver.
+PAGE+
+ 
+                EVEN
+XMSwordByte     LABEL BYTE
+XMSword         DW      0
+ 
+XMSmoveSTRUC    STRUC
+ 
+Length          DW      0
+LengthX         DW      0
+SrcHandle       DW      0
+SrcOffset       DW      0
+SrcOffsetX      DW      0
+DestHandle      DW      0
+DestOffset      DW      0
+DestOffsetX     DW      0
+ 
+XMSmoveSTRUC    ENDS
+ 
+XMSmainGET      XMSmoveSTRUC  <>
+XMSmainPUT      XMSmoveSTRUC  <>
+XMSwordGET      XMSmoveSTRUC  <2,,,,,,OFFSET XMSword>
+XMSwordPUT      XMSmoveSTRUC  <2,,,OFFSET XMSword>
+ 
+XMSfunctAdr     DW      0, 0
+ 
+ 
+; Don't try to call this from your programs
+ 
+XMS_setup               PROC NEAR
+ 
+        PUSH    DS
+        PUSH    ES
+        PUSH    BX
+ 
+        MOV     AX,CS                   ; Set Data segment to the code
+segment.
+        MOV     DS,AX                   ;
+        MOV     [XMSwordGET.DestOffsetX],AX  ; Set up the move data
+structures.
+        MOV     [XMSwordPUT.SrcOffsetX],AX   ;
+ 
+        MOV     AX,4300H                ; See if a XMS Driver Exists.
+        INT     2FH                     ;
+        CMP     AL,80H                  ;
+        MOV     AX,0                    ;
+        JNE     XMS_setup01             ; Return 0 if not.
+ 
+        MOV     AX,4310H                ; If so, set the driver's function
+        INT     2FH                     ;  address.
+        MOV     [XMSfunctAdr],BX        ;
+        MOV     [XMSfunctAdr+2],ES      ;
+ 
+        MOV     AX,1                    ; Return 1.
+ 
+  XMS_setup01:
+        POP     BX
+        POP     ES
+        POP     DS
+ 
+        RET
+ 
+XMS_setup               ENDP
+ 
+ 
+SUBTTL  LSHL - Shift an unsigned long left
+PAGE+
+ 
+ ;****************************************************************************
+ ;* 
+ ;* Shift an unsigned long integer left n number of bits.
+ ;*
+ ;****************************************************************************
+ 
+ ;
+ ; Stack frame definition for void LSHL( unsigned long *SHLnumber, unsigned n
+);
+ ;
+ 
+LSHLparms STRUC
+ 
+        DW      0, 0
+        DW      0
+SHLadr   DD      ?
+SHLn     DW      ?
+ 
+LSHLparms ENDS
+ 
+procname  LSHL
+ 
+        PUSH    BP
+        MOV     BP,SP
+ 
+        PUSH    BX
+        PUSH    CX
+        PUSH    DX
+ 
+        PUSH    DS
+        LDS     BX,SHLadr[BP]
+        MOV     CX,SHLn[BP]
+ 
+        MOV     AX,[BX]                 ; Get the long integer.
+        MOV     DX,[BX+2]               ; 
+ 
+ LSHL_01:
+        SHL     AX,1                    ; Do the long shift.
+        RCL     DX,1                    ; 
+        LOOP    LSHL_01                 ; 
+ 
+        MOV     [BX],AX                 ; Replace the addressed number.
+        MOV     [BX+2],DX               ; 
+ 
+        POP     DS
+        POP     DX
+        POP     CX
+        POP     BX
+ 
+        POP     BP
+        RET                             ; Exit
+ 
+endproc   LSHL
+ 
+ 
+SUBTTL  Extended Memory - Stack template for EXTget, EXTput
+PAGE+
+ 
+EXTgpparms STRUC
+ 
+        DW      0, 0
+        DW      0
+extgpBase    DW      ?
+extgpblk     DW      ?
+extgpblkAdr  DW      ?
+extgpBytes   DW      ?
+extgpmemAdr  DW      ?
+             DW      ?
+ 
+EXTgpparms ENDS
+ 
+ 
+ 
+SUBTTL  Extended Memory - XMS - Return total XMS memory.
+PAGE+
+ 
+ ; Use this function to detect wether or not XMS driver installed
+ ;
+ ; Stack frame definition for unsigned XMS_available( void );
+ ;
+ ;  The total XMS memory available (in 16k blocks) is returned.
+ ;
+procname  XMS_available
+ 
+        PUSH    BX
+        PUSH    CX
+        PUSH    DX
+ 
+        CALL    XMS_setup               ; Ensure XMS memory is set.
+        TEST    AX,AX                   ;
+        JZ      XMS_available01         ; Return zero if not.
+ 
+        MOV     AH,08H                  ; Set the size function code.
+        CALL    DWORD PTR CS:[XMSfunctAdr] ; Get the size.
+        TEST    AX,AX                   ;
+        JZ      XMS_available01         ;
+ 
+        MOV     AX,DX                   ; Set available Kbytes.
+        SUB     AX,64                   ; Subtract out the HMA (HIMEM.SYS
+bug).
+        JNC     XMS_available01         ;
+        XOR     AX,AX                   ; Set zero if underflow.
+ 
+  XMS_available01:
+        MOV     CL,4                    ; Divide Kbytes by 16 for blocks.
+        SHR     AX,CL                   ;
+ 
+        POP     DX
+        POP     CX
+        POP     BX
+ 
+        RET                             ; Exit
+ 
+endproc   XMS_available
+ 
+SUBTTL  Extended Memory - XMS - Return largest block XMS mem.
+PAGE+
+ 
+ ;
+ ; Stack frame definition for unsigned XMSblk_available( void );
+ ;
+ ;  The size of the largest block of XMS memory available,
+ ;  (in 16Kbyte blocks) is returned.
+ ;
+procname  XMSblk_available
+ 
+        PUSH    BX
+        PUSH    CX
+        PUSH    DX
+ 
+        CALL    XMS_setup               ; Ensure XMS memory is set.
+        TEST    AX,AX                   ;
+        JZ      XMSblk_available01      ; Return zero if not.
+ 
+        MOV     AH,08H                  ; Set the size function code.
+        CALL    DWORD PTR CS:[XMSfunctAdr] ; Get the size.
+        TEST    AX,AX                   ;
+        JZ      XMSblk_available01      ;
+ 
+        SUB     DX,64                   ; Subtract out the HMA (HIMEM.SYS
+bug).
+        JNC     XMSblk_available0X      ;
+        XOR     DX,DX                   ; Set zero if underflow.
+ 
+ XMSblk_available0X:
+        CMP     AX,DX                   ;
+        JBE     XMSblk_available01      ;
+        MOV     AX,DX                   ; Set available Kbytes.
+ 
+  XMSblk_available01:
+        MOV     CL,4                    ; Divide Kbytes by 16 for blocks.
+        SHR     AX,CL                   ;
+ 
+        POP     DX
+        POP     CX
+        POP     BX
+ 
+        RET                             ; Exit
+ 
+endproc   XMSblk_available
+ 
+SUBTTL  Extended Memory - XMS De-allocate a memory block.
+PAGE+
+ 
+ ;
+ ; Stack frame definition for int XMS_dealloc( int Hdl );
+ ;
+ ; Zero is returned if the operation fails, non-zero if success.
+ ;
+ ; its really important to do this, only other way to recover
+ ; XMS blocks is to re-boot
+ 
+XMSdealparms STRUC
+ 
+        DW      0, 0
+        DW      0
+xmsdealHdl  DW      ?
+ 
+XMSdealparms ENDS
+ 
+ 
+procname  XMS_dealloc
+ 
+        PUSH    BP
+        MOV     BP,SP
+ 
+        PUSH    BX
+        PUSH    DX
+ 
+;        CALL    XMS_setup               ; Ensure XMS memory is set.
+;        TEST    AX,AX                   ;
+;        JZ      XMS_dealloc01           ; Return zero if not.
+ 
+        MOV     DX,xmsdealHdl[BP]       ; Get the handle to de-allocate.
+        MOV     AH,0AH                  ;
+ 
+        CALL    DWORD PTR CS:[XMSfunctAdr] ; De-allocate it.
+ 
+  XMS_dealloc01:
+        POP     DX
+        POP     BX
+ 
+        POP     BP
+        RET                             ; Exit
+ 
+endproc   XMS_dealloc
+ 
+SUBTTL  Extended Memory - XMS Allocate a memory block.
+PAGE+
+ 
+ ;
+ ; Stack frame definition for int XMS_alloc( unsigned rsrvd, *size );
+ ;
+ ;     rsrved and size are in 16K byte blocks.
+ ;     rsrved is mem set aside for EMS, generaly zero
+ ;
+ ;  Zero is returned if the operation fails.
+ ;  Block (XMS) handle is returned if success.
+ ;
+ ;  size - is reduced by the amount of XMS memory actually allocated.
+ ;
+ 
+XMSalparms STRUC
+ 
+        DW      0, 0
+        DW      0
+xmsalrsrvd DW      ?
+xmsalsize  DD      ?
+ 
+XMSalparms ENDS
+ 
+procname  XMS_alloc
+ 
+        PUSH    BP
+        MOV     BP,SP
+ 
+        PUSH    BX
+        PUSH    CX
+        PUSH    DX
+        PUSH    DI
+        PUSH    ES
+        PUSH    DS
+ 
+        MOV     AX,CS                   ; Set the data segment to the code
+        MOV     DS,AX                   ;  segment.
+ 
+        MOV     CX,4                    ;
+        ADD     xmsalrsrvd[BP],CX       ; Subtract out the HMA (HIMEM.SYS
+bug).
+        SHL     xmsalrsrvd[BP],CL       ; Convert reserved blocks to K-bytes.
+ 
+        LES     DI,xmsalsize[BP]        ; Load size address.
+        XOR     AX,AX                   ;
+        MOV     BX,ES:[DI]              ; Get the requested size in blocks.
+ 
+        TEST    BX,0F000H               ; Check for more than 64 Megabytes.
+        JZ      XMS_alloc01             ;
+        MOV     BX,00FFFH               ;
+ 
+  XMS_alloc01:
+        MOV     CL,4                    ;
+        SHL     BX,CL                   ; Convert to K-Bytes.
+        MOV     CX,BX                   ; In CX.
+        JZ      XMS_alloc05             ; Return zero if no size requested.
+ 
+;        CALL    XMS_setup               ; Ensure XMS memory is set.
+;        TEST    AX,AX                   ;
+;        JZ      XMS_alloc05             ; Return zero if not.
+ 
+        XOR     BX,BX                   ;
+        MOV     AH,08H                  ; Set to Query Free XMS Memory.
+        CALL    DWORD PTR [XMSfunctAdr] ;
+ 
+        SUB     DX,xmsalrsrvd[BP]       ; Subtract out reserved blocks.
+        JB      XMS_alloc03             ; Ensure no borrow.
+        CMP     AX,DX                   ;
+        JBE     XMS_alloc02             ;
+        MOV     AX,DX                   ;
+ 
+  XMS_alloc02:
+        MOV     DX,AX                   ;
+        CMP     AX,68                   ; Ensure enough memory to allocate.
+ 
+  XMS_alloc03:
+        MOV     AX,0                    ;
+        JB      XMS_alloc05             ; Exit if not.
+ 
+        CMP     BL,80H                  ; Check for errors.
+        JE      XMS_alloc05             ;
+        CMP     BL,81H                  ;
+        JE      XMS_alloc05             ;
+ 
+        CMP     CX,DX                   ; Check actual against requested size.
+        JBE     XMS_alloc04             ;
+        MOV     CX,DX                   ; Set if actual < requested.
+ 
+  XMS_alloc04:
+        MOV     DX,CX                   ; Set requested size.
+        MOV     AH,09H                  ;
+        CALL    DWORD PTR [XMSfunctAdr] ; Allocate it.
+        DEC     AX                      ; Check for errors.
+        MOV     AX,0                    ;
+        JNZ     XMS_alloc05             ;
+ 
+ 
+        MOV     AX,CX                   ; Convert allocated size in KBytes
+        MOV     CL,4                    ; to allocated blocks.
+        SHR     AX,CL                   ;
+ 
+        SUB     ES:[DI],AX              ; Subtract the blocks allocated.
+        MOV     AX,DX                   ; Set to return the handle.
+ 
+  XMS_alloc05:
+        POP     DS
+        POP     ES
+        POP     DI
+        POP     DX
+        POP     CX
+        POP     BX
+ 
+        POP     BP
+        RET                             ; Exit
+ 
+endproc  XMS_alloc
+ 
+SUBTTL  Extended Memory - XMS get, put Stack Frame definition
+PAGE+
+ 
+ 
+XMSgpparms STRUC
+ 
+        DW      0, 0
+        DW      0
+xmsgpHdl     DW      ?
+xmsgpblk     DW      ?
+xmsgpblkAdr  DW      ?
+xmsgpBytes   DW      ?
+xmsgpmemAdr  DD      ?
+ 
+XMSgpparms ENDS
+ 
+SUBTTL  Extended Memory - XMStoMem
+PAGE+
+ 
+ 
+ ;
+ ; Stack frame definition for int XMStoMem( unsigned Handle,
+ ;                                          unsigned blk,
+ ;                                          unsigned blkAdr,
+ ;                                          unsigned Bytes,
+ ;                                          char     *memAdr
+ ;                                        );
+ ;
+ ;  XMSmemError is returned if the operation fails, Zero if success.
+ ;
+ 
+procname  XMStoMem
+ 
+        PUSH    BP
+        MOV     BP,SP
+ 
+        PUSH    BX
+        PUSH    CX
+        PUSH    DX
+        PUSH    SI
+        PUSH    DI
+        PUSH    ES
+        PUSH    DS
+ 
+        MOV     AX,CS                   ; Set Data Segment to Code Segment.
+        MOV     DS,AX                   ;
+ 
+        MOV     CX,xmsgpBytes[BP]       ; Get the number of bytes to transfer.
+        LES     BX,xmsgpmemAdr[BP]      ; Get the memory address.
+        MOV     DX,xmsgpHdl[BP]         ; Get the XMS handle.
+        MOV     [XMSmainGET.SrcHandle],DX ; Set it in the move structures.
+        MOV     [XMSwordGET.SrcHandle],DX ;
+ 
+        XOR     DX,DX                   ;
+        MOV     DI,xmsgpblk[BP]         ; Get the block number.
+        SHR     DI,1                    ; Form the 32 bit XMS address in
+        RCR     DX,1                    ;  DI:DX.
+        SHR     DI,1                    ;
+        RCR     DX,1                    ;
+        ADD     DX,xmsgpblkAdr[BP]      ;
+ 
+        TEST    CX,1                    ; Check for an odd number of bytes
+        JZ      XMStoMem02              ;  to transfer.
+ 
+        DEC     CX                      ; Decrement to an even number of
+bytes.
+ 
+        TEST    DX,1                    ; Check for an odd XMS address.
+        JZ      XMStoMem01              ;
+ 
+                                        ; XMS address is odd.
+                                        ; -------------------
+        DEC     DX                      ;
+        MOV     [XMSwordGET.SrcOffset],DX   ; Set the XMS address.
+        MOV     [XMSwordGET.SrcOffsetX],DI  ;
+ 
+        MOV     AH,0BH                  ; Set the XMS move, function code.
+        MOV     SI,OFFSET XMSwordGET    ; Set address of the move structure.
+ 
+        PUSH    BX                      ;
+        CALL    DWORD PTR [XMSfunctAdr] ; Call the XMS handler.
+        POP     BX                      ;
+        DEC     AX                      ; Check for errors.
+        JNZ     XMStoMem03              ; Error out if error.
+ 
+        MOV     AX,[XMSword]            ; Get the moved word.
+ 
+        MOV     ES:[BX],AH              ; Move the odd byte to memory.
+ 
+        INC     BX                      ; Reset the memory address.
+        ADD     DX,2                    ; And the XMS address.
+ 
+        JMP     XMStoMem02              ; Move the block.
+ 
+ 
+  XMStoMem01:
+                                        ; XMS address is even.
+                                        ; --------------------
+        ADD     DX,CX                   ;
+        MOV     [XMSwordGET.SrcOffset],DX   ; Set the XMS address.
+        SUB     DX,CX                       ;
+        MOV     [XMSwordGET.SrcOffsetX],DI  ;
+ 
+        MOV     AH,0BH                  ; Set the XMS move, function code.
+        MOV     SI,OFFSET XMSwordGET    ; Set address of the move structure.
+ 
+        PUSH    BX                      ;
+        CALL    DWORD PTR [XMSfunctAdr] ; Call the XMS handler.
+        POP     BX                      ;
+        DEC     AX                      ; Check for errors.
+        JNZ     XMStoMem03              ; Error out if error.
+ 
+        MOV     AX,[XMSword]            ; Get the moved word.
+ 
+        XCHG    DI,CX                   ;
+        MOV     ES:[BX+DI],AL           ; Move the odd byte to memory.
+        XCHG    DI,CX                   ;
+ 
+  XMStoMem02:
+        JCXZ    XMStoMem04              ; Avoid a zero byte move.
+ 
+        MOV     XMSmainGET.Length,CX    ; Set length for the move.
+ 
+        MOV     XMSmainGET.DestOffset,BX   ; Set Memory address.
+        MOV     XMSmainGET.DestOffsetX,ES  ;
+ 
+        MOV     XMSmainGET.SrcOffset,DX    ; Set XMS address.
+        MOV     XMSmainGET.SrcOffsetX,DI   ;
+ 
+        MOV     AH,0BH                  ; Set the XMS move, function code.
+        MOV     SI,OFFSET XMSmainGET    ; Set address of the move structure.
+ 
+        CALL    DWORD PTR [XMSfunctAdr] ; Call the XMS handler.
+        DEC     AX                      ; Check for errors.
+        JZ      XMStoMem05
+ 
+  XMStoMem03:
+        MOV     AX,XMSmemError          ; Set error code if error.
+        JMP     XMStoMem05              ;
+ 
+  XMStoMem04:
+        XOR     AX,AX                   ;
+ 
+  XMStoMem05:
+        POP     DS
+        POP     ES
+        POP     DI
+        POP     SI
+        POP     DX
+        POP     CX
+        POP     BX
+ 
+        POP     BP
+        RET                             ; Exit
+ 
+endproc  XMStoMem
+ 
+SUBTTL  Extended Memory - MemToXMS
+PAGE+
+ 
+ 
+ ;
+ ; Stack frame definition for int MemToXMS( unsigned Handle,
+ ;                                        unsigned blk,
+ ;                                        unsigned blkAdr,
+ ;                                        unsigned Bytes,
+ ;                                        char     *memAdr
+ ;                                       );
+ ;
+ ;  XMSmemError is returned if the operation fails, Zero if success.
+ ;
+ 
+procname  MemToXMS
+ 
+        PUSH    BP
+        MOV     BP,SP
+ 
+        PUSH    BX
+        PUSH    CX
+        PUSH    DX
+        PUSH    SI
+        PUSH    DI
+        PUSH    ES
+        PUSH    DS
+ 
+        MOV     AX,CS                   ;
+        MOV     DS,AX                   ;
+ 
+        MOV     CX,xmsgpBytes[BP]       ; Get the number of bytes to transfer.
+        LES     BX,xmsgpmemAdr[BP]      ; Get the memory address.
+        MOV     DX,xmsgpHdl[BP]         ; Get the XMS handle.
+        MOV     [XMSmainPUT.DestHandle],DX ; Set it in the move structures.
+        MOV     [XMSwordPUT.DestHandle],DX ;
+        MOV     [XMSwordGET.SrcHandle],DX  ;
+ 
+        XOR     DX,DX                   ;
+        MOV     DI,xmsgpblk[BP]         ; Get the block number.
+        SHR     DI,1                    ; Form the 32 bit XMS address in
+        RCR     DX,1                    ;  DI:DX.
+        SHR     DI,1                    ;
+        RCR     DX,1                    ;
+        ADD     DX,xmsgpblkAdr[BP]      ;
+ 
+        TEST    CX,1                    ; Check for an odd number of bytes
+        JZ      MemToXMS02              ;  to transfer.
+ 
+        DEC     CX                      ; Decrement to an even number of
+bytes.
+ 
+        TEST    DX,1                    ; Check for an odd XMS address.
+        JZ      MemToXMS01              ;
+ 
+                                        ; XMS address is odd.
+                                        ; -------------------
+        DEC     DX                      ;
+        MOV     [XMSwordGET.SrcOffset],DX   ; Set the XMS address.
+        MOV     [XMSwordGET.SrcOffsetX],DI  ;
+        MOV     [XMSwordPUT.DestOffset],DX  ;
+        MOV     [XMSwordPUT.DestOffsetX],DI ;
+ 
+        MOV     AH,0BH                  ; Set the XMS move, function code.
+        MOV     SI,OFFSET XMSwordGET    ; Set address of the move structure.
+ 
+        PUSH    BX                      ;
+        CALL    DWORD PTR [XMSfunctAdr] ; Call the XMS handler.
+        POP     BX                      ;
+        DEC     AX                      ; Check for errors.
+        JNZ     MemToXMS03              ; Error out if error.
+ 
+        MOV     AH,ES:[BX]              ; Get the odd memory byte.
+ 
+        MOV     [XMSwordByte+1],AH      ; Put it in the moved word.
+ 
+        MOV     AH,0BH                  ; Set the XMS move, function code.
+        MOV     SI,OFFSET XMSwordPUT    ; Set address of the move structure.
+ 
+        PUSH    BX                      ;
+        CALL    DWORD PTR [XMSfunctAdr] ; Call the XMS handler.
+        POP     BX                      ;
+        DEC     AX                      ; Check for errors.
+        JNZ     MemToXMS03              ; Error out if error.
+ 
+        INC     BX                      ; Reset the memory address.
+        ADD     DX,2                    ; And the XMS address.
+ 
+        JMP     MemToXMS02              ; Move the block.
+ 
+  MemToXMS01:
+                                        ; XMS address is even.
+                                        ; --------------------
+        ADD     DX,CX                   ;
+        MOV     [XMSwordGET.SrcOffset],DX   ; Set the XMS address.
+        MOV     [XMSwordPUT.DestOffset],DX  ;
+        SUB     DX,CX                       ;
+        MOV     [XMSwordGET.SrcOffsetX],DI  ;
+        MOV     [XMSwordPUT.DestOffsetX],DI ;
+ 
+        MOV     AH,0BH                  ; Set the XMS move, function code.
+        MOV     SI,OFFSET XMSwordGET    ; Set address of the move structure.
+ 
+        PUSH    BX                      ;
+        CALL    DWORD PTR [XMSfunctAdr] ; Call the XMS handler.
+        POP     BX                      ;
+        DEC     AX                      ; Check for errors.
+        JNZ     MemToXMS03              ; Error out if error.
+ 
+        XCHG    DI,CX                   ;
+        MOV     AL,ES:[BX+DI]           ; Get the odd memory byte.
+        XCHG    DI,CX                   ;
+ 
+        MOV     [XMSwordByte],AL        ; Set the moved word.
+ 
+        MOV     AH,0BH                  ; Set the XMS move, function code.
+        MOV     SI,OFFSET XMSwordPUT    ; Set address of the move structure.
+ 
+        PUSH    BX                      ;
+        CALL    DWORD PTR [XMSfunctAdr] ; Call the XMS handler.
+        POP     BX                      ;
+        DEC     AX                      ; Check for errors.
+        JNZ     MemToXMS03              ; Error out if error.
+ 
+  MemToXMS02:
+        JCXZ    MemToXMS04              ; Avoid a zero byte move.
+ 
+        MOV     XMSmainPUT.Length,CX    ; Set length for the move.
+ 
+        MOV     XMSmainPUT.SrcOffset,BX    ; Set Memory address.
+        MOV     XMSmainPUT.SrcOffsetX,ES   ;
+ 
+        MOV     XMSmainPUT.DestOffset,DX   ; Set XMS address.
+        MOV     XMSmainPUT.DestOffsetX,DI  ;
+ 
+        MOV     AH,0BH                  ; Set the XMS move, function code.
+        MOV     SI,OFFSET XMSmainPUT    ; Set address of the move structure.
+ 
+        CALL    DWORD PTR [XMSfunctAdr] ; Call the XMS handler.
+        DEC     AX                      ; Check for errors.
+        JZ      MemToXMS05
+ 
+  MemToXMS03:
+        MOV     AX,XMSmemError          ; Set error code if error.
+        JMP     MemToXMS05              ;
+ 
+  MemToXMS04:
+        XOR     AX,AX                   ;
+ 
+  MemToXMS05:
+        POP     DS
+        POP     ES
+        POP     DI
+        POP     SI
+        POP     DX
+        POP     CX
+        POP     BX
+ 
+        POP     BP
+        RET                             ; Exit
+ 
+endproc  MemToXMS
+ 
+ 
+SUBTTL  Last Page
+PAGE+
+ 
+pwrlolvl_TEXT   ENDS
+ 
+        END
+ 
diff --git a/src/lib/xmem/xmem.h b/src/lib/xmem/xmem.h
new file mode 100644
index 00000000..15df92c0
--- /dev/null
+++ b/src/lib/xmem/xmem.h
@@ -0,0 +1,79 @@
+#if !defined(_XMEM_H)
+#define _XMEM_H
+ 
+typedef struct xms_node
+   {
+   long start, size, off;
+   short used;
+   struct xms_node *next;
+   }
+xms_node_t;
+ 
+typedef struct
+   {
+   int handle;
+   unsigned long total;
+   unsigned long avail;
+   unsigned long next_off;
+   xms_node_t *next;
+   }
+xms_head_t;
+ 
+#define XMSBLOCK 16384u
+#define XMSBLOCKSHIFT 14
+ 
+extern void LSHL( unsigned long far *SHLnumber, unsigned short n );
+ 
+extern unsigned short XMS_available( void );
+ 
+extern unsigned short XMSblk_available( void );
+ 
+extern short XMS_alloc(unsigned short rsrvd,
+                       unsigned short far *size
+                      );
+ 
+extern short XMS_dealloc(unsigned short Hdl );
+ 
+extern short XMStoMem(unsigned short Handle,   // XMS handle returned by
+//XMS_alloc()
+                      unsigned short blk,      // which 16k block to copy to
+                      unsigned short blkAdr,   // offset within 16k block
+                      unsigned short Bytes,    // bytes to copy
+                      void   far *memAdr
+                     );
+ 
+extern short MemToXMS(unsigned short Handle,
+                      unsigned short blk,
+                      unsigned short blkAdr,
+                      unsigned short Bytes,
+                      void   far *memAdr
+                     );
+ 
+// call these for ease
+short alloc_xms(unsigned short far *size);  // size in 16k blocks
+// NOTE size is changed to the amount block size was altered by!
+// normaly this is zero
+ 
+short xms_to_mem(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);
+void deinit_xms(void);
+short init_xms(unsigned short min_blocks);
+void qfree_xms(xms_node_t *node);
+xms_node_t *qalloc_xms(unsigned long size);
+xms_node_t *xms_open(char *file);
+short xms_read(void far *buffer, unsigned short n, xms_node_t *node);
+short xms_write(void far *buffer, unsigned short n, xms_node_t *node);
+long xms_tell(xms_node_t *node);
+short xms_seek(xms_node_t *node, long off, short whence);
+void xms_close(xms_node_t *node);
+ 
+ 
+extern xms_head_t xms_head;
+ 
+ 
+ 
+#endif
+ 
+/* ---------------------------------- end of file --------------------- */
diff --git a/src/lib/xmem/xmem.txt b/src/lib/xmem/xmem.txt
new file mode 100644
index 00000000..306374c2
--- /dev/null
+++ b/src/lib/xmem/xmem.txt
@@ -0,0 +1,33 @@
+Newsgroups: rec.games.programmer
+From: alexad3@icebox.iceonline.com (Alexander J. Russell)
+Subject: xms for x2ftp.oulu.fi
+Date: Mon, 20 Mar 1995 08:16:21 GMT
+
+Can some kind soul please pass this on to x2ftp.oulu.fi for me.
+I can't ftp from my currrent connection.
+
+ 
+This file contains 3 files:
+xmem.h   : c include file
+xmem.asm : low level basic XMS acess
+xmemc.c  : super easy C access via functions like fopen, fread, fwrite
+           xopen, xread, xwrite, xseek etc...
+ 
+ 
+FOR DOS REAL mode programs, requires HIMEM.SYS to be loaded in
+config.sys.
+ 
+... 
+
+This should be enough code to do what ever you want with XMS.
+I like to use the file style access to remind myself it isn't
+as fast as say memcpy().
+
+Cheers.
+
+
+
+
+The AnArChIsT - Anarchy! NOT Chaos! aka Alec Russell
+alexad3@icebox.iceonline.com
+
diff --git a/src/lib/xmem/xmemc.c b/src/lib/xmem/xmemc.c
new file mode 100644
index 00000000..0ab1de3d
--- /dev/null
+++ b/src/lib/xmem/xmemc.c
@@ -0,0 +1,316 @@
+/*
+   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 ------------------------- */
diff --git a/src/scroll.c b/src/scroll.c
index 41e1c557..1a326fca 100644
--- a/src/scroll.c
+++ b/src/scroll.c
@@ -499,7 +499,7 @@ allocMap(int w, int h) {
 	result.height=h;
 	if(initxms()>0)
 	result.data = malloc(sizeof(byte) * w * h);
-	else (void huge*)result.data = xmsmalloc(sizeof(byte) * w * h);
+	else result.data = xmsmalloc(sizeof(byte) * w * h);
 
 	return result;
 }
@@ -513,17 +513,17 @@ initMap(map_t *map) {
 	int tile = 1;
 	if(initxms()>0)
 	map->tiles = malloc(sizeof(tiles_t));
-	else (void huge*)map->tiles = xmsmalloc(sizeof(tiles_t));
+	else map->tiles = xmsmalloc(sizeof(tiles_t));
 
 	/* create the tile set */
 	if(initxms()>0)
 	map->tiles->data = malloc(sizeof(bitmap_t));
-	else (void huge*)map->tiles->data = xmsmalloc(sizeof(bitmap_t));
+	else map->tiles->data = xmsmalloc(sizeof(bitmap_t));
 	map->tiles->data->width = (TILEWH*2);
 	map->tiles->data->height= TILEWH;
 	if(initxms()>0)
 	map->tiles->data->data = malloc((TILEWH*2)*TILEWH);
-	else (void huge*)map->tiles->data->data = xmsmalloc((TILEWH*2)*TILEWH);
+	else map->tiles->data->data = xmsmalloc((TILEWH*2)*TILEWH);
 	map->tiles->tileHeight = TILEWH;
 	map->tiles->tileWidth =TILEWH;
 	map->tiles->rows = 1;
-- 
2.39.5