Working on the CBM file functions

git-svn-id: svn://svn.cc65.org/cc65/trunk@1533 b7a2c559-68d2-44c3-8de9-860c34a00d81
This commit is contained in:
cuz 2002-11-17 22:45:55 +00:00
parent 43d5800702
commit 544ff5b900
11 changed files with 377 additions and 229 deletions

View File

@ -44,7 +44,7 @@ S_OBJS = c_acptr.o \
close.o \
ctype.o \
cvline.o \
diskerror.o \
diskcmd.o \
filedes.o \
filename.o \
filevars.o \
@ -57,6 +57,7 @@ S_OBJS = c_acptr.o \
oserror.o \
read.o \
revers.o \
rwcommon.o \
scratch.o \
sysremove.o \
systime.o \

View File

@ -51,8 +51,17 @@ IOBASE = $FFF3
;-----------------------------------------------------------------------------
; Device numbers
;
CBMDEV_KBD = 0
CBMDEV_DATASETTE= 1
CBMDEV_RS232 = 2
CBMDEV_SCREEN = 3
;-----------------------------------------------------------------------------
; Disk stuff
;
MAX_DRIVES = 24
FIRST_DRIVE = 8

View File

@ -6,8 +6,9 @@
.export _close
.import getdiskerror
.import readdiskerror, closecmdchannel
.import __errno, __oserror
.importzp tmp2
.include "errno.inc"
.include "cbm.inc"
@ -25,36 +26,40 @@
bne invalidfd
cmp #MAX_FDS ; Is it valid?
bcs invalidfd ; Jump if no
sta tmp2 ; Save the handle
; Check if the LFN is valid and the file is open for writing
; Check if the file is actually open
adc #LFN_OFFS ; Carry is already clear
tax
lda fdtab-LFN_OFFS,x; Get flags for this handle
lda fdtab,x ; Get flags for this handle
and #LFN_OPEN
beq notopen
; Valid lfn, close it. The close call is always error free, at least as far
; as the kernal is involved
lda #LFN_CLOSED
sta fdtab-LFN_OFFS,x
lda unittab,x
pha ; Push unit for this file
txa
sta fdtab,x
lda tmp2 ; Get the handle
clc
adc #LFN_OFFS ; Make LFN from handle
jsr CLOSE
pla
; Read the drive error channel
; Read the drive error channel, then close it
lda unittab,x
tax
jsr getdiskerror
cmp #$00
bne error
ldy tmp2 ; Get the handle
ldx unittab,y ; Get teh disk for this handle
jsr readdiskerror ; Read the disk error code
pha ; Save it on stack
ldy tmp2
ldx unittab,y
jsr closecmdchannel ; Close the disk command channel
pla ; Get the error code from the disk
bne error ; Jump if error
; Successful
tax
tax ; Return zero in a/x
rts
; Error entry, file descriptor is invalid

212
libsrc/cbm/diskcmd.s Normal file
View File

