From ca3582940557587f7833c3605b2803c424f6ec8a Mon Sep 17 00:00:00 2001 From: cpg Date: Tue, 30 May 2000 22:28:30 +0000 Subject: [PATCH] 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 --- libsrc/atari/fdtable.s | 274 ++++++++++++++++++++++++++++++++++++----- 1 file changed, 241 insertions(+), 33 deletions(-) diff --git a/libsrc/atari/fdtable.s b/libsrc/atari/fdtable.s index 660880d1c..f3efd0076 100644 --- a/libsrc/atari/fdtable.s +++ b/libsrc/atari/fdtable.s @@ -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