mirror of https://github.com/wwarthen/RomWBW.git
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
406 lines
9.7 KiB
406 lines
9.7 KiB
;===============================================================================
|
|
; Talk - Bare minimum terminal interface
|
|
;
|
|
; Console talks to designated character device.
|
|
;
|
|
;===============================================================================
|
|
;
|
|
; Author: Wayne Warthen (wwarthen@gmail.com)
|
|
;_______________________________________________________________________________
|
|
;
|
|
; Usage:
|
|
; TALK TTY:|CRT:|BAT:|UC1:
|
|
;_______________________________________________________________________________
|
|
;
|
|
; Change Log:
|
|
;_______________________________________________________________________________
|
|
;
|
|
; ToDo:
|
|
; 1) Handle ZCPR devices somehow
|
|
;_______________________________________________________________________________
|
|
;
|
|
;===============================================================================
|
|
; Definitions
|
|
;===============================================================================
|
|
;
|
|
stksiz .equ $40 ; Working stack size
|
|
;
|
|
restart .equ $0000 ; CP/M restart vector
|
|
bdos .equ $0005 ; BDOS invocation vector
|
|
iobyte .equ $0003 ; IOBYTE address
|
|
;
|
|
const .equ $06 ; CBIOS CONST function dispatch table offset
|
|
conin .equ $09 ; CBIOS CONIN function dispatch table offset
|
|
conout .equ $0C ; CBIOS CONOUT function dispatch table offset
|
|
;
|
|
;===============================================================================
|
|
; Code Section
|
|
;===============================================================================
|
|
;
|
|
.org $100
|
|
;
|
|
; setup stack (save old value)
|
|
ld (stksav),sp ; save stack
|
|
ld sp,stack ; set new stack
|
|
;
|
|
; initialization
|
|
call init ; initialize
|
|
jr nz,exit ; abort if init fails
|
|
;
|
|
ld de,msghel ; hello message
|
|
call prtstr ; print it
|
|
;
|
|
; save active iobyte (console)
|
|
ld a,(iobyte) ; get active IOBYTE
|
|
ld (iobcon),a ; save it to iobcon
|
|
;
|
|
; parse command line
|
|
call parse ; parse command line
|
|
jr nz,exit ; abort if parse fails
|
|
;
|
|
; startup message
|
|
;
|
|
ld de,msgtlk1 ; message prefix
|
|
call prtstr ; print it
|
|
call prtstrz ; print dev name at HL
|
|
ld de,msgtlk2 ; message suffix
|
|
call prtstr ; print it
|
|
;
|
|
; do the real work
|
|
call talk ; do the real work
|
|
;
|
|
; restore original iobyte
|
|
ld a,(iobcon) ; load original iobyte
|
|
ld (iobyte),a
|
|
;
|
|
ld de,msgbye ; goodbye message
|
|
call prtstr ; print it
|
|
;
|
|
exit: ; clean up and return to command processor
|
|
;
|
|
call crlf ; formatting
|
|
;
|
|
ld sp,(stksav) ; restore stack
|
|
ret ; return to CP/M w/o reset
|
|
;
|
|
; Initialization
|
|
;
|
|
init:
|
|
; add check for RomWBW?
|
|
;
|
|
; locate cbios function table address
|
|
ld hl,(restart+1) ; load address of CP/M restart vector
|
|
ld de,-3 ; adjustment for start of table
|
|
add hl,de ; HL now has start of table
|
|
ld (cbftbl),hl ; save it
|
|
; return success
|
|
xor a
|
|
ret
|
|
;
|
|
; Parse command line
|
|
; If success, Z set and HL points to device name string (zero terminated)
|
|
; ... else NZ set.
|
|
;
|
|
parse:
|
|
;
|
|
ld hl,$81 ; point to start of command tail (after length byte)
|
|
call nonblank ; skip blanks
|
|
jp z,erruse ; no parms
|
|
;
|
|
ld c,0 ; current table entry
|
|
ex de,hl ; point to parm with de
|
|
ld hl,devtbl ; point to device table with hl
|
|
;
|
|
parse0: ; compare loop
|
|
push bc
|
|
push de
|
|
push hl
|
|
call strcmp ; compare strings
|
|
pop hl
|
|
pop de
|
|
pop bc
|
|
jr z,parse1 ; if Z, we have a match
|
|
inc c ; increment table entry
|
|
ld a,5 ; bump hl by
|
|
call addhl ; ... table entry size
|
|
ld a,c ; get the table entry num to A
|
|
cp 4 ; past end of table?
|
|
jr nz,parse0 ; loop till done
|
|
jp errprm ; handle parm error
|
|
;
|
|
parse1: ; handle match
|
|
ld a,c ; device num to A
|
|
ld (iobcom),a ; save as com device iobyte
|
|
; return success
|
|
xor a ; signal error
|
|
ret ; and return
|
|
;
|
|
; Main routine
|
|
;
|
|
talk: ; CON: --> UC1:
|
|
;
|
|
ld a,(iobcon) ; setup iobyte to read from CON:
|
|
ld (iobyte),a
|
|
;
|
|
call cbios ; check for char pending using cbios
|
|
.db const ; ... const function
|
|
or a ; set flags
|
|
jr z,next ; no char ready
|
|
call cbios ; read char using cbios
|
|
.db conin ; ... conin function
|
|
cp $1A ; check for exit request (ctrl+z)
|
|
ret z ; if so, bail out
|
|
;
|
|
push af ; save the char we read
|
|
ld a,(iobcom) ; setup iobyte to read from UC1:
|
|
ld (iobyte),a
|
|
pop af ; recover the character
|
|
;
|
|
ld c,a ; move it to C
|
|
call cbios ; write char using cbios
|
|
.db conout ; ... conout function
|
|
;
|
|
next: ; UC1: --> CON:
|
|
;
|
|
ld a,(iobcom) ; setup iobyte to read from com device
|
|
ld (iobyte),a
|
|
;
|
|
call cbios ; check for char pending using cbios
|
|
.db const ; ... const function
|
|
or a ; set flags
|
|
jr z,talk ; no char ready
|
|
call cbios ; read char using cbios
|
|
.db conin ; ... conin function
|
|
;
|
|
push af ; save the char we read
|
|
ld a,(iobcon) ; setup iobyte to read from CON:
|
|
ld (iobyte),a
|
|
pop af ; recover the character
|
|
;
|
|
ld c,a ; move it to C
|
|
call cbios ; write char using cbios
|
|
.db conout ; ... conout function
|
|
;
|
|
jr talk ; loop
|
|
;
|
|
|
|
;
|
|
; Print character in A without destroying any registers
|
|
;
|
|
prtchr:
|
|
push bc ; save registers
|
|
push de
|
|
push hl
|
|
ld e,a ; character to print in E
|
|
ld c,$02 ; BDOS function to output a character
|
|
call bdos ; do it
|
|
pop hl ; restore registers
|
|
pop de
|
|
pop bc
|
|
ret
|
|
;
|
|
; Print a '$' terminated string at (DE) without destroying any registers
|
|
;
|
|
prtstr:
|
|
push bc ; save registers
|
|
push de
|
|
push hl
|
|
ld c,$09 ; BDOS function to output a '$' terminated string
|
|
call bdos ; do it
|
|
pop hl ; restore registers
|
|
pop de
|
|
pop bc
|
|
ret
|
|
;
|
|
; Print a zero terminated string at (HL) without destroying any registers
|
|
;
|
|
prtstrz:
|
|
push hl
|
|
;
|
|
prtstrz1:
|
|
ld a,(hl) ; get next char
|
|
or a
|
|
jr z,prtstrz2
|
|
call prtchr
|
|
inc hl
|
|
jr prtstrz1
|
|
;
|
|
prtstrz2:
|
|
pop hl ; restore registers
|
|
ret
|
|
;
|
|
; Print the value in A in hex without destroying any registers
|
|
;
|
|
prthex:
|
|
push af ; save AF
|
|
push de ; save DE
|
|
call hexascii ; convert value in A to hex chars in DE
|
|
ld a,d ; get the high order hex char
|
|
call prtchr ; print it
|
|
ld a,e ; get the low order hex char
|
|
call prtchr ; print it
|
|
pop de ; restore DE
|
|
pop af ; restore AF
|
|
ret ; done
|
|
;
|
|
; Convert binary value in A to ascii hex characters in DE
|
|
;
|
|
hexascii:
|
|
ld d,a ; save A in D
|
|
call hexconv ; convert low nibble of A to hex
|
|
ld e,a ; save it in E
|
|
ld a,d ; get original value back
|
|
rlca ; rotate high order nibble to low bits
|
|
rlca
|
|
rlca
|
|
rlca
|
|
call hexconv ; convert nibble
|
|
ld d,a ; save it in D
|
|
ret ; done
|
|
;
|
|
; Convert low nibble of A to ascii hex
|
|
;
|
|
hexconv:
|
|
and $0F ; low nibble only
|
|
add a,$90
|
|
daa
|
|
adc a,$40
|
|
daa
|
|
ret
|
|
;
|
|
; Start a new line
|
|
;
|
|
crlf:
|
|
ld a,13 ; <CR>
|
|
call prtchr ; print it
|
|
ld a,10 ; <LF>
|
|
jr prtchr ; print it
|
|
;
|
|
; Get the next non-blank character from (HL).
|
|
;
|
|
nonblank:
|
|
ld a,(hl) ; load next character
|
|
or a ; string ends with a null
|
|
ret z ; if null, return pointing to null
|
|
cp ' ' ; check for blank
|
|
ret nz ; return if not blank
|
|
inc hl ; if blank, increment character pointer
|
|
jr nonblank ; and loop
|
|
;
|
|
; Check character at (DE) for delimiter.
|
|
;
|
|
delim: or a
|
|
ret z
|
|
cp ' ' ; blank
|
|
ret z
|
|
jr c,delim1 ; handle control characters
|
|
cp '=' ; equal
|
|
ret z
|
|
cp '_' ; underscore
|
|
ret z
|
|
cp '.' ; period
|
|
ret z
|
|
cp ':' ; colon
|
|
ret z
|
|
cp $3b ; semicolon
|
|
ret z
|
|
cp '<' ; less than
|
|
ret z
|
|
cp '>' ; greater than
|
|
ret
|
|
delim1:
|
|
; treat control chars as delimiters
|
|
xor a ; set Z
|
|
ret ; return
|
|
;
|
|
; Compare $ terminated strings at HL & DE
|
|
; If equal return with Z set, else NZ
|
|
;
|
|
strcmp:
|
|
;
|
|
ld a,(de) ; get current source char
|
|
cp (hl) ; compare to current dest char
|
|
ret nz ; compare failed, return with NZ
|
|
or a ; set flags
|
|
ret z ; end of string, match, return with Z set
|
|
inc de ; point to next char in source
|
|
inc hl ; point to next char in dest
|
|
jr strcmp ; loop till done
|
|
;
|
|
; Invoke CBIOS function
|
|
; The CBIOS function offset must be stored in the byte
|
|
; following the call instruction. ex:
|
|
; call cbios
|
|
; .db $0C ; offset of CONOUT CBIOS function
|
|
;
|
|
cbios:
|
|
ex (sp),hl
|
|
ld a,(hl) ; get the function offset
|
|
inc hl ; point past value following call instruction
|
|
ex (sp),hl ; put address back at top of stack and recover HL
|
|
ld hl,(cbftbl) ; address of CBIOS function table to HL
|
|
call addhl ; determine specific function address
|
|
jp (hl) ; invoke CBIOS
|
|
;
|
|
; Add the value in A to HL (HL := HL + A)
|
|
;
|
|
addhl:
|
|
add a,l ; A := A + L
|
|
ld l,a ; Put result back in L
|
|
ret nc ; if no carry, we are done
|
|
inc h ; if carry, increment H
|
|
ret ; and return
|
|
;
|
|
; Errors
|
|
;
|
|
erruse: ; command usage error (syntax)
|
|
ld de,msguse
|
|
jr err
|
|
errprm: ; command parameter error (syntax)
|
|
ld de,msgprm
|
|
jr err
|
|
err: ; print error string and return error signal
|
|
call crlf ; print newline
|
|
call prtstr ; print error string
|
|
or $FF ; signal error
|
|
ret ; done
|
|
errdos: ; handle BDOS errors
|
|
push af ; save return code
|
|
call crlf ; newline
|
|
ld de,msgdos ; load
|
|
call prtstr ; and print error string
|
|
pop af ; recover return code
|
|
call prthex ; print error code
|
|
or $FF ; signal error
|
|
ret ; done
|
|
;
|
|
;===============================================================================
|
|
; Storage Section
|
|
;===============================================================================
|
|
;
|
|
cbftbl .dw 0 ; address of CBIOS function table
|
|
;
|
|
iobcon .db 0 ; iobyte value for console
|
|
iobcom .db 0 ; iobyte value for com device
|
|
;
|
|
devtbl: ; device table
|
|
.db "TTY:",0
|
|
.db "CRT:",0
|
|
.db "BAT:",0
|
|
.db "UC1:",0
|
|
;
|
|
stksav .dw 0 ; stack pointer saved at start
|
|
.fill stksiz,0 ; stack
|
|
stack .equ $ ; stack top
|
|
;
|
|
; Messages
|
|
;
|
|
msghel .db 13,10,"Talk v1.0",13,10,"$"
|
|
msgbye .db 13,10,13,10,"*** Finished talking ***","$"
|
|
msgtlk1 .db 13,10,"Talking on device $"
|
|
msgtlk2 .db " (press <Ctrl+Z> to exit)...",13,10,13,10,"$"
|
|
msguse .db "Usage: TALK TTY:|CRT:|BAT:|UC1:$"
|
|
msgprm .db "Parameter error$"
|
|
msgdos .db "DOS error, return code=0x$"
|
|
;
|
|
.end
|