@ -0,0 +1,212 @@
;
; Ullrich von Bassewitz, 17.11.2002
;
; Handle disk command channels
;
.export isdisk
.export opencmdchannel
.export closecmdchannel
.export readdiskerror
.export writediskcmd
.importzp tmp1, ptr1
.include "cbm.inc"
.include "filedes.inc"
;--------------------------------------------------------------------------
; isdisk: Return carry clear if the unit number in X is a disk, return
; carry set if not.
.proc isdisk
cpx #FIRST_DRIVE ; Disk unit?
bcc @L1 ; Branch if no disk
cpx #FIRST_DRIVE+MAX_DRIVES
rts
@L1: sec
rts
.endproc
;--------------------------------------------------------------------------
; Open the command channel for the disk unit in X. The function returns an
; error code in A and sets the flags according to the contents of A.
opencmdchannel:
jsr isdisk ; Disk unit?
bcs success
; Is this channel already open?
ldy opentab-FIRST_DRIVE,x
bne isopen
; Open the command channel, Carry is still clear
stx tmp1 ; Save the unit number
txa ; Get unit number
adc #(LFN_OFFS+MAX_FDS-FIRST_DRIVE)
ldy #15 ; Secondary address for cmd channel
jsr SETLFS
lda #0
jsr SETNAM ; No name supplied to OPEN
jsr OPEN
bcs done ; Error, code is in A
; Command channel is open now. Increment the count
ldx tmp1 ; Unit number
ldy opentab-FIRST_DRIVE,x
isopen: iny
tya
sta opentab-FIRST_DRIVE,x
; Done, return success
success:lda #$00
done: cmp #$00 ; Set flags for return code
rts
;--------------------------------------------------------------------------
; closecmdchannel: Decrement the counter for the disk command channel and
; close the channel if the counter drops to zero. The function expects the
; drive number in X and returns an error code in A. The flags for the return
; code are set when the function returns.
closecmdchannel:
jsr isdisk ; Disk unit?
bcs success
; Is this channel really open?
ldy opentab-FIRST_DRIVE,x
beq success ; OOPS! Channel is not open
; Decrement the count and stor it back
dey
tya
sta opentab-FIRST_DRIVE,x
; If the counter is now zero, close the channel. We still have carry clear
; when we come here.
bne success
txa ; Make LFN from drive number
adc #(LFN_OFFS+MAX_FDS-FIRST_DRIVE)
jsr CLOSE
bcs done
bcc success
;--------------------------------------------------------------------------
; readdiskerror: Read a disk error from an already open command channel.
; Returns an error code in A, which may either be the code read from the
; command channel, or another error when accessing the command channel failed.
readdiskerror:
jsr isdisk
bcs success
; Read the command channel. We won't check the status after the channel is
; open, because this seems to be unnecessary in most cases.
txa
clc ; Make LFN from drive number
adc #(LFN_OFFS+MAX_FDS-FIRST_DRIVE)
tax
jsr CHKIN ; Make the command channel input
bcs done ; Bail out with error code in A
jsr BASIN
and #$0F ; Make digit value from PETSCII
sta tmp1
asl a ; * 2
asl a ; * 4, carry clear
adc tmp1 ; * 5
asl a ; * 10
sta tmp1
jsr BASIN
and #$0F ; Make digit value from PETSCII
clc
adc tmp1
; Errors below 20 are not real errors. Fix that
cmp #20+1
bcs @L1
lda #$00
@L1: pha
; Read the remainder of the message and throw it away
@L2: jsr BASIN
cmp #$0D
bne @L2
; Close the input channel
jsr CLRCH
; Restore the error code (will also set the flags) and return
pla
rts
;--------------------------------------------------------------------------
; writediskcmd: Gets pointer to data in ptr1, length in A. Writes all data
; to the command channel of the given drive. Returns an error code in A,
; flags are set according to the contents of A.
writediskcmd:
jsr isdisk
bcs success
; Remember the length
sta tmp1
; Write to the command channel.
txa
clc ; Make LFN from drive number
adc #(LFN_OFFS+MAX_FDS-FIRST_DRIVE)
tax
jsr CKOUT ; Make the command channel output
bcs done ; Bail out with error code in A
ldy #$00
@L1: cpy tmp1
bcs @L3
lda (ptr1),y
iny
jsr BSOUT
bcc @L1
@L2: pha
jsr CLRCH
pla
rts
@L3: jsr CLRCH
lda #$00
rts
;--------------------------------------------------------------------------
; Data
.bss
opentab: .res MAX_DRIVES, 0

View File

@ -1,87 +0,0 @@
;
; Ullrich von Bassewitz, 16.11.2002
;
; Read the disk error channel
;
.export readdiskerror, getdiskerror
.import fnunit
.importzp tmp1
.include "cbm.inc"
;--------------------------------------------------------------------------
; readdiskerror: Read a disk error from an already open command channel.
; Returns an error code in A, which may either be the code read from the
; command channel, or another error when accessing the command channel failed.
.proc readdiskerror
; Read the command channel. We won't check the status after the channel is
; open, because this seems to be unnecessary in most cases.
ldx #15
jsr CHKIN ; Read from LFN 15
bcs done ; Bail out with error code in A
jsr BASIN
and #$0F ; Make digit value from PETSCII
sta tmp1
asl a ; * 2
asl a ; * 4, carry clear
adc tmp1 ; * 5
asl a ; * 10
sta tmp1
jsr BASIN
and #$0F ; Make digit value from PETSCII
clc
adc tmp1
; Errors below 20 are not real errors. Fix that
cmp #20+1
bcs done
lda #0
done: rts
.endproc
;--------------------------------------------------------------------------
; getdiskerror: Open the command channel to a disk unit with id in X. Read
; the error and close it again. Returns an error code in A, which may either
; be the code read from the command channel, or another error when accessing
; the command channel failed.
.proc getdiskerror
cpx #8 ; Disk unit?
bcc nodisk
lda #15 ; Command channel
tay ; Secondary address
jsr SETLFS
lda #$00
jsr SETNAM ; No name supplied to OPEN
jsr OPEN
bcs err
jsr readdiskerror
pha ; Save error code
lda #15
jsr CLOSE
pla
err: rts
nodisk: lda #$00
rts
.endproc

