;----------------------------------------------------------------------- ;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