home *** CD-ROM | disk | FTP | other *** search
/ Stars of Shareware: Programmierung / SOURCE.mdf / programm / msdos / asm / superspy / superspy.asm < prev    next >
Encoding:
Assembly Source File  |  1990-05-12  |  61.8 KB  |  1,197 lines

  1. CSEG               SEGMENT
  2.                    ORG    0100h
  3. MAIN               PROC   NEAR
  4.                    JMP    BEGIN
  5. ADDR_6845          DW     ?              ;Use for retrace check
  6. ATTR               DB     0              ;Current screen attribute
  7. BAD_DOS            DB     'Requires DOS 2.0 or above$'
  8. CUR_PAGE           DB     0
  9. CURSOR_HOLD        DW     0
  10. DELIMIT            DB     9,' ,;=/'      ;Delimiters in parameter
  11. BUFF_PT            DW     ?              ;Points within buffer
  12. FILE_OFFS          DW     -1, -1         ;Address within file of buff data
  13. FHANDLE            DW     ?              ;File handle
  14. FILE_NOT_F         DB     'File Not Found$'
  15. HORIZ_OFFS         DW     0              ;Horizontal offset for display
  16. HORIZ_SHFT         DB     8              ;Horizontal shift screen default
  17. COLS               DB     80             ;Length of line (from BIOS)
  18. ROWS               DB     25,0           ;Number of lines (check EGA BIOS)
  19. MSG                DB     10,13,'Thank You. SUPERSPY Ver. 2.00. Copr. '
  20.                    DB     '1989, 1990  Robert Wallingford, P.E.',10,13,'$'
  21. N_F_MSG            DB     '          Please type in the name of the '
  22.                    DB     'New File that',10,13,'          you want to '
  23.                    DB     'look into. Include its path',10,13,'          '
  24.                    DB     'if it is different than your present',10,13
  25.                    DB     '          directory.',10,13,10,13,10,13,'$'
  26. N_ENF_MEM          DB     'Not enough memory$'
  27. NON_W_S            DB     0FFh           ;AND value for non-WordStar mode
  28. RET_CHECK          DB     1              ;Flag zero if EGA or MONO used
  29. RGT_MRGN           DW     0              ;Right margin for offset display
  30. SCRN_PT            DW     ?              ;Points within buffer
  31. SCRN_OFFS          DW     0              ;Higher for non-page 0
  32. SCRN_SEG           DW     0B800h         ;Set to B000h for Mono Mode 7
  33. SEND               DW     HOME, UP, PG_UP, DUMMY, LEFT
  34.                    DW     DUMMY, RIGHT, DUMMY, ENDD, DOWN, PG_DN
  35. SCRN_SIZE          DW     ?              ;Size of screen in bytes
  36. UN_VID_M           DB     'Unsupported video mode$'
  37. BIOS_SEG           EQU    0040h          ;bios segment
  38. CURSOR_POSN        DW     ?
  39. ACTIVE_PAGE        DB     ?
  40. ERR_STAT           DB     ?              ;error status during file output
  41. FILE_PROMPT        DB     'Enter Filename: '
  42. FILENAME           DB     'CLIP.WWW'     ;the default filename
  43.                    DB     17 DUP (0)     ;leave room for drive and path
  44. NAME_BUFF          DW     42 DUP (0)     ;filename buffer
  45. BUFF_NEXT          DW     ?              ;pointer to next key in buffer
  46. BUFF_LAST          DW     ?              ;pointer to last key in buffer
  47. BUFFER_ST          DW     ?              ;offset buffer_st
  48. BUFF_SIZE          DW     2050           ;room for 25 rows of 80 columns
  49. BUFF_END           DW     ?              ;buffer_st+buff_size
  50. TOP_LEFT           LABEL  WORD           ;first corner of window
  51. LEFT_SIDE          DB     0              ;column number of left side
  52. TOP_ROW            DB     0              ;row number of top side
  53. BOT_RIGHT          LABEL  WORD           ;second corner of window
  54. RIGHT_SIDE         DB     ?              ;column number or right side
  55. BOT_ROW            DB     ?              ;Row number of bottom
  56. SEND_CHAR          DW     ?              ;Pointer to character handler
  57. WRIT_FILE          DB     0              ;if=1, need to write to disk
  58. HELP_MENU          DB     201,10 DUP(205),187
  59.                    DB     186,'ESC- quit ',186
  60.                    DB     186,' F - file ',186
  61.                    DB     186,' P - print',186
  62.                    DB     200,10 DUP(205),188
  63. HELP_DOC           DB     'SUPERSPY.DOC',0D
  64. ENVIRONMENT        EQU    002Ch          ;Offset of Environment
  65. NEWPARAMETER       EQU    007B           ;Parameter for COMMAND.COM
  66. MEMALLOCMSG        DB     'Memory Problem$'
  67. COMMANDMSG         DB     'COMMAND Problem$'
  68. COMSPEC            DB     'COMSPEC='     ;Search string in environment
  69. COMMANDASCIIZ1     DW     ?              ;Pointer to COMMAND address
  70. COMMANDASCIIZ2     DW     ?              ;Pointer to COMMAND segment
  71. PARAMBLOCK         DW     ?              ;Parameter Block for EXEC
  72.                    DW     007Bh,?        ;First ? must be replaced
  73.                    DW     005Ch,?        ;with Environment segment
  74.                    DW     006Ch,?        ;others with this segment
  75. CHAR_COUNT         DB     0              ;Char count in path
  76. LAST_CHAR_COUNT    DB     0              ;Last value
  77. DIR_FLAG           DB     0              ;Flag special dir
  78. A_D_MSG            DB     0Ah,0Dh,'  If you want another directory '
  79.                    DB     'type in its path and press ENTER.',0Ah,0Dh,'$'
  80. WRAP_FLAG          DB     00             ;For wrap around mode
  81.                    NOP
  82.                    NOP
  83. BEGIN:             MOV    BX,OFFSET BUFF
  84.                    ADD    BX,8934h
  85.                    ADD    BX,5070h       ;New end of program
  86.                    MOV    SP,BX          ;Set the stack pointer
  87.                    ADD    BX,15          ;Add 15 for rounding
  88.                    MOV    CL,4           ;Number of shifts
  89.                    SHR    BX,CL          ;Convert AX to segment
  90.                    MOV    AH,4AH         ;DOS call to shrink down
  91.                    INT    21H            ;allocated memory
  92.                    MOV    DX,OFFSET MEMALLOCMSG    ;Possible error message
  93.                    JNC    NO_ERR_1       ;Only print it if Carry set
  94.                    MOV    AH,9
  95.                    INT    21h
  96.                    INT    20h
  97. NO_ERR_1:          CALL   SET_IT_UP      ;Initialize everything
  98.                    CALL   GET_NAME
  99.                    CALL   KEYS
  100.                    INT    20h
  101.                    RET
  102. MAIN               ENDP
  103. NEWINT24           PROC   NEAR
  104.                    STI                   ;turn interrupts back on
  105.                    INC    ERR_STAT       ;set the error flag
  106.                    XOR    AL,AL          ;tells dos to ignore the error
  107.                    IRET                  ;thats all we do here
  108. NEWINT24           ENDP
  109. WRITE_TO_FILE      PROC   NEAR
  110.                    MOV    WRIT_FILE,00h  ;turn off request flag
  111.                    PUSH   AX             ;must preserve all registers
  112.                    PUSH   BX
  113.                    PUSH   CX
  114.                    PUSH   DX
  115.                    PUSH   DS
  116.                    PUSH   ES
  117.                    PUSH   CS
  118.                    POP    DS
  119.                    MOV    AX,3524h       ;get dos critical error vector
  120.                    INT    21h            ;dos function to get vector
  121.                    PUSH   BX             ;save old vector on stack
  122.                    PUSH   ES
  123.                    MOV    DX,OFFSET NEWINT24
  124.                    MOV    AX,2524h       ;setup to change int 24h vector
  125.                    INT    21h            ;change dos severe error vector
  126.                    MOV    DX,OFFSET FILENAME  ;point to filename
  127.                    MOV    AX,3D02h       ;dos function to open file
  128.                    INT    21h            ;dos will return with carry flag
  129.                    JB     FILE_NOT_FND   ;set if file doesn't exist.
  130.                    MOV    BX,AX          ;keep handle in bx also
  131.                    XOR    CX,CX          ;move dos file pointer to the
  132.                    XOR    DX,DX          ;end of the file. This lets us
  133.                    MOV    AX,4202h       ;append this to an existing file
  134.                    INT    21h            ;dos function to move pointer
  135.                    JNB    WRITE_FILE     ;if no error, continue to write
  136. DOS_ERROR:         CMP    ERR_STAT,00h   ;did a severe error occur?
  137.                    JNZ    REP_VECTOR     ;if severe error, just quit
  138.                    JMP    CLOSE_FILE     ;just close the file
  139. FILE_NOT_FND:      CMP    ERR_STAT,00h   ;did a severe error occur?
  140.                    JNZ    REP_VECTOR     ;if severe error, just quit
  141.                    MOV    CX,0020h       ;attribute for new file
  142.                    MOV    AH,3Ch         ;create file for writing
  143.                    INT    21h            ;dos function to create file
  144.                    JB     DOS_ERROR      ;on any error, take jump
  145.                    MOV    BX,AX          ;save handle in bx
  146. WRITE_FILE:        MOV    DX,BUFFER_ST   ;point to buffer
  147.                    MOV    CX,BUFF_LAST   ;get buffer pointer
  148.                    SUB    CX,DX          ;number of chars in buffer
  149.                    MOV    AH,40h         ;dos write to a device function
  150.                    INT    21h            ;write to the file
  151. CLOSE_FILE:        MOV    AH,3Eh         ;dos function to close the file
  152.                    INT    21h            ;get int 24h vector from stack
  153. REP_VECTOR:        POP    DS
  154.                    POP    DX
  155.                    MOV    AX,2524h       ;restore critical error vector
  156.                    INT    21h            ;dos function to change vector
  157.                    POP    ES             ;finally restore all registers
  158.                    POP    DS
  159.                    POP    DX
  160.                    POP    CX
  161.                    POP    BX
  162.                    POP    AX
  163.                    RET                   ;finished writing to disk
  164. WRITE_TO_FILE      ENDP
  165. CLIP               PROC   NEAR
  166.                    STI                   ;allow other interrupts
  167.                    PUSH   CS
  168.                    POP    DS             ;set ds to cseg
  169.                    CALL   GET_CURS_ADDR  ;cursor address for this page
  170.                    PUSH   [BX]           ;save the cursor location
  171.                    XOR    BX,BX          ;bx is increment for row/column
  172. GET_KB_KEY1:       MOV    DX,TOP_LEFT    ;get location of first corner
  173.                    ADD    DH,BH          ;add in the row increment
  174.                    ADD    DL,BL          ;add in the column increment
  175.                    CMP    DL,00h         ;at left edge of screen?
  176.                    JGE    NOT_LEFT_EDGE
  177.                    MOV    DL,COLS        ;jump to the right edge
  178.                    DEC    DL
  179. NOT_LEFT_EDGE:     CMP    DL,COLS        ;at right edge of screen yet?
  180.                    JB     NOT_RGT_EDGE   ;if not, keep moving right
  181.                    XOR    DL,DL          ;if yes, wrap to left edge
  182. NOT_RGT_EDGE:      CMP    DH,00h         ;at top of screen yet?
  183.                    JGE    NOT_AT_TOP
  184.                    MOV    DH,ROWS        ;jump down to the bottom
  185.                    DEC    DH             ;rows start at 0
  186. NOT_AT_TOP:        CMP    DH,ROWS        ;at bottom of screen?
  187.                    JL     NOT_AT_BOTTOM
  188.                    XOR    DH,DH          ;jump back to the top
  189. NOT_AT_BOTTOM:     MOV    TOP_LEFT,DX    ;save new corner location
  190.                    CALL   REV_VIDEO      ;change it to reverse video
  191.                    XOR    AH,AH          ;bios keyboard input
  192.                    INT    16h            ;get a keystroke
  193.                    PUSH   AX
  194.                    CALL   REV_VIDEO      ;put attribute back to normal
  195.                    POP    AX
  196.                    CMP    AH,01h         ;is it escape?
  197.                    JNZ    NOT_ESC
  198.                    CALL   GET_CURS_ADDR  ;cursor address for this page
  199.                    POP    [BX]           ;get back cursor  position
  200.                    RET                   ;just return to exit
  201. NOT_ESC:           MOV    BX,0FF00h      ;increment to subtract one row
  202.                    CMP    AH,48h         ;is it up arrow?
  203.                    JZ     GET_KB_KEY1
  204.                    MOV    BX,0100h       ;increment to add one row
  205.                    CMP    AH,50h         ;is it down arrow?
  206.                    JZ     GET_KB_KEY1
  207.                    MOV    BX,0001h       ;increment to add one column
  208.                    CMP    AH,4Dh         ;is it right arrow?
  209.                    JZ     GET_KB_KEY1
  210.                    MOV    BX,00FFh       ;increment to subtract one col.
  211.                    CMP    AH,4Bh         ;is it left arrow?
  212.                    JZ     GET_KB_KEY1
  213.                    XOR    BX,BX
  214.                    CMP    AL,0Dh         ;is it a carriage return?
  215.                    JNZ    GET_KB_KEY1
  216.                    MOV    DX,TOP_LEFT    ;a carriage return was pressed
  217.                    MOV    BOT_RIGHT,DX   ;initialize the second corner
  218.                    CALL   REV_VIDEO      ;change it back to reverse video
  219. GET_KB_KEY2:       XOR    AH,AH
  220.                    INT    16h            ;get a keystroke
  221. GOT_KEY2:          MOV    DX,BOT_RIGHT
  222.                    CMP    AH,48h         ;is it up arrow?
  223.                    JZ     SUB_ROW        ;subtract a row from window
  224.                    CMP    AH,50h         ;is it down arrow?
  225.                    JZ     ADD_ROW        ;add a row to the window
  226.                    CMP    AH,4Dh         ;is it right arrow?
  227.                    JZ     ADD_COL        ;add a column to the window
  228.                    CMP    AH,4Bh         ;is it left arrow?
  229.                    JZ     SUB_COL        ;subtract a column from window
  230.                    JMP    NOT_ARROW_KEY
  231. SUB_COL:           DEC    DL             ;subtract a column
  232.                    CMP    DL,LEFT_SIDE   ;don't erase it completely
  233.                    JL     GET_KB_KEY2
  234.                    MOV    RIGHT_SIDE,DL  ;save new right side column
  235.                    INC    DL
  236.                    JMP    COL_LOOP
  237. ADD_COL:           INC    DL             ;add a column
  238.                    CMP    DL,COLS        ;at right edge of screen?
  239.                    JNB    GET_KB_KEY2    ;stop when screen is filled
  240.                    MOV    RIGHT_SIDE,DL  ;save new right side column
  241. COL_LOOP:          CALL   REV_VIDEO      ;reverse this character
  242.                    DEC    DH             ;move to next row
  243.                    CMP    DH,TOP_ROW     ;at top row yet?
  244.                    JGE    COL_LOOP       ;loop until at top row
  245.                    JMP    GET_KB_KEY2
  246. SUB_ROW:           DEC    DH
  247.                    CMP    DH,TOP_ROW     ;at top of window?
  248.                    JL     GET_KB_KEY2    ;dont erase it completely
  249.                    MOV    BOT_ROW,DH
  250.                    INC    DH
  251.                    JMP    ROW_LOOP
  252. ADD_ROW:           INC    DH
  253.                    CMP    DH,ROWS        ;at bottom of screen?
  254.                    JGE    GET_KB_KEY2    ;stop when screen is filled
  255.                    MOV    BOT_ROW,DH
  256. ROW_LOOP:          CALL   REV_VIDEO      ;reverse this character
  257.                    DEC    DL             ;move to next column
  258.                    CMP    DL,LEFT_SIDE   ;at left edge yet?
  259.                    JGE    ROW_LOOP       ;continue until at left edge
  260.                    JMP    GET_KB_KEY2
  261. NOT_ARROW_KEY:     CMP    AH,19h         ;was it the "p" key?
  262.                    JNZ    NOT_P
  263.                    MOV    SEND_CHAR,OFFSET PRINT_CHAR
  264.                    CALL   READ_WINDOW
  265.                    CALL   GET_CURS_ADDR  ;cursor address for this page
  266.                    POP    [BX]           ;get back cursor  position
  267.                    RET
  268. NOT_P:             PUSH   AX
  269.                    MOV    AX,BUFFER_ST   ;initialize buffer
  270.                    MOV    BUFF_NEXT,AX
  271.                    MOV    BUFF_LAST,AX
  272.                    POP    AX
  273.                    MOV    SEND_CHAR,OFFSET BUFF_CHAR
  274.                    CMP    AH,21h         ;is it the "f" key
  275.                    JNZ    NOT_F
  276.                    MOV    WRIT_FILE,00h
  277.                    CALL   GET_FILENAME
  278.                    CMP    WRIT_FILE,0FFh ;was escape requested?
  279.                    JZ     ERASE_BOX
  280.                    CALL   READ_WINDOW    ;read it now
  281.                    MOV    WRIT_FILE,01h
  282.                    CALL   WRITE_TO_FILE  ;write it now
  283. RETURN:            CALL   GET_CURS_ADDR  ;cursor address for this page
  284.                    POP    [BX]           ;get back cursor  position
  285.                    RET
  286. NOT_F:             CMP    AH,01h         ;is it escape?
  287.                    JZ     ERASE_BOX      ;if yes, erase box and exit
  288.                    CMP    AL,0Dh         ;is it a carriage return?
  289.                    JZ     DISPLAY_HELP   ;if yes, display help
  290.                    JMP    GET_KB_KEY2    ;otherwise just get another key
  291. ERASE_BOX:         MOV    SEND_CHAR,OFFSET RETURN
  292.                    CALL   READ_WINDOW
  293.                    CALL   GET_CURS_ADDR  ;cursor address for this page
  294.                    POP    [BX]           ;get back cursor  position
  295.                    RET    
  296. DISPLAY_HELP:      CALL   EXCHANGE_HELP  ;put up the help menu
  297.                    XOR    AH,AH
  298.                    INT    16h            ;get another keystroke
  299.                    PUSH   AX             ;save the keystroke
  300.                    CALL   EXCHANGE_HELP  ;pull down the help menu
  301.                    POP    AX             ;get back the keystroke
  302.                    JMP    GOT_KEY2
  303. REV_VIDEO:         CALL   READ_CHAR      ;read character and attribute
  304.                    MOV    CL,04h         ;rotate four counts
  305.                    MOV    BL,AH          ;save attribute in bl
  306.                    AND    BL,88h         ;get blink and intensity bits
  307.                    AND    AH,77h         ;now look only at color bits
  308.                    ROR    AH,CL          ;rotate foreground and background
  309.                    OR     BL,AH          ;put back blink and intensity bits
  310.                    CALL   DISPLAY_CHAR   ;write character and attribute
  311.                    RET
  312. READ_WINDOW:       MOV    DX,TOP_LEFT    ;get location of first corner
  313. READ_LOOP:         CALL   REV_VIDEO      ;put attribute back to normal
  314.                    CALL   READ_CHAR      ;read the character
  315.                    CALL   SEND_CHAR      ;call to the pointer
  316.                    INC    DL             ;next char in row
  317.                    CMP    DL,RIGHT_SIDE  ;at the right border yet?
  318.                    JLE    READ_LOOP      ;do all characters in this row
  319.                    CALL   CR_LF          ;send cr-lf after each row
  320.                    INC    DH             ;move to next row
  321.                    MOV    DL,LEFT_SIDE   ;back to left edge
  322.                    CMP    DH,BOT_ROW     ;at the bottom border yet?
  323.                    JLE    READ_LOOP      ;read entire window
  324.                    RET
  325. CR_LF:             MOV    AL,0Dh
  326.                    CALL   SEND_CHAR      ;send a carriage return
  327.                    MOV    AL,0Ah
  328.                    CALL   SEND_CHAR      ;send a line feed
  329.                    RET
  330. DISPLAY_CHAR:      PUSH   BX             ;save the attribute
  331.                    CALL   GET_CURS_ADDR  ;get address of bios cursor
  332.                    MOV    [BX],DX        ;tell bios where the cursor is
  333.                    POP    BX             ;get back the attribute
  334.                    MOV    BH,ACTIVE_PAGE ;get active page
  335.                    PUSH   CX             ;save the loop count
  336.                    PUSH   AX             ;int10h fun02 changes AX
  337.                    MOV    AH,02h         ;set cursor position
  338.                    INT    10h
  339.                    POP    AX             ;get AX back
  340.                    MOV    CX,0001h       ;write 1 character
  341.                    MOV    AH,09h         ;write character and attribute
  342.                    INT    10h
  343.                    POP    CX             ;recover loop count
  344.                    RET                   ;done writing the character
  345. READ_CHAR:         CALL   GET_CURS_ADDR  ;get address of bios cursor
  346.                    MOV    [BX],DX        ;tell bios where the cursor is
  347.                    MOV    BH,ACTIVE_PAGE ;get active page
  348.                    MOV    AH,02h         ;set cursor position
  349.                    INT    10h
  350.                    MOV    AH,08h         ;bios function to read character
  351.                    INT    10h            ;read the character/attribute
  352.                    RET
  353. PRINT_CHAR:        PUSH   DX
  354.                    XOR    AH,AH          ;use function 0
  355.                    XOR    DX,DX          ;printer number 0
  356.                    INT    17h            ;bios print character function
  357.                    ROR    AH,1h          ;look at bit zero
  358.                    JNB    PRINT_OK       ;did a timeout occur?
  359.                    MOV    SEND_CHAR,OFFSET RETURN
  360. PRINT_OK:          POP    DX
  361.                    RET                   ;done printing character
  362. BUFF_CHAR:         MOV    BX,BUFF_LAST   ;get location of last character
  363.                    MOV    [BX],AL        ;put the character in buffer
  364.                    INC    BX             ;advance the pointer
  365.                    MOV    BUFF_LAST,BX   ;check for buffer full
  366.                    CMP    BX,BUFF_END    ;is the buffer full yet?
  367.                    JNZ    BUFF_OK        ;if not, keep going
  368.                    MOV    SEND_CHAR,OFFSET RETURN
  369. BUFF_OK:           RET                   ;now its in the buffer
  370. GET_CURS_ADDR:     MOV    BL,ACTIVE_PAGE ;get the current page number
  371.                    XOR    BH,BH          ;convert to a word offset
  372.                    SHL    BX,01h         ;times two for a word
  373.                    ADD    BX,OFFSET CURSOR_POSN    ;add in base address
  374.                    RET
  375. EXCHANGE_HELP:     XOR    DX,DX          ;start at top left corner
  376.                    LEA    SI,HELP_MENU
  377. EXCHANGE_LOOP:     CMP    DL,0Ch         ;at last col. in this row yet?
  378.                    JL     SWAP_CHAR
  379.                    XOR    DL,DL          ;back to first column
  380.                    INC    DH             ;do the next row
  381.                    CMP    DH,05h         ;at last row yet?
  382.                    JL     SWAP_CHAR      ;quit when last row is done
  383.                    RET
  384. SWAP_CHAR:         CALL   READ_CHAR      ;read character at this position
  385.                    XCHG   AL,CS:[SI]     ;swap with the help text
  386.                    MOV    BL,AH          ;attribute is the same
  387.                    CALL   DISPLAY_CHAR   ;put new character on screen
  388.                    INC    DL             ;point to next position
  389.                    INC    SI
  390.                    JMP    EXCHANGE_LOOP
  391. GET_FILENAME:      LEA    SI,FILE_PROMPT ;point to the prompt for source
  392.                    MOV    DX,OFFSET NAME_BUFF ;use buffer for name change
  393.                    MOV    DI,DX          ;set DI to buffer
  394.                    XOR    DX,DX          ;put prompt at top left corner
  395.                    MOV    CX,40          ;use max of 40 characters
  396. DISPLAY_PMPT:      PUSH   CX             ;save loop count
  397.                    CALL   READ_CHAR      ;get character on this line
  398.                    MOV    CS:[DI],AX     ;store it in the buffer
  399.                    INC    DI             ;add two for next character
  400.                    INC    DI
  401.                    MOV    AL,CS:[SI]     ;get next prompt character
  402.                    INC    SI             ;next character in prompt
  403.                    MOV    BL,47h         ;attribute for prompt
  404.                    CALL   DISPLAY_CHAR   ;put up the prompt character
  405.                    INC    DL             ;point to next column
  406.                    POP    CX             ;get back loop count
  407.                    LOOP   DISPLAY_PMPT   ;entire prompt and filename
  408.                    DEC    SI
  409.                    DEC    DL
  410. FIND_LAST_LTR:     DEC    SI             ;backup to last letter
  411.                    DEC    DL             ;backup to last column
  412.                    CMP    B[SI],00h      ;is this a letter?
  413.                    JZ     FIND_LAST_LTR  ;backup until a letter is found
  414.                    INC    DL             ;put blinking box at last letter
  415. READ_KB:           MOV    AL,0DBh        ;ascii for box character
  416.                    MOV    BL,0C7h        ;make it a blinking box character
  417.                    CALL   DISPLAY_CHAR   ;write the blinking box
  418.                    XOR    AH,AH          ;function 0 to get next key
  419.                    INT    16h            ;bios keyboard input
  420.                    CMP    AL,0Dh         ;is it a carriage return?
  421.                    JZ     ERASE_PROMPT
  422.                    CMP    AL,08h         ;is it a backspace?
  423.                    JZ     BACK_SPACE
  424.                    CMP    AH,01h         ;is it escape?
  425.                    JZ     ESC_RET
  426.                    CMP    AL,2Eh         ;Is it a valid letter?
  427.                    JL     READ_KB
  428.                    CMP    AL,7Ah         ;is it a valid letter?
  429.                    JG     READ_KB
  430.                    CMP    DL,27h         ;only allow 40 characters
  431.                    JGE    READ_KB
  432. TTY_KEY:           MOV    BL,47h         ;attribute for filename
  433.                    CALL   DISPLAY_CHAR   ;write the letter
  434.                    INC    DL             ;move to next column
  435.                    JMP    READ_KB        ;get another keystroke
  436. BACK_SPACE:        CMP    DL,10h         ;at beginning of line?
  437.                    JLE    READ_KB        ;if yes, can't backup from here
  438.                    MOV    AL,00h         ;write a normal blank (ascii 0)
  439.                    MOV    BL,47h         ;attribute for filename
  440.                    CALL   DISPLAY_CHAR   ;write the letter
  441.                    DEC    DL             ;backup the cursor
  442.                    JMP    READ_KB        ;then get the next key
  443. ESC_RET:           MOV    WRIT_FILE,0FFh ;indicate escape is requested
  444. ERASE_PROMPT:      XOR    AL,AL          ;get rid of the cursor
  445.                    CALL   DISPLAY_CHAR   ;write the letter
  446.                    LEA    DI,FILE_PROMPT ;copy to filename
  447.                    MOV    DX,OFFSET NAME_BUFF ;copy from buffer
  448.                    MOV    SI,DX          ;set SI to buffer
  449.                    XOR    DX,DX          ;prompt is at row zero
  450.                    MOV    CX,40          ;copy all 40 characters
  451. ERASE_LOOP:        CALL   READ_CHAR      ;get character on this line
  452.                    MOV    CS:[DI],AL     ;put in back in memory
  453.                    INC    DI
  454.                    MOV    AX,CS:[SI]     ;get the original character back
  455.                    MOV    BL,AH          ;put attribute into bl
  456.                    INC    SI
  457.                    INC    SI
  458.                    CALL   DISPLAY_CHAR   ;write original character
  459.                    INC    DL             ;move to next column
  460.                    LOOP   ERASE_LOOP     ;erase the entire prompt
  461.                    RET
  462. CLIP               ENDP
  463. SET_IT_UP          PROC   NEAR
  464.                    CLD                   ;String directions forward
  465.                    MOV    AH,30h         ;Get DOS Version Number
  466.                    INT    21h            ;DOS call
  467.                    CMP    AL,2           ;Check for 2.0 +
  468.                    JAE    DOS_OK
  469.                    MOV    DX,OFFSET BAD_DOS
  470.                    MOV    AH,9           ;Write message
  471.                    INT    21h            ;DOS call
  472.                    INT    20h            ;Exit
  473. DOS_OK:            PUSH   ES             ;Save register
  474.                    SUB    AX,AX
  475.                    MOV    ES,AX          ;Set ES to 0 (BIOS Data)
  476.                    MOV    AL,ES:[0449h]  ;Current Video Mode
  477.                    CMP    AL,3           ;Check if Color Alpha
  478.                    JBE    DISP_OK        ;Continue if so
  479.                    CMP    AL,7           ;Check if monochrome display
  480.                    JE     MONO           ;If so, branch
  481.                    MOV    DX,OFFSET UN_VID_M  ;Can't handle graphics
  482.                    MOV    AH,9           ;Write message
  483.                    INT    21h            ;DOS call
  484.                    INT    20h            ;Exit
  485. MONO:              MOV    SCRN_SEG,0B000h     ;Use Monochrome Segment
  486.                    MOV    RET_CHECK,0    ;Don't check retrace
  487. DISP_OK:           MOV    AL,ES:[044Ah]  ;Number of Columns
  488.                    MOV    COLS,AL        ;Save it
  489.                    MOV    AX,ES:[044Eh]  ;Offset to screen buffer
  490.                    MOV    SCRN_OFFS,AX   ;Save it
  491.                    MOV    AX,ES:[0463h]  ;Address of 6845 Regsiter
  492.                    MOV    ADDR_6845,AX   ;Save it
  493.                    PUSH   ES
  494.                    SUB    DL,DL          ;Set Rows to zero first
  495.                    SUB    BH,BH
  496.                    MOV    AX,1130h       ;EGA BIOS: Get Information
  497.                    INT    10h
  498.                    POP    ES
  499.                    OR     DL,DL          ;Check if DL is still zero
  500.                    JZ     NO_EGA         ;If so, skip
  501.                    INC    DL
  502.                    MOV    ROWS,DL        ;Save Number of Lines
  503.                    TEST   ES:B[0487h],4  ;Check if must check retrace
  504.                    JNZ    NO_EGA
  505.                    MOV    RET_CHECK,0    ;EGA, don't have to
  506. NO_EGA:            MOV    BH,ES:[0462h]  ;Get Current Page
  507.                    MOV    CUR_PAGE,BH    ;Save it
  508.                    POP    ES
  509.                    MOV    AL,COLS        ;Length of each line
  510.                    MUL    ROWS           ;Total chars on screen
  511.                    ADD    AX,AX          ;Double for attributes
  512.                    MOV    SCRN_SIZE,AX   ;Save it
  513.                    CMP    ATTR,0         ;Check if attribute pre-set
  514.                    JNZ    GOT_ATTR       ;If so, continue
  515.                    MOV    DL,' '         ;Write out a byte
  516.                    MOV    AH,2           ;using DOS
  517.                    INT    21h            ;DOS call
  518.                    MOV    AL,8           ;Backspace
  519.                    MOV    AH,14          ;using BIOS call
  520.                    INT    10h
  521.                    MOV    AH,8           ;Read character & attribute
  522.                    MOV    BH,CUR_PAGE    ;Current page from above
  523.                    INT    10h            ;Using BIOS call (BH = pg)
  524. GOT_ATTR:          MOV    ATTR,AH        ;Save attribute
  525.                    ADD    AX,OFFSET BUFF ;Add Screen size to code end
  526.                    ADD    AX,8934h
  527.                    ADD    AX,256         ;Add some stack room
  528.                    CMP    AX,SP          ;Check if stack pointer
  529.                    JBE    MEMOK          ;Continue if OK
  530.                    MOV    DX,OFFSET N_ENF_MEM ;Otherwise end program
  531.                    MOV    AH,9           ;Write message
  532.                    INT    21h            ;DOS call
  533.                    INT    20h            ;Exit
  534. MEMOK:             PUSH   ES             ;save it
  535.                    MOV    AX,0040h       ;bios segment
  536.                    MOV    ES,AX
  537.                    MOV    AX,ES:W[050h]
  538.                    MOV    CURSOR_POSN,AX ;cursor position
  539.                    MOV    CURSOR_HOLD,AX ;keep for reset
  540.                    MOV    AL,ES:[0062h]  ;active page
  541.                    MOV    ACTIVE_PAGE,AL
  542.                    POP    ES             ;get it back
  543.                    MOV    W[FILE_OFFS],-1     ;reset buffers
  544.                    MOV    W[FILE_OFFS + 2],-1
  545.                    MOV    AX,OFFSET BUFF
  546.                    MOV    BUFFER_ST,AX   ;buffer bookkeeping
  547.                    MOV    BUFF_NEXT,AX
  548.                    MOV    BUFF_LAST,AX
  549.                    ADD    AX,BUFF_SIZE
  550.                    MOV    BUFF_END,AX
  551.                    MOV    ES,W[ENVIRONMENT] ;Environment Segment
  552.                    SUB    DI,DI          ;Start search at beginning
  553.                    CLD                   ;String increment to forward
  554. TRY_IT:            ES     CMP B[DI],0    ;See if end of environment
  555.                    JZ     NO_FIND        ;If so, we have failed
  556.                    PUSH   DI             ;Save environment pointer
  557.                    MOV    SI,OFFSET COMSPEC ;String to search for
  558.                    MOV    CX,8           ;Characters in search string
  559.                    REPZ   CMPSB          ;Check if strings are same
  560.                    POP    DI             ;GEt back the pointer
  561.                    JZ     FOUND          ;Found string only zero flag
  562.                    SUB    AL,AL          ;Zero out AL
  563.                    MOV    CX,8000H       ;Set for big search
  564.                    REPNZ  SCASB          ;Find the next zero in string
  565.                    JMP    TRY_IT         ;And do the search from there
  566. NO_FIND:           MOV    DX,OFFSET COMMANDMSG     ;Message for COMSPEC error
  567.                    JMP    ERROREXIT      ;Print it and exit
  568. FOUND:             ADD    DI,8           ;So points after 'COMSPEC='
  569.                    MOV    COMMANDASCIIZ1,DI ;Save the address of
  570.                    MOV    COMMANDASCIIZ2,ES ;COMMAND ASCIIZ
  571.                    MOV    [PARAMBLOCK],ES     ;Segment of Environment string
  572.                    MOV    [PARAMBLOCK + 4],CS ;Segment of this program
  573.                    MOV    [PARAMBLOCK + 8],CS ;so points to FCB's
  574.                    MOV    [PARAMBLOCK + 12],CS     ;and NewParameter
  575.                    PUSH   CS             ;Push this segment so we can
  576.                    POP    ES             ;set ES to it
  577.                    MOV    B[NEWPARAMETER],06h ;Counter
  578.                    MOV    W[NEWPARAMETER + 1],'C/' ;i.e. '/C'
  579.                    MOV    W[NEWPARAMETER + 3],'ID' ;Then 'DI'
  580.                    MOV    W[NEWPARAMETER + 5],' R' ;And 'R '
  581.                    JMP    SAV_SCRN
  582. ERROREXIT:         MOV    AH,9           ;Set up for string write
  583.                    INT    21h            ;Using DOS
  584.                    INT    20h            ;Dishonorable discharge
  585.                    RET
  586. SAV_SCRN:          MOV    DI,OFFSET BUFF ;Screen destination
  587.                    ADD    DI,8834h
  588.                    MOV    CX,SCRN_SIZE   ;Screen size
  589.                    PUSH   DS             ;Save source segment
  590.                    MOV    SI,SCRN_OFFS   ;Get screen offset
  591.                    MOV    DS,SCRN_SEG    ;Get screen segment
  592.                    REP    MOVSB          ;Move in the bytes
  593.                    POP    DS             ;Restore source segment
  594.                    RET
  595. SET_IT_UP          ENDP
  596. CLS_MSG            PROC   NEAR
  597.                    MOV    AX,0700h       ;clear screen
  598.                    MOV    BX,0700h       ;attribute
  599.                    MOV    CX,0000h       ;top left
  600.                    MOV    DH,ROWS
  601.                    MOV    DL,COLS
  602.                    SUB    DH,01h
  603.                    SUB    DL,01h         ;bottom right
  604.                    INT    10h            ;BIOS call
  605.                    MOV    BH,CUR_PAGE    ;page number
  606.                    MOV    AH,02h         ;move cursor
  607.                    MOV    DX,0A00h       ;10 lines from top
  608.                    INT    10h            ;BIOS call
  609.                    MOV    DX,OFFSET N_F_MSG   ;print message
  610.                    MOV    AH,09h
  611.                    INT    21h            ;DOS call
  612.                    MOV    AH,02h         ;move cursor
  613.                    MOV    BH,CUR_PAGE    ;page number
  614.                    MOV    DX,1111h       ;to line 17
  615.                    INT    10H            ;BIOS call
  616.                    RET
  617. CLS_MSG            ENDP
  618. GET_NAME           PROC   NEAR
  619. GET_NAME_1:        MOV    SI,0081h       ;Points to parameter
  620. NAM_SCH:           LODSB                 ;Get byte
  621.                    CMP    AL,13          ;Carriage return ?
  622.                    JZ     NO_NAM         ;If so, noname
  623.                    MOV    DI,OFFSET DELIMIT   ;String of delimiters
  624.                    MOV    CX,5           ;Number of delimiters (no /)
  625.                    REPNE  SCASB          ;Match ?
  626.                    JE     NAM_SCH        ;If a delimiter, keep looking
  627.                    MOV    DX,SI          ;Otherwise found file name
  628.                    DEC    DX             ;Points to beginning of it
  629. END_SRCH:          LODSB                 ;Get next byte
  630.                    CMP    AL,13          ;Carriage return ?
  631.                    JE     GOT_END        ;If so, done
  632.                    MOV    DI,OFFSET DELIMIT   ;String of delimiters
  633.                    MOV    CX,6           ;Number (including /)
  634.                    REPNE  SCASB          ;Match ?
  635.                    JNE    END_SRCH       ;If not, still in file name
  636.                    MOV    B[SI - 1],0    ;If so, mark end of file name
  637.                    JCXZ   GOT_FLAG       ;If slash, check for W
  638.                    JMP    END_SRCH       ;Or continue flag search
  639. GOT_FLAG:          LODSB                 ;Get byte after / flag
  640.                    OR     AL,20h         ;Uncapitalize
  641.                    CMP    AL,'W'         ;See if w for WordStar mode
  642.                    JNZ    GOT_END        ;If not, ignore it
  643.                    MOV    NON_W_S,7Fh    ;AND value for WordStar
  644. GOT_END:           MOV    B[SI - 1],0    ;Mark end of file name
  645.                                          ;DX still points to name
  646.                    MOV    AX,3D00h       ;Open file for reading
  647.                    INT    21h            ;DOS call
  648.                    JNC    GOT_FILE       ;Continue
  649. NO_NAM:            MOV    DX,OFFSET FILE_NOT_F;Print a message
  650.                    MOV    AH,9           ;Write message
  651.                    INT    21h            ;DOS call
  652.                    PUSH   BX
  653.                    MOV    BX,0002h
  654.                    CALL   TIME_SEC
  655.                    POP    BX
  656.                    CALL   NEW_FILE       ;try again
  657.                    JMP    GET_NAME_1
  658. GOT_FILE:          MOV    FHANDLE,AX     ;Save file handle
  659.                    RET
  660. GET_NAME           ENDP
  661. NEW_FILE           PROC   NEAR
  662.                    MOV    AL,DIR_FLAG
  663.                    CMP    AL,00h
  664.                    JNE    NEW_FILE_2D
  665. NEW_FILE_P1:       CALL   CLS_MSG        ;Cls and print msg
  666. NEW_FILE_2D:       MOV    AL,00h
  667.                    MOV    DIR_FLAG,AL
  668.                    PUSH   DI             ;save DI
  669.                    MOV    DI,0080h       ;for file to read
  670. N_F_LOOP:          INC    DI             ;increment DI
  671. N_F_LOOP_P1:       MOV    AX,0100h       ;get character
  672.                    INT    21h            ;DOS call
  673.                    CMP    AL,0           ;Extended?
  674.                    JNZ    NO_EXT
  675.                    MOV    AX,0100h       ;Get extended
  676.                    INT    21h            ;DOS call
  677.                    CMP    AL,20h         ;Alt-D?
  678.                    JNZ    N_F_LOOP_P1
  679.                    CALL   GET_DIR        ;Get dir.
  680.                    POP    DI             ;Keep stack true
  681.                    JMP    NEW_FILE_P1
  682. NO_EXT:            CMP    AL,27          ;ESC ?
  683.                    JNE    DONT_QUIT      ;go on
  684.                    CALL   QUIT           ;quit
  685. DONT_QUIT:         CMP    AL,08          ;backspace ?
  686.                    JNE    N_F_L_1
  687.                    DEC    DI             ;decrement DI
  688.                    DEC    DI             ;twice
  689.                    CMP    DI,080h        ;not too far back
  690.                    JGE    N_F_L_2
  691.                    INC    DI             ;neutral DI
  692.                    MOV    BH,0           ;page number
  693.                    MOV    AH,3           ;get cursor
  694.                    INT    10h            ;BIOS call
  695.                    INC    DL             ;cancel backspace
  696.                    MOV    AH,2           ;by moving cursor
  697.                    INT    10h            ;BIOS call
  698. N_F_L_2:           MOV    AX,0A20h       ;write space
  699.                    MOV    CX,01          ;one character
  700.                    INT    10h            ;BIOS call
  701.                    JMP    N_F_LOOP       ;go for another char.
  702. N_F_L_1:           MOV    B[DI],AL       ;save character
  703.                    CMP    AL,0Dh         ;was it CR
  704.                    JE     EX_LOOP        ;got filename
  705.                    CMP    DI,0AAh        ;too many char ?
  706.                    JGE    EX_LOOP        ;test filename
  707.                    JMP    N_F_LOOP       ;get another letter
  708. EX_LOOP:           POP    DI             ;recover DI
  709.                    MOV    W[FILE_OFFS],-1;reset buffers
  710.                    MOV    W[FILE_OFFS + 2],-1
  711.                    MOV    AX,OFFSET BUFF
  712.                    MOV    BUFFER_ST,AX
  713.                    MOV    BUFF_NEXT,AX
  714.                    MOV    BUFF_LAST,AX
  715.                    RET
  716. NEW_FILE           ENDP
  717. HELP_ME            PROC   NEAR
  718.                    MOV    DI,081h
  719.                    MOV    SI,OFFSET HELP_DOC
  720.                    MOV    CX,000D
  721.                    REP    MOVSB
  722.                    MOV    W[FILE_OFFS],-1;reset buffers
  723.                    MOV    W[FILE_OFFS + 2],-1
  724.                    MOV    AX,OFFSET BUFF
  725.                    MOV    BUFFER_ST,AX
  726.                    MOV    BUFF_NEXT,AX
  727.                    MOV    BUFF_LAST,AX
  728.                    RET
  729. HELP_ME            ENDP
  730. GET_DIR            PROC   NEAR
  731.                    MOV    AH,07          ;Clear screen
  732.                    MOV    AL,0
  733.                    MOV    BH,07h
  734.                    MOV    CX,0000h
  735.                    MOV    DH,ROWS
  736.                    SUB    DH,01
  737.                    MOV    DL,COLS
  738.                    SUB    DL,01
  739.                    INT    10h
  740.                    MOV    AH,02h         ;Set cursor position
  741.                    MOV    BH,CUR_PAGE
  742.                    MOV    DX,0A00h
  743.                    INT    10H
  744.                    MOV    AH,09
  745.                    MOV    DX,OFFSET A_D_MSG   ;Want another directory?
  746.                    INT    21h
  747. PATH_L_M:          MOV    BL,CHAR_COUNT
  748.                    MOV    LAST_CHAR_COUNT,BL  ;Save old count
  749.                    MOV    BX,0006h
  750.                    MOV    CHAR_COUNT,BL  ;Initialize character count
  751.                    MOV    AX,0020h
  752.                    ADD    BL,NEWPARAMETER
  753.                    MOV    B[BX],AL       ;Store the character
  754. PATH_LOOP:         INC    CHAR_COUNT     ;Add a character to path
  755.                    MOV    AH,00h
  756.                    MOV    DIR_FLAG,AH    ;Reset DIR_FLAG
  757.                    MOV    AH,CHAR_COUNT
  758.                    MOV    [NEWPARAMETER],AH
  759.                    MOV    AH,01h         ;Get the character
  760.                    INT    21h            ;Using DOS
  761.                    CMP    AL,00h         ;Extended?
  762.                    JNZ    SKIP_IT
  763.                    MOV    AH,01h
  764.                    INT    21h
  765.                    CMP    AL,20h
  766.                    JNZ    SKIP_IT
  767.                    MOV    BH,0           ;To make word from byte
  768.                    MOV    BL,NEWPARAMETER
  769.                    ADD    BL,LAST_CHAR_COUNT  ;At this location
  770.                    MOV    B[BX],02Fh
  771.                    ADD    BX,01h
  772.                    MOV    B[BX],057h
  773.                    ADD    BX,01h
  774.                    MOV    B[BX],0Dh
  775.                    SUB    BL,07Bh
  776.                    MOV    [NEWPARAMETER],BL
  777.                    INC    DIR_FLAG
  778.                    JMP    CAR_RET
  779. SKIP_IT:           CMP    AL,1Bh         ;Esc?
  780.                    JZ     THATS_ALL
  781.                    CMP    AL,08h         ;Backspace?
  782.                    JZ     BACK_SP
  783.                    MOV    BH,0           ;To make word from byte
  784.                    MOV    BL,NEWPARAMETER
  785.                    ADD    BL,CHAR_COUNT  ;At this location
  786.                    MOV    B[BX],AL       ;Store the character
  787.                    CMP    AL,0Dh         ;CR?
  788.                    JZ     CAR_RET
  789.                    JMP    PATH_LOOP      ;Get another character
  790. BACK_SP:           DEC    CHAR_COUNT     ;Cancel inc command
  791.                    MOV    AH,CHAR_COUNT
  792.                    MOV    [NEWPARAMETER],AH   ;Readjust count
  793.                    CMP    CHAR_COUNT,06
  794.                    JBE    PATH_LOOP      ;Not before start
  795.                    DEC    CHAR_COUNT     ;One space back
  796.                    MOV    DL,' '         ;Use space
  797.                    MOV    AH,02          ;To remove char on screen
  798.                    INT    21h            ;Using DOS
  799.                    MOV    AH,03          ;Get cursor position
  800.                    MOV    BH,CUR_PAGE    ;On current page
  801.                    INT    10h            ;Using BIOS
  802.                    MOV    AH,02          ;Move cursor
  803.                    DEC    DL             ;back one space
  804.                    INT    10h            ;using BIOS
  805.                    JMP    PATH_LOOP      ;Get another character
  806. CAR_RET:           MOV    BX,OFFSET PARAMBLOCK ;ES:BX = address of block
  807.                    MOV    DX,COMMANDASCIIZ1 ;DS:DX = address of ASCIIZ
  808.                    MOV    DS,COMMANDASCIIZ2
  809.                    MOV    AX,4B00H       ;EXEC call 4Bh, type 0
  810.                    INT    21H            ;Load command processor
  811.                    PUSH   CS
  812.                    POP    DS             ;restore DS
  813.                    MOV    AH,DIR_FLAG
  814.                    CMP    AH,00h
  815.                    JZ     SKPIT
  816.                    POP    AX             ;Fake RET
  817.                    MOV    AH,09
  818.                    MOV    DX,OFFSET N_F_MSG   ;Want new file name
  819.                    INT    21h
  820.                    CALL   THATS_ALL
  821.                    JMP    NO_NEW_0
  822. SKPIT:             MOV    AH,09
  823.                    MOV    DX,OFFSET A_D_MSG   ;Want another directory?
  824.                    INT    21h
  825.                    JMP    PATH_L_M       ;Get another directory
  826. THATS_ALL:         MOV    AX,CS          ;Get this segment in AX
  827.                    MOV    DS,AX          ;Set DS to it
  828.                    MOV    SS,AX          ;And SS for stack segment
  829.                    RET
  830. GET_DIR            ENDP
  831. KEYS               PROC   NEAR
  832. KEYS_1:            CALL   HOME           ;Read file
  833.                    MOV    SCRN_PT,SI     ;Save buffer address
  834. KEY_LOOP:          CALL   WRIT_SCRN      ;Write file to screen
  835. GET_KEY:           MOV    AH,8           ;Get key
  836.                    INT    21h            ;DOS call
  837.                    CMP    AL,00
  838.                    JE     GO_NEXT
  839.                    CMP    AL,057h
  840.                    JZ     TOG_WRAP
  841.                    CMP    AL,077h
  842.                    JZ     TOG_WRAP
  843.                    JMP    NO_TOG_WRAP
  844. TOG_WRAP:          XOR    WRAP_FLAG,01h
  845.                    JMP    KEYS_1
  846. NO_TOG_WRAP:       CMP    AL,44h         ;D for dir
  847.                    JNE    NO_DIR_1
  848. YES_DIR:           CALL   GET_DIR
  849.                    JMP    KEYS_1
  850. NO_DIR_1:          CMP    AL,64h         ;d for dir
  851.                    JNE    NO_DIR_2
  852.                    JMP    YES_DIR
  853. NO_DIR_2:          CMP    AL,6Eh         ;n for new file
  854.                    JNE    NO_NEW_1
  855. NO_NEW_0:          MOV    BX,FHANDLE     ;Get File Handle
  856.                    MOV    AH,3Eh         ;Close File
  857.                    INT    21h            ;DOS call
  858.                    CALL   NEW_FILE       ;get a new file
  859.                    CALL   GET_NAME
  860.                    JMP    KEYS_1
  861. X_GET_KEY:         JMP    GET_KEY
  862. NO_NEW_1:          CMP    AL,4Eh         ;N for new file
  863.                    JNE    NO_NEW_2
  864.                    JMP    NO_NEW_0
  865. NO_NEW_2:          CMP    AL,48h         ;H for help
  866.                    JNE    NO_NEW_3
  867.                    JMP    H_HELP
  868. NO_NEW_3:          CMP    AL,68h         ;h for help
  869.                    JNE    NO_NEW_4
  870. H_HELP:            MOV    BX,FHANDLE     ;Get File Handle
  871.                    MOV    AH,3Eh         ;Close File
  872.                    INT    21h            ;DOS call
  873.                    CALL   HELP_ME
  874.                    CALL   GET_NAME
  875.                    JMP    KEYS_1
  876. NO_NEW_4:          CMP    AL,27          ;ESC ?
  877.                    JNE    NO_QT          ;Quit
  878.                    CALL   QUIT
  879. NO_QT:             CMP    AL,32          ;Space bar ?
  880.                    JNE    GO_NEXT        ;Go on if not
  881.                    CALL   CLIP           ;Get Clip
  882.                    JMP    KEY_LOOP       ;Do it
  883. GO_NEXT:           CMP    AL,0           ;Check if extended
  884.                    JNZ    X_GET_KEY      ;If not, try again
  885.                    MOV    AH,8           ;Get extended code
  886.                    INT    21h            ;DOS call
  887.                    CMP    AL,20h         ;Alt-D dir request
  888.                    JZ     YES_DIR        ;Get directory
  889.                    SUB    AL,71          ;Subtract Home key value
  890.                    JB     X_GET_KEY      ;If below that, not valid
  891.                    CMP    AL,(81 - 71)   ;Check if above PgDn
  892.                    JA     X_GET_KEY      ;If so, ignore it
  893.                    SUB    AH,AH          ;Zero top byte
  894.                    ADD    AX,AX          ;Double for word access
  895.                    MOV    BX,AX          ;Offset in Send table
  896.                    MOV    SI,SCRN_PT     ;Set buffer address
  897.                    CALL   [SEND + BX]    ;Do the call
  898.                    MOV    SCRN_PT,SI     ;Set buffer address
  899.                    JMP    KEY_LOOP       ;Update the screen
  900.                    RET
  901. KEYS               ENDP
  902. HOME               PROC   NEAR
  903.                    SUB    BX,BX          ;Zero out values
  904.                    MOV    AX,W[FILE_OFFS];Check if read in file
  905.                    OR     AX,W[FILE_OFFS + 2]
  906.                    MOV    W[FILE_OFFS],BX;Zero file address
  907.                    MOV    W[FILE_OFFS + 2],BX
  908.                    MOV    HORIZ_OFFS,BX  ;Zero horizontal offset
  909.                    MOV    SI,OFFSET BUFF ;Reset buffer address
  910.                    ADD    SI,834h
  911.                    JZ     NO_READ        ;Skip file read if in already
  912.                    MOV    CX,8000h       ;Number of bytes to read
  913.                    MOV    DX,OFFSET BUFF ;Area to read file to
  914.                    ADD    DX,834h
  915.                    CALL   READ_FILE      ;Read in file
  916. NO_READ:           RET
  917. HOME               ENDP
  918. UP                 PROC   NEAR
  919.                    CALL   PREV_CHAR      ;Get previous char in buffer
  920.                    JC     UP_DONE        ;If none available, finish
  921. UP_LOOP:           CALL   PREV_CHAR      ;Get previous char again
  922.                    JC     UP_DONE        ;if none, done
  923.                    CMP    AL,10          ;Line feed ?
  924.                    JNZ    UP_LOOP        ;Try again
  925.                    CALL   NEXT_CHAR      ;Get char after line feed
  926. UP_DONE:           RET
  927. UP                 ENDP
  928. PG_UP              PROC   NEAR
  929.                    MOV    CL,ROWS        ;Number of lines
  930. PG_UP_LOOP:        CALL   UP             ;Do UP that many times
  931.                    LOOP   PG_UP_LOOP
  932.                    RET
  933. PG_UP              ENDP
  934. LEFT               PROC   NEAR
  935.                    MOV    HORIZ_OFFS,0   ;Reset horizontal offset
  936.                    RET
  937. LEFT               ENDP
  938. RIGHT              PROC   NEAR
  939.                    MOV    AL,HORIZ_SHFT  ;Get places to shift
  940.                    SUB    AH,AH
  941.                    ADD    HORIZ_OFFS,AX  ;Move right that many
  942.                    RET
  943. RIGHT              ENDP
  944. ENDD               PROC   NEAR
  945.                    MOV    BX,SI          ;Save buffer address
  946.                    CALL   PG_DN          ;Do page down
  947.                    CMP    BX,SI          ;Check if done
  948.                    JNZ    ENDD           ;If so, do it again
  949.                    RET
  950. ENDD               ENDP
  951. DOWN               PROC   NEAR
  952.                    CALL   NEXT_CHAR      ;Get next character
  953.                    JC     NO_MORE_DOWN   ;If no more, we're done
  954. DOWN_LOOP:         CALL   NEXT_CHAR      ;Get one more
  955.                    JC     UP_LOOP        ;If no more, get prev LF
  956.                    CMP    AL,10          ;Line feed ?
  957.                    JNZ    DOWN_LOOP      ;Continue
  958. NO_MORE_DOWN:      RET
  959. DOWN               ENDP
  960. PG_DN              PROC   NEAR
  961.                    MOV    CL,ROWS        ;Number of lines
  962. PG_DN_LOOP:        CALL   DOWN           ;Do DOWN that many times
  963.                    LOOP   PG_DN_LOOP
  964.                    RET
  965. PG_DN              ENDP
  966. DUMMY              PROC   NEAR
  967.                    RET
  968. DUMMY              ENDP
  969. TIME_SEC           PROC   NEAR           ;time delay in BL
  970.                    PUSH   AX
  971.                    PUSH   BX
  972.                    MOV    AX,BX
  973.                    MOV    BL,18
  974.                    MUL    BL
  975.                    MOV    BX,AX
  976.                    PUSH   CX
  977.                    PUSH   DX
  978.                    MOV    AH,00h
  979.                    INT    1Ah
  980.                    ADD    BX,DX
  981. TIME_1:            MOV    AH,00h
  982.                    INT    1Ah
  983.                    CMP    BX,DX
  984.                    JNE    TIME_1
  985.                    POP    DX
  986.                    POP    CX
  987.                    POP    BX
  988.                    POP    AX
  989.                    RET
  990. TIME_SEC           ENDP
  991. READ_FILE:         PUSH   AX             ;Save some registers
  992.                    PUSH   BX
  993.                    PUSH   CX
  994.                    PUSH   DX
  995.                    MOV    BUFF_PT,-1     ;Initialize this
  996.                    MOV    DX,W[FILE_OFFS];Get file address to read
  997.                    MOV    CX,W[FILE_OFFS + 2]
  998.                    MOV    BX,FHANDLE     ;Get file Handle
  999.                    SUB    AL,AL          ;From beginning
  1000.                    MOV    AH,42h         ;Move file pointer call
  1001.                    INT    21h            ;DOS call
  1002.                    POP    DX             ;Get back destination
  1003.                    POP    CX             ;Get back count
  1004.                    MOV    AH,3Fh         ;Read file function call
  1005.                    INT    21h            ;DOS call
  1006.                    JNC    NO_ERR         ;If no error, continue
  1007.                    SUB    AX,AX          ;Otherwise read zero bytes
  1008. NO_ERR:            CMP    AX,CX          ;See if 32K has been read
  1009.                    JE     GOT_ALL        ;If so, done
  1010.                    ADD    AX,DX          ;Otherwise add to buffer addr
  1011.                    MOV    BUFF_PT,AX     ;And save as end of file
  1012. GOT_ALL:           POP    BX
  1013.                    POP    AX
  1014.                    RET
  1015. READ_FILE          ENDP
  1016. WRIT_SCRN          PROC   NEAR
  1017.                    PUSH   ES
  1018.                    MOV    SI,SCRN_PT     ;Address of data in buffer
  1019.                    MOV    DI,SCRN_OFFS   ;Display offset
  1020.                    MOV    ES,SCRN_SEG    ;Display segment
  1021.                    CMP    WRAP_FLAG,1
  1022.                    JNZ    WRAP1
  1023.                    SUB    CX,CX
  1024.                    MOV    HORIZ_OFFS,CX
  1025. WRAP1:             MOV    CX,SCRN_SIZE   ;Number of bytes in screen
  1026.                    SHR    CX,1           ;Half for number of chars
  1027.                    MOV    AL,' '         ;Blank screen
  1028.                    MOV    AH,ATTR        ;With screen attribute
  1029.                    REP    STOSW          ;Blank it
  1030.                    MOV    AL,COLS        ;Display line length
  1031.                    SUB    AH,AH
  1032.                    ADD    AX,HORIZ_OFFS  ;Add horizontal offset
  1033.                    MOV    RGT_MRGN,AX    ;Right display margin
  1034.                    SUB    DL,DL          ;Line Number
  1035. LINE_LOOP:         SUB    BX,BX          ;Column Number
  1036.                    MOV    AL,COLS        ;Use Line Length
  1037.                    MUL    DL             ;And Line Number
  1038.                    ADD    AX,AX          ;To recalculate
  1039.                    MOV    DI,AX          ;Display destination
  1040.                    ADD    DI,SCRN_OFFS   ;Add beginning address
  1041. CHAR_LOOP:         CALL   NEXT_CHAR      ;Get next character
  1042.                    JC     SCRN_END       ;If no more, done
  1043.                    AND    AL,NON_W_S     ;Will be 7Fh for WordStar
  1044.                    CMP    AL,13          ;Check for carriage return
  1045.                    JE     CHAR_LOOP      ;Do nothing if so
  1046.                    CMP    AL,10          ;Check for line feed
  1047.                    JE     LINE_FEED      ;Do routine if so
  1048.                    CMP    AL,9           ;Check for tab
  1049.                    JE     TAB            ;Do routine if so
  1050.                    MOV    CX,1           ;Just 1 char to display
  1051. PRINT_CHR:         CMP    BX,HORIZ_OFFS  ;See if we can print it
  1052.                    JB     NO_PRINT
  1053.                    CMP    WRAP_FLAG,1    ;Wrap around?
  1054.                    JNZ    WRAP_IT
  1055.                    CMP    BX,RGT_MRGN
  1056.                    JB     WRAP_IT
  1057.                    MOV    BX,0000
  1058.                    INC    DL
  1059. WRAP_IT:           CMP    BX,RGT_MRGN    ;See if within margin
  1060.                    JAE    NO_PRINT
  1061.                    MOV    AH,ATTR        ;Attribute for display
  1062.                    CMP    RET_CHECK,0    ;See if must stop snow
  1063.                    JZ     WRITE_IT       ;If not, skip retrace wait
  1064.                    PUSH   BX
  1065.                    PUSH   DX
  1066.                    MOV    BX,AX          ;Save character and attribute
  1067.                    MOV    DX,ADDR_6845   ;Set up I/O address
  1068.                    ADD    DX,6
  1069. RETR_WAIT_1:       IN     AL,DX          ;Check until
  1070.                    SHR    AL,1           ;Vertical retrace
  1071.                    JC     RETR_WAIT_1    ;Ends
  1072.                    CLI                   ;Clear interrupts
  1073. RETR_WAIT_2:       IN     AL,DX          ;Check until
  1074.                    SHR    AL,1           ;Vertical retrace
  1075.                    JNC    RETR_WAIT_2    ;Begins
  1076.                    MOV    AX,BX          ;Get back char & attr
  1077.                    STOSW                 ;Write to display
  1078.                    STI                   ;Enable interrupts again
  1079.                    POP    DX
  1080.                    POP    BX
  1081.                    JMP    NO_PRINT       ;Skip around "no snow"
  1082. LINE_LOOP_1:       JMP    LINE_LOOP
  1083. WRITE_IT:          STOSW                 ;Write without retrace wait
  1084. NO_PRINT:          INC    BX             ;Inc line counter
  1085.                    LOOP   PRINT_CHR      ;Do it CX times
  1086.                    JMP    CHAR_LOOP      ;Go back to top
  1087. TAB:               MOV    AX,BX          ;Column number
  1088.                    AND    AX,07h         ;Take lower three bits
  1089.                    MOV    CX,8
  1090.                    SUB    CX,AX          ;Subtract from 8
  1091.                    MOV    AL,' '         ;Print CX blanks
  1092.                    JMP    PRINT_CHR
  1093. LINE_FEED:         INC    DL             ;Next line
  1094.                    CMP    DL,ROWS        ;See if at bottom
  1095.                    JB     LINE_LOOP_1    ;If not, continue
  1096. SCRN_END:          POP    ES             ;All done -- quit
  1097.                    RET
  1098. WRIT_SCRN          ENDP
  1099. PREV_CHAR          PROC   NEAR
  1100.                    PUSH   AX
  1101.                    MOV    AX,OFFSET BUFF
  1102.                    ADD    AX,834h
  1103.                    CMP    SI,AX          ;See if at top of buffer
  1104.                    POP    AX
  1105.                    JA     C_G_P          ;If not, get character
  1106.                    MOV    AX,W[FILE_OFFS];See if at top of file
  1107.                    OR     AX,W[FILE_OFFS + 2]
  1108.                    JZ     ATTOP          ;If so, can't get anymore
  1109.                    PUSH   CX             ;Save some registers
  1110.                    PUSH   DX
  1111.                    MOV    SI,OFFSET BUFF ;Move 1st half of buffer
  1112.                    ADD    SI,834h
  1113.                    MOV    DI,OFFSET BUFF ;to 2nd half of buffer
  1114.                    ADD    DI,4834h
  1115.                    MOV    CX,4000h       ;Bytes to move
  1116.                    ADD    SCRN_PT,CX     ;New buffer address
  1117.                    REP    MOVSB          ;Do the move
  1118.                    SUB    W[FILE_OFFS],4000h  ;Adjust file addr for read
  1119.                    SBB    W[FILE_OFFS + 2],0
  1120.                    MOV    DX,OFFSET BUFF ;Area to read file into
  1121.                    ADD    DX,834h
  1122.                    MOV    CX,4000h       ;Number of bytes
  1123.                    CALL   READ_FILE      ;Read the file
  1124.                    POP    DX             ;Get back registers
  1125.                    POP    CX
  1126.                    JMP    C_G_P          ;Now get character
  1127. ATTOP:             STC                   ;CY flag set for no more
  1128.                    RET
  1129. C_G_P:             DEC    SI             ;Move pointer back
  1130.                    MOV    AL,[SI]        ;Get the character
  1131.                    CLC                   ;CY flag reset for success
  1132.                    RET
  1133. PREV_CHAR          ENDP
  1134. NEXT_CHAR          PROC   NEAR
  1135. NXT_CHAR:          CMP    SI,BUFF_PT     ;End of file ?
  1136.                    JAE    NO_CHAR        ;If so, no more chars
  1137.                    PUSH   AX
  1138.                    MOV    AX,OFFSET BUFF
  1139.                    ADD    AX,8834h
  1140.                    CMP    SI,AX          ;End of buffer ?
  1141.                    POP    AX
  1142.                    JB     GT_NXT         ;If not, get char
  1143.                    PUSH   CX             ;Save registers
  1144.                    PUSH   DX
  1145.                    PUSH   DI
  1146.                    PUSH   ES
  1147.                    PUSH   DS             ;Set ES to DS
  1148.                    POP    ES             ;(could be different)
  1149.                    MOV    SI,OFFSET BUFF ;Move 2nd buffer half
  1150.                    ADD    SI,4834h
  1151.                    MOV    DI,OFFSET BUFF ;to 1st buffer half
  1152.                    ADD    DI,834h
  1153.                    MOV    CX,4000h
  1154.                    SUB    SCRN_PT,CX     ;New buffer pointer
  1155.                    REP    MOVSB          ;Move them
  1156.                    MOV    SI,DI          ;SI also buffer pointer
  1157.                    ADD    W[FILE_OFFS],8000h  ;Adjust file addr to read
  1158.                    ADC    W[FILE_OFFS + 2],0
  1159.                    MOV    DX,OFFSET BUFF ;Place to read file
  1160.                    ADD    DX,4834h
  1161.                    MOV    CX,4000h       ;Number of bytes
  1162.                    CALL   READ_FILE      ;Read the file
  1163.                    SUB    W[FILE_OFFS],4000h  ;Adjust address
  1164.                    SBB    W[FILE_OFFS + 2],0  ;1st half of buffer
  1165.                    POP    ES             ;Get back registers
  1166.                    POP    DI
  1167.                    POP    DX
  1168.                    POP    CX
  1169.                    JMP    NXT_CHAR       ;Try again to get char
  1170. GT_NXT:            LODSB                 ;Get the character
  1171. NO_CHAR:           CMC                   ;Set CY if no more
  1172.                    RET
  1173. NEXT_CHAR          ENDP
  1174. QUIT               PROC   NEAR
  1175.                    MOV    SI,OFFSET BUFF ;Address of saved screen
  1176.                    ADD    SI,8834h
  1177.                    MOV    DI,SCRN_OFFS   ;Display offset
  1178.                    MOV    ES,SCRN_SEG    ;Display segment
  1179.                    MOV    CX,SCRN_SIZE   ;Number of characters
  1180.                    REP    MOVSB          ;Move them back
  1181.                    MOV    BX,FHANDLE     ;Get File Handle
  1182.                    MOV    AH,3Eh         ;Close File
  1183.                    INT    21h            ;DOS call
  1184.                    MOV    AH,02h         ;reset
  1185.                    MOV    DX,CURSOR_HOLD ;cursor
  1186.                    MOV    BH,CUR_PAGE    ;position
  1187.                    INT    10h
  1188.                    MOV    DX,OFFSET MSG  ;Thank You
  1189.                    MOV    AH,9           ;Write message
  1190.                    INT    21h            ;DOS call
  1191.                    INT    20h            ;Exit
  1192.                    RET
  1193. QUIT               ENDP
  1194. BUFF:
  1195. CSEG               ENDS                  ;End of segment
  1196.                    END  
  1197.