View File

@ -14,6 +14,8 @@ LFN_OFFS = 3 ; Start with logical file number 3
LFN_CLOSED = $00 ; LFN is closed
LFN_READ = $01 ; Open for reading
LFN_WRITE = $02 ; Open for writing
LFN_OPEN = (LFN_READ | LFN_WRITE)
LFN_EOF = $80 ; Read to EOF
LFN_STDIN = LFN_OFFS+0
LFN_STDOUT = LFN_OFFS+1

View File

@ -8,7 +8,7 @@
.import addysp, popax
.import scratch, fnparse, fncomplete, fnset
.import getdiskerror
.import opencmdchannel, closecmdchannel, readdiskerror
.import __errno, __oserror
.import fnunit
.importzp sp, tmp2, tmp3
@ -110,26 +110,18 @@ common: sta tmp3
jsr OPEN
bcs error
; Read the error channel
; Open the the drive command channel and read it
ldx fnunit
jsr getdiskerror
cmp #0
beq isopen ; Branch if no error
; We had an error, close the file
pha
lda tmp2
clc
adc #LFN_OFFS
jsr CLOSE
pla
bne error ; Branch always
jsr opencmdchannel
bne closeandexit
ldx fnunit
jsr readdiskerror
bne closeandexit ; Branch on error
; File is open. Mark it as open in the table
isopen: ldx tmp2
ldx tmp2
lda tmp3
sta fdtab,x
lda fnunit
@ -161,7 +153,18 @@ invflags:
sta __errno+1
beq errout
; Error entry: Close the file and exit
closeandexit:
pha
lda tmp2
clc
adc #LFN_OFFS
jsr CLOSE
ldx fnunit
jsr closecmdchannel
pla
bne error ; Branch always
.endproc

View File

@ -6,10 +6,11 @@
.export _read
.constructor initstdin
.import rwcommon
.import popax
.import __errno, __oserror
.importzp ptr1, ptr2, ptr3, tmp1, tmp2
.importzp ptr1, ptr2, ptr3, tmp1, tmp2, tmp3
.include "errno.inc"
.include "fcntl.inc"
@ -39,31 +40,8 @@
.proc _read
; Retrieve count
jsr popax ; Get count
eor #$FF
sta ptr1
txa
eor #$FF
sta ptr1+1 ; Remember -count-1
; Retrieve buf
jsr popax
sta ptr2
stx ptr2+1
; Retrieve the handle
jsr popax
; Check if we have a valid handle
cpx #$00
bne invalidfd
cmp #MAX_FDS ; Is it valid?
bcs invalidfd ; Jump if no
jsr rwcommon ; Pop params, check handle
bcs invalidfd ; Branch if handle not ok
; Check if the LFN is valid and the file is open for writing
@ -73,34 +51,27 @@
and #LFN_READ ; File open for writing?
beq notopen
; Check the EOF flag. If it is set, don't read anything
lda fdtab-LFN_OFFS,x; Get flags for this handle
bmi eof
; Valid lfn. Make it the input file
jsr CHKIN
bcs error
; Clear the byte counter
lda #$00
sta ptr3
sta ptr3+1
; Read the status to check if we are already at the end of the file
jsr READST
and #%01000000
bne done
; Go looping...
beq deccount ; Branch always
bcc @L3 ; Branch always
; Read the next byte
loop: jsr BASIN
@L0: jsr BASIN
sta tmp1 ; Save the input byte
jsr READST ; Read the IEEE status
sta tmp2 ; Save it
sta tmp3 ; Save it
and #%10111111 ; Check anything but the EOI bit
bne error5 ; Assume device not present
@ -121,17 +92,24 @@ loop: jsr BASIN
; Get the status again and check the EOI bit
@L2: lda tmp2
@L2: lda tmp3
and #%01000000 ; Check for EOI
bne done ; Jump if end of file reached
bne @L4 ; Jump if end of file reached
; Decrement the count
deccount:
inc ptr1
bne loop
@L3: inc ptr1
bne @L0
inc ptr1+1
bne loop
bne @L0
beq done ; Branch always
; Set the EOI flag and bail out
@L4: ldx tmp2 ; Get the handle
lda #LFN_EOF
ora fdtab,x
sta fdtab,x
; Read done, close the input channel
@ -139,7 +117,7 @@ done: jsr CLRCH
; Return the number of chars read
lda ptr3
eof: lda ptr3
ldx ptr3+1
rts
@ -157,7 +135,7 @@ invalidfd:
notopen:
lda #3 ; File not open
bne error
; Error entry, status not ok
error5: lda #5 ; Device not present

