home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
CP/M
/
CPM_CDROM.iso
/
mbug
/
mbug169.arc
/
Z80DOS2B.LBR
/
Z80DOSB.ZY0
/
Z80DOSB.ZY0
Wrap
Text File
|
1979-12-31
|
18KB
|
658 lines
;
; Z80DOS - Z80 Disk Operating System
;
; Version 2.0a - BETA TEST VERSION - 6 Nov 87 by Carson Wilson
; - modified for Z80 assembler 19 OCT 88 by B.J. White
; Support file: Z80DOSB.Z80
; Version: 2.0
; Date: 6 Nov 87
; Author: Carson Wilson
; Changes: Combined BIOS read and write error messages into one
; message - "Data error" so that BDOS error intecepts
; work same as standard CP/M.
;
; Added disk changed error routine.
;
; Description: DOS Entry Points, Character I/O, and Error Routines
;
ORG BDOS+6 ; Preserve serial number for CP/M
; ..overlay
;
; Start BDOS
;
START: JP ENTRY ; Jump to entry point DOS
;
; Error messages DOS - for programs which intercept DOS errors
;
STRW: DEFW RWERR ; Read or write error
STSEL: DEFW SELERR ; Select error
STRO: DEFW RDONLY ; Drive read only
SFILRO: DEFW FILRO ; File read only
;
; Run-time configurable options:
;
TIMEAD:
IF RTC
DEFW BIOSTIM ; Dummy or address of BIOS routine
ELSE
DEFW 0
ENDIF ;RTC
FLAGS: DEFB OPTIONS ; Flag byte for public and ^S interrupt
;
; 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,EXITP2 ; 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 LISTO ; 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,LISTO ; 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
AGAIN0 CALL CROUT ;added for CONTROL E
;
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
;Control E test added (BJW)
CP CONTE ; Test if Control E
JR NZ,RDBUF3 ; not then jump
PUSH HL ; save registers
PUSH BC
CALL AGAIN0 ; move cursor to next line
JR RDBUF2 ; and get next 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
;added jump to RDBUF1 to stop printing of control character (BJW)
RDBUF5: JR RDBUF1
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
;---------------------------
;
; Disk changed error
;
CHGERR:
LD DE,MCHG ; Load changed error message
JR DERROR ; And display error
;
; Select error
;
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/Write error
;
RWERR:
LD DE,MRWERR
JR DERROR
;
; Drive read only error
;
RDONLY: LD DE,MRO ; Load drive R/O message
DERROR: XOR A ; Set no file R/O message
; fall thru
;
; 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.
;
MCHG: DEFM 'Disk changed$' ; <crw>
MSEL: DEFM 'Illegal drive$'
MFILRO: DEFM 'File '
MRO: DEFM 'R/O$'
MRWERR: DEFM 'Data$' ; BIOS read/write error <crw>
MBERR: DEFM ' error on '
MDRIVE: DEFB 0
DEFB DRVSEP
DEFM '$'
MBFUNC: DEFW 0A0DH
DEFM 'Function'
DEFB TAB
DEFB '$'
MFILE: DEFW 0A0DH
DEFM 'File'
DEFW 0909H
DEFB '$'
CHAIN 'Z80DOSC.Z80'