home *** CD-ROM | disk | FTP | other *** search
/ Power-Programmierung / CD1.mdf / pascal / library / dos / dossys / execswap / execwswp.asm next >
Encoding:
Assembly Source File  |  1990-11-05  |  32.2 KB  |  770 lines

  1. ;EXECWSWP.ASM
  2. ;  Swap memory and exec another program, keeping child process's video
  3. ;  output to a specified portion of the screen
  4. ;  Copyright (c) 1988,1990 TurboPower Software
  5. ;  May be used freely as long as due credit is given
  6. ;
  7. ;-----------------------------------------------------------------------------
  8. DATA    SEGMENT WORD PUBLIC
  9.         EXTRN   BytesSwapped:DWORD      ;Bytes to swap to EMS/disk
  10.         EXTRN   EmsAllocated:BYTE       ;True when EMS allocated for swap
  11.         EXTRN   FileAllocated:BYTE      ;True when file allocated for swap
  12.         EXTRN   EmsHandle:WORD          ;Handle of EMS allocation block
  13.         EXTRN   FrameSeg:WORD           ;Segment of EMS page frame
  14.         EXTRN   FileHandle:WORD         ;Handle of DOS swap file
  15.         EXTRN   SwapName:BYTE           ;ASCIIZ name of swap file
  16.         EXTRN   PrefixSeg:WORD          ;Base segment of program
  17.         EXTRN   NewInt21Addr:WORD;      ;Hold addr on our int 21 handler
  18. DATA    ENDS
  19. ;-----------------------------------------------------------------------------
  20. CODE    SEGMENT WORD PUBLIC
  21.         ASSUME  CS:CODE,DS:DATA
  22.         PUBLIC  ExecWinWithSwap, FirstToSave
  23.         PUBLIC  AllocateSwapFile, DeallocateSwapFile
  24.         PUBLIC  DefaultDrive, DiskFree
  25.         PUBLIC  EmsInstalled, EmsPageFrame
  26.         PUBLIC  AllocateEmsPages, DeallocateEmsHandle
  27.         PUBLIC  InstallInt21, RestoreInt21, CheckCursor
  28.         PUBLIC  UpdateCsVars
  29. ;-----------------------------------------------------------------------------
  30. FileAttr        EQU     6               ;Swap file attribute (hidden+system)
  31. EmsPageSize     EQU     16384           ;Size of EMS page
  32. FileBlockSize   EQU     32768           ;Size of a file block
  33. StkSize         EQU     128             ;Bytes in temporary stack
  34. lo              EQU     (WORD PTR 0)    ;Convenient typecasts
  35. hi              EQU     (WORD PTR 2)
  36. ofst            EQU     (WORD PTR 0)
  37. segm            EQU     (WORD PTR 2)
  38. col             EQU     (BYTE PTR 0)
  39. row             EQU     (BYTE PTR 1)
  40.  
  41. ;-----------------------------------------------------------------------------
  42. ;Variables in CS
  43. EmsDevice       DB      'EMMXXXX0',0    ;Name of EMS device driver
  44. UsedEms         DB      0               ;1 if swapping to EMS, 0 if to file
  45. BytesSwappedCS  DD      0               ;Bytes to move during a swap
  46. EmsHandleCS     DW      0               ;EMS handle
  47. FrameSegCS      DW      0               ;Segment of EMS page window
  48. FileHandleCS    DW      0               ;DOS file handle
  49. PrefixSegCS     DW      0               ;Segment of base of program
  50. Status          DW      0               ;ExecSwap status code
  51. LeftToSwap      DD      0               ;Bytes left to move
  52. SaveSP          DW      0               ;Original stack pointer
  53. SaveSS          DW      0               ;Original stack segment
  54. PathPtr         DD      0               ;Pointer to program to execute
  55. CmdPtr          DD      0               ;Pointer to command line to execute
  56. ParasWeHave     DW      0               ;Paragraphs allocated to process
  57. CmdLine         DB      128 DUP(0)      ;Terminated command line passed to DOS
  58. Path            DB      64 DUP(0)       ;Terminated path name passed to DOS
  59. FileBlock1      DB      16 DUP(0)       ;FCB passed to DOS
  60. FileBlock2      DB      16 DUP(0)       ;FCB passed to DOS
  61. EnvironSeg      DW      0               ;Segment of environment for child
  62. CmdLinePtr      DD      0               ;Pointer to terminated command line
  63. FilePtr1        DD      0               ;Pointer to FCB file
  64. FilePtr2        DD      0               ;Pointer to FCB file
  65. OrigInt21       DD      0               ;Previous $21 vector
  66. WindPos         DW      0               ;Cursor position in window
  67. WindLo          DW      0               ;Top left corner of window
  68. WindHi          DW      0               ;   and bottom right corner.
  69. WindAttr        DB      0               ;Attribute with which to
  70. TempStack       DB      StkSize DUP(0)  ;Temporary stack
  71. StackTop        LABEL   WORD            ;Initial top of stack
  72.  
  73. ;-----------------------------------------------------------------------------
  74. ;Macros
  75. MovSeg          MACRO Dest,Src          ;Set one segment register to another
  76.         PUSH    Src
  77.         POP     Dest
  78.                 ENDM
  79.  
  80. MovMem          MACRO Dest,Src          ;Move from memory to memory via AX
  81.         MOV     AX,Src
  82.         MOV     Dest,AX
  83.                 ENDM
  84.  
  85. InitSwapCount   MACRO                   ;Initialize counter for bytes to swap
  86.         MovMem  LeftToSwap.lo,BytesSwappedCS.lo
  87.         MovMem  LeftToSwap.hi,BytesSwappedCS.hi
  88.                 ENDM
  89.  
  90. SetSwapCount    MACRO BlkSize           ;Return CX = bytes to move this block
  91.         LOCAL   FullBlk                 ;...and reduce total bytes left to move
  92.         MOV     CX,BlkSize              ;Assume we'll write a full block
  93.         CMP     LeftToSwap.hi,0         ;Is high word still non-zero?
  94.         JNZ     FullBlk                 ;Jump if so
  95.         CMP     LeftToSwap.lo,BlkSize   ;Low word still a block or more?
  96.         JAE     FullBlk                 ;Jump if so
  97.         MOV     CX,LeftToSwap.lo        ;Otherwise, move what's left
  98. FullBlk:SUB     LeftToSwap.lo,CX        ;Reduce number left to move
  99.         SBB     LeftToSwap.hi,0
  100.                 ENDM
  101.  
  102. NextBlock       MACRO SegReg, BlkSize   ;Point SegReg to next block to move
  103.         MOV     AX,SegReg
  104.         ADD     AX,BlkSize/16           ;Add paragraphs to next segment
  105.         MOV     SegReg,AX               ;Next block to move
  106.         MOV     AX,LeftToSwap.lo
  107.         OR      AX,LeftToSwap.hi        ;Bytes left to move?
  108.                 ENDM
  109.  
  110. EmsCall         MACRO FuncAH            ;Call EMM and prepare to check result
  111.         MOV     AH,FuncAH               ;Set up function
  112.         INT     67h
  113.         OR      AH,AH                   ;Error code in AH
  114.                 ENDM
  115.  
  116. DosCallAH       MACRO FuncAH            ;Call DOS subfunction AH
  117.         MOV     AH,FuncAH
  118.         INT     21h
  119.                 ENDM
  120.  
  121. DosCallAX       MACRO FuncAX            ;Call DOS subfunction AX
  122.         MOV     AX,FuncAX
  123.         INT     21h
  124.                 ENDM
  125.  
  126. InitSwapFile    MACRO
  127.         MOV     BX,FileHandleCS         ;BX = handle of swap file
  128.         XOR     CX,CX
  129.         XOR     DX,DX                   ;Start of file
  130.         DosCallAX 4200h                 ;DOS file seek
  131.                 ENDM
  132.  
  133. HaltWithError   MACRO Level             ;Halt if non-recoverable error occurs
  134.         MOV     AL,Level                ;Set errorlevel
  135.         DosCallAH 4Ch
  136.                 ENDM
  137.  
  138. MoveFast        MACRO                   ;Move CX bytes from DS:SI to ES:DI
  139.         CLD                             ;Forward
  140.         SHR     CX,1                    ;Convert to words
  141.         REP     MOVSW                   ;Move the words
  142.         RCL     CX,1                    ;Get the odd byte, if any
  143.         REP     MOVSB                   ;Move it
  144.                 ENDM
  145.  
  146. SetTempStack    MACRO                   ;Switch to temporary stack
  147.         MOV     AX,OFFSET StackTop      ;Point to top of stack
  148.         MOV     BX,CS                   ;Temporary stack in this code segment
  149.         CLI                             ;Interrupts off
  150.         MOV     SS,BX                   ;Change stack
  151.         MOV     SP,AX
  152.         STI                             ;Interrupts on
  153.                 ENDM
  154.  
  155. ToDos           MACRO                   ;Transfer control to DOS
  156.         JMP     DWORD PTR OrigInt21
  157.                 ENDM
  158.  
  159. ToApp           MACRO                   ;Transfer control back to caller
  160.         CLC                             ;Clear error flag
  161.         RET     2                       ;Return with flags intact
  162.                 ENDM
  163.  
  164. ;-----------------------------------------------------------------------------
  165. ;procedure CheckCursor
  166. ;
  167. CheckCursor PROC NEAR
  168.         PUSH    BP
  169.         MOV     BP,SP                   ;Set up stack frame
  170.  
  171.         MOV     AH,3
  172.         XOR     BH,BH
  173.         INT     10h                     ;Get cursor position
  174.         MOV     CX,WindLo
  175.         CMP     DH,CH                   ;Row above minimum?
  176.         JAE     CC1                     ;Jump if so
  177.         MOV     DH,CH                   ;Force to minimum
  178. CC1:    CMP     DL,CL                   ;Col above minimum?
  179.         JAE     CC2                     ;Jump is so
  180.         MOV     DL,CL                   ;Force to minimum
  181. CC2:    MOV     CX, WindHi
  182.         CMP     DH,CH                   ;Row below maximum?
  183.         JBE     CC3                     ;Jump if so
  184.         MOV     DH,CH                   ;Force to maximum
  185. CC3:    CMP     DL,CL                   ;Col below maximum?
  186.         JBE     CC4                     ;Jump if so
  187.         MOV     DL,CL                   ;Force to maximum
  188. CC4:    MOV     WindPos,DX              ;Save current position
  189.         MOV     AH,2
  190.         XOR     BH,BH
  191.         INT     10h                     ;Make it so
  192.  
  193.         POP     BP
  194.         RET                             ;Return
  195. CheckCursor ENDP
  196.  
  197. ;----------------------------------------------------------------------------
  198. ;procedure InstallInt21
  199. ;
  200. InstallInt21 PROC NEAR
  201.         PUSH    BP
  202.         MOV     BP,SP                   ;Set up stack frame
  203.  
  204. ;Get the current Int21 vector
  205.         DosCallAX 3521h                 ;ES:BX = vector
  206.         MOV     OrigInt21.ofst, BX      ;Save as pointer in OrigInt21
  207.         MOV     OrigInt21.segm, ES
  208.  
  209. ;Install our Int21 handler
  210.         PUSH    DS
  211.         MOV     DX, SEG NewInt21        ;Segment of our handler
  212.         MOV     DS, DX
  213.         MOV     DX, OFFSET NewInt21     ;Offset of our handler
  214.         DosCallAX 2521h                 ;Set it
  215.         POP     DS
  216.  
  217.         MOV     NewInt21Addr, OFFSET NewInt21
  218.         MOV     NewInt21Addr+2, SEG NewInt21    ;Show addr to caller
  219.  
  220.         POP     BP
  221.         RET                             ;Return
  222. InstallInt21 ENDP
  223.  
  224. ;-----------------------------------------------------------------------------
  225. ;procedure RestoreInt21
  226. ;
  227. RestoreInt21 PROC NEAR
  228.         PUSH    BP
  229.         MOV     BP,SP                   ;Set up stack frame
  230.  
  231.         PUSH    DS
  232.         LDS     DX, OrigInt21           ;DS:DX = OrigInt21
  233.         DosCallAX 2521h                 ;Restore it
  234.         POP     DS
  235.  
  236.         POP     BP
  237.         RET                             ;Return
  238. RestoreInt21 ENDP
  239.  
  240. ;-----------------------------------------------------------------------------
  241. ;procedure UpdateCsVars(Xlo, Ylo, Xhi, Yhi, Attr : Byte);
  242. ;
  243. UpdateCsVars PROC NEAR
  244.         PUSH    BP
  245.         MOV     BP,SP                   ;Set up stack frame
  246.  
  247. ;Move passed values to CS variables
  248.         MOV     AX,[BP+12]
  249.         DEC     AX
  250.         MOV     BYTE PTR WindLo.Col, AL ;Lo(WindLo) = Xlo
  251.         MOV     AX,[BP+10]
  252.         DEC     AX
  253.         MOV     BYTE PTR WindLo.Row, AL ;Hi(WindLo) = Ylo
  254.         MOV     AX,[BP+8]
  255.         DEC     AX
  256.         MOV     BYTE PTR WindHi.Col,AL  ;Lo(WindHi) = Xhi
  257.         MOV     AX, [BP+6]
  258.         DEC     AX
  259.         MOV     BYTE PTR WindHi.Row, AL ;Hi(WindHi) = Yhi
  260.         MOV     AX,[BP+4]
  261.         MOV     WindAttr, AL            ;Get attribute
  262.  
  263.         POP     BP
  264.         RET     10
  265. UpdateCsVars ENDP
  266.  
  267. ;-----------------------------------------------------------------------------
  268. ;function ExecWithSwap(Path, CmdLine : string;
  269. ;                      Xlo, Ylo, Xhi, Yhi, Attr : Byte ) : Word;
  270. ExecWinWithSwap PROC FAR
  271.         PUSH    BP
  272.         MOV     BP,SP                   ;Set up stack frame
  273.  
  274. ;Move variables to CS where we can easily access them later
  275.         MOV     Status,1                ;Assume failure
  276.         LES     DI,[BP+20]              ;ES:DI -> Path
  277.         MOV     PathPtr.ofst,DI
  278.         MOV     PathPtr.segm,ES         ;PathPtr -> path to execute
  279.         LES     DI,[BP+16]              ;ES:DI -> CmdLine
  280.         MOV     CmdPtr.ofst,DI
  281.         MOV     CmdPtr.segm,ES          ;CmdPtr -> command line string
  282.  
  283.         PUSH    [BP+14]
  284.         PUSH    [BP+12]
  285.         PUSH    [BP+10]
  286.         PUSH    [BP+8]
  287.         PUSH    [BP+6]
  288.         CALL    UpdateCsVars            ;Transfer parms to CS vars
  289.  
  290. ;Make sure cursor is within window
  291.         CALL    CheckCursor
  292.  
  293. ;Continue with swapping
  294.         MOV     SaveSP,SP               ;Save stack position
  295.         MOV     SaveSS,SS
  296.         MovMem  BytesSwappedCS.lo,BytesSwapped.lo
  297.         MovMem  BytesSwappedCS.hi,BytesSwapped.hi
  298.         MovMem  EmsHandleCS,EmsHandle
  299.         MovMem  FrameSegCS,FrameSeg
  300.         MovMem  FileHandleCS,FileHandle
  301.         MovMem  PrefixSegCS,PrefixSeg
  302.         InitSwapCount                   ;Initialize bytes LeftToSwap
  303.  
  304. ;Install our Int21 handler
  305.         CALL    InstallInt21
  306.  
  307. ;Check for swapping to EMS or file
  308.         CMP     EmsAllocated,0          ;Check flag for EMS method
  309.         JZ      NotEms                  ;Jump if EMS not used
  310.         JMP     WriteE                  ;Swap to EMS
  311. NotEms: CMP     FileAllocated,0         ;Check flag for swap file method
  312.         JNZ     WriteF                  ;Swap to file
  313.         JMP     ESDone                  ;Exit if no swapping method set
  314.  
  315. ;Write to swap file
  316. WriteF: MovSeg  DS,CS                   ;DS = CS
  317.         InitSwapFile                    ;Seek to start of swap file
  318.         JNC     EF0                     ;Jump if success
  319.         JMP     ESDone                  ;Exit if error
  320. EF0:    SetSwapCount FileBlockSize      ;CX = bytes to write
  321.         MOV     DX,OFFSET FirstToSave   ;DS:DX -> start of region to save
  322.         DosCallAH 40h                   ;File write
  323.         JC      EF1                     ;Jump if write error
  324.         CMP     AX,CX                   ;All bytes written?
  325.         JZ      EF2                     ;Jump if so
  326. EF1:    JMP     ESDone                  ;Exit if error
  327. EF2:    NextBlock DS,FileBlockSize      ;Point DS to next block to write
  328.         JNZ     EF0                     ;Loop if bytes left to write
  329.         MOV     UsedEms,0               ;Flag we used swap file for swapping
  330.         DosCallAH 45h                   ;DUP handle
  331.         JC      EF2a                    ;Jump if failed
  332.         MOV     BX,AX                   ;Prepare to close dup'ed handle
  333.         DosCallAH 3Eh                   ;Flush swap file
  334. EF2a:   JMP     SwapDone                ;Done swapping out
  335.  
  336. ;Write to EMS
  337. WriteE: MOV     ES,FrameSeg             ;ES -> page window
  338.         MOV     DX,EmsHandle            ;DX = handle of our EMS block
  339.         EmsCall 47h                     ;Save EMS context
  340.         XOR     BX,BX                   ;BX = initial logical page
  341.         MovSeg  DS,CS                   ;DS = CS
  342. EE0:    XOR     AL,AL                   ;Physical page 0
  343.         EmsCall 44h                     ;Map physical page
  344.         JZ      EE1                     ;Jump if success
  345.         JMP     ESDone                  ;Exit if error
  346. EE1:    SetSwapCount EmsPageSize        ;CX = Bytes to move
  347.         XOR     DI,DI                   ;ES:DI -> base of EMS page
  348.         MOV     SI,OFFSET FirstToSave   ;DS:SI -> region to save
  349.         MoveFast                        ;Move CX bytes from DS:SI to ES:DI
  350.         INC     BX                      ;Next logical page
  351.         NextBlock DS,EmsPageSize        ;Point DS to next page to move
  352.         JNZ     EE0                     ;Loop if bytes left to move
  353.         EmsCall 48h                     ;Restore EMS context
  354.         MOV     UsedEms,1               ;Flag we used EMS for swapping
  355.  
  356. ;Shrink memory allocated to this process
  357. SwapDone:MOV    AX,PrefixSegCS
  358.         MOV     ES,AX                   ;ES = segment of our memory block
  359.         DEC     AX
  360.         MOV     DS,AX                   ;DS = segment of memory control block
  361.         MOV     CX,DS:[0003h]           ;CX = current paragraphs owned
  362.         MOV     ParasWeHave,CX          ;Save current paragraphs owned
  363.         SetTempStack                    ;Switch to temporary stack
  364.         MOV     AX,OFFSET FirstToSave+15
  365.         MOV     CL,4
  366.         SHR     AX,CL                   ;Convert offset to paragraphs
  367.         ADD     BX,AX
  368.         SUB     BX,PrefixSegCS          ;BX = new paragraphs to keep
  369.         DosCallAH 4Ah                   ;SetBlock
  370.         JNC     EX0                     ;Jump if successful
  371.         JMP     EX5                     ;Swap back and exit
  372.  
  373. ;Set up parameters and call DOS Exec
  374. EX0:    MOV     AX,ES:[002Ch]           ;Get environment segment
  375.         MOV     EnvironSeg,AX
  376.         MovSeg  ES,CS                   ;ES = CS
  377.         LDS     SI,PathPtr              ;DS:SI -> path to execute
  378.         MOV     DI,OFFSET Path          ;ES:DI -> local ASCIIZ copy
  379.         CLD
  380.         LODSB                           ;Read current length
  381.         CMP     AL,63                   ;Truncate if exceeds space set aside
  382.         JB      EX1
  383.         MOV     AL,63
  384. EX1:    MOV     CL,AL
  385.         XOR     CH,CH                   ;CX = bytes to copy
  386.         REP     MOVSB
  387.         XOR     AL,AL
  388.         STOSB                           ;ASCIIZ terminate
  389.         LDS     SI,CmdPtr               ;DS:SI -> Command line to pass
  390.         MOV     DI,OFFSET CmdLine       ;ES:DI -> Local terminated copy
  391.         LODSB
  392.         CMP     AL,126                  ;Truncate command if exceeds space
  393.         JB      EX2
  394.         MOV     AL,126
  395. EX2:    STOSB
  396.         MOV     CL,AL
  397.         XOR     CH,CH                   ;CX = bytes to copy
  398.         REP     MOVSB
  399.         MOV     AL,0DH                  ;Terminate with ^M
  400.         STOSB
  401.         MovSeg  DS,CS                   ;DS = CS
  402.         MOV     SI,OFFSET CmdLine
  403.         MOV     CmdLinePtr.ofst,SI
  404.         MOV     CmdLinePtr.segm,DS      ;Store pointer to command line
  405.         INC     SI
  406.         MOV     DI,OFFSET FileBlock1
  407.         MOV     FilePtr1.ofst,DI
  408.         MOV     FilePtr1.segm,ES        ;Store pointer to filename 1, if any
  409.         DosCallAX 2901h                 ;Parse FCB
  410.         MOV     DI,OFFSET FileBlock2
  411.         MOV     FilePtr2.ofst,DI
  412.         MOV     FilePtr2.segm,ES        ;Store pointer to filename 2, if any
  413.         DosCallAX 2901h                 ;Parse FCB
  414.         MOV     DX,OFFSET Path
  415.         MOV     BX,OFFSET EnvironSeg
  416.         DosCallAX 4B00h                 ;Exec
  417.         JC      EX3                     ;Jump if error in DOS call
  418.         XOR     AX,AX                   ;Return zero for success
  419. EX3:    MOV     Status,AX               ;Save DOS error code
  420.  
  421. ;Set up temporary stack and reallocate original memory block
  422.         SetTempStack                    ;Set up temporary stack
  423.         MOV     ES,PrefixSegCS
  424.         MOV     BX,ParasWeHave
  425.         DosCallAH 4Ah                   ;SetBlock
  426.         JNC     EX4                     ;Jump if no error
  427.         HaltWithError 0FFh              ;Must halt if failure here
  428. EX4:    InitSwapCount                   ;Initialize LeftToSwap
  429.  
  430. ;Check which swap method is in use
  431. EX5:    CMP     UsedEms,0
  432.         JZ      ReadF                   ;Jump to read back from file
  433.         JMP     ReadE                   ;Read back from EMS
  434.  
  435. ;Read back from swap file
  436. ReadF:  MovSeg  DS,CS                   ;DS = CS
  437.         InitSwapFile                    ;Seek to start of swap file
  438.         JNC     EF3                     ;Jump if we succeeded
  439.         HaltWithError 0FEh              ;Must halt if failure here
  440. EF3:    SetSwapCount FileBlockSize      ;CX = bytes to read
  441.         MOV     DX,OFFSET FirstToSave   ;DS:DX -> start of region to restore
  442.         DosCallAH 3Fh                   ;Read file
  443.         JNC     EF4                     ;Jump if no error
  444.         HaltWithError 0FEh              ;Must halt if failure here
  445. EF4:    CMP     AX,CX
  446.         JZ      EF5                     ;Jump if full block read
  447.         HaltWithError 0FEh              ;Must halt if failure here
  448. EF5:    NextBlock DS,FileBlockSize      ;Point DS to next page to read
  449.         JNZ     EF3                     ;Jump if bytes left to read
  450.         JMP     ESDone                  ;We're done
  451.  
  452. ;Copy back from EMS
  453. ReadE:  MOV     DX,EmsHandleCS          ;DX = handle of our EMS block
  454.         EmsCall 47h                     ;Save EMS context for next time
  455.         MOV     DS,FrameSegCS           ;DS -> page window
  456.         XOR     BX,BX                   ;BX = initial logical page
  457.         MovSeg  ES,CS                   ;ES = CS
  458. EE3:    XOR     AL,AL                   ;Physical page 0
  459.         EmsCall 44h                     ;Map physical page
  460.         JZ      EE4                     ;Jump if success
  461.         HaltWithError 0FDh              ;Must halt if failure here
  462. EE4:    SetSwapCount EmsPageSize        ;CX = Bytes to move
  463.         XOR     SI,SI                   ;DS:SI -> base of EMS page
  464.         MOV     DI,OFFSET FirstToSave   ;ES:DI -> region to restore
  465.         MoveFast                        ;Move CX bytes from DS:SI to ES:DI
  466.         INC     BX                      ;Next logical page
  467.         NextBlock ES,EmsPageSize        ;Point ES to next page to move
  468.         JNZ     EE3                     ;Jump if so
  469.         EmsCall 48h                     ;Restore EMS context
  470.  
  471. ESDone: CLI                             ;Switch back to original stack
  472.         MOV     SS,SaveSS
  473.         MOV     SP,SaveSP
  474.         STI
  475.         CALL    RestoreInt21            ;Restore original int21
  476.         MOV     AX,SEG DATA
  477.         MOV     DS,AX                   ;Restore DS
  478.         MOV     AX,Status               ;Return status
  479.         POP     BP
  480.         RET     18                      ;Remove parameters and return
  481. ExecWinWithSwap ENDP
  482.  
  483. ;---------------------------------------------------------------------------
  484. ;procedure NewInt21
  485. ; Handle interrupt 21 to trap output calls
  486. NewInt21        PROC FAR
  487.         STI
  488.         CMP     AH,2                    ;Just get functions that go to StdOut
  489.         JZ      DispOut
  490.         CMP     AH,6
  491.         JZ      DirectOut
  492.         CMP     AH,9
  493.         JZ      StringOut
  494.         CMP     AH,40h                  ;Or maybe to StdErr
  495.         JZ      BlockOut
  496.         ToDos
  497.  
  498. ;-----------
  499. DispOut:                                ;DOS function 2
  500.         PUSH    AX
  501.         MOV     AL,DL                   ;Character to write in AL
  502.         CALL    WriteChar               ;Write via video BIOS
  503.         POP     AX
  504.         ToApp                           ;Return successfully
  505.  
  506. ;-----------
  507. DirectOut:                              ;DOS function 6
  508.         CMP     DL,0FFh                 ;Console input?
  509.         JNZ     DispOut                 ;Jump if not
  510.         ToDos                           ;Else transfer to DOS
  511.  
  512. ;------------
  513. StringOut:                              ;DOS function 9
  514.         PUSH    AX                      ;Save AX
  515.         PUSH    BX                      ;Save string index
  516.         MOV     BX,DX                   ;DS:BX -> string
  517. StringOut1:
  518.         MOV     AL,[BX]                 ;AL = next character to write
  519.         CMP     AL,'$'                  ;Terminator?
  520.         JZ      StringOut2              ;Exit if so
  521.         CALL    WriteChar               ;Write it
  522.         INC     BX                      ;Next character
  523.         JMP     StringOut1              ;Loop
  524. StringOut2:
  525.         POP     BX
  526.         POP     AX
  527.         ToApp                           ;Back to application
  528.  
  529. ;------------
  530. BlockOut:                               ;DOS function 40h
  531.         CMP     BX,1                    ;To StdOut?
  532.         JZ      BlockOut1               ;Jump if so
  533.         CMP     BX,2                    ;To StdErr?
  534.         JZ      BlockOut1               ;Jump if so
  535.         ToDos                           ;Else let DOS handle it
  536. BlockOut1:
  537.         JCXZ    BlockOut3               ;Get out if none to write
  538.         PUSH    AX
  539.         PUSH    BX
  540.         PUSH    CX                      ;Save loop counter
  541.         MOV     BX,DX                   ;DS:BX -> stuff to write
  542. BlockOut2:
  543.         MOV     AL,[BX]                 ;Next character to write
  544.         CALL    WriteChar               ;Write it
  545.         INC     BX                      ;Next index
  546.         LOOP    BlockOut2               ;Loop for all the characters
  547.         POP     CX
  548.         POP     BX
  549.         POP     AX
  550.         MOV     AX,CX                   ;Wrote all the characters
  551. BlockOut3:
  552.         ToApp                           ;Back to application
  553.  
  554. NewInt21 ENDP
  555.  
  556. ;------------
  557. ; Write a character to current position via BIOS
  558. ; Entry: AL is character to write
  559. ; Must preserve all but AX
  560. WriteChar  proc    near
  561.         PUSH    bp                   ;some versions of int 10 BIOS trash BP
  562.         PUSH    bx
  563.         PUSH    cx
  564.         PUSH    dx
  565.         PUSH    ds
  566.  
  567.         CMP     al,7                 ;Bell character?
  568.         JZ      BiosWriteDone        ;Don't write
  569.  
  570.         MOV     dx,WindPos           ;Current cursor pos in DX
  571.  
  572.         CMP     al,8                 ;Backspace?
  573.         JZ      BackSpace
  574.         CMP     al,9                 ;Tab?
  575.         JZ      Tab
  576.         CMP     al,10                ;Line feed?
  577.         JZ      LineFeed
  578.         CMP     al,13                ;Carriage return?
  579.         JZ      Carriage
  580.  
  581.         CALL    WriteOne             ;Write one normal character
  582.  
  583. BiosSetCursor:                          ;Position cursor
  584.         XOR     bh,bh
  585.         MOV     ah,2
  586.         INT     10h
  587.         MOV     WindPos,dx           ;Save new cursor position
  588.  
  589. BiosWriteDone:
  590.         POP     ds
  591.         POP     dx
  592.         POP     cx
  593.         POP     bx
  594.         POP     bp
  595.         RET
  596.  
  597. Carriage:
  598.         MOV     dl,WindLo.col        ;Move to left edge
  599.         JMP     BiosSetCursor
  600.  
  601. LineFeed:
  602.         CMP     dh,WindHi.row        ;Room to increment row?
  603.         JB      LineFeed1
  604.         MOV     ax,0601h             ;Scroll up one line
  605.         MOV     cx,WindLo
  606.         MOV     dx,WindHi
  607.         MOV     bh,WindAttr
  608.         INT     10h
  609.         JMP     BiosWriteDone
  610. LineFeed1:
  611.         INC     dh                   ;Increment row
  612.         JMP     BiosSetCursor        ;Set cursor
  613.  
  614. Tab:    MOV     cl,dl
  615.         SUB     cl,WindLo.Col        ;Characters beyond left edge
  616.         ADD     cl,8
  617.         AND     cl,0F8h              ;To next tab stop
  618.         ADD     cl,WindLo.Col        ;Window coords
  619.         SUB     cl,dl                ;Spaces to write
  620.         XOR     ch,ch                ;CX = spaces to write
  621. Tab1:   MOV     al,20h               ;Write spaces
  622.         PUSH    cx
  623.         CALL    WriteOne             ;One at a time
  624.         XOR     bh,bh
  625.         MOV     ah,2
  626.         INT     10h
  627.         MOV     WindPos,dx           ;Save new cursor position
  628.         POP     cx
  629.         LOOP    Tab1                 ;Do all of them
  630.         JMP     BiosWriteDone
  631.  
  632. BackSpace:
  633.         CMP     dl,WindLo.col        ;Beyond left edge?
  634.         JBE     BiosWriteDone        ;Exit if not
  635.         DEC     dl                   ;One left
  636.         XOR     bh,bh
  637.         MOV     ah,2                 ;Position cursor
  638.         INT     10h
  639.         MOV     WindPos,dx
  640.         MOV     cx,1                 ;Write character
  641.         MOV     bl,WindAttr
  642.         MOV     ax,0920h             ;Write a space
  643.         INT     10h
  644.         JMP     BiosWriteDone        ;Done now
  645.  
  646. WriteChar  endp
  647.  
  648. ;---------------
  649. ; Write one character and update cursor variable
  650. WriteOne   proc    near
  651.         MOV     cx,1                 ;Write character
  652.         MOV     bl,WindAttr
  653.         XOR     bh,bh
  654.         MOV     ah,9
  655.         INT     10h
  656.  
  657.         CMP     dl,WindHi.col        ;Below right border?
  658.         JB      IncCol               ;If so, just increment column
  659.         CMP     dh,WindHi.row        ;Room for CR/LF?
  660.         JB      IncRow               ;Jump if so
  661.  
  662.         MOV     ax,0601h             ;Scroll up one line
  663.         MOV     cx,WindLo
  664.         MOV     dx,WindHi
  665.         MOV     bh,WindAttr
  666.         INT     10h
  667.         DEC     dh                   ;Compensate for inc to follow
  668.  
  669. IncRow: INC     dh                   ;Next row
  670.         MOV     dl,WindLo.col        ;First col
  671.         DEC     dl                   ;Compensate for inc to follow
  672.  
  673. IncCol: INC     dl                   ;Increment column
  674.         RET
  675. WriteOne   endp
  676.  
  677. ;-----------------------------------------------------------------------------
  678. ;Label marks first location to swap
  679.         EVEN
  680. FirstToSave:
  681. ;-----------------------------------------------------------------------------
  682. ;function AllocateSwapFile : Boolean;
  683. AllocateSwapFile PROC NEAR
  684.         MOV     CX,FileAttr             ;Attribute for swap file
  685.         MOV     DX,OFFSET SwapName+1    ;DS:DX -> ASCIIZ swap name
  686.         DosCallAH 3Ch                   ;Create file
  687.         MOV     FileHandle,AX           ;Save handle assuming success
  688.         MOV     AL,0                    ;Assume failure
  689.         JC      ASDone                  ;Failed if carry set
  690.         INC     AL                      ;Return true for success
  691. ASDone: RET
  692. AllocateSwapFile ENDP
  693. ;-----------------------------------------------------------------------------
  694. ;procedure DeallocateSwapFile;
  695. DeallocateSwapFile PROC NEAR
  696.         MOV     BX,FileHandle           ;Handle of swap file
  697.         DosCallAH 3Eh                   ;Close file
  698.         XOR     CX,CX                   ;Normal attribute
  699.         MOV     DX,OFFSET SwapName+1    ;DS:DX -> ASCIIZ swap name
  700.         DosCallAX 4301h                 ;Set file attribute
  701.         DosCallAH 41h                   ;Delete file
  702.         RET
  703. DeallocateSwapFile ENDP
  704. ;-----------------------------------------------------------------------------
  705. ;function EmsInstalled : Boolean;
  706. EmsInstalled    PROC FAR
  707.         PUSH    DS
  708.         MovSeg  DS,CS                   ;DS = CS
  709.         MOV     DX,OFFSET EmsDevice     ;DS:DX -> EMS driver name
  710.         DosCallAX 3D02h                 ;Open for read/write
  711.         POP     DS
  712.         MOV     BX,AX                   ;Save handle in case one returned
  713.         MOV     AL,0                    ;Assume FALSE
  714.         JC      EIDone
  715.         DosCallAH 3Eh                   ;Close file
  716.         MOV     AL,1                    ;Return TRUE
  717. EIDone: RET
  718. EmsInstalled    ENDP
  719. ;-----------------------------------------------------------------------------
  720. ;function EmsPageFrame : Word;
  721. EmsPageFrame    PROC FAR
  722.         EmsCall 41h                     ;Get page frame
  723.         MOV     AX,BX                   ;AX = segment
  724.         JZ      EPDone                  ;Done if Error = 0
  725.         XOR     AX,AX                   ;Else segment = 0
  726. EPDone: RET
  727. EmsPageFrame    ENDP
  728. ;-----------------------------------------------------------------------------
  729. ;function AllocateEmsPages(NumPages : Word) : Word;
  730. AllocateEmsPages PROC FAR
  731.         MOV     BX,SP                   ;Set up stack frame
  732.         MOV     BX,SS:[BX+4]            ;BX = NumPages
  733.         EmsCall 43h                     ;Allocate EMS
  734.         MOV     AX,DX                   ;Assume success
  735.         JZ      APDone                  ;Done if not 0
  736.         MOV     AX,0FFFFh               ;$FFFF for failure
  737. APDone: RET     2                       ;Remove parameter and return
  738. AllocateEmsPages ENDP
  739. ;-----------------------------------------------------------------------------
  740. ;procedure DeallocateEmsHandle(Handle : Word);
  741. DeallocateEmsHandle PROC FAR
  742.         MOV     BX,SP                   ;Set up stack frame
  743.         MOV     DX,SS:[BX+4]            ;DX = Handle
  744.         EmsCall 45h                     ;Deallocate EMS
  745.         RET     2                       ;Remove parameter and return
  746. DeallocateEmsHandle ENDP
  747. ;-----------------------------------------------------------------------------
  748. ;function DefaultDrive : Char;
  749. DefaultDrive    PROC FAR
  750.         DosCallAH 19h                   ;Get default drive
  751.         ADD     AL,'A'                  ;Convert to character
  752.         RET
  753. DefaultDrive    ENDP
  754. ;-----------------------------------------------------------------------------
  755. ;function DiskFree(Drive : Byte) : LongInt;
  756. DiskFree        PROC FAR
  757.         MOV     BX,SP                   ;Set up stack frame
  758.         MOV     DL,SS:[BX+4]            ;DL = Drive to check
  759.         DosCallAH 36h                   ;Get disk space
  760.         MOV     DX,AX                   ;Return 0FFFFFFFFh for failure
  761.         CMP     AX,0FFFFh               ;Bad drive number?
  762.         JZ      DFDone                  ;Jump if so
  763.         MUL     CX                      ;AX = bytes/cluster
  764.         MUL     BX                      ;DX:AX = bytes free
  765. DFDone: RET     2                       ;Remove parameter and return
  766. DiskFree        ENDP
  767. ;-----------------------------------------------------------------------------
  768. CODE    ENDS
  769.         END
  770.