47
libsrc/cbm/rwcommon.s Normal file
View File

@ -0,0 +1,47 @@
;
; Ullrich von Bassewitz, 17.11.2002
;
; Common stuff for the read/write routines
;
.export rwcommon
.import popax
.importzp ptr1, ptr2, ptr3, tmp2
.include "filedes.inc"
;--------------------------------------------------------------------------
; rwcommon: Pop the parameters from stack, preprocess them and place them
; into zero page locations. Return carry set if the handle is invalid,
; return carry clear if it is ok. If the carry is clear, the handle is
; returned in A.
.proc rwcommon
jsr popax ; Get count
eor #$FF
sta ptr1
txa
eor #$FF
sta ptr1+1 ; Remember -count-1
jsr popax ; Get buf
sta ptr2
stx ptr2+1
lda #$00
sta ptr3
sta ptr3+1 ; Clear ptr3
jsr popax ; Get the handle
sta tmp2
cpx #$01
bcs inv
cmp #MAX_FDS
inv: rts
.endproc

View File

@ -5,8 +5,9 @@
;
.export scratch
.import readdiskerror
.import opencmdchannel, closecmdchannel, writediskcmd
.import fnunit, fnlen, fncmd
.importzp ptr1
.include "cbm.inc"
@ -18,28 +19,27 @@
.proc scratch
lda #15 ; Command channel
ldx fnunit ; Unit
tay ; Secondary address
jsr SETLFS
ldx fnunit
jsr opencmdchannel
bne done
lda #'s' ; Scratch command
sta fncmd
lda #<fncmd
sta ptr1
lda #>fncmd
sta ptr1+1
ldx fnlen
inx ; Account for "S"
txa ; Length of name into A
ldx #<fncmd
ldy #>fncmd
jsr SETNAM
jsr OPEN
bcs done
jsr readdiskerror ; Read the command channel
ldx fnunit ; Unit
jsr writediskcmd
pha
lda #15
jsr CLOSE
ldx fnunit
jsr closecmdchannel
pla
done: rts

View File

@ -7,9 +7,9 @@
.export _write
.constructor initstdout
.import incsp6
.import rwcommon
.import __errno, __oserror
.importzp sp, ptr1, ptr2
.importzp sp, ptr1, ptr2, ptr3
.include "errno.inc"
.include "fcntl.inc"
@ -44,13 +44,8 @@
.proc _write
ldy #4
lda (sp),y ; Get fd
; Check if we have a valid handle
cmp #MAX_FDS ; Is it valid?
bcs invalidfd ; Jump if no
jsr rwcommon ; Pop params, check handle
bcs invalidfd ; Branch if handle not ok
; Check if the LFN is valid and the file is open for writing
@ -64,49 +59,35 @@
jsr CKOUT
bcs error
; Calculate -count-1 for easier looping
ldy #0
lda (sp),y
eor #$FF
sta ptr1
iny
lda (sp),y
eor #$FF
sta ptr1+1
; Get the pointer to the data buffer
iny
lda (sp),y
sta ptr2
iny
lda (sp),y
sta ptr2+1
jmp deccount
bcc @L2
; Read the IEEE488 status
loop: jsr READST
@L0: jsr READST
cmp #0
bne error5
; Output the next character from the buffer
ldy #0
lda (ptr2),y
inc ptr2
bne @L1
inc ptr2+1 ; A = *buf++;
@L1: jsr BSOUT
; Count characters written
inc ptr3
bne @L2
inc ptr3+1
; Decrement count
deccount:
inc ptr1
bne loop
@L2: inc ptr1
bne @L0
inc ptr1+1
bne loop
bne @L0
; Wrote all chars, close the output channel
@ -114,12 +95,9 @@ deccount:
; Return the number of chars written
ldy #1
lda (sp),y
tax
dey
lda (sp),y
jmp incsp6
lda ptr3
ldx ptr3+1
rts
; Error entry, file descriptor is invalid
@ -142,7 +120,7 @@ error5: lda #5 ; Device not present
error: sta __oserror
errout: lda #$FF
tax ; Return -1
jmp incsp6
rts
.endproc