home *** CD-ROM | disk | FTP | other *** search
/ Shareware Supreme Volume 6 #1 / swsii.zip / swsii / 099 / SH164AS.ZIP / SHELL / SH0.ASM < prev    next >
Assembly Source File  |  1992-02-28  |  30KB  |  1,773 lines

  1.     TITLE   sh0.asm
  2.     NAME    sh0
  3.     .8087
  4.  
  5. ; MS-DOS SHELL - Swapper
  6. ;
  7. ; MS-DOS SHELL - Copyright (c) 1990 Data Logic Limited
  8. ;
  9. ; This code is subject to the following copyright restrictions:
  10. ;
  11. ; 1.  Redistribution and use in source and binary forms are permitted
  12. ;     provided that the above copyright notice is duplicated in the
  13. ;     source form and the copyright notice in file sh6.c is displayed
  14. ;     on entry to the program.
  15. ;
  16. ; 2.  The sources (or parts thereof) or objects generated from the sources
  17. ;     (or parts of sources) cannot be sold under any circumstances.
  18. ;
  19. ;    $Header: D:/SRC/SHELL/RCS/sh0.asm 1.10 90/05/31 17:46:31 MS_user Exp $
  20. ;
  21. ;    $Log:    sh0.asm $
  22. ;    Revision 1.10  90/05/31  17:46:31  MS_user
  23. ;    Enasure that correct block zero is written for partial write
  24. ;    
  25. ;    Revision 1.9  90/05/31  10:04:56  MS_user
  26. ;    Implement partial write on disk swapping
  27. ;    
  28. ;    Revision 1.8  90/04/25  22:32:31  MS_user
  29. ;    Fix missing disk full check on writing swap file
  30. ;    
  31. ;    Revision 1.7  90/04/11  12:54:38  MS_user
  32. ;    Fix non-disk device name print in CEH
  33. ;    
  34. ;    Revision 1.6  90/03/26  04:31:01  MS_user
  35. ;    Remove original Interrupt 24 save address
  36. ;    
  37. ;    Revision 1.5  90/03/26  04:12:38  MS_user
  38. ;    Add Full Interrupt 24 handler
  39. ;    
  40. ;    Revision 1.4  90/03/05  13:47:05  MS_user
  41. ;    Add XMS driver
  42. ;    
  43. ;    Revision 1.3  90/02/22  16:50:23  MS_user
  44. ;    Add XMS Driver support
  45. ;    
  46. ;    Revision 1.2  90/02/14  04:45:58  MS_user
  47. ;    Add Interrupt 24 processing and clean up interrupt 0 and 23 processing
  48. ;    
  49. ;    Revision 1.1  90/01/25  13:43:36  MS_user
  50. ;    Initial revision
  51. ;    
  52. ;
  53.  
  54. ;
  55. ; Segment declarations
  56. ;
  57.  
  58. SH0_TEXT    segment word public 'CODE'
  59. SH0_TEXT    ends
  60.  
  61. _DATA        segment word public 'DATA'
  62. _DATA        ends
  63.  
  64. CONST        segment word public 'CONST'
  65. CONST        ends
  66.  
  67. _BSS        segment word public 'BSS'
  68. _BSS        ends
  69.  
  70. DGROUP        group    CONST, _BSS, _DATA
  71.  
  72. C_ETEXT        segment word public 'ENDCODE' 
  73. C_ETEXT        ends 
  74.  
  75. ;
  76. ; Declare external functions and data
  77. ;
  78.     extrn    _raise:far
  79.     extrn    __maperror:far
  80.     extrn    _errno:word
  81.     extrn    __psp:word
  82.  
  83. ;
  84. ; Declare end of text variable.  The ENDCODE segment appears to be the last
  85. ; code segment loaded by the Microsoft loader
  86. ;
  87.  
  88. C_ETEXT        segment word public 'ENDCODE' 
  89.         public    cetext
  90. cetext        equ    $
  91. C_ETEXT        ends 
  92.  
  93. ;
  94. ; Start of the spawn function
  95. ;
  96.  
  97. SH0_TEXT    segment
  98.         assume  cs: SH0_TEXT, ds: NOTHING, ss: DGROUP
  99.  
  100. ;
  101. ; For this function, all the code and data space are in the code space
  102. ;
  103.         public    _cmd_line
  104.         public    _path_line
  105.         public    _SW_intr
  106.         public    _SW_Blocks
  107.         public    _SW_SBlocks
  108.         public    _SW_fp
  109.         public    _SW_I0_V
  110.         public    _SW_I23_V
  111.         public    _SW_EMstart
  112.         public    _SW_Mode
  113.         public    _SW_EMSFrame
  114.         public    _SW_Int24
  115.         public    _SW_XMS_Driver
  116.         public    _SW_XMS_Gversion
  117.         public    _SW_XMS_Allocate
  118.         public    _SW_XMS_Free
  119.         public    _etext
  120.         public    _SW_Pwrite
  121.  
  122.  
  123. _cmd_line    db    129 dup (?)    ; Command line
  124. _path_line    db    80 dup (?)    ; Path line
  125. _etext        dw    seg cetext    ; End of text segment
  126. _SW_Blocks    dw    0        ; Number of blocks to read/write
  127. _SW_SBlocks    dw    0        ; Short Number of blocks to read/write
  128. _SW_fp        dw    0        ; File ID
  129. _SW_Pwrite    dw    0        ; Partial write to disk?
  130. _SW_I0_V    dd    0        ; Our Interrupt Zero address
  131. _SW_I23_V    dd    0        ; Our Interrupt 23 address
  132. _SW_EMstart    dd    0100000H    ; Default Extended Mem start
  133. _SW_Mode    dw    0        ; Type of swapping to do
  134.                     ;   1 - disk
  135.                     ;   2 - Extended memory
  136.                     ;   3 - EMS driver
  137.                     ;   4 - XMS driver
  138. _SW_EMSFrame    dw    0        ; EMS Frame segment
  139. _SW_intr    dw    0        ; Interrupt 23 detected.
  140. _SW_XMS_Driver    dd    0        ; XMS Driver Interface
  141.  
  142. ;
  143. ; Some addition variables
  144. ;
  145.  
  146. SW_LMstart    dd    0        ; Low Mem start for Extended Mem swap
  147. N_mcb        dw    0        ; Start write address
  148. Result        dw    0        ; Return value
  149. InShell        db    0        ; In shell flag for Interrupt 23
  150.  
  151. ;
  152. ; Stack save pointers
  153. ;
  154.  
  155. S_ss        dw    0            ; Save Stack pointers
  156. S_sp        dw    0
  157. S_di        dw    0            ; Save DI, SI
  158. S_si        dw    0
  159. S_ds        dw    0            ; Save the original DS
  160.  
  161. ;
  162. ; Two blank FCB
  163. ;
  164.  
  165. FCB1        dw    16    dup (?)
  166. FCB2        dw    16    dup (?)
  167.  
  168. ;
  169. ; XMS Driver Move structure
  170. ;
  171.  
  172. XMS_DIF        equ    $
  173. XMS_Length    dd    0            ; Number of bytes
  174. XMS_SHandle    dw    0            ; Source Handler
  175. XMS_Soffset    dd    0            ; Source Offset
  176. XMS_DHandle    dw    0            ; Destination Handler
  177. XMS_Doffset    dd    0            ; Destination Offset
  178.  
  179. ;
  180. ; Extended Memory Global Descriptor tables
  181. ;
  182.         org    XMS_DIF
  183. GD_table    equ    $
  184. GDT_Dummy    dw    4    dup (0)        ; Dummy
  185. GDT_self    dw    4    dup (0)        ; For self
  186. GDT_src        equ    $            ; Source
  187.         dw    04000H            ; Length - 16K bytes
  188. GDT_src_low    dw    0            ;     Low Order address
  189. GDT_src_high    db    0            ;     High Order address
  190.         db    093h            ;     Access Rights
  191.         dw    0            ;     Reserved
  192. GDT_dest    equ    $            ; Destination
  193.         dw    04000H            ;     Length - 16K bytes
  194. GDT_dest_low    dw    0            ;     Low Order address
  195. GDT_dest_high    db    0            ;     High Order address
  196.         db    093h            ;     Access Rights
  197.         dw    0            ;     Reserved
  198. GDT_bios    dw    4    dup (0)        ; Bios
  199. GDT_stack    dw    4    dup (0)        ; Stack
  200.  
  201. ;
  202. ; Execute interrupt structure
  203. ;
  204.  
  205. exec_parms    equ    $
  206. exec_env    dw    0
  207.         dw    offset _cmd_line    ; Command line address
  208. exec_cseg    dw    ?
  209.         dw    offset FCB1        ; FCB1 address
  210. exec_f1seg    dw    ?
  211.         dw    offset FCB2        ; FCB1 address
  212. exec_f2seg    dw    ?
  213.  
  214. Swap_PANIC    db    'PANIC: Swap file re-load error - REBOOT', 0aH, 0dH
  215.         db    '$'
  216.  
  217. Swap_DZERO    db    'PANIC: Divide by zero', 0aH, 0dH
  218.         db    '$'
  219.  
  220. ;
  221. ; OK - exec requires a local stack, cause some programs overwrite it
  222. ;
  223.         even
  224.         db    398 dup (0)
  225. Local_Stack:
  226.         dw    0
  227.  
  228. ;
  229. ; Code starts
  230. ;
  231.     public    _SA_spawn
  232.  
  233. _SA_spawn    proc    far
  234.  
  235.     push    bp
  236.     mov    bp, sp
  237.  
  238. ;
  239. ; Entry Offsets
  240. ;
  241. ;    Environment      = 6
  242. ;
  243.  
  244.     mov    word ptr cs:S_di, di        ; Save registers
  245.     mov    word ptr cs:S_si, si
  246.     mov    word ptr cs:S_ds, ds
  247.  
  248. ;
  249. ; Set up to ingnore Control C interrupts
  250. ;
  251.  
  252.     push    ds
  253.     mov    ax, 02523H        ; Set Control C Interrupt
  254.     mov    dx, offset SA_IRET
  255.     push    cs
  256.     pop    ds
  257.     mov    byte ptr cs:InShell, 0    ; Set In shell flag for Interrupt 23
  258.     int    021H
  259.  
  260.     mov    ax, 02500H        ; Set Divide Zero Interrupt
  261.     mov    dx, offset SA_DZERO
  262.     push    cs
  263.     pop    ds
  264.     int    021H
  265.  
  266.     pop    ds
  267.  
  268. ;
  269. ; Save the length of the current MCB block;
  270. ;
  271.  
  272.     mov    ax, word ptr ds:__psp
  273.     dec    ax
  274.     mov    word ptr cs:N_mcb, ax        ; Save MCB address for swap out
  275.  
  276. ; Calculate low mem start for extended memory
  277.  
  278.     mov    bx, ax                ; Save copy
  279.     mov    cl, 4                ; mult low order by 16
  280.     shl    ax, cl
  281.     mov    word ptr cs:SW_LMstart, ax    ; Save low order
  282.     mov    cl, 12                ; div by 16 ** 3
  283.     shr    bx, cl
  284.     mov    byte ptr cs:SW_LMstart + 2, bl    ; Save low order
  285.  
  286. ;
  287. ; Set up Environment segment in execute structure
  288. ;
  289.  
  290.     mov    bx, cs
  291.     mov    ax, offset Env_OWrite
  292.     mov    cl, 4
  293.     shr    ax, cl
  294.     add    ax, bx
  295.     mov    word ptr cs:exec_env, ax    ; Save Env seg.
  296.  
  297. ;
  298. ; Set up rest of execute structure
  299. ;
  300.  
  301.     mov    word ptr cs:exec_cseg, cs    ; Command line address
  302.     mov    word ptr cs:exec_f1seg, cs    ; FCB 1 address
  303.     mov    word ptr cs:exec_f2seg, cs    ; FCB 2 address
  304.  
  305. ;
  306. ; Generate the FCBs
  307. ;
  308.  
  309.     mov    ax, cs        ; Set up segments
  310.     mov    ds, ax
  311.     mov    es, ax
  312.  
  313.     mov    ax, 02901H    ; Set up FCB interrupt
  314.     mov    si, offset _cmd_line + 1
  315.     mov    di, offset FCB1    ; FCB 1;
  316.  
  317.     int    021H        ; Execute the interrupt
  318.  
  319.     mov    ax, cs        ; Set up segment
  320.     mov    es, ax
  321.  
  322.     mov    ax, 02901H    ; Reset AX cause errors are ignored
  323.     mov    di, offset FCB2    ; FCB 2;
  324.  
  325.     int    021H        ; Execute the interrupt
  326.  
  327. ;
  328. ; Copy out to the swap file
  329. ;
  330.  
  331.     mov    bx, word ptr cs:_SW_fp        ; Load file handler
  332.     mov    si, word ptr cs:_SW_Blocks    ; Load Number of blocks to read
  333.     mov    ax, word ptr cs:N_mcb        ; Load the start address
  334.  
  335. ;
  336. ;  Check for Partial write on disk swap file
  337. ;
  338.  
  339.     cmp    word ptr cs: _SW_Mode, 1    ; Partial disk write ?
  340.     jnz    SPart_Write
  341.     cmp    word ptr cs: _SW_Pwrite, 0
  342.     jz    SPart_Write
  343.  
  344.     mov    si, word ptr cs:_SW_SBlocks    ; Load Number of blocks to read
  345.     mov    ax, word ptr cs:_etext        ; Load the start address
  346.  
  347. SPart_Write:
  348.     push    ax
  349.  
  350. ; load up extended memory GDT for destination
  351.  
  352.     mov    ax, word ptr cs:_SW_EMstart
  353.     mov    dl, byte ptr cs:_SW_EMstart + 2
  354.     call    $GDT_dest_load
  355.  
  356. ;
  357. ; set up DS register with start of start copy
  358. ;
  359.  
  360.     pop    ax
  361.     mov    ds, ax
  362.     mov    ax, word ptr cs:SW_LMstart     ; Load Full start address
  363.     mov    dl, byte ptr cs:SW_LMstart + 2
  364.     call    $GDT_src_load
  365.  
  366. ;
  367. ; Check for end of copy - BX contains the file handler for disk write
  368. ;
  369.  
  370. $Write_loop:
  371.     or    si, si
  372.     jnz    $Write_L1
  373.     jmp    $Write_Complete
  374.  
  375. ; OK - Copy next 0x4000 bytes - switch on device
  376.  
  377. $Write_L1:
  378.     mov    ax, word ptr cs: _SW_Mode
  379.     dec    ax
  380.     jz    $W_disk
  381.     dec    ax
  382.     jnz    $Write_L2
  383.     jmp    $W_extend
  384. $Write_L2:
  385.     dec    ax
  386.     jnz    $W_xms
  387.     jmp    $W_expand
  388.  
  389. ;
  390. ; Write to XMS driver.  In this case, we do one write and let the driver
  391. ; sort out the blocking
  392. ;
  393. $W_xms:
  394.     xor    ax, ax
  395.     mov    word ptr cs:XMS_SHandle, ax    ; Source - normal memory
  396.     mov    word ptr cs:XMS_DHandle, bx    ; Dest - XMS
  397.  
  398.     mov    word ptr cs:XMS_Doffset, ax    ; Dest offset - zero
  399.     mov    word ptr cs:XMS_Doffset + 2, ax
  400.  
  401.     mov    word ptr cs:XMS_Soffset, ax    ; Source offset DS:0
  402.     mov    ax, ds
  403.     mov    word ptr cs:XMS_Soffset + 2, ax
  404.  
  405. ;
  406. ; Set up number of bytes SW_Block * 16 * 1024
  407. ;
  408.  
  409.     mov    ax, si
  410.     mov    dx, si
  411.     mov    cl, 14
  412.     shl    ax, cl
  413.     mov    cl, 2
  414.     shr    dx, cl
  415.     mov    word ptr cs:XMS_Length, ax    ; Load number of bytes
  416.     mov    word ptr cs:XMS_Length + 2, dx
  417.  
  418.     mov    ah, 0BH                ; Set up parameters
  419.     mov    dx, cs
  420.     mov    ds, dx
  421.     mov    si, offset XMS_DIF
  422.     call    cs:[_SW_XMS_Driver]
  423.     or    ax, ax
  424.     jnz     $Write_Complete
  425.  
  426. ; XMS error - abort
  427.     
  428.     mov    ah, bl
  429.     jmp    $Write_error
  430.  
  431. ;
  432. ; Write to disk
  433. ;
  434. $W_disk:
  435.     call    $Write_disk
  436.  
  437. ; Increment counter
  438.  
  439. $Write_Incr:
  440.     dec    si            ; Decrement block count
  441.     mov    ax, ds            ; Increment offset
  442.     add    ax, 0400H
  443.     mov    ds, ax
  444.     jmp    $Write_loop
  445.  
  446. ; Write to extended memory
  447.  
  448. $W_extend:
  449.     call    $Write_extend
  450.     jc    $Write_error        ; NO - abort
  451.  
  452.     dec    si            ; Decrement block count
  453.     call    $Inc_Extend
  454.     jmp    $Write_loop
  455.  
  456. ; Write to expanded memory
  457. ;    BX - handler
  458. ;    SI - count
  459. ;    DS - source segment
  460. ;
  461. $W_expand:
  462.     call    $map_ems_page        ; Map in the current EMS page
  463.     jnz    $Write_error
  464.  
  465.     push    ds            ; Save DS and SI
  466.     push    si
  467.     mov    es, word ptr cs:_SW_EMSFrame    ; Set Dest Seg
  468.     xor    si, si            ; Clear start
  469.     xor    di, di
  470.     mov    cx, 02000H        ; move 16K
  471.     pushf                ; Save direction flag
  472.     cld
  473.     rep movsw
  474.     popf                ; Restore direction flag
  475.     pop    si            ; And DS, SI
  476.     pop    ds
  477.     jmp    $Write_Incr        ; Increment DS and dec SI
  478.  
  479. ;
  480. ; Error - abort.  The error code is in AH.
  481. ;
  482.  
  483. $Write_error:
  484.     mov    ds, word ptr cs:S_ds    ; Restore DS
  485.     mov    al, ah
  486.     xor    ah, ah
  487.     mov    word ptr ds:_errno, ax    ; Save error code
  488.  
  489. $Write_Error1:
  490.     mov    ax, 0FFFEH
  491.     jmp    $SA_spawn_Exit        ; Exit
  492.  
  493. ;
  494. ; Swap file is now written, set up environment.  If this was a partial
  495. ; write, we need to write the first 4K.
  496. ;
  497.  
  498. $Write_Complete:
  499.     cmp    word ptr cs: _SW_Mode, 1    ; Partial disk write ?
  500.     jnz    S1Part_Write
  501.     cmp    word ptr cs: _SW_Pwrite, 0
  502.     jz    S1Part_Write
  503.  
  504.     mov    ax, 04200H            ; Set seek
  505.     xor    dx, dx
  506.     xor    cx, cx
  507.     int    021H
  508.     jnc    $Write_C1            ; Abort - swap file error
  509.     jmp    $Map_error
  510.  
  511. $Write_C1:
  512.     mov    ax, word ptr cs:N_mcb        ; Load the start address
  513.     mov    ds, ax
  514.     call    $Write_disk
  515.  
  516. S1Part_Write:
  517.     mov    ds, word ptr cs:exec_env    ; Load Env seg.
  518.     xor    si, si                ; Clear start offset
  519.  
  520. ;
  521. ; Copy into Env Seg
  522. ;
  523.  
  524. $Copy_Env:
  525.     les    bx, dword ptr ss:[bp + 6]    ; Check for end of loop
  526.     mov    ax, word ptr es:[bx + 0]
  527.     or    ax, word ptr es:[bx + 2]
  528.     je    $Copy_End
  529.  
  530. ;
  531. ; Save start address
  532. ;
  533.     add    word ptr ss:[bp + 6], 4        ; Increment environment by 4
  534.  
  535.     mov    cx, word ptr es:[bx + 0]    ; Load address of cur Env string
  536.     mov    ax, word ptr es:[bx + 2]    ; into es:bx
  537.     mov    es, ax
  538.     mov    bx, cx
  539.  
  540. ;
  541. ; Copy this value
  542. ;
  543.  
  544. $Copy_Val:
  545.     mov    al, byte ptr es:[bx]    ; Copy across
  546.     mov    byte ptr ds:[si], al
  547.     inc    bx            ; Increment pointers
  548.     inc    si
  549.     or    al, al
  550.     jne    $Copy_Val
  551.     jmp    $Copy_Env
  552.  
  553. ;
  554. ; Set up exec parameter block     - DS is on stack
  555. ;
  556. $Copy_End:
  557.     xor    ax, ax
  558.     mov    word ptr ds:[si], ax    ; Terminate environment
  559.     add    si, 2
  560.  
  561. ;
  562. ; Set up new program length
  563. ;
  564.     add    si, 16            ; Round up paras
  565.     mov    dx, si            ; Save end offset in DX
  566.     mov    bx, ds
  567.  
  568.     mov    cl, 4
  569.     shr    si, cl            ; # paras used by Env
  570.     add    si, bx            ; End para number
  571.  
  572.     mov    bx, word ptr cs:N_mcb    ; Load our MCB address in BX
  573.     mov    ax, bx
  574.     inc    ax
  575.     sub    si, ax
  576.     mov    cx, si            ; Save new max paras in CX
  577.  
  578. ;
  579. ; Use interrupt 4a to shrink memory.  First release all memory above us.
  580. ;
  581.     push    ax
  582.     push    cx            ; Save Max paras and location
  583.     mov    ds, bx            ; Set up the segement for MCB
  584.     mov    cx, word ptr ds:3    ; Get the MCB length
  585.  
  586. ; Are we the only one in the chain?
  587.  
  588.     cmp    byte ptr ds:0, 'Z'    ; End of chain ?
  589.     jz    $Shrink_First
  590.  
  591. ;
  592. ; Loop round releasing memory blocks
  593. ;
  594. ;    CX - original length of block;
  595. ;    DS - segement of the previous block
  596. ;
  597. $Shrink_Next:
  598.     mov    ax, ds            ; Move to the next block
  599.     add    cx, ax
  600.     inc    cx
  601.     mov    ds, cx
  602.  
  603.     cmp    byte ptr ds:0, 'Z'    ; End of chain ?
  604.     jz    $Shrink_First
  605.  
  606.     mov    cx, word ptr ds:3    ; Save the length of this block
  607.  
  608.     mov    ax, ds            ; Advance to the block itself
  609.     inc    ax
  610.     mov    es, ax            ; Set up Block address
  611.  
  612.     mov    ah, 049H
  613.     int    021H
  614.     jmp    $Shrink_Next
  615.  
  616. ;
  617. ;    Shrink the PSP segment
  618. ;
  619.  
  620. $Shrink_First:
  621.     pop    cx
  622.     pop    ax
  623.         mov    es, ax            ; Set PSP address
  624.     mov    bx, cx            ; Set max length
  625.     mov    ah, 04aH
  626.     int    021H
  627.  
  628. ;
  629. ; Execute function
  630. ;
  631.  
  632.     mov    word ptr cs: S_sp, sp    ; Save the current stack
  633.     mov    word ptr cs: S_ss, ss
  634.  
  635. ;
  636. ; Move to the local stack so that it doesn't get overwritten.
  637. ;
  638.     mov    ax, cs
  639.     cli
  640.     mov    sp, offset Local_Stack
  641.     mov    ss, ax
  642.     sti
  643.  
  644. ; Clear out Interrupts
  645.  
  646.     mov    ah, 00bH        ; Check Keyboard status
  647.     int    021H
  648.  
  649. ;
  650. ;  Check for interrupt 23 detected
  651. ;
  652.     mov    ax, word ptr cs:_SW_intr
  653.     or    ax, ax
  654.     jz    $I23_Cf            ; No - continue;
  655.  
  656. ;
  657. ; Interrupt 23 detected - abort
  658. ;
  659.     mov    ax, cs            ; Set up for reload
  660.     cli
  661.     mov    sp, offset Local_Stack
  662.     mov    ss, ax
  663.     sti
  664.  
  665.     mov    ds, word ptr cs:S_ds    ; Restore DS
  666.     xor    ax, ax
  667.     jmp    $Exec_Complete
  668.  
  669. ;
  670. ; No interrupts - continue
  671. ;
  672. $I23_Cf:
  673.     mov    ax, cs            ; Set up segments
  674.     mov    es, ax
  675.     mov    ds, ax
  676.  
  677.     mov    ax, 04b00H        ; Load and execute function
  678.     mov    dx, offset _path_line    ; Load path
  679.     mov    bx, offset exec_parms    ; Load the execute structure
  680.     mov    byte ptr cs:InShell, 1    ; Set not In shell flag for Interrupt 23
  681.     int    021H
  682.     mov    byte ptr cs:InShell, 0    ; Set In shell flag for Interrupt 23
  683.  
  684. ; Disable interrupts while we restore the stack to the local one
  685.  
  686.     mov    ax, cs
  687.     cli
  688.     mov    sp, offset Local_Stack
  689.     mov    ss, ax
  690.     sti
  691.  
  692. ;
  693. ; Did an error occur?
  694. ;
  695.     jnc    $Exec_OK
  696.  
  697. ;
  698. ; Error
  699. ;
  700.  
  701. $Map_error:
  702.     mov    ds, word ptr cs:S_ds    ; Restore DS
  703.     mov    ah, al
  704.     call    far ptr __maperror    ; Map the error
  705.  
  706. $Exec_Error:
  707.     mov    ax, 0FFFFH
  708.     jmp    $Exec_Complete
  709.  
  710. ;
  711. ; No - get the exit code and check for interrupts
  712. ;
  713.  
  714. $Exec_OK:
  715.     mov    ax, 04d00H
  716.     int    021H
  717.     dec    ah            ; Interrupt termination ?
  718.     jnz    $Exec_OK1
  719.  
  720.     inc    word ptr ds:_SW_intr    ; Set Interrupt 23 detected.
  721.  
  722. $Exec_OK1:
  723.     xor    ah, ah
  724.  
  725. ;
  726. ; Save the result code
  727. ;
  728.  
  729. $Exec_Complete:
  730.     mov    word ptr cs:Result, ax        ; Save response
  731.  
  732. ;
  733. ; Very Dangerous - Restore Environment
  734. ;
  735. ;     Seek to 0x4000 in file
  736. ;
  737.     mov    bx, word ptr cs:_SW_fp        ; Load File Handler
  738.     mov    ax, word ptr cs: _SW_Mode    ; Skip if not disk
  739.     dec    ax
  740.     jnz    $Seek_OK
  741.  
  742. ; Seek in file to skip 16K
  743.  
  744.     mov    dx, 04000H
  745.     call    $Seek_Disk
  746.  
  747. ;
  748. ;     Load from N_mcb:0x4000 to end of file.
  749. ;
  750.  
  751. $Seek_OK:
  752.     mov    si, word ptr cs:_SW_Blocks    ; Load number of transfers
  753.     dec    si                ; Skip first block
  754.  
  755. ;
  756. ; set up ES register with start of load
  757. ;
  758.     mov    ax, word ptr cs:N_mcb    ; Load the start address
  759.     add    ax, 0400H
  760.     mov    ds, ax
  761.  
  762. ; load up extended memory GDT for destination
  763.  
  764.     call    $GDT_reload
  765.     call    $Inc_Extend            ; Increment addresses by 16K
  766.  
  767. ;
  768. ; Check for end of copy    - BX - File Handler for disk
  769. ;
  770.  
  771. $Read_loop:
  772.     or    si, si
  773.     je    $Read_Complete
  774.  
  775. ; OK - Copy next 0x4000 bytes - switch on device
  776.  
  777.     mov    ax, word ptr cs: _SW_Mode
  778.     dec    ax
  779.     jz    $R_disk
  780.     dec    ax
  781.     jz    $R_extend
  782.     dec    ax
  783.     jz    $R_expand
  784.  
  785. ;
  786. ; Read from XMS driver.  In this case, we do one read and let the driver
  787. ; sort out the blocking
  788. ;
  789.     call    $Read_XMS
  790.     jmp     $Read_Complete
  791.  
  792. ; Read from disk
  793.  
  794. $R_disk:
  795.     call    $Read_disk
  796.     jmp    $Read_loop
  797.  
  798. ; Read from extended memory
  799.  
  800. $R_extend:
  801.     call    $Read_extend
  802.     jmp    $Read_loop
  803.  
  804. ; Read from expanded memory
  805.  
  806. $R_expand:
  807.     call    $Read_EMS
  808.     jmp    $Read_loop
  809.  
  810. ;
  811. ; Re-load is now complete, Restore original stack which has just been
  812. ; reloaded.  BX contains FP
  813. ;
  814.  
  815. $Read_Complete:
  816.     cli
  817.     mov    sp, word ptr cs: S_sp        ; Save the current stack
  818.     mov    ss, word ptr cs: S_ss
  819.     sti
  820.  
  821. ;  Save exit code
  822.  
  823.     push    word ptr cs:Result        ; Save response
  824.     push    word ptr cs:_SW_intr        ; and interrupt flag
  825.  
  826. ;
  827. ; Read in the first block - BX - File Handler
  828. ;
  829.  
  830.     mov    ax, word ptr cs: _SW_Mode    ; Skip if not disk
  831.     dec    ax
  832.     jnz    $Seek1_OK
  833.  
  834. ; Seek to 0 in file
  835.  
  836.     xor    dx, dx
  837.     call    $Seek_Disk
  838.  
  839. ;
  840. ;     Load one block at N_mcb:0x0000
  841. ;
  842. $Seek1_OK:
  843.     mov    ds, word ptr cs:N_mcb        ; Load the start address
  844.     call    $GDT_reload            ; Load the GDT for extend mem
  845.  
  846.     mov    ax, word ptr cs: _SW_Mode    ; Skip if not disk
  847.     dec    ax
  848.     jz    $R1_Disk
  849.     dec    ax
  850.     jz    $R1_Extend
  851.     dec    ax
  852.     jz    $R1_Expand
  853.  
  854.     mov    si, 1                ; Read one block
  855.     call    $Read_XMS
  856.     jmp    $Read1_OK
  857.  
  858. $R1_Disk:
  859.     call    $Read_disk
  860.     jmp    $Read1_OK
  861.  
  862. $R1_Extend:
  863.     call    $Read_extend
  864.     jmp    $Read1_OK
  865.  
  866. $R1_Expand:
  867.     mov    si, word ptr cs:_SW_Blocks    ; Read first block
  868.     call    $Read_EMS
  869.  
  870. ;
  871. ; Complete - load error code and return
  872. ;
  873.  
  874. $Read1_OK:
  875.     pop    word ptr cs:_SW_intr        ; Restore interrupt flag
  876.     pop    ax
  877.  
  878. ;
  879. ; Exit function - Restore Control Interrupt handler
  880. ;
  881.  
  882. $SA_spawn_Exit:
  883.     push    ax                ; Save exit code
  884.     mov    ax, 02523H            ; Set Control C Interrupt
  885.     mov    dx, word ptr cs:_SW_I23_V
  886.     mov    ds, word ptr cs:_SW_I23_V + 2
  887.     int    021H
  888.  
  889.     mov    ax, 02500H            ; Set Divide Zero Interrupt
  890.     mov    dx, word ptr cs:_SW_I0_V
  891.     mov    ds, word ptr cs:_SW_I0_V + 2
  892.  
  893. ;
  894.  
  895.     mov    di, word ptr cs:S_di        ; Restore saved registers
  896.     mov    si, word ptr cs:S_si
  897.     mov    ds, word ptr cs:S_ds
  898.  
  899. ; If interrupt 23 detected - raise the flag
  900.  
  901.     mov    ax, word ptr cs:_SW_intr    ; Set Interrupt 23 detected.
  902.     or    ax, ax
  903.     jz    $SA_Exit1
  904.  
  905.     mov    ax, 02H
  906.     push    ax                ; Set SIGINT
  907.     call    _raise
  908.     add    sp, 2
  909.  
  910. $SA_Exit1:
  911.     pop    ax                ; Restore result
  912.     mov    sp, bp
  913.     pop    bp
  914.     ret
  915.  
  916. _SA_spawn    endp
  917.  
  918. ;
  919. ; READ XMS DRIVER FUNCTION
  920. ;
  921. ;    BX - file handler
  922. ;    SI - Block count
  923. ;    DS - Output data segement
  924. ;
  925. $Read_XMS    proc    near
  926.     xor    ax, ax
  927.     mov    word ptr cs:XMS_SHandle, bx    ; Source - XMS
  928.     mov    word ptr cs:XMS_DHandle, ax    ; Dest - normal memory
  929.  
  930.     mov    word ptr cs:XMS_Soffset, ax    ; Source offset - zero
  931.     mov    word ptr cs:XMS_Soffset + 2, ax
  932.  
  933.     mov    word ptr cs:XMS_Doffset, ax    ; Dest offset DS:0
  934.     mov    ax, ds
  935.     mov    word ptr cs:XMS_Doffset + 2, ax
  936.  
  937.     cmp    si, 1                ; If first block, the
  938.     jz    $Read_X1            ; source offset is
  939.                         ; 4000H
  940.     mov    word ptr cs:XMS_Soffset, 04000H
  941.  
  942. ;
  943. ; Set up number of bytes: si * 16 * 1024
  944. ;
  945.  
  946. $Read_X1:
  947.     mov    ax, si
  948.     mov    dx, si
  949.     mov    cl, 14
  950.     shl    ax, cl
  951.     mov    cl, 2
  952.     shr    dx, cl
  953.     mov    word ptr cs:XMS_Length, ax    ; Load number of bytes
  954.     mov    word ptr cs:XMS_Length + 2, dx
  955.  
  956.     mov    ah, 0BH                ; Set up parameters
  957.     mov    dx, cs
  958.     mov    ds, dx
  959.     mov    si, offset XMS_DIF
  960.     call    cs:[_SW_XMS_Driver]
  961.     or    ax, ax
  962.     jnz     $Read_XMS1
  963.     jmp    Load_Error            ; XMS error - abort
  964.  
  965. $Read_XMS1:
  966.     ret
  967.  
  968. $Read_XMS    endp
  969.  
  970. ;
  971. ; WRITE DISK FUNCTION
  972. ;
  973. ;    BX - file handler
  974. ;    SI - Block count
  975. ;    DS - Output data segement
  976. ;
  977.  
  978. $Write_disk    proc    near
  979.  
  980.     mov    ax, 04000H        ; Set up to write
  981.     mov    cx, ax            ; Load count
  982.     xor    dx, dx            ; Clear start address
  983.     push    bx            ; Save FP
  984.     push    si            ; Save count and Data Segment
  985.  
  986.     int    021H            ; Write the data
  987.  
  988.     pop    si            ; Restore Regs
  989.     pop    bx
  990.     jnc    $Write_disk1        ; NO error - continue
  991.  
  992. ;
  993. ; Error - abort
  994. ;
  995.     mov    ds, word ptr cs:S_ds    ; Restore DS
  996.     mov    ah, al
  997.     call    far ptr __maperror    ; Map the error
  998.     jmp    $Write_Error1
  999.  
  1000. ; Check for 16K write
  1001.  
  1002. $Write_disk1:
  1003.     cmp    ax, 04000H
  1004.     jnz    $Write_disk2
  1005.     ret
  1006.  
  1007. $Write_disk2:
  1008.     mov    ax,01c1cH        ; Set disk full
  1009.     jmp    $Write_error        ; NO - abort
  1010.  
  1011. $Write_disk    endp
  1012.  
  1013. ;
  1014. ; READ DISK FUNCTION
  1015. ;
  1016. ;    BX - file handler
  1017. ;    SI - Block count
  1018. ;    DS - Output data segement
  1019. ;
  1020.  
  1021. $Read_disk    proc    near
  1022.  
  1023.     mov    ax, 03f00H        ; Set up to read
  1024.     mov    cx, 04000H        ; Load count
  1025.     xor    dx, dx            ; Clear start address
  1026.  
  1027.     int    021H            ; Read the data
  1028.  
  1029.     jnc    $Read_OK        ; NO - abort
  1030.     jmp    Load_Error        ; Abort - swap file error
  1031.  
  1032. ;
  1033. ; Read OK - next block
  1034. ;
  1035.  
  1036. $Read_OK:
  1037.     dec    si            ; Decrement block count
  1038.     mov    ax, ds            ; Increment offset
  1039.     add    ax, 0400H
  1040.     mov    ds, ax
  1041.     ret
  1042.  
  1043. $Read_disk    endp
  1044.  
  1045. ;
  1046. ; READ EMS FUNCTION
  1047. ;
  1048. ;    BX - file handler
  1049. ;    SI - Block count - counts from max
  1050. ;    DS - Output data segement
  1051. ;
  1052.  
  1053. $Read_EMS    proc    near
  1054.  
  1055.     call    $map_ems_page        ; Map in the current EMS page
  1056.     jnz    Load_Error
  1057.  
  1058.     push    ds            ; Save DS and SI
  1059.     push    si
  1060.     mov    ax, ds
  1061.     mov    es, ax
  1062.     mov    ds, word ptr cs:_SW_EMSFrame    ; Set Dest Seg
  1063.     xor    si, si            ; Clear start
  1064.     xor    di, di
  1065.     mov    cx, 02000H        ; move 16K
  1066.     pushf                ; Save direction flag
  1067.     cld
  1068.     rep movsw
  1069.     popf                ; Restore direction flag
  1070.     pop    si            ; And DS, SI
  1071.     pop    ds
  1072.     jmp    $Read_OK        ; Increment DS and dec SI
  1073.  
  1074. $Read_EMS    endp
  1075.  
  1076. ;
  1077. ; MAP IN THE CURRENT EMS PAGE
  1078. ;
  1079. ;    BX - file handler
  1080. ;    SI - Block count - counts from max
  1081. ;    DS - Output data segement
  1082. ;
  1083.  
  1084. $map_ems_page    proc    near
  1085.  
  1086.     push    bx            ; Need to save BX
  1087.     mov    ax, 04400h        ; Map into physical page zero
  1088.     mov    dx, bx            ; Set up handler
  1089.     mov    bx, word ptr cs: _SW_Blocks
  1090.     sub    bx, si
  1091.  
  1092.     int    067H
  1093.     pop    bx
  1094.  
  1095.     or    ah, ah
  1096.     ret
  1097.  
  1098. $map_ems_page    endp
  1099.  
  1100. ;
  1101. ; DISK SEEK FUNCTION
  1102. ;
  1103. ;    BX - file handler
  1104. ;    DX - offset
  1105. ;
  1106. $Seek_Disk    proc    near
  1107.  
  1108.     mov    ax, 04200H        ; Set seek
  1109.     xor    cx, cx
  1110.     int    021H
  1111.     jc    Load_Error        ; Abort - swap file error
  1112.     ret
  1113.  
  1114. $Seek_Disk    endp
  1115.  
  1116. ;
  1117. ; PANIC - Abort
  1118. ;
  1119.  
  1120. Load_Error    proc    near
  1121.  
  1122.     mov    di, offset Swap_PANIC
  1123.     mov    bx, cs
  1124.     mov    ds, bx
  1125.     call    I24_Display
  1126. $Wait_L:
  1127.     sti
  1128.     hlt
  1129.     jmp    $Wait_L
  1130.  
  1131. Load_Error    endp
  1132.  
  1133. ;
  1134. ;  WRITE EXTENDED MEMORY
  1135. ;
  1136. ;    SI - Block count
  1137. ;
  1138. $Write_extend    proc    near
  1139.  
  1140.     push    si            ; Save SI (block counter)
  1141.     mov    cx, 02000H        ; Copy a 16K block
  1142.     mov    ax, cs            ; Set up GDT address
  1143.     mov    es, ax
  1144.     mov    si, offset GD_table
  1145.  
  1146.     mov    ah, 087H        ; EMS function
  1147.     int    015H
  1148.     pop    si
  1149.     ret
  1150.  
  1151. $Write_extend    endp
  1152.  
  1153. ;
  1154. ;  READ FROM EXTENDED MEMORY
  1155. ;
  1156. ;    SI - Block count
  1157. ;
  1158.  
  1159. $Read_extend    proc    near
  1160.  
  1161.     call    $Write_extend
  1162.     jc    Load_Error        ; NO - abort
  1163.  
  1164.     dec    si            ; Decrement block count
  1165.  
  1166. $Read_extend    endp
  1167.  
  1168. ;
  1169. ; INCREMENT Extended MEMORY GDT
  1170. ;
  1171. ;    AX - used
  1172. ;
  1173. $Inc_Extend    proc    near
  1174.  
  1175.     mov    ax, 04000H        ; Increment address by 16K
  1176.     add    word ptr cs:GDT_dest_low, ax
  1177.     adc    byte ptr cs:GDT_dest_high, 0
  1178.     add    word ptr cs:GDT_src_low, ax
  1179.     adc    byte ptr cs:GDT_src_high, 0
  1180.     ret
  1181.  
  1182. $Inc_Extend    endp
  1183.  
  1184. ;
  1185. ; LOAD SOURCE GDT ADDRESS
  1186. ;
  1187. ;    AX - low order
  1188. ;    DL - high order
  1189. ;
  1190. $GDT_src_load    proc    near
  1191.  
  1192.  
  1193.     mov    word ptr cs:GDT_src_low, ax
  1194.     mov    byte ptr cs:GDT_src_high, dl
  1195.     ret
  1196.  
  1197. $GDT_src_load    endp
  1198.  
  1199. ;
  1200. ; LOAD DESTINATION GDT ADDRESS
  1201. ;
  1202. ;    AX - low order
  1203. ;    DL - high order
  1204. ;
  1205. $GDT_dest_load    proc    near
  1206.  
  1207.     mov    word ptr cs:GDT_dest_low, ax
  1208.     mov    byte ptr cs:GDT_dest_high, dl
  1209.     ret
  1210.  
  1211. $GDT_dest_load    endp
  1212.  
  1213. ;
  1214. ; LOAD the GDT for reloading
  1215. ;
  1216.  
  1217. $GDT_reload    proc    near
  1218.     mov    ax, word ptr cs:_SW_EMstart     ; Load Full start address
  1219.     mov    dl, byte ptr cs:_SW_EMstart + 2
  1220.     call    $GDT_src_load
  1221.  
  1222.     mov    ax, word ptr cs:SW_LMstart     ; Load Full start address
  1223.     mov    dl, byte ptr cs:SW_LMstart + 2
  1224.     call    $GDT_dest_load
  1225.     ret
  1226. $GDT_reload    endp
  1227.  
  1228. ;
  1229. ; CONTROL C INTERRUPT HANDLER - IGNORE
  1230. ;
  1231.  
  1232. SA_IRET        proc    far
  1233.     inc    word ptr cs:_SW_intr    ; Set Interrupt 23 detected.
  1234.     cmp    byte ptr cs:InShell, 0    ; Are we in the shell ?
  1235.     jz    $SA_Ins
  1236.  
  1237. ; In another program - move the stack around
  1238.  
  1239.     stc
  1240.     ret
  1241.  
  1242.  
  1243. ; In shell - ignore interrupt 23 for the moment
  1244.  
  1245. $SA_Ins:
  1246.     iret
  1247.  
  1248. SA_IRET        endp
  1249.  
  1250. ;
  1251. ; DIVIDE BY ZERO INTERRUPT HANDLER - Output message
  1252. ;
  1253.  
  1254. SA_DZERO    proc    far
  1255.  
  1256.     mov    ax, 00900H
  1257.     mov    dx, offset Swap_DZERO
  1258.     mov    bx, cs
  1259.     mov    ds, bx
  1260.     int    021H
  1261.  
  1262.     mov    ax, 04CFFh        ; Exit
  1263.     int    021H
  1264.  
  1265. SA_DZERO    endp
  1266.  
  1267. ;
  1268. ; INTERRUPT 24 - ERROR HANDLER - Output message
  1269. ;
  1270. ;    AH - Bit  7    = 0 Disk error
  1271. ;            = 1 FAT error if block device
  1272. ;                Error code in DI if character device
  1273. ;      Bit  6    UNUSED
  1274. ;      Bit  5    = 1 Ignore allowed
  1275. ;      Bit  4    = 1 Retry allowed
  1276. ;      Bit  3    = 1 Fail allowed
  1277. ;      Bits 2 & 1    = Disk Area
  1278. ;      Bit  0    = 1 Writing error
  1279. ;    AL         = Disk drive number
  1280. ;    DI            = Error code
  1281. ;    BP:SI        = Header of device driver for which error occured
  1282. ;
  1283. ;
  1284. ; Return
  1285. ;    AL            = 0 Ignore Error
  1286. ;            = 1 Retry operation
  1287. ;            = 2 Abort program
  1288. ;            = 3 Fail system call
  1289. ;
  1290.  
  1291. I24_Errors    equ    $
  1292. I24_EC00:    db    'Write protect error$'
  1293. I24_EC01:    db    'Unknown unit$'
  1294. I24_EC02:    db    'Drive not ready$'
  1295. I24_EC03:    db    'Unknown command$'
  1296. I24_EC04:    db    'Data error$'
  1297. I24_EC05:    db    'Bad request$'
  1298. I24_EC06:    db    'Seek error$'
  1299. I24_EC07:    db    'Unknown media type$'
  1300. I24_EC08:    db    'Sector not found$'
  1301. I24_EC09:    db    'Paper out$'
  1302. I24_EC0A:    db    'Write fault$'
  1303. I24_EC0B:    db    'Read fault$'
  1304. I24_EC0C:    db    'General failure$'
  1305. I24_EC0D:    db    'Unknown code$'
  1306. I24_EC0F:    db    'Invalid disk change$'
  1307. I24_EC10:    db    'FCB unavailable$'
  1308. I24_EC11:    db    'Sharing buffer overflow$'
  1309.  
  1310. ;
  1311. ; Error message address table
  1312. ;
  1313.  
  1314. I24_ECTABLE:    dw    offset I24_EC00
  1315.         dw    offset I24_EC01
  1316.         dw    offset I24_EC02
  1317.         dw    offset I24_EC03
  1318.         dw    offset I24_EC04
  1319.         dw    offset I24_EC05
  1320.         dw    offset I24_EC06
  1321.         dw    offset I24_EC07
  1322.         dw    offset I24_EC08
  1323.         dw    offset I24_EC09
  1324.         dw    offset I24_EC0A
  1325.         dw    offset I24_EC0B
  1326.         dw    offset I24_EC0C
  1327.         dw    offset I24_EC0D
  1328.         dw    offset I24_EC0D        ; 0E - no message
  1329.         dw    offset I24_EC0F
  1330.         dw    offset I24_EC10
  1331.         dw    offset I24_EC11
  1332.  
  1333. I24_ECON:    db    ' when $'
  1334. I24_ECREAD:    db    'reading $'
  1335. I24_ECWRITE:    db    'writing $'
  1336. I24_ECDEVICE:    db    'device $'
  1337. I24_ECDISK:    db    'disk $'
  1338. I24_EABORT:    db    'Abort$'
  1339. I24_EFAIL:    db    ', Fail$'
  1340. I24_EIGNORE:    db    ', Ignore$'
  1341. I24_ERETRY:    db    ', Retry$'
  1342. I24_EDRIVE:    db    '?$'
  1343. I24_EQUESTION    db    '? $'
  1344. I24_RESPONSE:    db    ' '
  1345. I24_ENL:    db    0dH, 0aH, '$'
  1346. I24_EBELL:    db    07H, '$'
  1347. I24_EDNAME:    db    '12345678$'
  1348. I24_EXTECODE:    db    0dH, 0aH, '(Extended Code: '
  1349. I24_E_AL:    db    '  '
  1350.         db    ' Class: '
  1351. I24_E_BH:    db    '  '
  1352.         db    ' Action: '
  1353. I24_E_BL:    db    '  '
  1354.         db    ' Locus: '
  1355. I24_E_CH:    db    '  )', 0dH, 0aH, '$'
  1356.  
  1357. ;
  1358. ; Save DS, ES, BX, CX, DX
  1359. ;
  1360. _SW_Int24    proc    far
  1361.     push    ds        ; Save registers
  1362.     push    es
  1363.     push    bx
  1364.     push    cx
  1365.     push    dx
  1366.  
  1367.     push    cs        ; Set up data segment
  1368.     pop    ds
  1369.  
  1370.     mov    cx, ax        ; Save the error information in CX
  1371.  
  1372.     push    di
  1373.     mov    di, offset I24_ENL
  1374.     call    I24_Display
  1375.     pop    di
  1376.  
  1377. ;
  1378. ;  Check inside message range
  1379. ;
  1380.     cmp    di, 012H
  1381.     jb    SWI24a
  1382.     mov    di, 0dH
  1383.  
  1384. ;
  1385. ; Write the error message
  1386. ;
  1387.  
  1388. SWI24a:
  1389.     add    di, di
  1390.  
  1391.     mov    di, word ptr ds:I24_ECTABLE[di]
  1392.     call    I24_Display
  1393.  
  1394. ;
  1395. ; Output on message
  1396. ;
  1397.  
  1398.     mov    di, offset I24_ECON
  1399.     call    I24_Display
  1400.  
  1401. ;
  1402. ; Output reading or write message
  1403. ;
  1404.  
  1405.     mov    di, offset I24_ECWRITE
  1406.     test    ch, 01H
  1407.     jnz    SWI24b
  1408.     mov    di, offset I24_ECREAD
  1409.  
  1410. SWI24b:
  1411.     call    I24_Display
  1412.  
  1413. ;
  1414. ; Output device message
  1415. ;
  1416.  
  1417.     test    ch, 080H
  1418.     jz    SWI24c
  1419.  
  1420.     mov    di, offset I24_ECDEVICE
  1421.     call    I24_Display
  1422.  
  1423. ;
  1424. ; Output device name - up to eight characters
  1425. ;
  1426.  
  1427.     add    si, 0aH            ; Move to device name
  1428.     push    ds
  1429.     mov    ds, bp
  1430.     xor    di, di            ; Set counter
  1431.  
  1432. SWI24b1:
  1433.     mov    dl, byte ptr ds:[si]    ; Get next character in name
  1434.     cmp    dl, ' '
  1435.     jz    SWI24d
  1436.  
  1437.     mov    byte ptr cs:[I24_EDNAME + di], dl
  1438.  
  1439.     inc    si
  1440.     inc    di
  1441.     cmp    di, 8
  1442.     jnz    SWI24b1
  1443. ;
  1444. ; Append a $
  1445.  
  1446. SWI24d:
  1447.     pop    ds
  1448.     mov    byte ptr cs:[I24_EDNAME + di], '$'
  1449.     mov    di, offset I24_EDNAME
  1450.     jmp    SWI24e
  1451.  
  1452. ;
  1453. ; Write disk error
  1454. ;
  1455. SWI24c:
  1456.     mov    di, offset I24_ECDISK
  1457.     call    I24_Display
  1458.  
  1459.     mov    dl, cl
  1460.     add    dl, 'A'
  1461.     mov    byte ptr cs:I24_EDRIVE, dl
  1462.  
  1463.     mov    di, offset I24_EDRIVE
  1464. SWI24e:
  1465.     call    I24_Display
  1466.  
  1467. ;
  1468. ; Get extended error codes
  1469. ;
  1470.     push    cx
  1471.     push    ds
  1472.     mov    ah, 059H
  1473.     xor    bx, bx
  1474.     int    021H
  1475.  
  1476. ;
  1477. ; Save responses
  1478. ;
  1479.  
  1480.     mov    byte ptr cs:I24_E_AL, al
  1481.     mov    byte ptr cs:I24_E_BL, bl
  1482.     mov    byte ptr cs:I24_E_BH, bh
  1483.     mov    byte ptr cs:I24_E_CH, ch
  1484.     pop    ds
  1485.     pop    cx
  1486.  
  1487. ; Convert to display Hex.
  1488.  
  1489.     mov    di, offset I24_E_AL
  1490.     call    I24_Convert
  1491.     mov    di, offset I24_E_BL
  1492.     call    I24_Convert
  1493.     mov    di, offset I24_E_BH
  1494.     call    I24_Convert
  1495.     mov    di, offset I24_E_CH
  1496.     call    I24_Convert
  1497.     mov    di, offset I24_EXTECODE
  1498.     call    I24_Display
  1499. ;
  1500. ; Output Options 
  1501. ;
  1502.     mov    di, offset I24_EABORT
  1503.     call    I24_Display
  1504.  
  1505.     test    ch, 020H        ; Ignore allowed ?
  1506.     jz    SWI24f
  1507.     mov    di, offset I24_EIGNORE
  1508.     call    I24_Display
  1509.  
  1510. SWI24f:
  1511.     test    ch, 010H        ; Retry allowed ?
  1512.     jz    SWI24g
  1513.     mov    di, offset I24_ERETRY
  1514.     call    I24_Display
  1515.  
  1516. SWI24g:
  1517.     test    ch, 08H            ; Fail allowed ?
  1518.     jz    SWI24h
  1519.     mov    di, offset I24_EFAIL
  1520.     call    I24_Display
  1521.  
  1522. ;
  1523. ; Append a question mark.
  1524. ;
  1525.  
  1526. SWI24h:
  1527.     mov    di, offset I24_EQUESTION
  1528.     call    I24_Display
  1529.  
  1530. ;
  1531. ; Get the valid key codes
  1532. ;
  1533. SWI24j:
  1534.     xor    ax, ax            ; Read a keyboard character
  1535.     int    16H
  1536.     and    al, 05fH        ; Upper case
  1537.  
  1538.     xor    ah, ah            ; Clear counter
  1539.     cmp    al, 'I'            ; Ignore ?
  1540.     jnz    SWI24k
  1541.     test    ch, 020H
  1542.     jnz    SWI24n
  1543. SWI24k:
  1544.     inc    ah
  1545.     cmp    al, 'R'            ; Retry ?
  1546.     jnz    SWI24l
  1547.     test    ch, 010H
  1548.     jnz    SWI24n
  1549. SWI24l:
  1550.     inc    ah
  1551.     cmp    al, 'A'            ; Abort ?
  1552.     jz    SWI24n
  1553.  
  1554.     inc    ah
  1555.     cmp    al, 'F'            ; Fail ?
  1556.     jnz    SWI24m
  1557.     test    ch, 08H
  1558.     jnz    SWI24n
  1559. SWI24m:
  1560.     mov    di, offset I24_EBELL
  1561.     call    I24_Display
  1562.     jmp    SWI24j
  1563.  
  1564. ;
  1565. ; OK - got code
  1566. ;
  1567. SWI24n:
  1568.     mov    cl, ah
  1569.     mov    byte ptr ds:I24_RESPONSE, al
  1570.     mov    di, offset I24_RESPONSE
  1571.     call    I24_Display
  1572.     mov    ax, cx
  1573.  
  1574. ;
  1575. ; Are we in the shell ?
  1576. ;
  1577.     cmp    byte ptr cs:InShell, 0    ; Are we in the shell ? 
  1578.     jnz    $SW_int24a        ; No - no processing
  1579.  
  1580.     cmp    al, 02H            ; Abort?
  1581.     jnz    $SW_int24a        ; No - exit
  1582.  
  1583.     test    ah, 008h        ; If fail allowed - convert to fail
  1584.     jz    $SW_int24a
  1585.  
  1586.     mov    al, 003h        ; Fail system call
  1587.  
  1588. $SW_int24a:
  1589.     pop    dx            ; Restore registers
  1590.     pop    cx
  1591.     pop    bx
  1592.     pop    es
  1593.     pop    ds        
  1594.     iret
  1595. _SW_Int24    endp
  1596.  
  1597. ;
  1598. ; Convert Hex code to display code
  1599. ;
  1600. ; ds:di Offset of code to replace
  1601. ; ax is available
  1602. ;
  1603. I24_Convert    proc    near
  1604.     push    cx
  1605.     mov    al, byte ptr ds:[di]    ; Get the code
  1606.     mov    ah, al
  1607.     mov    cl, 4
  1608.     shr    ah, cl
  1609.     and    ah, 0fh
  1610.  
  1611.     cmp    ah, 10
  1612.     jb    I24_C1
  1613.     add    ah, 'A' - 10
  1614.     jmp    I24_C2
  1615. I24_C1:
  1616.     add    ah, '0'
  1617. I24_C2:
  1618.     mov    byte ptr ds:[di], ah
  1619.  
  1620. ; Now LSB
  1621.  
  1622.     and    al, 0fh
  1623.     cmp    al, 10
  1624.     jb    I24_C3
  1625.     add    al, 'A' - 10
  1626.     jmp    I24_C4
  1627. I24_C3:
  1628.     add    al, '0'
  1629. I24_C4:
  1630.     mov    byte ptr ds:[di + 1], al
  1631.     pop    cx
  1632.     ret
  1633. I24_Convert    endp
  1634. ;
  1635. ;  Display message function for Interrupt 24 processing
  1636. ;
  1637. ;  DS:DI message
  1638. ;  AX is available
  1639. ;
  1640.  
  1641. I24_Display    proc    near
  1642.     mov    ah, 08H            ; Get foreground colour
  1643.     xor    bx, bx
  1644.     int    10H
  1645.     mov    bl, ah
  1646.     and    bl, 07h
  1647.  
  1648. ;
  1649. ; Loop until a $ is hit, outputting the characters
  1650. ;
  1651. I24D:
  1652.     mov    al, byte ptr ds:[di]
  1653.     cmp    al, '$'
  1654.     jnz    I24Da
  1655.     ret
  1656.  
  1657. I24Da:
  1658.     push    di
  1659.     mov    ah, 0EH
  1660.     int    10H
  1661.     pop    di
  1662.     inc    di
  1663.     jmp    I24D
  1664.  
  1665. I24_Display    endp
  1666.  
  1667. ;
  1668. ;  Start of overwrite area for environment.  Align on a paragraph
  1669. ;
  1670. ;  Also the XMS driver functions used by SH3.C live here
  1671. ;
  1672.         ALIGN    16
  1673. Env_OWrite:
  1674.  
  1675. ;
  1676. ; XMS INTERFACE
  1677. ;
  1678. ; Get Version number.  Return the release number in AX
  1679. ;
  1680.  
  1681. _SW_XMS_Gversion    proc    far
  1682.  
  1683.     push    bp            ; Save stack info
  1684.     mov    bp, sp
  1685.  
  1686.     xor    ax, ax
  1687.     call    cs:[_SW_XMS_Driver]
  1688.  
  1689.     mov    sp, bp
  1690.     pop    bp
  1691.     ret
  1692.  
  1693. _SW_XMS_Gversion    endp
  1694.  
  1695. ;
  1696. ; Allocate N kbytes.  Return the Handler in AX or -1 and error code in
  1697. ; errno.
  1698. ;
  1699. ; Size will be in bp + 6.
  1700. ;
  1701.  
  1702. _SW_XMS_Allocate    proc    far
  1703.  
  1704.     push    bp            ; Save stack info
  1705.     mov    bp, sp
  1706.  
  1707.     mov    dx, word ptr ss:[bp + 6]
  1708.     mov    ah, 09H
  1709.     call    cs:[_SW_XMS_Driver]
  1710.     or    ax, ax
  1711.     jnz    $SW_A1
  1712.  
  1713. ;
  1714. ; Allocate Failed - return error code
  1715. ;
  1716.     xor    ax, ax
  1717.     neg    ax
  1718.     xor    bh, bh
  1719.     mov    word ptr ds:_errno, bx    ; Save error code
  1720.     jmp    $SW_F2
  1721.  
  1722. ;
  1723. ; Allocate OK - return handler
  1724. ;
  1725.  
  1726. $SW_A1:
  1727.     mov    ax, dx
  1728.  
  1729. $SW_A2:
  1730.     mov    sp, bp
  1731.     pop    bp
  1732.     ret
  1733.  
  1734. _SW_XMS_Allocate    endp
  1735.  
  1736. ;
  1737. ; Release handler.  Return 0 or error code.
  1738. ;
  1739. ; Handler will be in bp + 6.
  1740. ;
  1741.  
  1742. _SW_XMS_Free         proc    far
  1743.  
  1744.     push    bp            ; Save stack info
  1745.     mov    bp, sp
  1746.  
  1747.     mov    dx, word ptr ss:[bp + 6]
  1748.     mov    ah, 0AH
  1749.     call    cs:[_SW_XMS_Driver]
  1750.     or    ax, ax
  1751.     jnz    $SW_F1
  1752. ;
  1753. ; Free Failed - return error code
  1754. ;
  1755.     mov    al, bl
  1756.     jmp    $SW_F2
  1757.  
  1758. ;
  1759. ; Free OK - return zero
  1760. ;
  1761. $SW_F1:
  1762.     xor    ax, ax
  1763.  
  1764. $SW_F2:
  1765.     mov    sp, bp
  1766.     pop    bp
  1767.     ret
  1768.  
  1769. _SW_XMS_Free         endp
  1770. SH0_TEXT    ends
  1771.         end
  1772.