323 lines
No EOL
8 KiB
NASM
Executable file
323 lines
No EOL
8 KiB
NASM
Executable file
TITLE Turbo Pascal XMS support for loading overlays - By Wilbert van Leijen
|
|
PAGE 65, 132
|
|
LOCALS @@
|
|
|
|
Data SEGMENT Word Public
|
|
ASSUME DS:Data
|
|
|
|
; XMS block move record
|
|
|
|
XmsMoveType STRUC
|
|
BlkSize DD ?
|
|
SrcHandle DW ?
|
|
SrcOffset DD ?
|
|
DestHandle DW ?
|
|
DestOffset DD ?
|
|
XmsMoveType ENDS
|
|
|
|
; TP overlay manager record
|
|
|
|
OvrHeader STRUC
|
|
ReturnAddr DD ? ; Virtual return address
|
|
FileOfs DD ? ; Offset into overlay file
|
|
CodeSize DW ? ; Size of overlay
|
|
FixupSize DW ? ; Size of fixup table
|
|
EntryPts DW ? ; Number of procedures
|
|
CodeListNext DW ? ; Segment of next overlay
|
|
LoadSeg DW ? ; Start segment in memory
|
|
Reprieved DW ? ; Loaded in memory flag
|
|
LoadListNext DW ? ; Segment of next in load list
|
|
XmsOffset DD ? ; Offset into allocated XMS block
|
|
UserData DW 3 DUP(?)
|
|
OvrHeader ENDS
|
|
|
|
XmsDriver DD ? ; Entry point of XMS driver
|
|
ExitSave DD ? ; Pointer to previous exit proc
|
|
XmsMove XmsMoveType <>
|
|
OvrXmsHandle DW ? ; Returned by XMS driver
|
|
|
|
Extrn PrefixSeg : Word
|
|
Extrn ExitProc : DWord
|
|
Extrn OvrResult : Word
|
|
Extrn OvrCodeList : Word
|
|
Extrn OvrDosHandle : Word
|
|
Extrn OvrHeapOrg : Word
|
|
Extrn OvrReadBuf : DWord
|
|
Data ENDS
|
|
|
|
Code SEGMENT Byte Public
|
|
ASSUME CS:Code
|
|
Public OvrInitXMS
|
|
|
|
ovrIOError EQU -4
|
|
ovrNoXMSDriver EQU -7
|
|
ovrNoXMSMemory EQU -8
|
|
|
|
OvrXmsExit PROC
|
|
|
|
; Release handle and XMS memory
|
|
|
|
MOV DX, [OvrXmsHandle]
|
|
MOV AH, 10
|
|
CALL [XmsDriver]
|
|
|
|
; Restore pointer to previous exit procedure
|
|
|
|
LES AX, [ExitSave]
|
|
MOV Word Ptr [ExitProc], AX
|
|
MOV Word Ptr [ExitProc+2], ES
|
|
RETF
|
|
OvrXmsExit ENDP
|
|
|
|
AllocateXms PROC
|
|
|
|
; Determine the size of the XMS block to allocate:
|
|
; Walk the CodeListNext chain
|
|
; Store the total codesize in DX:AX
|
|
|
|
XOR AX, AX
|
|
XOR DX, DX
|
|
MOV BX, [OvrCodeList]
|
|
@@1: ADD BX, [PrefixSeg]
|
|
ADD BX, 10h
|
|
MOV ES, BX
|
|
ADD AX, ES:[OvrHeader.CodeSize]
|
|
ADC DX, 0
|
|
MOV BX, ES:[OvrHeader.CodeListNext]
|
|
OR BX, BX
|
|
JNZ @@1
|
|
|
|
; Obtain number of kilobytes to allocate
|
|
|
|
MOV BX, 1024
|
|
DIV BX
|
|
XCHG DX, AX
|
|
INC DX
|
|
|
|
; Allocate the block
|
|
|
|
MOV AH, 9
|
|
CALL [XmsDriver]
|
|
OR AX, AX
|
|
JZ @@2
|
|
MOV [OvrXmsHandle], DX
|
|
@@2: RETN
|
|
AllocateXms ENDP
|
|
|
|
; Function XmsReadFunc(OvrSeg : Word) : Integer; Far;
|
|
|
|
XmsReadFunc PROC
|
|
|
|
; Swap the code from XMS to the heap
|
|
|
|
PUSH BP
|
|
MOV BP, SP
|
|
MOV ES, [BP+6]
|
|
MOV AX, ES:[OvrHeader.CodeSize]
|
|
MOV Word Ptr [XmsMove.BlkSize], AX
|
|
XOR AX, AX
|
|
MOV Word Ptr [XmsMove.BlkSize+2], AX
|
|
MOV AX, [OvrXmsHandle]
|
|
MOV [XmsMove.SrcHandle], AX
|
|
MOV AX, Word Ptr ES:[OvrHeader.XmsOffset]
|
|
MOV Word Ptr [XmsMove.SrcOffset], AX
|
|
MOV AX, Word Ptr ES:[OvrHeader.XmsOffset+2]
|
|
MOV Word Ptr [XmsMove.SrcOffset+2], AX
|
|
XOR AX, AX
|
|
MOV [XmsMove.DestHandle], AX
|
|
MOV Word Ptr [XmsMove.DestOffset], AX
|
|
MOV AX, ES:[OvrHeader.LoadSeg]
|
|
MOV Word Ptr [XmsMove.DestOffset+2], AX
|
|
MOV AH, 11
|
|
LEA SI, XmsMove
|
|
CALL [XmsDriver]
|
|
OR AX, AX
|
|
JZ @@1
|
|
DEC AX
|
|
JMP @@2
|
|
|
|
@@1: MOV AX, ovrIOError
|
|
@@2: POP BP
|
|
RETF 2
|
|
XmsReadFunc ENDP
|
|
|
|
; Copy an overlaid unit from the heap to XMS
|
|
; If successful, carry flag is cleared
|
|
; In/Out:
|
|
; BX:DI = offset into XMS memory block
|
|
|
|
CopyUnitToXms PROC
|
|
|
|
; XMS requires that an even number of bytes is moved
|
|
|
|
MOV DX, ES:[OvrHeader.CodeSize]
|
|
TEST DX, 1
|
|
JZ @@1
|
|
INC DX
|
|
INC ES:[OvrHeader.CodeSize]
|
|
|
|
; Get the fields of the XMS block move structure
|
|
|
|
@@1: MOV Word Ptr [XmsMove.BlkSize], DX
|
|
XOR AX, AX
|
|
MOV Word Ptr [XmsMove.BlkSize+2], AX
|
|
MOV [XmsMove.SrcHandle], AX
|
|
MOV Word Ptr [XmsMove.SrcOffset], AX
|
|
MOV AX, [OvrHeapOrg]
|
|
MOV Word Ptr [XmsMove.SrcOffset+2], AX
|
|
MOV AX, [OvrXmsHandle]
|
|
MOV [XmsMove.DestHandle], AX
|
|
MOV Word Ptr [XmsMove.DestOffset], DI
|
|
MOV Word Ptr [XmsMove.DestOffset+2], BX
|
|
MOV AH, 11
|
|
LEA SI, XmsMove
|
|
CALL [XmsDriver]
|
|
|
|
; Bump code size
|
|
|
|
ADD DI, DX
|
|
ADC BX, 0
|
|
|
|
; Check return code from XMS driver
|
|
|
|
OR AX, AX
|
|
JZ @@2
|
|
CLC
|
|
RETN
|
|
|
|
@@2: STC
|
|
RETN
|
|
CopyUnitToXms ENDP
|
|
|
|
OvrXmsLoad PROC
|
|
PUSH BP
|
|
MOV BP, SP
|
|
|
|
; Walk the CodeList chain
|
|
; First segment is PrefixSeg+10h+OvrCodeList
|
|
; Push each element of overlaid unit list on the stack
|
|
; Keep the size of the linked list in CX
|
|
|
|
MOV AX, [OvrCodeList]
|
|
XOR CX, CX
|
|
@@1: ADD AX, [PrefixSeg]
|
|
ADD AX, 10h
|
|
MOV ES, AX
|
|
PUSH AX
|
|
INC CX
|
|
MOV AX, ES:[OvrHeader.CodeListNext]
|
|
OR AX, AX
|
|
JNZ @@1
|
|
|
|
; Loop:
|
|
; Pop each element of the overlaid unit list from the stack
|
|
|
|
XOR BX, BX
|
|
XOR DI, DI
|
|
@@2: POP ES
|
|
PUSH CX
|
|
MOV AX, [OvrHeapOrg]
|
|
MOV ES:[OvrHeader.LoadSeg], AX
|
|
MOV Word Ptr ES:[OvrHeader.XmsOffset+2], BX
|
|
MOV Word Ptr ES:[OvrHeader.XmsOffset], DI
|
|
|
|
; Load overlay from disk
|
|
|
|
PUSH BX
|
|
PUSH DI
|
|
PUSH ES
|
|
PUSH ES
|
|
CALL [OvrReadBuf]
|
|
POP ES
|
|
POP DI
|
|
POP BX
|
|
|
|
; Flag unit as 'unloaded'; check return code
|
|
|
|
MOV ES:[OvrHeader.LoadSeg], 0
|
|
NEG AX
|
|
JC @@3
|
|
|
|
CALL CopyUnitToXms
|
|
JC @@3
|
|
|
|
POP CX
|
|
LOOP @@2
|
|
|
|
@@3: MOV SP, BP
|
|
POP BP
|
|
RETN
|
|
OvrXMSLoad ENDP
|
|
|
|
OvrInitXMS PROC
|
|
|
|
; Make sure the file's been opened
|
|
|
|
XOR AX, AX
|
|
CMP AX, [OvrDOSHandle]
|
|
JNE @@1
|
|
DEC AX ; ovrError
|
|
JMP @@5
|
|
|
|
; Check presence of XMS driver
|
|
|
|
@@1: MOV AX, 4300h
|
|
INT 2Fh
|
|
CMP AL, 80h
|
|
JE @@2
|
|
MOV AX, ovrNoXmsDriver
|
|
JMP @@5
|
|
|
|
; Get XMS driver's entry point
|
|
|
|
@@2: MOV AX, 4310h
|
|
INT 2Fh
|
|
MOV Word Ptr [XmsDriver], BX
|
|
MOV Word Ptr [XmsDriver+2], ES
|
|
CALL AllocateXms
|
|
JNZ @@3
|
|
MOV AX, ovrNoXMSMemory
|
|
JMP @@5
|
|
|
|
; Load the overlay into XMS
|
|
|
|
@@3: CALL OvrXmsLoad
|
|
JNC @@4
|
|
|
|
; An error occurred. Release handle and XMS memory
|
|
|
|
MOV DX, [OvrXmsHandle]
|
|
MOV AH, 10
|
|
CALL [XmsDriver]
|
|
MOV AX, ovrIOError
|
|
JMP @@5
|
|
|
|
; Close file
|
|
|
|
@@4: MOV BX, [OvrDOSHandle]
|
|
MOV AH, 3Eh
|
|
INT 21h
|
|
|
|
; OvrReadBuf := XmsReadFunc
|
|
|
|
MOV Word Ptr [OvrReadBuf], Offset XmsReadFunc
|
|
MOV Word Ptr [OvrReadBuf+2], CS
|
|
|
|
; ExitSave := ExitProc
|
|
; ExitProc := OvrXmsExit
|
|
|
|
LES AX, [ExitProc]
|
|
MOV Word Ptr [ExitSave], AX
|
|
MOV Word Ptr [ExitSave+2], ES
|
|
MOV Word Ptr [ExitProc], Offset OvrXmsExit
|
|
MOV Word Ptr [ExitProc+2], CS
|
|
|
|
; Return result of initialisation
|
|
|
|
XOR AX, AX
|
|
@@5: MOV [OvrResult], AX
|
|
RETF
|
|
OvrInitXMS ENDP
|
|
|
|
Code ENDS
|
|
END |