home *** CD-ROM | disk | FTP | other *** search
- CSEG SEGMENT
- ORG 0100h
- MAIN PROC NEAR
- JMP BEGIN
- ADDR_6845 DW ? ;Use for retrace check
- ATTR DB 0 ;Current screen attribute
- BAD_DOS DB 'Requires DOS 2.0 or above$'
- CUR_PAGE DB 0
- CURSOR_HOLD DW 0
- DELIMIT DB 9,' ,;=/' ;Delimiters in parameter
- BUFF_PT DW ? ;Points within buffer
- FILE_OFFS DW -1, -1 ;Address within file of buff data
- FHANDLE DW ? ;File handle
- FILE_NOT_F DB 'File Not Found$'
- HORIZ_OFFS DW 0 ;Horizontal offset for display
- HORIZ_SHFT DB 8 ;Horizontal shift screen default
- COLS DB 80 ;Length of line (from BIOS)
- ROWS DB 25,0 ;Number of lines (check EGA BIOS)
- MSG DB 10,13,'Thank You. SUPERSPY Ver. 2.00. Copr. '
- DB '1989, 1990 Robert Wallingford, P.E.',10,13,'$'
- N_F_MSG DB ' Please type in the name of the '
- DB 'New File that',10,13,' you want to '
- DB 'look into. Include its path',10,13,' '
- DB 'if it is different than your present',10,13
- DB ' directory.',10,13,10,13,10,13,'$'
- N_ENF_MEM DB 'Not enough memory$'
- NON_W_S DB 0FFh ;AND value for non-WordStar mode
- RET_CHECK DB 1 ;Flag zero if EGA or MONO used
- RGT_MRGN DW 0 ;Right margin for offset display
- SCRN_PT DW ? ;Points within buffer
- SCRN_OFFS DW 0 ;Higher for non-page 0
- SCRN_SEG DW 0B800h ;Set to B000h for Mono Mode 7
- SEND DW HOME, UP, PG_UP, DUMMY, LEFT
- DW DUMMY, RIGHT, DUMMY, ENDD, DOWN, PG_DN
- SCRN_SIZE DW ? ;Size of screen in bytes
- UN_VID_M DB 'Unsupported video mode$'
- BIOS_SEG EQU 0040h ;bios segment
- CURSOR_POSN DW ?
- ACTIVE_PAGE DB ?
- ERR_STAT DB ? ;error status during file output
- FILE_PROMPT DB 'Enter Filename: '
- FILENAME DB 'CLIP.WWW' ;the default filename
- DB 17 DUP (0) ;leave room for drive and path
- NAME_BUFF DW 42 DUP (0) ;filename buffer
- BUFF_NEXT DW ? ;pointer to next key in buffer
- BUFF_LAST DW ? ;pointer to last key in buffer
- BUFFER_ST DW ? ;offset buffer_st
- BUFF_SIZE DW 2050 ;room for 25 rows of 80 columns
- BUFF_END DW ? ;buffer_st+buff_size
- TOP_LEFT LABEL WORD ;first corner of window
- LEFT_SIDE DB 0 ;column number of left side
- TOP_ROW DB 0 ;row number of top side
- BOT_RIGHT LABEL WORD ;second corner of window
- RIGHT_SIDE DB ? ;column number or right side
- BOT_ROW DB ? ;Row number of bottom
- SEND_CHAR DW ? ;Pointer to character handler
- WRIT_FILE DB 0 ;if=1, need to write to disk
- HELP_MENU DB 201,10 DUP(205),187
- DB 186,'ESC- quit ',186
- DB 186,' F - file ',186
- DB 186,' P - print',186
- DB 200,10 DUP(205),188
- HELP_DOC DB 'SUPERSPY.DOC',0D
- ENVIRONMENT EQU 002Ch ;Offset of Environment
- NEWPARAMETER EQU 007B ;Parameter for COMMAND.COM
- MEMALLOCMSG DB 'Memory Problem$'
- COMMANDMSG DB 'COMMAND Problem$'
- COMSPEC DB 'COMSPEC=' ;Search string in environment
- COMMANDASCIIZ1 DW ? ;Pointer to COMMAND address
- COMMANDASCIIZ2 DW ? ;Pointer to COMMAND segment
- PARAMBLOCK DW ? ;Parameter Block for EXEC
- DW 007Bh,? ;First ? must be replaced
- DW 005Ch,? ;with Environment segment
- DW 006Ch,? ;others with this segment
- CHAR_COUNT DB 0 ;Char count in path
- LAST_CHAR_COUNT DB 0 ;Last value
- DIR_FLAG DB 0 ;Flag special dir
- A_D_MSG DB 0Ah,0Dh,' If you want another directory '
- DB 'type in its path and press ENTER.',0Ah,0Dh,'$'
- WRAP_FLAG DB 00 ;For wrap around mode
- NOP
- NOP
- BEGIN: MOV BX,OFFSET BUFF
- ADD BX,8934h
- ADD BX,5070h ;New end of program
- MOV SP,BX ;Set the stack pointer
- ADD BX,15 ;Add 15 for rounding
- MOV CL,4 ;Number of shifts
- SHR BX,CL ;Convert AX to segment
- MOV AH,4AH ;DOS call to shrink down
- INT 21H ;allocated memory
- MOV DX,OFFSET MEMALLOCMSG ;Possible error message
- JNC NO_ERR_1 ;Only print it if Carry set
- MOV AH,9
- INT 21h
- INT 20h
- NO_ERR_1: CALL SET_IT_UP ;Initialize everything
- CALL GET_NAME
- CALL KEYS
- INT 20h
- RET
- MAIN ENDP
- NEWINT24 PROC NEAR
- STI ;turn interrupts back on
- INC ERR_STAT ;set the error flag
- XOR AL,AL ;tells dos to ignore the error
- IRET ;thats all we do here
- NEWINT24 ENDP
- WRITE_TO_FILE PROC NEAR
- MOV WRIT_FILE,00h ;turn off request flag
- PUSH AX ;must preserve all registers
- PUSH BX
- PUSH CX
- PUSH DX
- PUSH DS
- PUSH ES
- PUSH CS
- POP DS
- MOV AX,3524h ;get dos critical error vector
- INT 21h ;dos function to get vector
- PUSH BX ;save old vector on stack
- PUSH ES
- MOV DX,OFFSET NEWINT24
- MOV AX,2524h ;setup to change int 24h vector
- INT 21h ;change dos severe error vector
- MOV DX,OFFSET FILENAME ;point to filename
- MOV AX,3D02h ;dos function to open file
- INT 21h ;dos will return with carry flag
- JB FILE_NOT_FND ;set if file doesn't exist.
- MOV BX,AX ;keep handle in bx also
- XOR CX,CX ;move dos file pointer to the
- XOR DX,DX ;end of the file. This lets us
- MOV AX,4202h ;append this to an existing file
- INT 21h ;dos function to move pointer
- JNB WRITE_FILE ;if no error, continue to write
- DOS_ERROR: CMP ERR_STAT,00h ;did a severe error occur?
- JNZ REP_VECTOR ;if severe error, just quit
- JMP CLOSE_FILE ;just close the file
- FILE_NOT_FND: CMP ERR_STAT,00h ;did a severe error occur?
- JNZ REP_VECTOR ;if severe error, just quit
- MOV CX,0020h ;attribute for new file
- MOV AH,3Ch ;create file for writing
- INT 21h ;dos function to create file
- JB DOS_ERROR ;on any error, take jump
- MOV BX,AX ;save handle in bx
- WRITE_FILE: MOV DX,BUFFER_ST ;point to buffer
- MOV CX,BUFF_LAST ;get buffer pointer
- SUB CX,DX ;number of chars in buffer
- MOV AH,40h ;dos write to a device function
- INT 21h ;write to the file
- CLOSE_FILE: MOV AH,3Eh ;dos function to close the file
- INT 21h ;get int 24h vector from stack
- REP_VECTOR: POP DS
- POP DX
- MOV AX,2524h ;restore critical error vector
- INT 21h ;dos function to change vector
- POP ES ;finally restore all registers
- POP DS
- POP DX
- POP CX
- POP BX
- POP AX
- RET ;finished writing to disk
- WRITE_TO_FILE ENDP
- CLIP PROC NEAR
- STI ;allow other interrupts
- PUSH CS
- POP DS ;set ds to cseg
- CALL GET_CURS_ADDR ;cursor address for this page
- PUSH [BX] ;save the cursor location
- XOR BX,BX ;bx is increment for row/column
- GET_KB_KEY1: MOV DX,TOP_LEFT ;get location of first corner
- ADD DH,BH ;add in the row increment
- ADD DL,BL ;add in the column increment
- CMP DL,00h ;at left edge of screen?
- JGE NOT_LEFT_EDGE
- MOV DL,COLS ;jump to the right edge
- DEC DL
- NOT_LEFT_EDGE: CMP DL,COLS ;at right edge of screen yet?
- JB NOT_RGT_EDGE ;if not, keep moving right
- XOR DL,DL ;if yes, wrap to left edge
- NOT_RGT_EDGE: CMP DH,00h ;at top of screen yet?
- JGE NOT_AT_TOP
- MOV DH,ROWS ;jump down to the bottom
- DEC DH ;rows start at 0
- NOT_AT_TOP: CMP DH,ROWS ;at bottom of screen?
- JL NOT_AT_BOTTOM
- XOR DH,DH ;jump back to the top
- NOT_AT_BOTTOM: MOV TOP_LEFT,DX ;save new corner location
- CALL REV_VIDEO ;change it to reverse video
- XOR AH,AH ;bios keyboard input
- INT 16h ;get a keystroke
- PUSH AX
- CALL REV_VIDEO ;put attribute back to normal
- POP AX
- CMP AH,01h ;is it escape?
- JNZ NOT_ESC
- CALL GET_CURS_ADDR ;cursor address for this page
- POP [BX] ;get back cursor position
- RET ;just return to exit
- NOT_ESC: MOV BX,0FF00h ;increment to subtract one row
- CMP AH,48h ;is it up arrow?
- JZ GET_KB_KEY1
- MOV BX,0100h ;increment to add one row
- CMP AH,50h ;is it down arrow?
- JZ GET_KB_KEY1
- MOV BX,0001h ;increment to add one column
- CMP AH,4Dh ;is it right arrow?
- JZ GET_KB_KEY1
- MOV BX,00FFh ;increment to subtract one col.
- CMP AH,4Bh ;is it left arrow?
- JZ GET_KB_KEY1
- XOR BX,BX
- CMP AL,0Dh ;is it a carriage return?
- JNZ GET_KB_KEY1
- MOV DX,TOP_LEFT ;a carriage return was pressed
- MOV BOT_RIGHT,DX ;initialize the second corner
- CALL REV_VIDEO ;change it back to reverse video
- GET_KB_KEY2: XOR AH,AH
- INT 16h ;get a keystroke
- GOT_KEY2: MOV DX,BOT_RIGHT
- CMP AH,48h ;is it up arrow?
- JZ SUB_ROW ;subtract a row from window
- CMP AH,50h ;is it down arrow?
- JZ ADD_ROW ;add a row to the window
- CMP AH,4Dh ;is it right arrow?
- JZ ADD_COL ;add a column to the window
- CMP AH,4Bh ;is it left arrow?
- JZ SUB_COL ;subtract a column from window
- JMP NOT_ARROW_KEY
- SUB_COL: DEC DL ;subtract a column
- CMP DL,LEFT_SIDE ;don't erase it completely
- JL GET_KB_KEY2
- MOV RIGHT_SIDE,DL ;save new right side column
- INC DL
- JMP COL_LOOP
- ADD_COL: INC DL ;add a column
- CMP DL,COLS ;at right edge of screen?
- JNB GET_KB_KEY2 ;stop when screen is filled
- MOV RIGHT_SIDE,DL ;save new right side column
- COL_LOOP: CALL REV_VIDEO ;reverse this character
- DEC DH ;move to next row
- CMP DH,TOP_ROW ;at top row yet?
- JGE COL_LOOP ;loop until at top row
- JMP GET_KB_KEY2
- SUB_ROW: DEC DH
- CMP DH,TOP_ROW ;at top of window?
- JL GET_KB_KEY2 ;dont erase it completely
- MOV BOT_ROW,DH
- INC DH
- JMP ROW_LOOP
- ADD_ROW: INC DH
- CMP DH,ROWS ;at bottom of screen?
- JGE GET_KB_KEY2 ;stop when screen is filled
- MOV BOT_ROW,DH
- ROW_LOOP: CALL REV_VIDEO ;reverse this character
- DEC DL ;move to next column
- CMP DL,LEFT_SIDE ;at left edge yet?
- JGE ROW_LOOP ;continue until at left edge
- JMP GET_KB_KEY2
- NOT_ARROW_KEY: CMP AH,19h ;was it the "p" key?
- JNZ NOT_P
- MOV SEND_CHAR,OFFSET PRINT_CHAR
- CALL READ_WINDOW
- CALL GET_CURS_ADDR ;cursor address for this page
- POP [BX] ;get back cursor position
- RET
- NOT_P: PUSH AX
- MOV AX,BUFFER_ST ;initialize buffer
- MOV BUFF_NEXT,AX
- MOV BUFF_LAST,AX
- POP AX
- MOV SEND_CHAR,OFFSET BUFF_CHAR
- CMP AH,21h ;is it the "f" key
- JNZ NOT_F
- MOV WRIT_FILE,00h
- CALL GET_FILENAME
- CMP WRIT_FILE,0FFh ;was escape requested?
- JZ ERASE_BOX
- CALL READ_WINDOW ;read it now
- MOV WRIT_FILE,01h
- CALL WRITE_TO_FILE ;write it now
- RETURN: CALL GET_CURS_ADDR ;cursor address for this page
- POP [BX] ;get back cursor position
- RET
- NOT_F: CMP AH,01h ;is it escape?
- JZ ERASE_BOX ;if yes, erase box and exit
- CMP AL,0Dh ;is it a carriage return?
- JZ DISPLAY_HELP ;if yes, display help
- JMP GET_KB_KEY2 ;otherwise just get another key
- ERASE_BOX: MOV SEND_CHAR,OFFSET RETURN
- CALL READ_WINDOW
- CALL GET_CURS_ADDR ;cursor address for this page
- POP [BX] ;get back cursor position
- RET
- DISPLAY_HELP: CALL EXCHANGE_HELP ;put up the help menu
- XOR AH,AH
- INT 16h ;get another keystroke
- PUSH AX ;save the keystroke
- CALL EXCHANGE_HELP ;pull down the help menu
- POP AX ;get back the keystroke
- JMP GOT_KEY2
- REV_VIDEO: CALL READ_CHAR ;read character and attribute
- MOV CL,04h ;rotate four counts
- MOV BL,AH ;save attribute in bl
- AND BL,88h ;get blink and intensity bits
- AND AH,77h ;now look only at color bits
- ROR AH,CL ;rotate foreground and background
- OR BL,AH ;put back blink and intensity bits
- CALL DISPLAY_CHAR ;write character and attribute
- RET
- READ_WINDOW: MOV DX,TOP_LEFT ;get location of first corner
- READ_LOOP: CALL REV_VIDEO ;put attribute back to normal
- CALL READ_CHAR ;read the character
- CALL SEND_CHAR ;call to the pointer
- INC DL ;next char in row
- CMP DL,RIGHT_SIDE ;at the right border yet?
- JLE READ_LOOP ;do all characters in this row
- CALL CR_LF ;send cr-lf after each row
- INC DH ;move to next row
- MOV DL,LEFT_SIDE ;back to left edge
- CMP DH,BOT_ROW ;at the bottom border yet?
- JLE READ_LOOP ;read entire window
- RET
- CR_LF: MOV AL,0Dh
- CALL SEND_CHAR ;send a carriage return
- MOV AL,0Ah
- CALL SEND_CHAR ;send a line feed
- RET
- DISPLAY_CHAR: PUSH BX ;save the attribute
- CALL GET_CURS_ADDR ;get address of bios cursor
- MOV [BX],DX ;tell bios where the cursor is
- POP BX ;get back the attribute
- MOV BH,ACTIVE_PAGE ;get active page
- PUSH CX ;save the loop count
- PUSH AX ;int10h fun02 changes AX
- MOV AH,02h ;set cursor position
- INT 10h
- POP AX ;get AX back
- MOV CX,0001h ;write 1 character
- MOV AH,09h ;write character and attribute
- INT 10h
- POP CX ;recover loop count
- RET ;done writing the character
- READ_CHAR: CALL GET_CURS_ADDR ;get address of bios cursor
- MOV [BX],DX ;tell bios where the cursor is
- MOV BH,ACTIVE_PAGE ;get active page
- MOV AH,02h ;set cursor position
- INT 10h
- MOV AH,08h ;bios function to read character
- INT 10h ;read the character/attribute
- RET
- PRINT_CHAR: PUSH DX
- XOR AH,AH ;use function 0
- XOR DX,DX ;printer number 0
- INT 17h ;bios print character function
- ROR AH,1h ;look at bit zero
- JNB PRINT_OK ;did a timeout occur?
- MOV SEND_CHAR,OFFSET RETURN
- PRINT_OK: POP DX
- RET ;done printing character
- BUFF_CHAR: MOV BX,BUFF_LAST ;get location of last character
- MOV [BX],AL ;put the character in buffer
- INC BX ;advance the pointer
- MOV BUFF_LAST,BX ;check for buffer full
- CMP BX,BUFF_END ;is the buffer full yet?
- JNZ BUFF_OK ;if not, keep going
- MOV SEND_CHAR,OFFSET RETURN
- BUFF_OK: RET ;now its in the buffer
- GET_CURS_ADDR: MOV BL,ACTIVE_PAGE ;get the current page number
- XOR BH,BH ;convert to a word offset
- SHL BX,01h ;times two for a word
- ADD BX,OFFSET CURSOR_POSN ;add in base address
- RET
- EXCHANGE_HELP: XOR DX,DX ;start at top left corner
- LEA SI,HELP_MENU
- EXCHANGE_LOOP: CMP DL,0Ch ;at last col. in this row yet?
- JL SWAP_CHAR
- XOR DL,DL ;back to first column
- INC DH ;do the next row
- CMP DH,05h ;at last row yet?
- JL SWAP_CHAR ;quit when last row is done
- RET
- SWAP_CHAR: CALL READ_CHAR ;read character at this position
- XCHG AL,CS:[SI] ;swap with the help text
- MOV BL,AH ;attribute is the same
- CALL DISPLAY_CHAR ;put new character on screen
- INC DL ;point to next position
- INC SI
- JMP EXCHANGE_LOOP
- GET_FILENAME: LEA SI,FILE_PROMPT ;point to the prompt for source
- MOV DX,OFFSET NAME_BUFF ;use buffer for name change
- MOV DI,DX ;set DI to buffer
- XOR DX,DX ;put prompt at top left corner
- MOV CX,40 ;use max of 40 characters
- DISPLAY_PMPT: PUSH CX ;save loop count
- CALL READ_CHAR ;get character on this line
- MOV CS:[DI],AX ;store it in the buffer
- INC DI ;add two for next character
- INC DI
- MOV AL,CS:[SI] ;get next prompt character
- INC SI ;next character in prompt
- MOV BL,47h ;attribute for prompt
- CALL DISPLAY_CHAR ;put up the prompt character
- INC DL ;point to next column
- POP CX ;get back loop count
- LOOP DISPLAY_PMPT ;entire prompt and filename
- DEC SI
- DEC DL
- FIND_LAST_LTR: DEC SI ;backup to last letter
- DEC DL ;backup to last column
- CMP B[SI],00h ;is this a letter?
- JZ FIND_LAST_LTR ;backup until a letter is found
- INC DL ;put blinking box at last letter
- READ_KB: MOV AL,0DBh ;ascii for box character
- MOV BL,0C7h ;make it a blinking box character
- CALL DISPLAY_CHAR ;write the blinking box
- XOR AH,AH ;function 0 to get next key
- INT 16h ;bios keyboard input
- CMP AL,0Dh ;is it a carriage return?
- JZ ERASE_PROMPT
- CMP AL,08h ;is it a backspace?
- JZ BACK_SPACE
- CMP AH,01h ;is it escape?
- JZ ESC_RET
- CMP AL,2Eh ;Is it a valid letter?
- JL READ_KB
- CMP AL,7Ah ;is it a valid letter?
- JG READ_KB
- CMP DL,27h ;only allow 40 characters
- JGE READ_KB
- TTY_KEY: MOV BL,47h ;attribute for filename
- CALL DISPLAY_CHAR ;write the letter
- INC DL ;move to next column
- JMP READ_KB ;get another keystroke
- BACK_SPACE: CMP DL,10h ;at beginning of line?
- JLE READ_KB ;if yes, can't backup from here
- MOV AL,00h ;write a normal blank (ascii 0)
- MOV BL,47h ;attribute for filename
- CALL DISPLAY_CHAR ;write the letter
- DEC DL ;backup the cursor
- JMP READ_KB ;then get the next key
- ESC_RET: MOV WRIT_FILE,0FFh ;indicate escape is requested
- ERASE_PROMPT: XOR AL,AL ;get rid of the cursor
- CALL DISPLAY_CHAR ;write the letter
- LEA DI,FILE_PROMPT ;copy to filename
- MOV DX,OFFSET NAME_BUFF ;copy from buffer
- MOV SI,DX ;set SI to buffer
- XOR DX,DX ;prompt is at row zero
- MOV CX,40 ;copy all 40 characters
- ERASE_LOOP: CALL READ_CHAR ;get character on this line
- MOV CS:[DI],AL ;put in back in memory
- INC DI
- MOV AX,CS:[SI] ;get the original character back
- MOV BL,AH ;put attribute into bl
- INC SI
- INC SI
- CALL DISPLAY_CHAR ;write original character
- INC DL ;move to next column
- LOOP ERASE_LOOP ;erase the entire prompt
- RET
- CLIP ENDP
- SET_IT_UP PROC NEAR
- CLD ;String directions forward
- MOV AH,30h ;Get DOS Version Number
- INT 21h ;DOS call
- CMP AL,2 ;Check for 2.0 +
- JAE DOS_OK
- MOV DX,OFFSET BAD_DOS
- MOV AH,9 ;Write message
- INT 21h ;DOS call
- INT 20h ;Exit
- DOS_OK: PUSH ES ;Save register
- SUB AX,AX
- MOV ES,AX ;Set ES to 0 (BIOS Data)
- MOV AL,ES:[0449h] ;Current Video Mode
- CMP AL,3 ;Check if Color Alpha
- JBE DISP_OK ;Continue if so
- CMP AL,7 ;Check if monochrome display
- JE MONO ;If so, branch
- MOV DX,OFFSET UN_VID_M ;Can't handle graphics
- MOV AH,9 ;Write message
- INT 21h ;DOS call
- INT 20h ;Exit
- MONO: MOV SCRN_SEG,0B000h ;Use Monochrome Segment
- MOV RET_CHECK,0 ;Don't check retrace
- DISP_OK: MOV AL,ES:[044Ah] ;Number of Columns
- MOV COLS,AL ;Save it
- MOV AX,ES:[044Eh] ;Offset to screen buffer
- MOV SCRN_OFFS,AX ;Save it
- MOV AX,ES:[0463h] ;Address of 6845 Regsiter
- MOV ADDR_6845,AX ;Save it
- PUSH ES
- SUB DL,DL ;Set Rows to zero first
- SUB BH,BH
- MOV AX,1130h ;EGA BIOS: Get Information
- INT 10h
- POP ES
- OR DL,DL ;Check if DL is still zero
- JZ NO_EGA ;If so, skip
- INC DL
- MOV ROWS,DL ;Save Number of Lines
- TEST ES:B[0487h],4 ;Check if must check retrace
- JNZ NO_EGA
- MOV RET_CHECK,0 ;EGA, don't have to
- NO_EGA: MOV BH,ES:[0462h] ;Get Current Page
- MOV CUR_PAGE,BH ;Save it
- POP ES
- MOV AL,COLS ;Length of each line
- MUL ROWS ;Total chars on screen
- ADD AX,AX ;Double for attributes
- MOV SCRN_SIZE,AX ;Save it
- CMP ATTR,0 ;Check if attribute pre-set
- JNZ GOT_ATTR ;If so, continue
- MOV DL,' ' ;Write out a byte
- MOV AH,2 ;using DOS
- INT 21h ;DOS call
- MOV AL,8 ;Backspace
- MOV AH,14 ;using BIOS call
- INT 10h
- MOV AH,8 ;Read character & attribute
- MOV BH,CUR_PAGE ;Current page from above
- INT 10h ;Using BIOS call (BH = pg)
- GOT_ATTR: MOV ATTR,AH ;Save attribute
- ADD AX,OFFSET BUFF ;Add Screen size to code end
- ADD AX,8934h
- ADD AX,256 ;Add some stack room
- CMP AX,SP ;Check if stack pointer
- JBE MEMOK ;Continue if OK
- MOV DX,OFFSET N_ENF_MEM ;Otherwise end program
- MOV AH,9 ;Write message
- INT 21h ;DOS call
- INT 20h ;Exit
- MEMOK: PUSH ES ;save it
- MOV AX,0040h ;bios segment
- MOV ES,AX
- MOV AX,ES:W[050h]
- MOV CURSOR_POSN,AX ;cursor position
- MOV CURSOR_HOLD,AX ;keep for reset
- MOV AL,ES:[0062h] ;active page
- MOV ACTIVE_PAGE,AL
- POP ES ;get it back
- MOV W[FILE_OFFS],-1 ;reset buffers
- MOV W[FILE_OFFS + 2],-1
- MOV AX,OFFSET BUFF
- MOV BUFFER_ST,AX ;buffer bookkeeping
- MOV BUFF_NEXT,AX
- MOV BUFF_LAST,AX
- ADD AX,BUFF_SIZE
- MOV BUFF_END,AX
- MOV ES,W[ENVIRONMENT] ;Environment Segment
- SUB DI,DI ;Start search at beginning
- CLD ;String increment to forward
- TRY_IT: ES CMP B[DI],0 ;See if end of environment
- JZ NO_FIND ;If so, we have failed
- PUSH DI ;Save environment pointer
- MOV SI,OFFSET COMSPEC ;String to search for
- MOV CX,8 ;Characters in search string
- REPZ CMPSB ;Check if strings are same
- POP DI ;GEt back the pointer
- JZ FOUND ;Found string only zero flag
- SUB AL,AL ;Zero out AL
- MOV CX,8000H ;Set for big search
- REPNZ SCASB ;Find the next zero in string
- JMP TRY_IT ;And do the search from there
- NO_FIND: MOV DX,OFFSET COMMANDMSG ;Message for COMSPEC error
- JMP ERROREXIT ;Print it and exit
- FOUND: ADD DI,8 ;So points after 'COMSPEC='
- MOV COMMANDASCIIZ1,DI ;Save the address of
- MOV COMMANDASCIIZ2,ES ;COMMAND ASCIIZ
- MOV [PARAMBLOCK],ES ;Segment of Environment string
- MOV [PARAMBLOCK + 4],CS ;Segment of this program
- MOV [PARAMBLOCK + 8],CS ;so points to FCB's
- MOV [PARAMBLOCK + 12],CS ;and NewParameter
- PUSH CS ;Push this segment so we can
- POP ES ;set ES to it
- MOV B[NEWPARAMETER],06h ;Counter
- MOV W[NEWPARAMETER + 1],'C/' ;i.e. '/C'
- MOV W[NEWPARAMETER + 3],'ID' ;Then 'DI'
- MOV W[NEWPARAMETER + 5],' R' ;And 'R '
- JMP SAV_SCRN
- ERROREXIT: MOV AH,9 ;Set up for string write
- INT 21h ;Using DOS
- INT 20h ;Dishonorable discharge
- RET
- SAV_SCRN: MOV DI,OFFSET BUFF ;Screen destination
- ADD DI,8834h
- MOV CX,SCRN_SIZE ;Screen size
- PUSH DS ;Save source segment
- MOV SI,SCRN_OFFS ;Get screen offset
- MOV DS,SCRN_SEG ;Get screen segment
- REP MOVSB ;Move in the bytes
- POP DS ;Restore source segment
- RET
- SET_IT_UP ENDP
- CLS_MSG PROC NEAR
- MOV AX,0700h ;clear screen
- MOV BX,0700h ;attribute
- MOV CX,0000h ;top left
- MOV DH,ROWS
- MOV DL,COLS
- SUB DH,01h
- SUB DL,01h ;bottom right
- INT 10h ;BIOS call
- MOV BH,CUR_PAGE ;page number
- MOV AH,02h ;move cursor
- MOV DX,0A00h ;10 lines from top
- INT 10h ;BIOS call
- MOV DX,OFFSET N_F_MSG ;print message
- MOV AH,09h
- INT 21h ;DOS call
- MOV AH,02h ;move cursor
- MOV BH,CUR_PAGE ;page number
- MOV DX,1111h ;to line 17
- INT 10H ;BIOS call
- RET
- CLS_MSG ENDP
- GET_NAME PROC NEAR
- GET_NAME_1: MOV SI,0081h ;Points to parameter
- NAM_SCH: LODSB ;Get byte
- CMP AL,13 ;Carriage return ?
- JZ NO_NAM ;If so, noname
- MOV DI,OFFSET DELIMIT ;String of delimiters
- MOV CX,5 ;Number of delimiters (no /)
- REPNE SCASB ;Match ?
- JE NAM_SCH ;If a delimiter, keep looking
- MOV DX,SI ;Otherwise found file name
- DEC DX ;Points to beginning of it
- END_SRCH: LODSB ;Get next byte
- CMP AL,13 ;Carriage return ?
- JE GOT_END ;If so, done
- MOV DI,OFFSET DELIMIT ;String of delimiters
- MOV CX,6 ;Number (including /)
- REPNE SCASB ;Match ?
- JNE END_SRCH ;If not, still in file name
- MOV B[SI - 1],0 ;If so, mark end of file name
- JCXZ GOT_FLAG ;If slash, check for W
- JMP END_SRCH ;Or continue flag search
- GOT_FLAG: LODSB ;Get byte after / flag
- OR AL,20h ;Uncapitalize
- CMP AL,'W' ;See if w for WordStar mode
- JNZ GOT_END ;If not, ignore it
- MOV NON_W_S,7Fh ;AND value for WordStar
- GOT_END: MOV B[SI - 1],0 ;Mark end of file name
- ;DX still points to name
- MOV AX,3D00h ;Open file for reading
- INT 21h ;DOS call
- JNC GOT_FILE ;Continue
- NO_NAM: MOV DX,OFFSET FILE_NOT_F;Print a message
- MOV AH,9 ;Write message
- INT 21h ;DOS call
- PUSH BX
- MOV BX,0002h
- CALL TIME_SEC
- POP BX
- CALL NEW_FILE ;try again
- JMP GET_NAME_1
- GOT_FILE: MOV FHANDLE,AX ;Save file handle
- RET
- GET_NAME ENDP
- NEW_FILE PROC NEAR
- MOV AL,DIR_FLAG
- CMP AL,00h
- JNE NEW_FILE_2D
- NEW_FILE_P1: CALL CLS_MSG ;Cls and print msg
- NEW_FILE_2D: MOV AL,00h
- MOV DIR_FLAG,AL
- PUSH DI ;save DI
- MOV DI,0080h ;for file to read
- N_F_LOOP: INC DI ;increment DI
- N_F_LOOP_P1: MOV AX,0100h ;get character
- INT 21h ;DOS call
- CMP AL,0 ;Extended?
- JNZ NO_EXT
- MOV AX,0100h ;Get extended
- INT 21h ;DOS call
- CMP AL,20h ;Alt-D?
- JNZ N_F_LOOP_P1
- CALL GET_DIR ;Get dir.
- POP DI ;Keep stack true
- JMP NEW_FILE_P1
- NO_EXT: CMP AL,27 ;ESC ?
- JNE DONT_QUIT ;go on
- CALL QUIT ;quit
- DONT_QUIT: CMP AL,08 ;backspace ?
- JNE N_F_L_1
- DEC DI ;decrement DI
- DEC DI ;twice
- CMP DI,080h ;not too far back
- JGE N_F_L_2
- INC DI ;neutral DI
- MOV BH,0 ;page number
- MOV AH,3 ;get cursor
- INT 10h ;BIOS call
- INC DL ;cancel backspace
- MOV AH,2 ;by moving cursor
- INT 10h ;BIOS call
- N_F_L_2: MOV AX,0A20h ;write space
- MOV CX,01 ;one character
- INT 10h ;BIOS call
- JMP N_F_LOOP ;go for another char.
- N_F_L_1: MOV B[DI],AL ;save character
- CMP AL,0Dh ;was it CR
- JE EX_LOOP ;got filename
- CMP DI,0AAh ;too many char ?
- JGE EX_LOOP ;test filename
- JMP N_F_LOOP ;get another letter
- EX_LOOP: POP DI ;recover DI
- MOV W[FILE_OFFS],-1;reset buffers
- MOV W[FILE_OFFS + 2],-1
- MOV AX,OFFSET BUFF
- MOV BUFFER_ST,AX
- MOV BUFF_NEXT,AX
- MOV BUFF_LAST,AX
- RET
- NEW_FILE ENDP
- HELP_ME PROC NEAR
- MOV DI,081h
- MOV SI,OFFSET HELP_DOC
- MOV CX,000D
- REP MOVSB
- MOV W[FILE_OFFS],-1;reset buffers
- MOV W[FILE_OFFS + 2],-1
- MOV AX,OFFSET BUFF
- MOV BUFFER_ST,AX
- MOV BUFF_NEXT,AX
- MOV BUFF_LAST,AX
- RET
- HELP_ME ENDP
- GET_DIR PROC NEAR
- MOV AH,07 ;Clear screen
- MOV AL,0
- MOV BH,07h
- MOV CX,0000h
- MOV DH,ROWS
- SUB DH,01
- MOV DL,COLS
- SUB DL,01
- INT 10h
- MOV AH,02h ;Set cursor position
- MOV BH,CUR_PAGE
- MOV DX,0A00h
- INT 10H
- MOV AH,09
- MOV DX,OFFSET A_D_MSG ;Want another directory?
- INT 21h
- PATH_L_M: MOV BL,CHAR_COUNT
- MOV LAST_CHAR_COUNT,BL ;Save old count
- MOV BX,0006h
- MOV CHAR_COUNT,BL ;Initialize character count
- MOV AX,0020h
- ADD BL,NEWPARAMETER
- MOV B[BX],AL ;Store the character
- PATH_LOOP: INC CHAR_COUNT ;Add a character to path
- MOV AH,00h
- MOV DIR_FLAG,AH ;Reset DIR_FLAG
- MOV AH,CHAR_COUNT
- MOV [NEWPARAMETER],AH
- MOV AH,01h ;Get the character
- INT 21h ;Using DOS
- CMP AL,00h ;Extended?
- JNZ SKIP_IT
- MOV AH,01h
- INT 21h
- CMP AL,20h
- JNZ SKIP_IT
- MOV BH,0 ;To make word from byte
- MOV BL,NEWPARAMETER
- ADD BL,LAST_CHAR_COUNT ;At this location
- MOV B[BX],02Fh
- ADD BX,01h
- MOV B[BX],057h
- ADD BX,01h
- MOV B[BX],0Dh
- SUB BL,07Bh
- MOV [NEWPARAMETER],BL
- INC DIR_FLAG
- JMP CAR_RET
- SKIP_IT: CMP AL,1Bh ;Esc?
- JZ THATS_ALL
- CMP AL,08h ;Backspace?
- JZ BACK_SP
- MOV BH,0 ;To make word from byte
- MOV BL,NEWPARAMETER
- ADD BL,CHAR_COUNT ;At this location
- MOV B[BX],AL ;Store the character
- CMP AL,0Dh ;CR?
- JZ CAR_RET
- JMP PATH_LOOP ;Get another character
- BACK_SP: DEC CHAR_COUNT ;Cancel inc command
- MOV AH,CHAR_COUNT
- MOV [NEWPARAMETER],AH ;Readjust count
- CMP CHAR_COUNT,06
- JBE PATH_LOOP ;Not before start
- DEC CHAR_COUNT ;One space back
- MOV DL,' ' ;Use space
- MOV AH,02 ;To remove char on screen
- INT 21h ;Using DOS
- MOV AH,03 ;Get cursor position
- MOV BH,CUR_PAGE ;On current page
- INT 10h ;Using BIOS
- MOV AH,02 ;Move cursor
- DEC DL ;back one space
- INT 10h ;using BIOS
- JMP PATH_LOOP ;Get another character
- CAR_RET: MOV BX,OFFSET PARAMBLOCK ;ES:BX = address of block
- MOV DX,COMMANDASCIIZ1 ;DS:DX = address of ASCIIZ
- MOV DS,COMMANDASCIIZ2
- MOV AX,4B00H ;EXEC call 4Bh, type 0
- INT 21H ;Load command processor
- PUSH CS
- POP DS ;restore DS
- MOV AH,DIR_FLAG
- CMP AH,00h
- JZ SKPIT
- POP AX ;Fake RET
- MOV AH,09
- MOV DX,OFFSET N_F_MSG ;Want new file name
- INT 21h
- CALL THATS_ALL
- JMP NO_NEW_0
- SKPIT: MOV AH,09
- MOV DX,OFFSET A_D_MSG ;Want another directory?
- INT 21h
- JMP PATH_L_M ;Get another directory
- THATS_ALL: MOV AX,CS ;Get this segment in AX
- MOV DS,AX ;Set DS to it
- MOV SS,AX ;And SS for stack segment
- RET
- GET_DIR ENDP
- KEYS PROC NEAR
- KEYS_1: CALL HOME ;Read file
- MOV SCRN_PT,SI ;Save buffer address
- KEY_LOOP: CALL WRIT_SCRN ;Write file to screen
- GET_KEY: MOV AH,8 ;Get key
- INT 21h ;DOS call
- CMP AL,00
- JE GO_NEXT
- CMP AL,057h
- JZ TOG_WRAP
- CMP AL,077h
- JZ TOG_WRAP
- JMP NO_TOG_WRAP
- TOG_WRAP: XOR WRAP_FLAG,01h
- JMP KEYS_1
- NO_TOG_WRAP: CMP AL,44h ;D for dir
- JNE NO_DIR_1
- YES_DIR: CALL GET_DIR
- JMP KEYS_1
- NO_DIR_1: CMP AL,64h ;d for dir
- JNE NO_DIR_2
- JMP YES_DIR
- NO_DIR_2: CMP AL,6Eh ;n for new file
- JNE NO_NEW_1
- NO_NEW_0: MOV BX,FHANDLE ;Get File Handle
- MOV AH,3Eh ;Close File
- INT 21h ;DOS call
- CALL NEW_FILE ;get a new file
- CALL GET_NAME
- JMP KEYS_1
- X_GET_KEY: JMP GET_KEY
- NO_NEW_1: CMP AL,4Eh ;N for new file
- JNE NO_NEW_2
- JMP NO_NEW_0
- NO_NEW_2: CMP AL,48h ;H for help
- JNE NO_NEW_3
- JMP H_HELP
- NO_NEW_3: CMP AL,68h ;h for help
- JNE NO_NEW_4
- H_HELP: MOV BX,FHANDLE ;Get File Handle
- MOV AH,3Eh ;Close File
- INT 21h ;DOS call
- CALL HELP_ME
- CALL GET_NAME
- JMP KEYS_1
- NO_NEW_4: CMP AL,27 ;ESC ?
- JNE NO_QT ;Quit
- CALL QUIT
- NO_QT: CMP AL,32 ;Space bar ?
- JNE GO_NEXT ;Go on if not
- CALL CLIP ;Get Clip
- JMP KEY_LOOP ;Do it
- GO_NEXT: CMP AL,0 ;Check if extended
- JNZ X_GET_KEY ;If not, try again
- MOV AH,8 ;Get extended code
- INT 21h ;DOS call
- CMP AL,20h ;Alt-D dir request
- JZ YES_DIR ;Get directory
- SUB AL,71 ;Subtract Home key value
- JB X_GET_KEY ;If below that, not valid
- CMP AL,(81 - 71) ;Check if above PgDn
- JA X_GET_KEY ;If so, ignore it
- SUB AH,AH ;Zero top byte
- ADD AX,AX ;Double for word access
- MOV BX,AX ;Offset in Send table
- MOV SI,SCRN_PT ;Set buffer address
- CALL [SEND + BX] ;Do the call
- MOV SCRN_PT,SI ;Set buffer address
- JMP KEY_LOOP ;Update the screen
- RET
- KEYS ENDP
- HOME PROC NEAR
- SUB BX,BX ;Zero out values
- MOV AX,W[FILE_OFFS];Check if read in file
- OR AX,W[FILE_OFFS + 2]
- MOV W[FILE_OFFS],BX;Zero file address
- MOV W[FILE_OFFS + 2],BX
- MOV HORIZ_OFFS,BX ;Zero horizontal offset
- MOV SI,OFFSET BUFF ;Reset buffer address
- ADD SI,834h
- JZ NO_READ ;Skip file read if in already
- MOV CX,8000h ;Number of bytes to read
- MOV DX,OFFSET BUFF ;Area to read file to
- ADD DX,834h
- CALL READ_FILE ;Read in file
- NO_READ: RET
- HOME ENDP
- UP PROC NEAR
- CALL PREV_CHAR ;Get previous char in buffer
- JC UP_DONE ;If none available, finish
- UP_LOOP: CALL PREV_CHAR ;Get previous char again
- JC UP_DONE ;if none, done
- CMP AL,10 ;Line feed ?
- JNZ UP_LOOP ;Try again
- CALL NEXT_CHAR ;Get char after line feed
- UP_DONE: RET
- UP ENDP
- PG_UP PROC NEAR
- MOV CL,ROWS ;Number of lines
- PG_UP_LOOP: CALL UP ;Do UP that many times
- LOOP PG_UP_LOOP
- RET
- PG_UP ENDP
- LEFT PROC NEAR
- MOV HORIZ_OFFS,0 ;Reset horizontal offset
- RET
- LEFT ENDP
- RIGHT PROC NEAR
- MOV AL,HORIZ_SHFT ;Get places to shift
- SUB AH,AH
- ADD HORIZ_OFFS,AX ;Move right that many
- RET
- RIGHT ENDP
- ENDD PROC NEAR
- MOV BX,SI ;Save buffer address
- CALL PG_DN ;Do page down
- CMP BX,SI ;Check if done
- JNZ ENDD ;If so, do it again
- RET
- ENDD ENDP
- DOWN PROC NEAR
- CALL NEXT_CHAR ;Get next character
- JC NO_MORE_DOWN ;If no more, we're done
- DOWN_LOOP: CALL NEXT_CHAR ;Get one more
- JC UP_LOOP ;If no more, get prev LF
- CMP AL,10 ;Line feed ?
- JNZ DOWN_LOOP ;Continue
- NO_MORE_DOWN: RET
- DOWN ENDP
- PG_DN PROC NEAR
- MOV CL,ROWS ;Number of lines
- PG_DN_LOOP: CALL DOWN ;Do DOWN that many times
- LOOP PG_DN_LOOP
- RET
- PG_DN ENDP
- DUMMY PROC NEAR
- RET
- DUMMY ENDP
- TIME_SEC PROC NEAR ;time delay in BL
- PUSH AX
- PUSH BX
- MOV AX,BX
- MOV BL,18
- MUL BL
- MOV BX,AX
- PUSH CX
- PUSH DX
- MOV AH,00h
- INT 1Ah
- ADD BX,DX
- TIME_1: MOV AH,00h
- INT 1Ah
- CMP BX,DX
- JNE TIME_1
- POP DX
- POP CX
- POP BX
- POP AX
- RET
- TIME_SEC ENDP
- READ_FILE: PUSH AX ;Save some registers
- PUSH BX
- PUSH CX
- PUSH DX
- MOV BUFF_PT,-1 ;Initialize this
- MOV DX,W[FILE_OFFS];Get file address to read
- MOV CX,W[FILE_OFFS + 2]
- MOV BX,FHANDLE ;Get file Handle
- SUB AL,AL ;From beginning
- MOV AH,42h ;Move file pointer call
- INT 21h ;DOS call
- POP DX ;Get back destination
- POP CX ;Get back count
- MOV AH,3Fh ;Read file function call
- INT 21h ;DOS call
- JNC NO_ERR ;If no error, continue
- SUB AX,AX ;Otherwise read zero bytes
- NO_ERR: CMP AX,CX ;See if 32K has been read
- JE GOT_ALL ;If so, done
- ADD AX,DX ;Otherwise add to buffer addr
- MOV BUFF_PT,AX ;And save as end of file
- GOT_ALL: POP BX
- POP AX
- RET
- READ_FILE ENDP
- WRIT_SCRN PROC NEAR
- PUSH ES
- MOV SI,SCRN_PT ;Address of data in buffer
- MOV DI,SCRN_OFFS ;Display offset
- MOV ES,SCRN_SEG ;Display segment
- CMP WRAP_FLAG,1
- JNZ WRAP1
- SUB CX,CX
- MOV HORIZ_OFFS,CX
- WRAP1: MOV CX,SCRN_SIZE ;Number of bytes in screen
- SHR CX,1 ;Half for number of chars
- MOV AL,' ' ;Blank screen
- MOV AH,ATTR ;With screen attribute
- REP STOSW ;Blank it
- MOV AL,COLS ;Display line length
- SUB AH,AH
- ADD AX,HORIZ_OFFS ;Add horizontal offset
- MOV RGT_MRGN,AX ;Right display margin
- SUB DL,DL ;Line Number
- LINE_LOOP: SUB BX,BX ;Column Number
- MOV AL,COLS ;Use Line Length
- MUL DL ;And Line Number
- ADD AX,AX ;To recalculate
- MOV DI,AX ;Display destination
- ADD DI,SCRN_OFFS ;Add beginning address
- CHAR_LOOP: CALL NEXT_CHAR ;Get next character
- JC SCRN_END ;If no more, done
- AND AL,NON_W_S ;Will be 7Fh for WordStar
- CMP AL,13 ;Check for carriage return
- JE CHAR_LOOP ;Do nothing if so
- CMP AL,10 ;Check for line feed
- JE LINE_FEED ;Do routine if so
- CMP AL,9 ;Check for tab
- JE TAB ;Do routine if so
- MOV CX,1 ;Just 1 char to display
- PRINT_CHR: CMP BX,HORIZ_OFFS ;See if we can print it
- JB NO_PRINT
- CMP WRAP_FLAG,1 ;Wrap around?
- JNZ WRAP_IT
- CMP BX,RGT_MRGN
- JB WRAP_IT
- MOV BX,0000
- INC DL
- WRAP_IT: CMP BX,RGT_MRGN ;See if within margin
- JAE NO_PRINT
- MOV AH,ATTR ;Attribute for display
- CMP RET_CHECK,0 ;See if must stop snow
- JZ WRITE_IT ;If not, skip retrace wait
- PUSH BX
- PUSH DX
- MOV BX,AX ;Save character and attribute
- MOV DX,ADDR_6845 ;Set up I/O address
- ADD DX,6
- RETR_WAIT_1: IN AL,DX ;Check until
- SHR AL,1 ;Vertical retrace
- JC RETR_WAIT_1 ;Ends
- CLI ;Clear interrupts
- RETR_WAIT_2: IN AL,DX ;Check until
- SHR AL,1 ;Vertical retrace
- JNC RETR_WAIT_2 ;Begins
- MOV AX,BX ;Get back char & attr
- STOSW ;Write to display
- STI ;Enable interrupts again
- POP DX
- POP BX
- JMP NO_PRINT ;Skip around "no snow"
- LINE_LOOP_1: JMP LINE_LOOP
- WRITE_IT: STOSW ;Write without retrace wait
- NO_PRINT: INC BX ;Inc line counter
- LOOP PRINT_CHR ;Do it CX times
- JMP CHAR_LOOP ;Go back to top
- TAB: MOV AX,BX ;Column number
- AND AX,07h ;Take lower three bits
- MOV CX,8
- SUB CX,AX ;Subtract from 8
- MOV AL,' ' ;Print CX blanks
- JMP PRINT_CHR
- LINE_FEED: INC DL ;Next line
- CMP DL,ROWS ;See if at bottom
- JB LINE_LOOP_1 ;If not, continue
- SCRN_END: POP ES ;All done -- quit
- RET
- WRIT_SCRN ENDP
- PREV_CHAR PROC NEAR
- PUSH AX
- MOV AX,OFFSET BUFF
- ADD AX,834h
- CMP SI,AX ;See if at top of buffer
- POP AX
- JA C_G_P ;If not, get character
- MOV AX,W[FILE_OFFS];See if at top of file
- OR AX,W[FILE_OFFS + 2]
- JZ ATTOP ;If so, can't get anymore
- PUSH CX ;Save some registers
- PUSH DX
- MOV SI,OFFSET BUFF ;Move 1st half of buffer
- ADD SI,834h
- MOV DI,OFFSET BUFF ;to 2nd half of buffer
- ADD DI,4834h
- MOV CX,4000h ;Bytes to move
- ADD SCRN_PT,CX ;New buffer address
- REP MOVSB ;Do the move
- SUB W[FILE_OFFS],4000h ;Adjust file addr for read
- SBB W[FILE_OFFS + 2],0
- MOV DX,OFFSET BUFF ;Area to read file into
- ADD DX,834h
- MOV CX,4000h ;Number of bytes
- CALL READ_FILE ;Read the file
- POP DX ;Get back registers
- POP CX
- JMP C_G_P ;Now get character
- ATTOP: STC ;CY flag set for no more
- RET
- C_G_P: DEC SI ;Move pointer back
- MOV AL,[SI] ;Get the character
- CLC ;CY flag reset for success
- RET
- PREV_CHAR ENDP
- NEXT_CHAR PROC NEAR
- NXT_CHAR: CMP SI,BUFF_PT ;End of file ?
- JAE NO_CHAR ;If so, no more chars
- PUSH AX
- MOV AX,OFFSET BUFF
- ADD AX,8834h
- CMP SI,AX ;End of buffer ?
- POP AX
- JB GT_NXT ;If not, get char
- PUSH CX ;Save registers
- PUSH DX
- PUSH DI
- PUSH ES
- PUSH DS ;Set ES to DS
- POP ES ;(could be different)
- MOV SI,OFFSET BUFF ;Move 2nd buffer half
- ADD SI,4834h
- MOV DI,OFFSET BUFF ;to 1st buffer half
- ADD DI,834h
- MOV CX,4000h
- SUB SCRN_PT,CX ;New buffer pointer
- REP MOVSB ;Move them
- MOV SI,DI ;SI also buffer pointer
- ADD W[FILE_OFFS],8000h ;Adjust file addr to read
- ADC W[FILE_OFFS + 2],0
- MOV DX,OFFSET BUFF ;Place to read file
- ADD DX,4834h
- MOV CX,4000h ;Number of bytes
- CALL READ_FILE ;Read the file
- SUB W[FILE_OFFS],4000h ;Adjust address
- SBB W[FILE_OFFS + 2],0 ;1st half of buffer
- POP ES ;Get back registers
- POP DI
- POP DX
- POP CX
- JMP NXT_CHAR ;Try again to get char
- GT_NXT: LODSB ;Get the character
- NO_CHAR: CMC ;Set CY if no more
- RET
- NEXT_CHAR ENDP
- QUIT PROC NEAR
- MOV SI,OFFSET BUFF ;Address of saved screen
- ADD SI,8834h
- MOV DI,SCRN_OFFS ;Display offset
- MOV ES,SCRN_SEG ;Display segment
- MOV CX,SCRN_SIZE ;Number of characters
- REP MOVSB ;Move them back
- MOV BX,FHANDLE ;Get File Handle
- MOV AH,3Eh ;Close File
- INT 21h ;DOS call
- MOV AH,02h ;reset
- MOV DX,CURSOR_HOLD ;cursor
- MOV BH,CUR_PAGE ;position
- INT 10h
- MOV DX,OFFSET MSG ;Thank You
- MOV AH,9 ;Write message
- INT 21h ;DOS call
- INT 20h ;Exit
- RET
- QUIT ENDP
- BUFF:
- CSEG ENDS ;End of segment
- END