home *** CD-ROM | disk | FTP | other *** search
- ;EXECWSWP.ASM
- ; Swap memory and exec another program, keeping child process's video
- ; output to a specified portion of the screen
- ; Copyright (c) 1988,1990 TurboPower Software
- ; May be used freely as long as due credit is given
- ;
- ;-----------------------------------------------------------------------------
- DATA SEGMENT WORD PUBLIC
- EXTRN BytesSwapped:DWORD ;Bytes to swap to EMS/disk
- EXTRN EmsAllocated:BYTE ;True when EMS allocated for swap
- EXTRN FileAllocated:BYTE ;True when file allocated for swap
- EXTRN EmsHandle:WORD ;Handle of EMS allocation block
- EXTRN FrameSeg:WORD ;Segment of EMS page frame
- EXTRN FileHandle:WORD ;Handle of DOS swap file
- EXTRN SwapName:BYTE ;ASCIIZ name of swap file
- EXTRN PrefixSeg:WORD ;Base segment of program
- EXTRN NewInt21Addr:WORD; ;Hold addr on our int 21 handler
- DATA ENDS
- ;-----------------------------------------------------------------------------
- CODE SEGMENT WORD PUBLIC
- ASSUME CS:CODE,DS:DATA
- PUBLIC ExecWinWithSwap, FirstToSave
- PUBLIC AllocateSwapFile, DeallocateSwapFile
- PUBLIC DefaultDrive, DiskFree
- PUBLIC EmsInstalled, EmsPageFrame
- PUBLIC AllocateEmsPages, DeallocateEmsHandle
- PUBLIC InstallInt21, RestoreInt21, CheckCursor
- PUBLIC UpdateCsVars
- ;-----------------------------------------------------------------------------
- FileAttr EQU 6 ;Swap file attribute (hidden+system)
- EmsPageSize EQU 16384 ;Size of EMS page
- FileBlockSize EQU 32768 ;Size of a file block
- StkSize EQU 128 ;Bytes in temporary stack
- lo EQU (WORD PTR 0) ;Convenient typecasts
- hi EQU (WORD PTR 2)
- ofst EQU (WORD PTR 0)
- segm EQU (WORD PTR 2)
- col EQU (BYTE PTR 0)
- row EQU (BYTE PTR 1)
-
- ;-----------------------------------------------------------------------------
- ;Variables in CS
- EmsDevice DB 'EMMXXXX0',0 ;Name of EMS device driver
- UsedEms DB 0 ;1 if swapping to EMS, 0 if to file
- BytesSwappedCS DD 0 ;Bytes to move during a swap
- EmsHandleCS DW 0 ;EMS handle
- FrameSegCS DW 0 ;Segment of EMS page window
- FileHandleCS DW 0 ;DOS file handle
- PrefixSegCS DW 0 ;Segment of base of program
- Status DW 0 ;ExecSwap status code
- LeftToSwap DD 0 ;Bytes left to move
- SaveSP DW 0 ;Original stack pointer
- SaveSS DW 0 ;Original stack segment
- PathPtr DD 0 ;Pointer to program to execute
- CmdPtr DD 0 ;Pointer to command line to execute
- ParasWeHave DW 0 ;Paragraphs allocated to process
- CmdLine DB 128 DUP(0) ;Terminated command line passed to DOS
- Path DB 64 DUP(0) ;Terminated path name passed to DOS
- FileBlock1 DB 16 DUP(0) ;FCB passed to DOS
- FileBlock2 DB 16 DUP(0) ;FCB passed to DOS
- EnvironSeg DW 0 ;Segment of environment for child
- CmdLinePtr DD 0 ;Pointer to terminated command line
- FilePtr1 DD 0 ;Pointer to FCB file
- FilePtr2 DD 0 ;Pointer to FCB file
- OrigInt21 DD 0 ;Previous $21 vector
- WindPos DW 0 ;Cursor position in window
- WindLo DW 0 ;Top left corner of window
- WindHi DW 0 ; and bottom right corner.
- WindAttr DB 0 ;Attribute with which to
- TempStack DB StkSize DUP(0) ;Temporary stack
- StackTop LABEL WORD ;Initial top of stack
-
- ;-----------------------------------------------------------------------------
- ;Macros
- MovSeg MACRO Dest,Src ;Set one segment register to another
- PUSH Src
- POP Dest
- ENDM
-
- MovMem MACRO Dest,Src ;Move from memory to memory via AX
- MOV AX,Src
- MOV Dest,AX
- ENDM
-
- InitSwapCount MACRO ;Initialize counter for bytes to swap
- MovMem LeftToSwap.lo,BytesSwappedCS.lo
- MovMem LeftToSwap.hi,BytesSwappedCS.hi
- ENDM
-
- SetSwapCount MACRO BlkSize ;Return CX = bytes to move this block
- LOCAL FullBlk ;...and reduce total bytes left to move
- MOV CX,BlkSize ;Assume we'll write a full block
- CMP LeftToSwap.hi,0 ;Is high word still non-zero?
- JNZ FullBlk ;Jump if so
- CMP LeftToSwap.lo,BlkSize ;Low word still a block or more?
- JAE FullBlk ;Jump if so
- MOV CX,LeftToSwap.lo ;Otherwise, move what's left
- FullBlk:SUB LeftToSwap.lo,CX ;Reduce number left to move
- SBB LeftToSwap.hi,0
- ENDM
-
- NextBlock MACRO SegReg, BlkSize ;Point SegReg to next block to move
- MOV AX,SegReg
- ADD AX,BlkSize/16 ;Add paragraphs to next segment
- MOV SegReg,AX ;Next block to move
- MOV AX,LeftToSwap.lo
- OR AX,LeftToSwap.hi ;Bytes left to move?
- ENDM
-
- EmsCall MACRO FuncAH ;Call EMM and prepare to check result
- MOV AH,FuncAH ;Set up function
- INT 67h
- OR AH,AH ;Error code in AH
- ENDM
-
- DosCallAH MACRO FuncAH ;Call DOS subfunction AH
- MOV AH,FuncAH
- INT 21h
- ENDM
-
- DosCallAX MACRO FuncAX ;Call DOS subfunction AX
- MOV AX,FuncAX
- INT 21h
- ENDM
-
- InitSwapFile MACRO
- MOV BX,FileHandleCS ;BX = handle of swap file
- XOR CX,CX
- XOR DX,DX ;Start of file
- DosCallAX 4200h ;DOS file seek
- ENDM
-
- HaltWithError MACRO Level ;Halt if non-recoverable error occurs
- MOV AL,Level ;Set errorlevel
- DosCallAH 4Ch
- ENDM
-
- MoveFast MACRO ;Move CX bytes from DS:SI to ES:DI
- CLD ;Forward
- SHR CX,1 ;Convert to words
- REP MOVSW ;Move the words
- RCL CX,1 ;Get the odd byte, if any
- REP MOVSB ;Move it
- ENDM
-
- SetTempStack MACRO ;Switch to temporary stack
- MOV AX,OFFSET StackTop ;Point to top of stack
- MOV BX,CS ;Temporary stack in this code segment
- CLI ;Interrupts off
- MOV SS,BX ;Change stack
- MOV SP,AX
- STI ;Interrupts on
- ENDM
-
- ToDos MACRO ;Transfer control to DOS
- JMP DWORD PTR OrigInt21
- ENDM
-
- ToApp MACRO ;Transfer control back to caller
- CLC ;Clear error flag
- RET 2 ;Return with flags intact
- ENDM
-
- ;-----------------------------------------------------------------------------
- ;procedure CheckCursor
- ;
- CheckCursor PROC NEAR
- PUSH BP
- MOV BP,SP ;Set up stack frame
-
- MOV AH,3
- XOR BH,BH
- INT 10h ;Get cursor position
- MOV CX,WindLo
- CMP DH,CH ;Row above minimum?
- JAE CC1 ;Jump if so
- MOV DH,CH ;Force to minimum
- CC1: CMP DL,CL ;Col above minimum?
- JAE CC2 ;Jump is so
- MOV DL,CL ;Force to minimum
- CC2: MOV CX, WindHi
- CMP DH,CH ;Row below maximum?
- JBE CC3 ;Jump if so
- MOV DH,CH ;Force to maximum
- CC3: CMP DL,CL ;Col below maximum?
- JBE CC4 ;Jump if so
- MOV DL,CL ;Force to maximum
- CC4: MOV WindPos,DX ;Save current position
- MOV AH,2
- XOR BH,BH
- INT 10h ;Make it so
-
- POP BP
- RET ;Return
- CheckCursor ENDP
-
- ;----------------------------------------------------------------------------
- ;procedure InstallInt21
- ;
- InstallInt21 PROC NEAR
- PUSH BP
- MOV BP,SP ;Set up stack frame
-
- ;Get the current Int21 vector
- DosCallAX 3521h ;ES:BX = vector
- MOV OrigInt21.ofst, BX ;Save as pointer in OrigInt21
- MOV OrigInt21.segm, ES
-
- ;Install our Int21 handler
- PUSH DS
- MOV DX, SEG NewInt21 ;Segment of our handler
- MOV DS, DX
- MOV DX, OFFSET NewInt21 ;Offset of our handler
- DosCallAX 2521h ;Set it
- POP DS
-
- MOV NewInt21Addr, OFFSET NewInt21
- MOV NewInt21Addr+2, SEG NewInt21 ;Show addr to caller
-
- POP BP
- RET ;Return
- InstallInt21 ENDP
-
- ;-----------------------------------------------------------------------------
- ;procedure RestoreInt21
- ;
- RestoreInt21 PROC NEAR
- PUSH BP
- MOV BP,SP ;Set up stack frame
-
- PUSH DS
- LDS DX, OrigInt21 ;DS:DX = OrigInt21
- DosCallAX 2521h ;Restore it
- POP DS
-
- POP BP
- RET ;Return
- RestoreInt21 ENDP
-
- ;-----------------------------------------------------------------------------
- ;procedure UpdateCsVars(Xlo, Ylo, Xhi, Yhi, Attr : Byte);
- ;
- UpdateCsVars PROC NEAR
- PUSH BP
- MOV BP,SP ;Set up stack frame
-
- ;Move passed values to CS variables
- MOV AX,[BP+12]
- DEC AX
- MOV BYTE PTR WindLo.Col, AL ;Lo(WindLo) = Xlo
- MOV AX,[BP+10]
- DEC AX
- MOV BYTE PTR WindLo.Row, AL ;Hi(WindLo) = Ylo
- MOV AX,[BP+8]
- DEC AX
- MOV BYTE PTR WindHi.Col,AL ;Lo(WindHi) = Xhi
- MOV AX, [BP+6]
- DEC AX
- MOV BYTE PTR WindHi.Row, AL ;Hi(WindHi) = Yhi
- MOV AX,[BP+4]
- MOV WindAttr, AL ;Get attribute
-
- POP BP
- RET 10
- UpdateCsVars ENDP
-
- ;-----------------------------------------------------------------------------
- ;function ExecWithSwap(Path, CmdLine : string;
- ; Xlo, Ylo, Xhi, Yhi, Attr : Byte ) : Word;
- ExecWinWithSwap PROC FAR
- PUSH BP
- MOV BP,SP ;Set up stack frame
-
- ;Move variables to CS where we can easily access them later
- MOV Status,1 ;Assume failure
- LES DI,[BP+20] ;ES:DI -> Path
- MOV PathPtr.ofst,DI
- MOV PathPtr.segm,ES ;PathPtr -> path to execute
- LES DI,[BP+16] ;ES:DI -> CmdLine
- MOV CmdPtr.ofst,DI
- MOV CmdPtr.segm,ES ;CmdPtr -> command line string
-
- PUSH [BP+14]
- PUSH [BP+12]
- PUSH [BP+10]
- PUSH [BP+8]
- PUSH [BP+6]
- CALL UpdateCsVars ;Transfer parms to CS vars
-
- ;Make sure cursor is within window
- CALL CheckCursor
-
- ;Continue with swapping
- MOV SaveSP,SP ;Save stack position
- MOV SaveSS,SS
- MovMem BytesSwappedCS.lo,BytesSwapped.lo
- MovMem BytesSwappedCS.hi,BytesSwapped.hi
- MovMem EmsHandleCS,EmsHandle
- MovMem FrameSegCS,FrameSeg
- MovMem FileHandleCS,FileHandle
- MovMem PrefixSegCS,PrefixSeg
- InitSwapCount ;Initialize bytes LeftToSwap
-
- ;Install our Int21 handler
- CALL InstallInt21
-
- ;Check for swapping to EMS or file
- CMP EmsAllocated,0 ;Check flag for EMS method
- JZ NotEms ;Jump if EMS not used
- JMP WriteE ;Swap to EMS
- NotEms: CMP FileAllocated,0 ;Check flag for swap file method
- JNZ WriteF ;Swap to file
- JMP ESDone ;Exit if no swapping method set
-
- ;Write to swap file
- WriteF: MovSeg DS,CS ;DS = CS
- InitSwapFile ;Seek to start of swap file
- JNC EF0 ;Jump if success
- JMP ESDone ;Exit if error
- EF0: SetSwapCount FileBlockSize ;CX = bytes to write
- MOV DX,OFFSET FirstToSave ;DS:DX -> start of region to save
- DosCallAH 40h ;File write
- JC EF1 ;Jump if write error
- CMP AX,CX ;All bytes written?
- JZ EF2 ;Jump if so
- EF1: JMP ESDone ;Exit if error
- EF2: NextBlock DS,FileBlockSize ;Point DS to next block to write
- JNZ EF0 ;Loop if bytes left to write
- MOV UsedEms,0 ;Flag we used swap file for swapping
- DosCallAH 45h ;DUP handle
- JC EF2a ;Jump if failed
- MOV BX,AX ;Prepare to close dup'ed handle
- DosCallAH 3Eh ;Flush swap file
- EF2a: JMP SwapDone ;Done swapping out
-
- ;Write to EMS
- WriteE: MOV ES,FrameSeg ;ES -> page window
- MOV DX,EmsHandle ;DX = handle of our EMS block
- EmsCall 47h ;Save EMS context
- XOR BX,BX ;BX = initial logical page
- MovSeg DS,CS ;DS = CS
- EE0: XOR AL,AL ;Physical page 0
- EmsCall 44h ;Map physical page
- JZ EE1 ;Jump if success
- JMP ESDone ;Exit if error
- EE1: SetSwapCount EmsPageSize ;CX = Bytes to move
- XOR DI,DI ;ES:DI -> base of EMS page
- MOV SI,OFFSET FirstToSave ;DS:SI -> region to save
- MoveFast ;Move CX bytes from DS:SI to ES:DI
- INC BX ;Next logical page
- NextBlock DS,EmsPageSize ;Point DS to next page to move
- JNZ EE0 ;Loop if bytes left to move
- EmsCall 48h ;Restore EMS context
- MOV UsedEms,1 ;Flag we used EMS for swapping
-
- ;Shrink memory allocated to this process
- SwapDone:MOV AX,PrefixSegCS
- MOV ES,AX ;ES = segment of our memory block
- DEC AX
- MOV DS,AX ;DS = segment of memory control block
- MOV CX,DS:[0003h] ;CX = current paragraphs owned
- MOV ParasWeHave,CX ;Save current paragraphs owned
- SetTempStack ;Switch to temporary stack
- MOV AX,OFFSET FirstToSave+15
- MOV CL,4
- SHR AX,CL ;Convert offset to paragraphs
- ADD BX,AX
- SUB BX,PrefixSegCS ;BX = new paragraphs to keep
- DosCallAH 4Ah ;SetBlock
- JNC EX0 ;Jump if successful
- JMP EX5 ;Swap back and exit
-
- ;Set up parameters and call DOS Exec
- EX0: MOV AX,ES:[002Ch] ;Get environment segment
- MOV EnvironSeg,AX
- MovSeg ES,CS ;ES = CS
- LDS SI,PathPtr ;DS:SI -> path to execute
- MOV DI,OFFSET Path ;ES:DI -> local ASCIIZ copy
- CLD
- LODSB ;Read current length
- CMP AL,63 ;Truncate if exceeds space set aside
- JB EX1
- MOV AL,63
- EX1: MOV CL,AL
- XOR CH,CH ;CX = bytes to copy
- REP MOVSB
- XOR AL,AL
- STOSB ;ASCIIZ terminate
- LDS SI,CmdPtr ;DS:SI -> Command line to pass
- MOV DI,OFFSET CmdLine ;ES:DI -> Local terminated copy
- LODSB
- CMP AL,126 ;Truncate command if exceeds space
- JB EX2
- MOV AL,126
- EX2: STOSB
- MOV CL,AL
- XOR CH,CH ;CX = bytes to copy
- REP MOVSB
- MOV AL,0DH ;Terminate with ^M
- STOSB
- MovSeg DS,CS ;DS = CS
- MOV SI,OFFSET CmdLine
- MOV CmdLinePtr.ofst,SI
- MOV CmdLinePtr.segm,DS ;Store pointer to command line
- INC SI
- MOV DI,OFFSET FileBlock1
- MOV FilePtr1.ofst,DI
- MOV FilePtr1.segm,ES ;Store pointer to filename 1, if any
- DosCallAX 2901h ;Parse FCB
- MOV DI,OFFSET FileBlock2
- MOV FilePtr2.ofst,DI
- MOV FilePtr2.segm,ES ;Store pointer to filename 2, if any
- DosCallAX 2901h ;Parse FCB
- MOV DX,OFFSET Path
- MOV BX,OFFSET EnvironSeg
- DosCallAX 4B00h ;Exec
- JC EX3 ;Jump if error in DOS call
- XOR AX,AX ;Return zero for success
- EX3: MOV Status,AX ;Save DOS error code
-
- ;Set up temporary stack and reallocate original memory block
- SetTempStack ;Set up temporary stack
- MOV ES,PrefixSegCS
- MOV BX,ParasWeHave
- DosCallAH 4Ah ;SetBlock
- JNC EX4 ;Jump if no error
- HaltWithError 0FFh ;Must halt if failure here
- EX4: InitSwapCount ;Initialize LeftToSwap
-
- ;Check which swap method is in use
- EX5: CMP UsedEms,0
- JZ ReadF ;Jump to read back from file
- JMP ReadE ;Read back from EMS
-
- ;Read back from swap file
- ReadF: MovSeg DS,CS ;DS = CS
- InitSwapFile ;Seek to start of swap file
- JNC EF3 ;Jump if we succeeded
- HaltWithError 0FEh ;Must halt if failure here
- EF3: SetSwapCount FileBlockSize ;CX = bytes to read
- MOV DX,OFFSET FirstToSave ;DS:DX -> start of region to restore
- DosCallAH 3Fh ;Read file
- JNC EF4 ;Jump if no error
- HaltWithError 0FEh ;Must halt if failure here
- EF4: CMP AX,CX
- JZ EF5 ;Jump if full block read
- HaltWithError 0FEh ;Must halt if failure here
- EF5: NextBlock DS,FileBlockSize ;Point DS to next page to read
- JNZ EF3 ;Jump if bytes left to read
- JMP ESDone ;We're done
-
- ;Copy back from EMS
- ReadE: MOV DX,EmsHandleCS ;DX = handle of our EMS block
- EmsCall 47h ;Save EMS context for next time
- MOV DS,FrameSegCS ;DS -> page window
- XOR BX,BX ;BX = initial logical page
- MovSeg ES,CS ;ES = CS
- EE3: XOR AL,AL ;Physical page 0
- EmsCall 44h ;Map physical page
- JZ EE4 ;Jump if success
- HaltWithError 0FDh ;Must halt if failure here
- EE4: SetSwapCount EmsPageSize ;CX = Bytes to move
- XOR SI,SI ;DS:SI -> base of EMS page
- MOV DI,OFFSET FirstToSave ;ES:DI -> region to restore
- MoveFast ;Move CX bytes from DS:SI to ES:DI
- INC BX ;Next logical page
- NextBlock ES,EmsPageSize ;Point ES to next page to move
- JNZ EE3 ;Jump if so
- EmsCall 48h ;Restore EMS context
-
- ESDone: CLI ;Switch back to original stack
- MOV SS,SaveSS
- MOV SP,SaveSP
- STI
- CALL RestoreInt21 ;Restore original int21
- MOV AX,SEG DATA
- MOV DS,AX ;Restore DS
- MOV AX,Status ;Return status
- POP BP
- RET 18 ;Remove parameters and return
- ExecWinWithSwap ENDP
-
- ;---------------------------------------------------------------------------
- ;procedure NewInt21
- ; Handle interrupt 21 to trap output calls
- NewInt21 PROC FAR
- STI
- CMP AH,2 ;Just get functions that go to StdOut
- JZ DispOut
- CMP AH,6
- JZ DirectOut
- CMP AH,9
- JZ StringOut
- CMP AH,40h ;Or maybe to StdErr
- JZ BlockOut
- ToDos
-
- ;-----------
- DispOut: ;DOS function 2
- PUSH AX
- MOV AL,DL ;Character to write in AL
- CALL WriteChar ;Write via video BIOS
- POP AX
- ToApp ;Return successfully
-
- ;-----------
- DirectOut: ;DOS function 6
- CMP DL,0FFh ;Console input?
- JNZ DispOut ;Jump if not
- ToDos ;Else transfer to DOS
-
- ;------------
- StringOut: ;DOS function 9
- PUSH AX ;Save AX
- PUSH BX ;Save string index
- MOV BX,DX ;DS:BX -> string
- StringOut1:
- MOV AL,[BX] ;AL = next character to write
- CMP AL,'$' ;Terminator?
- JZ StringOut2 ;Exit if so
- CALL WriteChar ;Write it
- INC BX ;Next character
- JMP StringOut1 ;Loop
- StringOut2:
- POP BX
- POP AX
- ToApp ;Back to application
-
- ;------------
- BlockOut: ;DOS function 40h
- CMP BX,1 ;To StdOut?
- JZ BlockOut1 ;Jump if so
- CMP BX,2 ;To StdErr?
- JZ BlockOut1 ;Jump if so
- ToDos ;Else let DOS handle it
- BlockOut1:
- JCXZ BlockOut3 ;Get out if none to write
- PUSH AX
- PUSH BX
- PUSH CX ;Save loop counter
- MOV BX,DX ;DS:BX -> stuff to write
- BlockOut2:
- MOV AL,[BX] ;Next character to write
- CALL WriteChar ;Write it
- INC BX ;Next index
- LOOP BlockOut2 ;Loop for all the characters
- POP CX
- POP BX
- POP AX
- MOV AX,CX ;Wrote all the characters
- BlockOut3:
- ToApp ;Back to application
-
- NewInt21 ENDP
-
- ;------------
- ; Write a character to current position via BIOS
- ; Entry: AL is character to write
- ; Must preserve all but AX
- WriteChar proc near
- PUSH bp ;some versions of int 10 BIOS trash BP
- PUSH bx
- PUSH cx
- PUSH dx
- PUSH ds
-
- CMP al,7 ;Bell character?
- JZ BiosWriteDone ;Don't write
-
- MOV dx,WindPos ;Current cursor pos in DX
-
- CMP al,8 ;Backspace?
- JZ BackSpace
- CMP al,9 ;Tab?
- JZ Tab
- CMP al,10 ;Line feed?
- JZ LineFeed
- CMP al,13 ;Carriage return?
- JZ Carriage
-
- CALL WriteOne ;Write one normal character
-
- BiosSetCursor: ;Position cursor
- XOR bh,bh
- MOV ah,2
- INT 10h
- MOV WindPos,dx ;Save new cursor position
-
- BiosWriteDone:
- POP ds
- POP dx
- POP cx
- POP bx
- POP bp
- RET
-
- Carriage:
- MOV dl,WindLo.col ;Move to left edge
- JMP BiosSetCursor
-
- LineFeed:
- CMP dh,WindHi.row ;Room to increment row?
- JB LineFeed1
- MOV ax,0601h ;Scroll up one line
- MOV cx,WindLo
- MOV dx,WindHi
- MOV bh,WindAttr
- INT 10h
- JMP BiosWriteDone
- LineFeed1:
- INC dh ;Increment row
- JMP BiosSetCursor ;Set cursor
-
- Tab: MOV cl,dl
- SUB cl,WindLo.Col ;Characters beyond left edge
- ADD cl,8
- AND cl,0F8h ;To next tab stop
- ADD cl,WindLo.Col ;Window coords
- SUB cl,dl ;Spaces to write
- XOR ch,ch ;CX = spaces to write
- Tab1: MOV al,20h ;Write spaces
- PUSH cx
- CALL WriteOne ;One at a time
- XOR bh,bh
- MOV ah,2
- INT 10h
- MOV WindPos,dx ;Save new cursor position
- POP cx
- LOOP Tab1 ;Do all of them
- JMP BiosWriteDone
-
- BackSpace:
- CMP dl,WindLo.col ;Beyond left edge?
- JBE BiosWriteDone ;Exit if not
- DEC dl ;One left
- XOR bh,bh
- MOV ah,2 ;Position cursor
- INT 10h
- MOV WindPos,dx
- MOV cx,1 ;Write character
- MOV bl,WindAttr
- MOV ax,0920h ;Write a space
- INT 10h
- JMP BiosWriteDone ;Done now
-
- WriteChar endp
-
- ;---------------
- ; Write one character and update cursor variable
- WriteOne proc near
- MOV cx,1 ;Write character
- MOV bl,WindAttr
- XOR bh,bh
- MOV ah,9
- INT 10h
-
- CMP dl,WindHi.col ;Below right border?
- JB IncCol ;If so, just increment column
- CMP dh,WindHi.row ;Room for CR/LF?
- JB IncRow ;Jump if so
-
- MOV ax,0601h ;Scroll up one line
- MOV cx,WindLo
- MOV dx,WindHi
- MOV bh,WindAttr
- INT 10h
- DEC dh ;Compensate for inc to follow
-
- IncRow: INC dh ;Next row
- MOV dl,WindLo.col ;First col
- DEC dl ;Compensate for inc to follow
-
- IncCol: INC dl ;Increment column
- RET
- WriteOne endp
-
- ;-----------------------------------------------------------------------------
- ;Label marks first location to swap
- EVEN
- FirstToSave:
- ;-----------------------------------------------------------------------------
- ;function AllocateSwapFile : Boolean;
- AllocateSwapFile PROC NEAR
- MOV CX,FileAttr ;Attribute for swap file
- MOV DX,OFFSET SwapName+1 ;DS:DX -> ASCIIZ swap name
- DosCallAH 3Ch ;Create file
- MOV FileHandle,AX ;Save handle assuming success
- MOV AL,0 ;Assume failure
- JC ASDone ;Failed if carry set
- INC AL ;Return true for success
- ASDone: RET
- AllocateSwapFile ENDP
- ;-----------------------------------------------------------------------------
- ;procedure DeallocateSwapFile;
- DeallocateSwapFile PROC NEAR
- MOV BX,FileHandle ;Handle of swap file
- DosCallAH 3Eh ;Close file
- XOR CX,CX ;Normal attribute
- MOV DX,OFFSET SwapName+1 ;DS:DX -> ASCIIZ swap name
- DosCallAX 4301h ;Set file attribute
- DosCallAH 41h ;Delete file
- RET
- DeallocateSwapFile ENDP
- ;-----------------------------------------------------------------------------
- ;function EmsInstalled : Boolean;
- EmsInstalled PROC FAR
- PUSH DS
- MovSeg DS,CS ;DS = CS
- MOV DX,OFFSET EmsDevice ;DS:DX -> EMS driver name
- DosCallAX 3D02h ;Open for read/write
- POP DS
- MOV BX,AX ;Save handle in case one returned
- MOV AL,0 ;Assume FALSE
- JC EIDone
- DosCallAH 3Eh ;Close file
- MOV AL,1 ;Return TRUE
- EIDone: RET
- EmsInstalled ENDP
- ;-----------------------------------------------------------------------------
- ;function EmsPageFrame : Word;
- EmsPageFrame PROC FAR
- EmsCall 41h ;Get page frame
- MOV AX,BX ;AX = segment
- JZ EPDone ;Done if Error = 0
- XOR AX,AX ;Else segment = 0
- EPDone: RET
- EmsPageFrame ENDP
- ;-----------------------------------------------------------------------------
- ;function AllocateEmsPages(NumPages : Word) : Word;
- AllocateEmsPages PROC FAR
- MOV BX,SP ;Set up stack frame
- MOV BX,SS:[BX+4] ;BX = NumPages
- EmsCall 43h ;Allocate EMS
- MOV AX,DX ;Assume success
- JZ APDone ;Done if not 0
- MOV AX,0FFFFh ;$FFFF for failure
- APDone: RET 2 ;Remove parameter and return
- AllocateEmsPages ENDP
- ;-----------------------------------------------------------------------------
- ;procedure DeallocateEmsHandle(Handle : Word);
- DeallocateEmsHandle PROC FAR
- MOV BX,SP ;Set up stack frame
- MOV DX,SS:[BX+4] ;DX = Handle
- EmsCall 45h ;Deallocate EMS
- RET 2 ;Remove parameter and return
- DeallocateEmsHandle ENDP
- ;-----------------------------------------------------------------------------
- ;function DefaultDrive : Char;
- DefaultDrive PROC FAR
- DosCallAH 19h ;Get default drive
- ADD AL,'A' ;Convert to character
- RET
- DefaultDrive ENDP
- ;-----------------------------------------------------------------------------
- ;function DiskFree(Drive : Byte) : LongInt;
- DiskFree PROC FAR
- MOV BX,SP ;Set up stack frame
- MOV DL,SS:[BX+4] ;DL = Drive to check
- DosCallAH 36h ;Get disk space
- MOV DX,AX ;Return 0FFFFFFFFh for failure
- CMP AX,0FFFFh ;Bad drive number?
- JZ DFDone ;Jump if so
- MUL CX ;AX = bytes/cluster
- MUL BX ;DX:AX = bytes free
- DFDone: RET 2 ;Remove parameter and return
- DiskFree ENDP
- ;-----------------------------------------------------------------------------
- CODE ENDS
- END