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