Added F_RANDREC. F_OPEN now sets RC, seq rec num.

This commit is contained in:
Bobbi Webber-Manners 2019-10-20 20:20:03 -04:00
parent 372e15941b
commit 539b3c571e
3 changed files with 93 additions and 30 deletions

View File

@ -15,10 +15,11 @@
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;
; TODO: Populate FCBs properly so PIP etc. work!! Do this in MAKE2PATH.
; TODO: Populate FCBs properly so PIP etc. work!! Do this in PATH2FCB.
; TODO: Note that PIP uses random reads and writes.
; TODO: F_ATTRIB needs to work with FCB with wildcards and leave the FCB at DMAADDR
; TODO: Implement missing system calls:
; - Random read/write (F_READRAND,F_WRITERAND,F_RANDREC,F_WRITEZF)
; - Random read/write (F_READRAND,F_WRITERAND,F_WRITEZF)
; - RS232 (A_READ, A_WRITE)
; - Printer (LWRITE)
; - Other (F_ATTRIB)
@ -96,7 +97,7 @@ FCB1NAM DEFM 'FILENAMEEXT' ; FCB filename and extension
FCB1EX DEFB 00H ; FCB extent field
FCB1S1 DEFB 00H ; FCB S1 field
FCB1S2 DEFB 00H ; FCB S2 field
FCB1RC DEFB 00H ; FCB RC field
FCB1RC DEFB 00H ; FCB RC field (# recs used this extent)
FCB1MAP ; Map of blocks in file (overlaps FCB2)
ORG 006CH ; Standard addr of 32 byte FCB2
@ -106,7 +107,7 @@ FCB2NAM DEFM 'FILENAMEEXT' ; FCB filename and extension
FCB2EX DEFB 00H ; FCB extent field
FCB2S1 DEFB 00H ; FCB S1 field
FCB2S2 DEFB 00H ; FCB S2 field
FCB2RC DEFB 00H ; FCB RC field
FCB2RC DEFB 00H ; FCB RC field (# recs used this extent)
FCB2MAP ; Map of blocks in file (overlaps buffer)
ORG 0080H ; Standard addr of 128 byte File Buffer
@ -521,13 +522,14 @@ B_DRV_ROVEC EQU 1DH ; Return bitmap of read-only drives
B_DRV_DPB EQU 1FH ; Get Drive Parameter Block address
B_F_USERNUM EQU 20H ; Get/set user number
B_F_SIZE EQU 23H ; Compute file size
B_F_RANDREC EQU 24H ; Update random access pointer
B_DRV_RESET EQU 25H ; Selectively reset disk drives
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
ORG BDOSADDR
BDOSINIT LD SP,STCKTOP ; Initialize SP
LD A,0 ;
XOR A ; A=0
LD (IOBYTE),A ; Initialize IOBYTE
LD (CURDRV),A ; Drive A:, User 0
LD (FILEBUF),A ; Zero chars in command tail
@ -591,7 +593,7 @@ BDOSVEC DEFW C_TERMCPM ; C=00H
DEFW UNIMP ; C=21H (F_READRAND)
DEFW UNIMP ; C=22H (F_WRITERAND)
DEFW F_SIZE ; C=23H
DEFW UNIMP ; C=24H (F_RANDREC)
DEFW F_RANDREC ; C=24H
DEFW DRV_RESET ; C=25H
DEFW UNIMP ; C=26H (*nothing* in CP/M 2.2)
DEFW UNIMP ; C=27H (*nothing* in CP/M 2.2)
@ -680,7 +682,7 @@ RIS1 LD A,3 ; CMD=3 means peek at keyboard
AND 7FH ; Mask high bit
LD L,A ; Copy A to L
RET ;
RIS2 LD A,0 ; No chars waiting, A=0
RIS2 XOR A ; No chars waiting, A=0
LD L,A ; Return in L also
RET
@ -718,7 +720,7 @@ C_READSTR LD H,D ; HL will be the working pointer
INC HL ; ... 3rd byte of the buffer
PUSH DE ; Put DE into IX
POP IX ; ...
LD A,0 ; Set number of chars read to zero
XOR A ; Set number of chars read to zero
LD (IX+1),A ; ...
CRSL1 PUSH HL ; Preserve HL
CALL C_READ ; Read a character into A
@ -782,7 +784,7 @@ DRV_SET LD A,E ; Prepare to compare disk number
AND 0F0H ; Mask out old drive number
OR B ; Replace with new drive number
LD (CURDRV),A ; Store the requested drive number
LD A,0 ; Return code meaning success
XOR A ; A=0: Return code meaning success
JP DSRET ;
DSERR LD A,0FFH ; Return code for error
DSRET LD L,A ; Return code in L too
@ -802,7 +804,7 @@ _F_OPEN LD IX,PATHBUF ; Destination buffer
PUSH DE ; Preserve pointer to FCB
; Work out which IOBUF to allocate for this file
LD A,0 ; Looking for FRN slot with value 0
XOR A ; Looking for FRN slot with value 0
CALL GETIOADDR ; Returns FRN slot in A, IOBUF in HL
CP 0FFH ; Check for error
JP Z,FOERR ; If no slots available, error out
@ -823,9 +825,39 @@ _F_OPEN LD IX,PATHBUF ; Destination buffer
LD A,(FOMLIN) ; Get ProDOS file reference number
LD H,D ; Pointer to FCB ...
LD L,E ; ... into HL
LD BC,14 ; Offset to S2 field (reserved field)
LD BC,0EH ; Offset to S2 field (reserved field)
ADD HL,BC ; Compute address
LD (HL),A ; Store file reference number is S2 field
PUSH HL ; Keep pointer into FCB for later
; ProDOS GET_EOF call. Convert bytes to records (ie: divide by 128)
; Assumes no files > 64K on ProDOS filesystem
LD HL,FO2MLI ; Pass address of 6502 JSR instruction
CALL PRODOS ; Invoke ProDOS MLI (GET_EOF)
LD A,(FO2MLIE2) ; Most significant byte of length
SLA A ; Max file size per extent is 16K: 128*128
LD B,A ; Stash in B for now
LD A,(FO2MLIE1) ; Least significant byte of length
AND 80H ; Keep most significant bit, mask off others
SRA A ; Move to LSB (shift seven times)
SRA A ; ...
SRA A ; ...
SRA A ; ...
SRA A ; ...
SRA A ; ...
SRA A ; ...
OR B ; Leaves file length in records in A
; Store records used
POP HL ; Recover pointer into FCB
INC HL ; Advance to records used field
LD (HL),A ; Set records used
; Set sequential record number to zero
LD BC,20H-0FH ; Skip ahead to offset 20H - seq rec num
ADD HL,BC ; ...
XOR A ; Zero the sequential record number
LD (HL),A ; ...
; Store ProDOS FRN in slot FRN1 - FRN4
LD A,(FOIOB) ; Obtain IOBUF idx (1,2,3,4)
@ -836,7 +868,7 @@ _F_OPEN LD IX,PATHBUF ; Destination buffer
lD A,(FOMLIN) ; Get ProDOS file reference number
LD (HL),A ; Store in FRN slot
LD A,0 ; Success
XOR A ; Success
LD L,A ; Copy to L
RET ; Done
@ -854,6 +886,16 @@ FOMLIP DEFW PATHBUF+OFFSET ; ProDOS PL: pointer to path in 6502 addr
FOMLII DEFW 0000H ; ProDOS PL: pointer to IO buffer
FOMLIN DEFB 0 ; ProDOS PL: File reference number
FO2MLI DEFB 20H,00H,0BFH ; JSR $BF00 in 6502 code
DEFB 0D1H ; ProDOS GET_EOF call
DEFW FO2MLIPL+OFFSET ; Pointer to parm list in 6502 addr space
DEFB 60H ; RTS in 6502 code
FO2MLIPL DEFB 2 ; ProDOS PL: Two parameters
FO2MLIN DEFB 0 ; ProDOS PL: File reference number
FO2MLIE1 DEFB 0 ; ProDOS PL: EOF position (LS-byte)
FO2MLIE2 DEFB 0 ; ProDOS PL: EOF position
FO2MLIE3 DEFB 0 ; ProDOS PL: EOF position (MS-byte)
FOIOB DEFB 0 ; Local variable to record IOBUF idx
; Close file
@ -881,17 +923,17 @@ F_CLOSE LD H,D ; Pointer to FCB ...
LD B,0 ; ...
LD C,A ; ...
ADD HL,BC ; ...
LD A,0 ; And zero it
XOR A ; And zero it
LD (HL),A ; ...
LD H,D ; Pointer to FCB ...
LD L,E ; ... into HL
LD BC,14 ; Offset to S2 field (reserved field)
ADD HL,BC ; Compute address
LD A,0 ; Zero out the S2 field
XOR A ; Zero out the S2 field
LD (HL),A ; ...
FCSUCC LD A,0 ; Return zero for error
FCSUCC XOR A ; Return zero for error
LD L,A ; Return in L also
RET
@ -931,7 +973,7 @@ FSFL1 LD DE,DFCB ; Use this FCB to read the directory
LD BC,DIRHDSZ ; ...
ADD HL,BC ; ...
LD (CDBPTR),HL ; Start out at first file entry
LD A,0 ; Set file count to zero
XOR A ; Set file count to zero
LD (CDBCOUNT),A ; ...
POP DE ; Get ptr to search FCB back
@ -942,7 +984,7 @@ FSFL1 LD DE,DFCB ; Use this FCB to read the directory
JP Z,FSFS1 ; If so, return
JP FSFL1 ; Loop
FSFS1 LD A,0 ; Match
FSFS1 XOR A ; Match
RET ;
FSFS2 LD A,0FFH ; No match
RET
@ -970,12 +1012,12 @@ FSNL1 PUSH HL ; Preserve HL
LD BC,DIRHDSZ ; ...
ADD HL,BC ; ...
LD (CDBPTR),HL ; Start out at first file entry
LD A,0 ; Set file count to zero
XOR A ; Set file count to zero
LD (CDBCOUNT),A ; ...
JP FSNL1 ; Loop
FSNS1 LD A,0 ; Match
FSNS1 XOR A ; Match
RET ;
FSNS2 LD A,0FFH ; No match
RET
@ -1019,6 +1061,8 @@ FDMLIP DEFW PATHBUF+OFFSET ; ProDOS PL: Pointer to path in 6502 addr
; DE is the address of the FCB describing the file from which to read
; Returns error codes in A and L:
; 0 OK, 1 EOF, 9 invalid FCB, 10 media changed, 0FFH h/w error
; TODO: Use Sequential Record field of FCB to determine from where to begin
; reading. Increment it so next read advances to next record.
F_READ LD H,D ; Pointer to FCB ...
LD L,E ; ... into HL
LD BC,14 ; Offset to S2 field (reserved field)
@ -1038,7 +1082,7 @@ F_READ LD H,D ; Pointer to FCB ...
JP Z,FRBFCB ; If so, return invalid FCB code (9)
CP 0 ; See if there was some other error
JP NZ,FRERR ; If so, return code 0FFH (h/w error)
LD A,0 ; Zero for success
XOR A ; Zero for success
LD L,A ; Return code in L also
RET ; Done
FREOF LD A,1 ; EOF return code
@ -1065,6 +1109,8 @@ FRMLITC DEFW 0000H ; ProDOS PL: Number of bytes transferred
; DE is the address of the FCB describing the file to which to write
; Returns error codes in A and L:
; 0 OK, 1 dir full, 2 disk full, 9 invalid FCB, 10 media changed, 0FFH h/w error
; TODO: Use Sequential Record field of FCB to determine from where to begin
; writing. Increment it so next write advances to next record.
F_WRITE LD H,D ; Pointer to FCB ...
LD L,E ; ... into HL
LD BC,14 ; Offset to S2 field (reserved field)
@ -1085,7 +1131,7 @@ F_WRITE LD H,D ; Pointer to FCB ...
JP Z,FWDF ; If so, return disk full code (2)
CP 0 ; See if there was some other error
JP NZ,FWERR ; If so, return code 0FFH (h/w error)
LD A,0 ; Zero for success
XOR A ; Zero for success
LD L,A ; Return code in L also
RET ; Done
FWBFCB LD A,9 ; Invalid FCB return code
@ -1158,7 +1204,7 @@ F_RENAME CALL F_SFIRST ; Search for file, create FCB
CALL PRODOS ; Invoke ProDOS MLI
CP 0 ; See if there was an error
JP NZ,FRNERR ; Handle error
LD A,0 ; Success
XOR A ; Success
LD L,A ; Return code in L also
RET
FRNERR LD A,0FFH ; 0FFH for error
@ -1264,10 +1310,10 @@ F_SIZE CALL FCB2PATH ; Populate PATHLEN and PATH
POP IX ; ... into IX
LD (IX+21H),L ; Store LSB of recs used in R0
LD (IX+22H),H ; Store LSB of recs used in R1
LD A,0 ; Store zero in R2
XOR A ; Store zero in R2
LD (IX+23H),A ; ...
LD A,0 ; Success
XOR A ; Success
LD L,A ; Return in L also
RET
FSERR LD A,0FFH ; File not found
@ -1291,6 +1337,23 @@ FSMLICD DEFW 0000H ; ProDOS PL: Create date
FSMLICT DEFW 0000H ; ProDOS PL: Create time
; Update random access pointer
; DE contains the pointer to the FCB to update
; Sets the random access record of the FCB to the value of the last record
; read or written sequentially
F_RANDREC LD H,D ; Copy FCB pointer into HL for arithmetic
LD L,E ; ...
LD BC,20H ; Offset 20H is the sequential rec number
ADD HL,BC ; ...
LD A,(HL) ; Put sequential record number in A
DEC A ; Remember F_READ/F_WRITE increment this
INC HL ; Offset 21H is LSB of random rec number
LD (HL),A ; Write sequential rec # to random LSB
INC HL ; Offset 22H is MSB of random rec number
XOR A ; A=0
LD (HL),A ; Set MSB of random rec number to 0
RET
; Selectively reset disk drives
; DE contains bitmap of drives to reset (bit 0 of E if A:, bit 7 of D is P:)
; Returns A=00H if okay, A=FFH if error
@ -1407,7 +1470,7 @@ PATH2FCB EX DE,HL ; Stash HL in DE so we can use HL here
LD HL,(DMAADDR) ; Set all 32 bytes to FCB to zero
LD C,0 ; ...
LD A,0 ; ...
XOR A ; ...
P2FL1 LD (HL),C ; ...
INC HL ; ...
INC A ; ...
@ -1417,7 +1480,7 @@ P2FL1 LD (HL),C ; ...
LD HL,(DMAADDR) ; Set all filename chars in FCB to space
INC HL ; ...
LD C,' ' ; ...
LD A,0 ; ...
XOR A ; ...
P2FL2 LD (HL),C ; ...
INC HL ; ...
INC A ; ...
@ -1496,7 +1559,7 @@ RDDIRBLK LD HL,(DMAADDR) ; Save existing DMA address
CP 0 ; See if there was an error
JP NZ,RDBS1 ; If so, quit with error code
LD A,0 ; Return code for success
XOR A ; Return code for success
JP RDBS2 ; Successful return
RDBS1 LD A,0FFH ; Error return code
@ -1529,7 +1592,7 @@ MFS1 INC DE ; Advance source pointer
LD A,8+3 ; Compare character counter
CP C ; ...
JP NZ,MFL1 ; Loop if characters left
LD A,0 ; We have a match
XOR A ; We have a match
RET ;
MFS2 LD A,0FFH ; No match
RET
@ -1558,7 +1621,7 @@ CHKDIRENT LD B,0 ; Hardcode drive A: for now. TODO: fix!
JP Z,CDES2 ; If so, return
CDES1 LD A,0FFH ; No match
RET ;
CDES2 LD A,0 ; Match
CDES2 XOR A ; Match
RET
; Search a 512 byte block of a ProDOS directory for a matching file entry
@ -1585,7 +1648,7 @@ CDBL1 CALL CHKDIRENT ; Match the file entry at HL
JP NZ,CDBL1 ; If not, loop
LD A,0FFH ; No match
RET ;
CDBS1 LD A,0 ; Match
CDBS1 XOR A ; Match
RET
; The following variables are used to preserve state between calls

Binary file not shown.

Binary file not shown.