include 'gsos.equ' include 'minix.equ' include 'fst.equ' include 'fst.macros' include 'M16.Debug' include 'records.equ' include 'p.equ' ; ; dirent_entry 0 is a special case. ; (assuming base = 1, displacement = 1) ; first call: ; before ; dirent_entry = 0, dirent_zone = 0, dirent_offset = 0 ; after: ; dirent_entry = 1, dirent_zone = 0, dirent_offset = 0 ; ; subsequent calls: ; before ; dirent_entry = 1, dirent_zone = ..., dirent_offset = ... ; after ; dirent_entry = 2, dirent_zone = ..., dirent_offset = ... ; gde_dp record dp ; size of the directory, divided by dirent_size. size ds.l 1 displacement ds.w 1 dirent_size ds.w 1 dirent_zone ds.w 1 dirent_offset ds.w 1 dirent_entry ds.w 1 IF *>=$d4 THEN AERROR 'dp -- too large.' ENDIF endr data record dirent ds v1L_dirent endr import init_fcr import init_vcr import load_inode import read_data_block import do_ignore import do_eof import do_blocks import do_r_eof import do_r_blocks import do_access import do_file_sys_id import do_option_list import do_create_date_time import do_mod_date_time import do_file_type import do_aux_type entry init entry base_displace entry find_next_dirent entry find_absolute_dirent entry find_dirent_block entry count_entries entry count_dirent_block entry do_flags entry do_name_buffer_0 entry do_name_buffer_1 entry do_entry_num get_dir_entry procname export with fst_parms with dp with gde_dp jsr init_fcr jsr init_vcr ; check for read-access ldy #fcr.access lda [ return total count. ; cmp #0 beq @count jmp find_absolute_dirent @count jmp count_entries forward jmp find_next_dirent ; backward ; backward 0 ? == forward 0 cmp #0 beq forward eor #$ffff sec ; inc / clc adc dirent_entry sta displacement jmp find_absolute_dirent endp count_entries proc ; count the number of entries. with fst_parms with dp, gde_dp ; read each block and count the entries. ; only handles direct blocks. so there. ; disk inode has been copied to the dp. stz dirent_entry ldx #0 zone_loop lda disk_inode.zone,x beq next ; directory should not be sparse! phx ; save jsr read_data_block plx ; and restore bcs exit jsr count_dirent_block lda size beq done next inx inx cpx #v1.NR_DZONES*2 bcs done bra zone_loop ; ; minix has 16-byte dirents. ; linux has 32-byte dirents. done ; also reset the displacement to 0. lda #0 ldy #fcr.dirent_entry sta [my_fcr],y ldy #fcr.dirent_zone sta [my_fcr],y ldy #fcr.dirent_offset sta [my_fcr],y clc exit rts endp count_dirent_block proc ; 16-byte dirent entries -- 64 per block. with dp, gde_dp ldy #0 loop lda [io_buffer],y beq next inc dirent_entry next ; not 32-bit safe. dec size beq done tya clc adc dirent_size tay cmp #1024 bcc loop done rts endp strlen proc ; strlen the dirent. ; will be 0-terminated unless if < dirent size. with gde_dp lda data.dirent.inode beq exit ldx #2 short m loop lda data.dirent,x beq zero inx cpx dirent_size bcc loop zero long m txa dec a ; -2 for dirent.inode dec a exit rts endp do_flags proc with fst_parms ; $8000 for extended file, 0 for everything else. lda #0 sta [param_blk_ptr],y rts endp do_entry_num proc with fst_parms with gde_dp lda dirent_entry sta [param_blk_ptr],y rts endp do_name_buffer_0 proc with fst_parms with dp lda [param_blk_ptr],y sta ptr iny iny lda [param_blk_ptr],y sta ptr+2 ora ptr beq exit copy_it phx jsr strlen ; strlen handles inode = 0 tax tay short m sta [ptr] ; no need to dey since there is a length byte. dex bmi @done @loop lda data.dirent.name,x sta [ptr],y dey dex bpl @loop @done long m plx exit rts endp do_name_buffer_1 proc with fst_parms with dp lda [param_blk_ptr],y sta ptr iny iny lda [param_blk_ptr],y sta ptr+2 ora ptr beq exit phx jsr strlen pha ; save lda [ptr] ; total output buffer size sec sbc #4 bmi error cmp 1,s bcs ok error_store_size ldy #2 sta [ptr],y error pla lda #buff_too_small sta tool_error plx rts ok pla ; strlen ldy #2 sta [ptr],y tax tay iny ; skip gs/os string overhead iny iny short m dex bmi @done @loop lda data.dirent.name,x sta [ptr],y dey dex bpl @loop @done long m plx exit rts endp ; ; ; new code.... ; here's our big insight ; 1. base 1, displacement xxx is equivalent to stepping forward xxx entries. ; 2. base 2, displacement xxx is equivalent to base 0, displacement fcr.dirent_entry - displacement ; 2a. if displacement is 0, is equivalent to stepping forward 0 entries. ; 3. base 0, displacement xxx is equivalent to base 1 displacement xxx when fcr.dirent_entry = 0 ; ; therefore the only special case is dirent_entry == 0 (since displacement 1 -> read entry 0) ; ; find_absolute_dirent proc with gde_dp ; if displacement > dirent_entry, we can re-use that info. lda displacement cmp dirent_entry bcc no sec sbc dirent_entry sta displacement bra find_next_dirent no stz dirent_entry stz dirent_zone stz dirent_offset bra find_next_dirent endp find_next_dirent proc with gde_dp, dp lda dirent_entry bne @ok ; if currently on dirent entry 0, displacement -= 1 inc dirent_entry dec displacement bmi eod @ok ldx dirent_zone loop lda disk_inode.zone,x beq sparse ; should never happen... phx ; save jsr read_data_block plx bcs exit jsr find_dirent_block bcs exit bvc found_it next inx inx stz dirent_offset cpx #v1.NR_DZONES*2 bcs exit ; also check size lda size beq eod bmi eod bra loop sparse ; should never happen... ; skip over 1 block. ; size -= dirents per block -- 32 for linux, 64 for minix lda dirent_size ; 16 or 32. 32 -> 32, 16 -> 64. cmp #32 beq @ok lda #64 @ok eor #$ffff sec ; + 1 adc size sta size bra next found_it stx dirent_zone sty dirent_offset clc exit rts eod lda #end_of_dir sec rts endp ; ; returns: ; carry set on error. ; overflow clear if found ; ; inputs y = dirent offset find_dirent_block proc with dp, gde_dp ldy dirent_offset loop lda [io_buffer],y beq next inc dirent_entry dec displacement bmi found_it next dec size beq eod tya clc adc dirent_size tay cmp #1024 bcc loop ; not found ... lda #0 clc sep #p.v rts eod lda #end_of_dir sec rts found_it ; we found our entry!!! ; copy it over. stx dirent_zone sty dirent_offset ; dirent_entry updated above. lda [io_buffer],y ldx #0 @loop lda [io_buffer],y sta data.dirent,x iny iny inx inx cpx dirent_size bcc @loop ; update the fcr. lda dirent_entry ldy #fcr.dirent_entry sta [my_fcr],y lda dirent_offset ldy #fcr.dirent_offset sta [my_fcr],y lda dirent_zone ldy #fcr.dirent_zone sta [my_fcr],y lda #0 clc clv rts endp end