; ============================================================================
;
; LT-DOS - Int 21h console
;
; ============================================================================
SPACE EQU 20h ; space character (first printable)
DELETE EQU 7fh ; delete character
TAB EQU 9 ; tabulator character
CR EQU 13 ; CR character (Carriage Return)
LF EQU 10 ; LF character (Line Feed)
; ----------------------------------------------------------------------------
; Push registers and execute console device transfer
; ----------------------------------------------------------------------------
; ------------- Store return address
StdPush: pop word [cs:ConPushAddr] ; store return address
; ------------- Push registers
; ----------------------------------------------------------------------------
; Slow write character to STDOUT (in file mode)
; ----------------------------------------------------------------------------
; INPUT: AL = character
; ----------------------------------------------------------------------------
StdSWrite:
; ----------------------------------------------------------------------------
; Direct write character to STDOUT
; ----------------------------------------------------------------------------
; INPUT: AL = character
; ----------------------------------------------------------------------------
; ------------- Push registers
StdWrite: push bx ; push BX
push di ; push DI
push es ; push ES
; ------------- Get FCB of STDIN file (-> ES:DI)
mov bx,STDOUT ; BX <- 1 standard output device
call GetFileFCB ; get FCB of file
jc StdWrite8 ; error
; ------------- Check if it is fast character device Int 29h
test byte [es:di+OFT_DevAttr-OFT_FCB],B7 ; is it character device?
jz StdWrite6 ; no, it is block device
push ds ; push DS
lds bx,[es:di+OFT_Device-OFT_FCB] ; DS:BX <- device header
test byte [bx+DDH_attr],DEV_FAST ; use fast Int 29h?
pop ds ; pop DS
jz StdWrite6 ; don't use fast Int 29h
; ------------- Output character with fast Int 29h
int 29h ; output character
jmp short StdWrite8
; ------------- Output character in file mode
StdWrite6: call StdSWrite ; slow output to STDOUT
; ------------- Pop registers
StdWrite8: pop es ; pop ES
pop di ; pop DI
pop bx ; pop BX
ret
; ----------------------------------------------------------------------------
; Int 21h, function 01h - read character from STDIN with echo to STDOUT
; ----------------------------------------------------------------------------
; INT21 INPUT: AH = 01h (function code)
; INT21 OUTPUT: AL = ASCII character (8 bits) or 0 if extended ASCII follows
; ----------------------------------------------------------------------------
; NOTES: - Does echo on STDOUT
; - Check for Ctrl+C (executes Int 23h)
; - 0 means that extended ASCII code follows
; - Ctrl+P toggles the DOS-internal echo-to-printer flag
; ----------------------------------------------------------------------------
Int2101:
; call Int21022 ; output character to STDOUT
ret
; ----------------------------------------------------------------------------
; Write character or control character to STDOUT
; ----------------------------------------------------------------------------
; INPUT: AL = character to write
; DESTROYS: AL
; ----------------------------------------------------------------------------
; ------------- Write printable character
StdOutCtrl: cmp al,SPACE ; is it control character?
jae StdOutCh1 ; write printable character
; ------------- Write tabulator
cmp al,TAB ; is it tabulator?
je StdOutCh1 ; write tabulator
; ------------- Print control character
push ax ; push AX
mov al,'^' ; ^ character
call StdOutCh1 ; print ^ character
pop ax ; pop AX
or al,40h ; convert to printable character
jmp short StdOutCh1 ; print character
; ----------------------------------------------------------------------------
; Int 21h, function 02h - write character to STDOUT
; ----------------------------------------------------------------------------
; INT21 INPUT: AH = 02h (function code)
; DL = ASCII character to write
; INT21 OUTPUT: AL = writted ASCII character (= DL, 9 is expanded to 20h)
; ----------------------------------------------------------------------------
; NOTES: - If character is 08h (BS) it moves 1 position left
; - Check for Ctrl+C (executes Int 23h)
; ----------------------------------------------------------------------------
; ------------- Character to output
Int2102: xchg ax,dx ; AL <- character to output
; StdOutChar function must follow!
; ----------------------------------------------------------------------------
; Write character to STDOUT
; ----------------------------------------------------------------------------
; INPUT: AL = character to write
; ----------------------------------------------------------------------------
; ------------- Check if it is control character
StdOutCh: cmp al,SPACE ; is it control character?
jb StdOutCh4 ; it is control character
; ------------- Increase character position (except DELETE character)
StdOutCh1: cmp al,DELETE ; is it DELETE character?
je StdOutCh2 ; it is DELETE character, skip
inc byte [cs:CharPos] ; increase character position
; ------------- Break test
StdOutCh2: dec byte [cs:BreakCount] ; Break test counter
jnz StdOutCh3 ; do not do break test
mov byte [cs:BreakCount],4 ; init new break test counter
call ConCtrl ; console control service
StdOutCh3:
BreakCounter
StdOutCh4:
; ----------------------------------------------------------------------------
; Int 21h, function 06h - direct STDIN or STDOUT
; ----------------------------------------------------------------------------
; INT21 INPUT: AH = 06h (function code)
; DL = ASCII character to write (except 0ffh)
; or DL = 0ffh to read ASCII character
; INT21 OUTPUT: AL = writted ASCII character (on write = DL, 9 expands to 20h)
; if read character:
; ZF is set (=ZY) if no character available, AL = 0
; ZF is clear (=NZ) if character available
; ----------------------------------------------------------------------------
; NOTES: - Does not check for Ctrl+C
; ----------------------------------------------------------------------------
Int2106:
; ----------------------------------------------------------------------------
; Int 21h, function 07h - read character from STDIN without echo
; ----------------------------------------------------------------------------
; INT21 INPUT: AH = 07h (function code)
; INT21 OUTPUT: AL = ASCII character (8 bits) or 0 if extended ASCII follows
; ----------------------------------------------------------------------------
; NOTES: - Does not check for Ctrl+C
; - 0 means that extended ASCII code follows
; ----------------------------------------------------------------------------
Int2107:
ret
; ----------------------------------------------------------------------------
; Int 21h, function 08h - read character from STDIN without echo
; ----------------------------------------------------------------------------
; INT21 INPUT: AH = 08h (function code)
; INT21 OUTPUT: AL = ASCII character (8 bits) or 0 if extended ASCII follows
; ----------------------------------------------------------------------------
; NOTES: - Check for Ctrl+C (executes Int 23h)
; - 0 means that extended ASCII code follows
; ----------------------------------------------------------------------------
Int2108:
ret
; ----------------------------------------------------------------------------
; Int 21h, function 09h - write string to STDOUT
; ----------------------------------------------------------------------------
; INT21 INPUT: AH = 09h (function code)
; DS:DX = ASCII string terminated with '$' dollar character
; INT21 OUTPUT: AL = '$'
; ----------------------------------------------------------------------------
; NOTES: - Check for Ctrl+C (executes Int 23h)
; ----------------------------------------------------------------------------
Int2109:
; ----------------------------------------------------------------------------
; Int 21h, function 0Ah - read string from STDIN
; ----------------------------------------------------------------------------
; INT21 INPUT: AH = 0Ah (function code)
; DS:DX = buffer:
; 0: (1) (in) maximum characters
; 1: (1) (in/out) number of chars in buffer, without CR
; 2: (N) characters with the final CR
; INT21 OUTPUT: buffer filled with user input
; ----------------------------------------------------------------------------
; NOTES: - Check for Ctrl+C (executes Int 23h)
; ----------------------------------------------------------------------------
Int210A:
; ----------------------------------------------------------------------------
; Int 21h, function 0Bh - get STDIN status
; ----------------------------------------------------------------------------
; INT21 INPUT: AH = 0Bh (function code)
; INT21 OUTPUT: AL = status
; 0: no character available
; 1: character is available
; ----------------------------------------------------------------------------
; NOTES: - Check for Ctrl+C (executes Int 23h)
; ----------------------------------------------------------------------------
Int210B:
; ----------------------------------------------------------------------------
; Int 21h, function 0Ch - flush buffer and read from STDIN
; ----------------------------------------------------------------------------
; INT21 INPUT: AH = 0Ch (function code)
; INT21 OUTPUT: AL = function (1, 6, 7, 8, 0Ah as in Int 21h functions)
; ----------------------------------------------------------------------------
Int210C:
; ----------------------------------------------------------------------------
; Break test during Int 21h function
; ----------------------------------------------------------------------------
; NOTES: - If Ctrl+C (or Ctrl+Break) occurs, it terminates program
; ----------------------------------------------------------------------------
; ------------- Test if DOS function is active at first (basic) level
BreakTest: cmp byte [cs:DOSActive],1 ; DOS is active at first level?
jne BreakTest9 ; DOS is not active at fist level
; ------------- Push registers
push ax ; push AX
push bx ; push BX
push si ; push SI
push ds ; push DS
push es ; push ES
; ------------- Prepare DDR
mov bx,DOSDDR ; BX <- DOS DDR table pointer
push cs ; push CS
pop ds ; DS <- CS
mov byte [bx+DDR_len],14 ; DDR size
mov byte [bx+DDR_cmd],CMD_INTEST ; command, test input
mov word [bx+DDR_errorstatus],0 ; clear status
; ------------- Read console status
push cs ; push CS
pop es ; ES <- CS
lds si,[ConDev] ; DS:SI <- console device header
call DevExec ; execute device service
push cs ; push CS
pop ds ; DS <- data segment
; ------------- Check returned status
test ah,S_BUSY ; is console busy?
jnz BreakTest8 ; no character is ready
; ------------- Test character
cmp byte [bx+13],BREAK ; is it BREAK (Ctrl+C) character?
jne BreakTest8 ; it is not BREAK
; ------------- Delete BREAK (Ctrl+C) character from console buffer
xor ax,ax ; AL <- 0 unit, AH <- 0 media
mov bx,ConBuff ; BX <- console data buffer
mov cx,1 ; CX <- 1 size of data
xor dx,dx ; DX <- starting offset
call InitR16DDR ; prepare DDR table
lds si,[ConDev] ; DS:SI <- console device header
call DevExec ; execute device service
xor ax,ax ; set ZF to indicate terminate program
; ------------- Pop registers (here is ZY=terminate program)
BreakTest8: pop es ; pop ES
pop ds ; pop DS
pop si ; pop SI
pop bx ; pop BX
pop ax ; pop AX
; ------------- Terminate program
jnz BreakTest9 ; don't terminate program
jmp Terminate ; terminate program
BreakTest9: ret
; ----------------------------------------------------------------------------
; Console control service
; ----------------------------------------------------------------------------
; DESTROYS: If returns OK it destroys nothing
; ----------------------------------------------------------------------------
; ------------- Break test
ConCtrl: call BreakTest ; break test
; ------------- Read character from console
; ----------------------------------------------------------------------------
; Terminate current program from console
; ----------------------------------------------------------------------------
; ------------- Display Ctrl+C character
Terminate: mov al,BREAK ; BREAK character (Ctrl+C)
ret
; ----------------------------------------------------------------------------
; Call Int 28h idle service
; ----------------------------------------------------------------------------
; ------------- Check if Int 28h idle service is enabled
DoInt28: pushf ; push flags
cmp byte [cs:Int24Active],0 ; is Int 24h active?
jne DoInt282 ; Int 24h is active
cmp byte [cs:Int28Enabled],1 ; is Int 28h service enabled?
jne DoInt282 ; Int 28h service is not enabled
int 28h ; call Int 28h service
DoInt282: popf ; pop flags
ret
; ----------------------------------------------------------------------------
; Data
; ----------------------------------------------------------------------------
ConBuff: db 0 ; console data buffer
Break: db 0 ; BREAK flag (1=break is on)
CharPos: db 0 ; character position on line
Int28Enabled: db 1 ; 1=enabled Int 28h idle service
BreakCount: db 1 ; break test counter
ConPushAddr: dw 0 ; push console return address
|