home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
ftp.barnyard.co.uk
/
2015.02.ftp.barnyard.co.uk.tar
/
ftp.barnyard.co.uk
/
cpm
/
walnut-creek-CDROM
/
CPM
/
BDOS
/
Z80DOS10.LBR
/
Z80DCHAR.ZZ0
/
Z80DCHAR.Z8°
Wrap
Text File
|
2000-06-30
|
17KB
|
623 lines
; Z80DOS - Z80 Disk Operating System
;
; Version 1.0 - 05 Sept. 87 by Carson Wilson
;
; -------------------------------------------------------------------
;
; Z80DCHAR.Z80 - DOS Entry Points, Character I/O, and Error Routines
;
; -------------------------------------------------------------------
org DOS+6 ; Preserve serial number for CP/M
; ..overlay
;
; Start DOS
;
start: jp entry ; Jump to entry point DOS
;
; Error messages DOS - for programs which intercept DOS errors
;
defw 0 ; Bad Sector - not implemented
StSel: defw SelErr ; Select error
stro: defw rdonly ; Drive read only
sfilro: defw filro ; File read only
;
; Run-time configurable options:
;
timead: defw BIOStim ; Dummy or address of BIOS routine
; ..configurable at run time
flags: defb options ; Flag bite
;
; Entry point for DOS commands
;
Entry: ld a,c ; Get function number
ld (funct),a ; Save it for later use
ld hl,0 ; Set hl to zero
ld (pexit),hl ; Clear exit code
xor a ; Clear a
ld (fldrv),a ; Reset drive select done flag
ld (rdwr),a ; Reset read/write flag
ld (spsave),sp ; Save stack pointer
ld sp,DOSs ; Get internal stack pointer
push ix ; Save index register
push de ; Save parameter register
pop ix ; Get it back in ix
ld hl,p2exit ; Get exit address DOS
push hl ; Save it on stack to return from DOS
ld a,c ; Get function code
cp 105 ; Test get time <crw>
jp z,gettim ; Yes then get time
cp 104 ; Test set time <crw>
jp z,settim ; Yes then set time
cp 55 ; Test use time stamp <crw>
jp z,UseStp
cp 54 ; Test get time stamp <crw>
jp z,Getstp
cp MaxCmd+1 ; Test greater then MaxCmd
ret nc ; If so return to caller and do nothing
ld hl,ctable ; Load table
ld b,0 ; Prepare 16 bit add
add hl,bc ; Add
add hl,bc ; Add twice to get word value
ld a,(hl) ; Get LSB
inc hl ; Pointer to MSB
ld h,(hl) ; Get MSB
ld l,a ; Save LSB in l
jp (hl) ; Jump to routine
;
; Command Jump Table
;
CTable: defw WBoot ; Warm boot
defw rdcon ; Console input
defw bwrcon ; Console output
defw rdrdr ; Reader input
defw wpunch ; Punch output
defw wlist ; List output
defw dcio ; Direct console I/O
defw giost ; Get I/O byte
defw siost ; Set I/O byte
defw mess ; Print string
defw rdbuf ; Read console buffer
defw tstcs ; Get console status
defw cmnd12 ; Return version number
defw cmnd13 ; Reset disk system
defw cmnd14 ; Select disk
defw cmnd15 ; Open file
defw cmnd16 ; Close file
defw cmnd17 ; Search for first
defw cmnd18 ; Search for next
defw cmnd19 ; Delete file
defw cmnd20 ; Read sequential
defw cmnd21 ; Write sequential
defw cmnd22 ; Make file
defw cmnd23 ; Rename file
defw cmnd24 ; Return login vector
defw cmnd25 ; Return current disk
defw cmnd26 ; Set DMA address
defw cmnd27 ; Get address allocation vector
defw cmnd28 ; Write protect disk
defw cmnd29 ; Get R/O vector
defw cmnd30 ; Set file attributes
defw cmnd31 ; Get address disk parameter header(dph)
defw cmnd32 ; Get/set user code
defw cmnd33 ; Read random
defw cmnd34 ; Write random
defw cmnd35 ; Compute file size
defw cmnd36 ; Set random record
defw cmnd37 ; Reset multiple drive
defw dummy ; Access drive - not implemented
defw dummy ; Free drive - not implemented
defw cmnd40 ; Write random with zero fill
; ---------------------------------
; Character Routines
; ---------------------------------
; DOS console input
;
; Read character from console and echo
; if char=cr, lf, tab, ContH or >=space
;
RdCon: call getch ; Get character
call tstch ; Test if cr,lf,tab,ContH or >=space
jr c,exit ; No then exit
call wrcon ; Echo character
exit: ld (pexit),a ; Return character
dummy: ret ; And exit DOS
;
; DOS write console
;
bwrcon: ld a,e ; Copy character
jr wrcon ; And output it
;
; read reader
;
rdrdr: call reader ; Get character from reader
jr exit ; And return it to caller
;
; write punch
;
wpunch: ld c,e ; Copy character
jp punch ; And output it to punch device
;
; Write list
;
wlist: ld c,e ; Copy character
jp list ; And output it to list device
;
; Direct console input/output
;
DCIO: ld c,e ; Copy character
inc e ; Test if 0ffh
jr z,dcio0 ; Yes do input
inc e ; Test if 0feh
jp nz,ConOut ; No then output character
call ConSt ; Get console status
and 1 ; Test it
jr exit ; And return it to caller
DCIO0: call ConSt ; Get console status
and 1 ; Test it
ret z ; Exit if no character present
call ConIn ; Get character
jr exit ; And return it to caller
;
; Get I/O status byte
;
giost: ld a,(RamLow+00003h) ; Get I/O byte from ram
jr exit ; And return it to caller
;
; Set I/O status byte
;
siost: ld a,e ; Copy I/O byte
ld (RamLow+00003h),a ; And save it in ram
ret ; Exit to caller
;
; Test console status
;
tstcs: call gConSt ; Get console status
jr exit ; And return it to caller
;
; Output char (control char = ^char)
;
outch: call tstch ; Test it cr,lf,tab,ContH or >=space
jr nc,wrcon ; Yes then jump
push af ; Save character
ld a,'^' ; Load a with '^'
call wrcon ; Output it
pop af ; Get character back
push af ; Save it again
add a,'A'-1 ; Add offset
call wrcon ; Output it
pop af ; Get character
ret ; Return to caller
;
; Echo cr,lf
;
CROut: ld a,cr ; A=carriage return
call wrcon ; Output it
ld a,lf ; A=line feed
; Fall through to output routine
;
; Write character on console
;
wrcon: cp tab ; Test if tab
jr nz,wrcon1 ; No then jump
wrcon0: ld a,' ' ; Expand tab with spaces
call wrcon ; Write space
ld a,(tabcnt) ; Get tab count
and 7 ; Test if done
jr nz,wrcon0 ; No then repeat
ld a,tab ; Return tab
ret ; Return to caller
wrcon1: push af ; Save character
call gConSt ; Test status and ContS/ContC
pop af ; Get character back
push af ; Save it again
ld c,a ; Copy it
call ConOut ; Output it
pop af ; Get character back
push af ; Save it again
ld c,a ; Copy it
ld a,(fContP) ; Get printer echo flag
or a ; Test it
call nz,list ; Non zero => output char to printer
ld a,(flags) ; Get flag byte
bit 1,a ; Test delay 256 bytes active
jr z,wrcon2 ; No then exit
ld hl,delay ; Get delay counter
xor a ; A=0
or (hl) ; Test counter=0
jr z,wrcon2 ; Yes then exit
dec (hl) ; Else decrement counter
wrcon2: pop af ; Restore character
; Fall through to count routine
;
; Count characters in line
;
countc: ld hl,tabcnt ; Get pointer to tab counter
inc (hl) ; Increment tab counter
cp ' ' ; Test if char >= ' '
ret nc ; Yes, normal character then exit
dec (hl) ; Control character, decrement tab count
cp ContH ; Test backspace
jr nz,count0 ; No backspace then jump
dec (hl) ; Decrement tab counter
ret ; And exit
count0: cp cr ; Test carriage return
jr nz,count1 ; No then jump
ld (hl),0 ; Reset tab count
ret ; And exit
count1: cp tab ; Test tab character
ret nz ; No then exit
push af ; Save character
ld a,(hl) ; Get tab count
add a,8 ; Advance it 8 position
and 0f8h ; Set it to next tab position
ld (hl),a ; Save it
pop af ; Restore character
ret ; And exit
;
; Get character from console
;
getch: ld hl,lastch ; Get pointer to last input character
ld a,(hl) ; Get character
ld (hl),0 ; Reset last character
or a ; Test if character present
ret nz ; Return if so
jp ConIn ; Else get character
;
; Get console status
;
gConSt: ld a,(delay) ; Get 256 bytes delay
or a ; Test it
jr nz,gcons0 ; Non zero, delay stil active or disabled
call ConSt ; Get console status
and 1 ; Test it
jr nz,gcons1 ; Non zero then get character
gcons0: ld a,(lastch) ; Get last character
or a ; Test it
jr nz,gcons3 ; Non zero then character present
call ConSt ; Get console status
and 1 ; Test it
ret z ; Return if no character present
gcons1: call ConIn ; Get character
cp ContS ; Test stop character
jr nz,gcons2 ; Not then exit character
call ConIn ; Get next character
cp ContC ; Test if user wants to exit
jp z,RamLow+00000h ; Yes then warm boot
jr gConSt ; Test again
gcons2: ld (lastch),a ; Save character
ld a,0ffh ; Set delay counter
ld (delay),a ; And save it
gcons3: ld a,1 ; Character present code
ret ; Return to caller
;
; Test character
; exit carry=0: cr,lf,tab,ContH or >=space
; carry=1: all other characters
;
tstch: cp cr ; Test carriage return
ret z ; Return if so
cp tab ; Test tab
ret z ; Return if so
cp ContH ; Test backspace
ret z ; Return if so
cp rubout
ret z
cp ' ' ; Test >=space
ret ; Return to caller
;
; Write backspace, space, backspace
;
wContH: call wcont0 ; Write backspace
ld c,' ' ; Load space
call ConOut ; And output it
wcont0: ld c,ContH ; Load backspace
jp ConOut ; And output it
;
; Output message
;
mess: ld a,(de) ; Get byte from buffer
cp '$' ; Test last byte
ret z ; Yes, then return to caller
inc de ; Point to next byte
push de ; Save pointer
call wrcon ; Output character
pop de ; Restore pointer
jr mess ; And test again
;
again: ld hl,tabcnt ; Get tab count pointer
ld a,(tabcx1) ; Get position first character line
cp (hl) ; Check it
ret z ; Return if on same position
ld a,' ' ; Load space
call wrcon ; Output it
jr again ; And test again
;
; Delete char
; entry : HL = start buffer - 1
; B = character counter (always > 0)
;
delch: dec b ; Decrement character counter
ld a,(tabcnt) ; Get tab counter
push af ; Save it
push bc ; Save character counter
ld a,(tabcx1) ; Get position first character line
ld (tabcnt),a ; Save it in tab counter
delch0: ld a,b ; Copy character counter
or a ; Test if 0
jr z,delch2 ; Yes then jump
dec b ; Decrement it
inc hl ; Increment buffer pointer
ld a,(hl) ; Get character from buffer
push hl ; Save buffer pointer
call tstch ; Test if cr,lf,tab,ContH or >=sp
jr nc,delch1 ; Yes then jump
rra ; Else must be control character
call countc ; Count control character twice
delch1: call countc ; Count character
pop hl ; Get buffer pointer
jr delch0 ; And test again
delch2: pop bc ; Restore character counter
pop af ; And tab counter
push hl ; Save buffer pointer
push bc ; And character counter
ld hl,tabcnt ; Get tab counter pointer
sub (hl) ; Calculate difference
delch3: dec a ; Decrement it
cp 8 ; Compare with 8
jr nc,delch4 ; Jump if >=8
push af ; Save difference
call wContH ; Remove character end line
pop af ; Restore counter
jr delch3 ; Remove more characters
delch4: pop bc ; Restore character counter
pop hl ; Restore buffer pointer
ret ; And return to caller
;
; Read buffer
;
rdbuf: ld a,(tabcnt) ; Get current position cursor
ld (tabcx1),a ; Save it
rdbuf0: push ix ; Save start address buffer
pop hl ; Get it in hl
ld c,(hl) ; Get maximum line lenght
inc hl ; Increment to line lenght position
ld b,0 ; Clear line lenght counter
push hl ; Save start line - 1
rdbuf1: push hl ; Save registers
push bc
rdbuf2: call getch ; Get character
pop bc ; Restore registers
pop hl
and 07fh ; Mask character
rdbuf3: cp ContH ; Test backspace
jr nz,rdbuf4 ; Not then jump
doback: ld a,b ; Test if deleting char from empty line
or a
jr z,rdbuf1 ; Yes then get next char
pop hl ; Get start line
push hl ; And save it again
call delch ; Delete character
jr rdbuf1 ; Get next character
rdbuf4: cp ContP ; Test print enable/disable
jr nz,rdbufC ; Not then jump
ld a,(fContP) ; Complement print flag
cpl
ld (fContP),a
rdbufc: cp ContX ; Test delete line
jr nz,rdbufe ; Not then jump
rdbufd: pop hl ; Get start line
ld a,b ; Test if last character deleted
or a
jp z,RDBUF ; Yes start routine again
push hl ; Save pointer
call delch ; Delete last character line
jr rdbufd ; Test last character deleted
rdbufe: cp rubout ; Test delete last character
jr nz,rdbuff ; Not then jump
jr doback ; Part of delete key fix
rdbuff: cp cr ; Test carriage return
jr z,rdbufi ; Yes, then exit
inc hl ; Increment pointer
ld (hl),a ; And save character
inc b ; Increment line counter
rdbufg: push hl ; Save registers
push bc
call outch ; Echo character
pop bc ; Restore registers
pop hl
cp ContC ; Test warm boot
ld a,b ; Get line count
jr nz,rdbufh ; No warm boot then jump
cp 1 ; Test ContC is first character line
jp z,RamLow+00000h ; Yes then execute warm boot
rdbufh: cp c ; Test line length=maximum line length
jp nz,rdbuf1 ; Not then get next character
rdbufi: pop hl ; Get start line - 1
ld (hl),b ; Save line counter
ld a,cr ; Load carriage return
jp wrcon ; And echo it
;---------------------------
; Error routines
;---------------------------
SelErr: ld de,msel ; Load selected error message
jr derror ; And display error
;
; File read only error
;
FilRO: ld de,mfilro ; Load file R/O message
ld a,0ffh ; Set file R/O message flag
jr error ; And display error
;
; Read error message--b.h.
;
rderr: ld de,mrderr
jr derror
;
; Write error message--b.h.
wrterr: ld de,mwrter
jr derror
;
; Drive read only error
;
rdonly: ld de,mro ; Load drive R/O message
derror: xor a ; Set no file R/O message
;
; Display error message
;
; "Error message" error on d:
; Function nn
; File filename.typ
;
error: ld c,a ; Save file R/O message flag
push bc
push de ; Save error message pointer
call crout ; Display cr/lf
pop de
call mess ; Display error
ld a,(defdrv) ; Get current drive
add a,'A' ; Make ASCII
ld (mdrive),a ; Save it
ld de,mberr ; Load message " error on d:"
call mess ; Display message
ld de,mbfunc ; Load message "function "
call mess ; Display message
ld a,(funct) ; Get function number
push af ; Save it
ld bc,100 ; Display number / 100
call num
ld c,10 ; Display number / 10
call num
ld bc,101h ; Always display number / 1
call num
pop af ; Get function number
pop bc ; Get file R/O flag
cp 15 ; Test if FCB used in command
jr c,error3 ; Commands <16, don't show filename
cp 24
jr c,error1 ; Commands 16..23 show file
cp 30
jr z,error1 ; Command 30 show file
cp 33
jr c,error3 ; Other commands 24..32 no file
cp 37
jr c,error1 ; 33..36 show
cp 40
jr nz,error3 ; 37 don't show
error1: push ix ; Display "file ="
sub 19 ; Test delete file function
jr nz,error2 ; Not then jump
or c ; Test file R/O flag
jr z,error2 ; No file R/O then jump
call caldir ; Get FCB from directory buffer
ex (sp),hl ; Save it
error2: ld de,mfile ; Get message " file ="
call mess ; Display message
pop hl ; Get pointer FCB
ld b,8 ; Display first 8 characters
call filenm
ld a,'.' ; Load '.'
push hl ; Save FCB pointer
call wrcon ; Echo it
pop hl ; Restore FCB pointer
ld b,3 ; Display last 3 characters
call filenm
; Absorb any pending characters:
error3: call gConSt ; Test if character pending
or a
jr z,error4 ; No then jump
call getch ; Get character
jr error3 ; And test again
;
; Allow retry on read/write errors
;
error4:
ld a,(retflg) ; Allow retry?
or a
jr z,error5 ; No
xor a
ld (retflg),a ; Reset flag <crw>
call getch
cp ContC ; Control-c entered?
ret nz ; No, retry
error5: jp RamLow+00000h ; Do warm boot
;
; Display number
;
num: ld d,-1 ; Load number -1
num1: inc d ; Increment number
sub c ; Divide by c
jr nc,num1 ; Not finished then loop
add a,c ; Restore last value
push af ; Save it
ld a,d ; Test if "0"
or b ; And if leading zero
jr z,num2 ; Yes, then exit
ld b,a ; Set no leading zero
ld a,d ; Get number
add a,'0' ; Make ASCII
push bc ; Save registers
call wrcon ; Echo number
pop bc ; Restore registers
num2: pop af ; Restore number
ret ; And exit
;
; Display filename.typ
;
filenm: inc hl ; Increment pointer FCB
ld a,(hl) ; Get character from FCB
and 07fh ; Mask it
push hl ; Save registers
push bc
call wrcon ; Echo character
pop bc ; Restore registers
pop hl
djnz filenm ; Repeat b times
ret ; And exit
;
; Error messages
; Made more meaningful--b.h.
;
msel: defm 'Illegal drive$'
mfilro: defm 'File '
mro: defm 'R/O$'
mrderr: db 'Read$'
mwrter: db 'Write$'
mberr: defm ' error on '
mdrive: defb 0
defb DrvSep
defm '$'
mbfunc: defm cr,lf,'Function', tab, '$'
mfile: defm cr,lf,'File', tab, tab, '$'
; END Z80DCHAR.Z80