first working version (with filenames at least, devices not tested yet)

git-svn-id: svn://svn.cc65.org/cc65/trunk@18 b7a2c559-68d2-44c3-8de9-860c34a00d81
This commit is contained in:
cpg 2000-05-30 22:28:30 +00:00
parent d1d9ebe9e7
commit ca35829405
1 changed files with 241 additions and 33 deletions

View File

@ -5,22 +5,26 @@
;
.include "atari.inc"
.importzp tmp2,ptr4,sp
.importzp tmp1,tmp2,tmp3,ptr4,sp
.import subysp,addysp
.export fdtoiocb
.export fdtoiocb_down
.export fd_table
.export fddecusage
.export newfd
.export getfd
.export _fd_table,_fd_index
.data
MAX_FD_INDEX = 12
_fd_index:
fd_index: ; fd number is index into this table, entry's value specifies the fd_table entry
.res MAX_FD_INDEX,$ff
fd_table:
.byte 0,$ff,0,0
.byte 0,$ff,0,0
.byte 0,$ff,0,0
.byte 0,$ff,0,0
.byte 0,$ff,0,0
_fd_table:
fd_table: ; each entry represents an open iocb
.byte 0,0,'E',0 ; system console, app starts with opened iocb #0 for E:
.byte 0,$ff,0,0
.byte 0,$ff,0,0
.byte 0,$ff,0,0
@ -31,9 +35,13 @@ fd_table:
MAX_FD_VAL = (* - fd_table) / 4
ft_entrylen = 4 ; length of table entry (it's not sufficient to change here!
; the code sometimes does two bit shifts to multiply/divide by
; this length)
ft_usa = 0 ; usage counter
ft_iocb = 1 ; iocb index (0,$10,$20,etc.), $ff for empty entry
ft_dev = 2 ; device of open iocb
ft_dev = 2 ; device of open iocb (0 - device not remembered, eg. filename specified)
ft_flag = 3 ; flags
; lower 3 bits: device number (for R: and D:)
@ -48,8 +56,14 @@ ft_flag = 3 ; flags
cpx #0
bne inval
cmp #MAX_FD_VAL
cmp #MAX_FD_INDEX
bcs inval
tax
lda fd_index,x ; get index
tay
lda #$ff
sta fd_index,x ; clear entry
tya
asl a ; create index into fd table
asl a
tax
@ -92,8 +106,10 @@ inval: ldx #$ff ; sets N
cpx #0
bne inval
cmp #MAX_FD_VAL
cmp #MAX_FD_INDEX
bcs inval
tax
lda fd_index,x
asl a ; create index into fd table
asl a
tax
@ -114,8 +130,14 @@ inval: ldx #$ff ; sets N
.proc fddecusage
lda tmp2 ; get fd
cmp #MAX_FD_VAL
cmp #MAX_FD_INDEX
bcs ret ; invalid index, do nothing
tax
lda fd_index,x
pha
lda #$ff
sta fd_index,x
pla
asl a ; create index into fd table
asl a
tax
@ -138,16 +160,17 @@ ret: rts
;
; called from open() function
; finds a fd to use for an open request
; checks whether it's a device or file (file: characters following the ':')
; checks whether it's a device or file (file: characters follow the ':')
; files always get an exclusive slot
; for devices it is checked whether the device is already open, and if yes,
; a link to this open device is returned
;
; Calling paramteter:
; Calling parameters:
; tmp3 - length of filename + 1
; AX - points to filename
; Y - iocb to use (if we need a new open)
; Return parameters:
; tmp2 - fd num
; tmp2 - fd num ($ff and C=0 in case of error - no free slot)
; C - 0/1 for no open needed/open should be performed
; all registers preserved!
@ -157,13 +180,14 @@ ret: rts
; ptr4 - 3,4 (backup)
; devnum - 5
loc_A = 0
loc_X = 1
loc_Y = 2
loc_ptr4_l = 3
loc_ptr4_h = 4
loc_devnum = 5
loc_size = 6
;loc_A = 0
;loc_X = 1
loc_Y = 0
loc_ptr4_l = 1
loc_ptr4_h = 2
loc_tmp1 = 3
loc_devnum = 4
loc_size = 5
.proc newfd
@ -179,6 +203,12 @@ loc_size = 6
lda #0
sta (sp),y ; loc_devnum
dey
lda tmp1
sta (sp),y ; loc_tmp1
lda #0
sta tmp1 ; init tmp1
sta tmp2 ; init tmp2
dey
lda ptr4+1
sta (sp),y ; loc_ptr4_h
dey
@ -187,13 +217,13 @@ loc_size = 6
dey
pla
sta (sp),y ; loc_Y
dey
; dey
pla
sta (sp),y ; loc_X
; sta (sp),y ; loc_X
sta ptr4+1
dey
; dey
pla
sta (sp),y ; loc_A
; sta (sp),y ; loc_A
sta ptr4
; ptr4 points to filename
@ -207,23 +237,201 @@ loc_size = 6
beq colon2
; no colon there!? OK, then we use a fresh iocb....
; return error here? no, the subsequent open call should fail
do_open:nop ; @@@TODO
ldy #loc_size
jsr addysp
rts
colon2: dey
do_open_nd: ; do open and don't remember device
lda #2
sta tmp1
do_open:lda tmp1
ora #1
sta tmp1 ; set flag to return 'open needed' : C = 1
ldx #ft_iocb
ldy #$ff
srchfree:
tya
pha
cmp fd_table,x
beq freefnd ; found a free slot
txa
clc
adc #ft_entrylen
tax
cmp #(MAX_FD_VAL*4)+ft_iocb ; end of table reached?
bcc srchfree
; error: no free slot found
noslot: ldx #0
stx tmp1 ; return with C = 0
dex
stx tmp2 ; iocb: $ff marks error
jmp finish
; found a free slot
freefnd:txa
sec
sbc #ft_iocb ; normalize
tax
lsr a
lsr a
sta tmp2 ; return fd
lda #2
bit tmp1 ; remember device?
beq l1 ; yes
lda #0 ; no, put 0 in field
beq l2
l1: ldy #0
lda (sp),y ; get device
l2: sta fd_table+ft_dev,x ; set device
lda #1
sta fd_table+ft_usa,x ; set usage counter
ldy #loc_Y
lda (sp),y
sta fd_table+ft_iocb,x ; set iocb index
ldy #loc_devnum
lda (sp),y ; get (optional) device number
and #7 ; only 3 bits
sta fd_table+ft_flag,x
lda tmp2
jsr fdt_to_fdi ; get new index
bcs noslot ; no one available
;cmp #$ff ; no one available
;beq noslot ;@@@ cleanup needed
sta tmp2 ; return index
jmp finish
; string in "Xn:xxx" format
colon2: dey
lda (ptr4),y ; get device number
sec
sbc #'0'
and #7
ldy #loc_devnum
sta (sp),y ; save it
sta tmp2 ; save it for speed later here also
lda #4 ; max. length if only device + number ("Xn:")
cmp tmp3
bcc do_open_nd ; string is longer -> contains filename
bcs check_dev ; handle device only string
; string in "X:xxx" format
colon1: lda #3 ; max. length if device only ("X:")
cmp tmp3
bcc do_open_nd ; string is longer -> contains filename
; get device and search it in fd table
check_dev:
ldy #0
lda (ptr4),y ; get device id
tay
ldx #(MAX_FD_VAL*4) - ft_entrylen
srchdev:lda #$ff
cmp fd_table+ft_iocb,x ; is entry valid?
beq srch2 ; no, skip this entry
tya
cmp fd_table+ft_dev,x
beq fnddev
srch2: txa
sec
sbc #ft_entrylen+1
tax
bpl srchdev
; not found, open new iocb
jmp do_open
; helper for branch out of range
noslot1:jmp noslot
; found device in table, check device number (e.g R0 - R3)
fnddev: lda fd_table+ft_flag,x
and #7
cmp tmp2 ; contains devnum
bne srch2 ; different device numbers
; found existing open iocb with same device
txa
lsr a
lsr a
sta tmp2
inc fd_table+ft_usa,x ; increment usage counter
jsr fdt_to_fdi ; get new index
bcs noslot1 ; no one available
sta tmp2 ; return index
; clean up and go home
finish: lda ptr4
pha
lda ptr4+1
pha
ldy #loc_Y
lda (sp),y
pha
lda tmp1
pha
ldy #loc_tmp1
lda (sp),y
sta tmp1
ldy #loc_size
jsr addysp
pla
lsr a ; set C as needed
pla
tay
colon1:
pla
tax
pla
rts
.endproc
; ftp_to_fdi
; returns a fd_index entry pointing to the given ft_table entry
; get fd_table entry in A
; return C = 0/1 for OK/error
; return fd_index entry in A if OK
; registers destroyed
.proc fdt_to_fdi
tay
lda #$ff
tax
inx
loop: cmp fd_index,x
beq found
inx
cpx #MAX_FD_INDEX
bcc loop
rts
found: tya
sta fd_index,x
txa
clc
rts
.endproc
; getfd
; get a new fd pointing to a ft_table entry
; usage counter of ft_table entry incremented
; A - fd_table entry
; return C = 0/1 for OK/error
; returns fd in A if OK
; registers destroyed, tmp1 destroyed
.proc getfd
sta tmp1 ; save fd_table entry
jsr fdt_to_fdi
bcs error
pha
lda tmp1
asl a
asl a ; also clears C
tax
inc fd_table+ft_usa,x ; increment usage counter
pla
error: rts
.endproc