diff --git a/desk.acc/sort.directory.s b/desk.acc/sort.directory.s index 4b3163d..e92815d 100644 --- a/desk.acc/sort.directory.s +++ b/desk.acc/sort.directory.s @@ -10,12 +10,18 @@ .org $800 + +CHAR_MASK := $7F +CASE_MASK := $DF + + ;;; ============================================================ cli jmp start -L0804: .byte 0 + ;; unit_num for active window, for block operations +unit_num: .byte 0 save_stack: .byte 0 @@ -24,20 +30,22 @@ save_stack: start: tsx stx save_stack - jmp L0932 + jmp start2 -L080D: ldx save_stack +.proc exit + ldx save_stack txs lda a:$0A - bne L0817 + bne :+ rts -L0817: lda #$40 +: lda #$40 pha lda #$0B pha lda a:$0A rts +.endproc ;;; ============================================================ ;;; ProDOS Relays @@ -118,6 +126,7 @@ L0817: lda #$40 .endproc ;;; ============================================================ +;;; ProDOS call parameter blocks DEFINE_ON_LINE_PARAMS on_line_params,, on_line_buffer on_line_buffer: @@ -128,9 +137,13 @@ on_line_buffer: .byte 0 - DEFINE_OPEN_PARAMS open_params, path_buf, $1C00 - DEFINE_READ_PARAMS read_params, $0E00, $0E00 - DEFINE_WRITE_PARAMS write_params, $0E00, $0E00 + io_buf := $1C00 + buffer := $0E00 + buffer_len := $0E00 + + DEFINE_OPEN_PARAMS open_params, path_buf, io_buf + DEFINE_READ_PARAMS read_params, buffer, buffer_len + DEFINE_WRITE_PARAMS write_params, buffer, buffer_len DEFINE_CLOSE_PARAMS close_params DEFINE_GET_FILE_INFO_PARAMS file_info_params, path_buf @@ -140,71 +153,91 @@ path_buf: .res 65, 0 ;;; ============================================================ +;;; Main DA logic -L0932: sta ALTZPON +.proc start2 + sta ALTZPON lda LCBANK1 lda LCBANK1 - yax_call JUMP_TABLE_MGTK_RELAY, MGTK::FrontWindow, $0A - lda $0A - beq L094C - cmp #$09 - bcc L094F -L094C: jmp L080D -L094F: asl a + ptr := $0A + + yax_call JUMP_TABLE_MGTK_RELAY, MGTK::FrontWindow, ptr + lda ptr ; any window open? + beq bail ; nope, bail + + cmp #9 ; DeskTop windows are 1-8 + bcc has_window +bail: jmp exit +.endproc + +has_window: + +.scope + ;; Copy window path to buffer + asl a ; window index * 2 tay - lda $DFB3,y - sta $06 - lda $DFB4,y - sta $07 - ldy #$00 - sty $10 + copy16 path_table,y, $06 + ldy #0 + sty $10 ; ??? lda ($06),y - sta L0976 + sta len sta path_buf -L0967: iny +loop: iny lda ($06),y - and #$7F - cmp #$61 - bcc L0972 - and #$DF -L0972: sta path_buf,y - L0976 := *+1 + and #CHAR_MASK + cmp #'a' ; lower case? + bcc :+ + and #CASE_MASK ; restore to upper-case +: sta path_buf,y + len := *+1 cpy #0 - bne L0967 - ldy $BF31 - sty L0A92 -L097F: ldy L0A92 - lda $BF32,y - and #$F0 + bne loop +.endscope + +.scope + ;; Enumerate devices to find unit_num matching path. + ldy DEVCNT + sty dev_num +loop: ldy dev_num + lda DEVLST,y + and #$F0 ; mask off drive/slot sta on_line_params::unit_num jsr on_line - bne L0994 - jsr L0AB0 - beq L099C -L0994: dec L0A92 - bpl L097F -L0999: jmp L080D + bne next + jsr compare_paths_for_unit_num + beq found_unit_num +next: dec dev_num + bpl loop +.endscope -L099C: lda on_line_params::unit_num - sta L0804 +exit1: jmp exit + +found_unit_num: + lda on_line_params::unit_num + sta unit_num jsr open - bne L0999 + bne exit1 lda open_params::ref_num sta read_params::ref_num sta close_params::ref_num + + ;; Read a chunk of the directory jsr read jsr close - bne L0999 + bne exit1 ldx #$02 -L09BA: .byte $AD - .byte $02 -L09BC: asl $959D - asl a - .byte $AD - .byte $03 -L09C2: asl $969D - asl a + + L09BC := *+2 +L09BA: lda buffer + 2 + + sta L0A95,x + + L09C2 := *+2 + lda buffer + 3 + + sta L0A95+1,x + ora L0A95,x beq L09DD inc L09BC @@ -215,6 +248,7 @@ L09C2: asl $969D inx cpx #$0E bne L09BA + L09DD: txa clc adc #$0E @@ -222,28 +256,25 @@ L09DD: txa jsr L0B40 L09E7: jsr L0B16 bcs L0A3B - ldy #$00 + ldy #0 lda ($06),y - and #$F0 + and #STORAGE_TYPE_MASK beq L09E7 - ldy #$25 + ldy #SubdirectoryHeader::file_count lda ($06),y sta L0A95 iny lda ($06),y - sta L0A96 + sta L0A95+1 jsr L0AE8 - lda L0804 + lda unit_num sta block_params::unit_num lda #$00 sta L0A94 L0A0F: lda L0A94 asl a tay - lda L0A95,y - sta block_params::block_num - lda L0A96,y - sta block_params::block_num+1 + copy16 L0A95,y, block_params::block_num ora block_params::block_num beq L0A3E tya @@ -256,17 +287,17 @@ L0A0F: lda L0A94 bne L0A3B inc L0A94 bne L0A0F -L0A3B: jmp L080D +L0A3B: jmp exit L0A3E: copy16 #$1C00, block_params::data_buffer jsr L0B40 L0A4B: jsr L0B16 bcs L0A8E - ldy #$00 + ldy #0 lda ($06),y - and #$F0 + and #STORAGE_TYPE_MASK beq L0A4B - cmp #$D0 + cmp #(ST_LINKED_DIRECTORY << 4) bne L0A4B ldy #$11 lda ($06),y @@ -281,59 +312,39 @@ L0A4B: jsr L0B16 sbc #$0E and #$FE tay - lda L0A95,y - sta $1C27 - lda L0A96,y - sta $1C28 - lda L0AAF - sta $1C29 + copy16 L0A95,y, $1C27 + copy L0AAF, $1C29 jsr write_block jmp L0A4B L0A8E: pla -L0A8F: jmp L080D +L0A8F: jmp exit + +dev_num: + .byte 0 -L0A92: .byte 0 L0A93: .byte 0 L0A94: .byte 0 -L0A95: .byte 0 -L0A96: .byte 0 - .byte 0 - .byte 0 - .byte 0 - .byte 0 - .byte 0 - .byte 0 - .byte 0 - .byte 0 - .byte 0 - .byte 0 - .byte 0 - .byte 0 - .byte 0 - .byte 0 - .byte 0 - .byte 0 - .byte 0 - .byte 0 - .byte 0 - .byte 0 - .byte 0 - .byte 0 - .byte 0 - .byte 0 + +L0A95: .res 26, 0 + L0AAF: .byte 0 -L0AB0: lda on_line_buffer +;;; ============================================================ +;;; Compare path from ON_LINE vs. path from window, since we +;;; need unit_num for block operations. + +.proc compare_paths_for_unit_num + lda on_line_buffer and #$0F sta on_line_buffer - ldy #$00 + ldy #0 L0ABA: iny lda on_line_buffer,y - and #$7F - cmp #$61 + and #CHAR_MASK + cmp #'a' bcc L0AC6 - and #$DF + and #CASE_MASK ; make upper-case L0AC6: cmp path_buf+1,y bne L0AE5 cpy on_line_buffer @@ -344,13 +355,17 @@ L0AC6: cmp path_buf+1,y cmp path_buf beq L0AE2 lda path_buf+2,y - cmp #$2F + cmp #'/' bne L0AE5 L0AE2: return #$00 L0AE5: return #$FF +.endproc -L0AE8: lda #$00 +;;; ============================================================ + +.proc L0AE8 + lda #$00 sta L0B15 jsr L0B40 jsr L0B16 @@ -359,7 +374,7 @@ L0AF3: copy16 $06, $08 bcs L0B0F jsr L0B5E bcc L0AF3 - jsr L0B4E + jsr swap_entries lda #$FF sta L0B15 bne L0AF3 @@ -368,150 +383,187 @@ L0B0F: lda L0B15 rts L0B15: .byte 0 +.endproc ;;; ============================================================ -L0B16: inc L0AAF - lda $06 +.proc L0B16 + ptr := $06 + + inc L0AAF + lda ptr clc - adc #$27 - sta $06 - bcc L0B24 - inc $07 -L0B24: lda $06 + adc #.sizeof(FileEntry) + sta ptr + bcc :+ + inc ptr+1 + +: lda ptr cmp #$FF - bne L0B3C - inc $07 - lda #$01 + bne rtcc + inc ptr+1 + lda #1 sta L0AAF - lda #$04 - sta $06 - lda $07 + lda #$04 ; skip over block header ??? + sta ptr + lda ptr+1 cmp L0A93 - bcs L0B3E -L0B3C: clc + bcs rtcs + +rtcc: clc rts -L0B3E: sec +rtcs: sec rts +.endproc + +;;; ============================================================ L0B40: lda #$01 sta L0AAF - lda #$04 - sta $06 - lda #$0E - sta $07 + copy16 #$0E04, $06 rts -L0B4E: ldy #$26 -L0B50: lda ($06),y +;;; ============================================================ +;;; Swap file entries + +.proc swap_entries + ptr1 := $06 + ptr2 := $08 + + ldy #.sizeof(FileEntry) - 1 +loop: lda (ptr1),y pha - lda ($08),y - sta ($06),y + lda (ptr2),y + sta (ptr1),y pla - sta ($08),y + sta (ptr2),y dey - bpl L0B50 + bpl loop rts - -L0B5E: ldy #$00 - lda ($06),y - and #$F0 - bne L0B69 - jmp L0BF0 - -L0B69: lda ($08),y - and #$F0 - bne L0B72 - jmp L0BEE - -L0B72: lda $DF21 - beq L0B7F - lda $DF20 - beq L0B7F - jmp L0BF5 - -L0B7F: lda $08 - ldx $09 - jsr L0CFC - bcc L0BF0 - lda $06 - ldx $07 - jsr L0CFC - bcc L0BEE - ldy #$00 - lda ($08),y - and #$F0 - sta L0BF2 - ldy #$00 - lda ($06),y - and #$F0 - sta L0BF3 - lda L0BF2 - cmp #$D0 - beq L0BB3 - lda L0BF3 - cmp #$D0 - beq L0BEE - bne L0BC1 -L0BB3: lda L0BF3 - cmp #$D0 - bne L0BF0 - jsr L0D33 - bcc L0BF0 - bcs L0BEE -L0BC1: lda #$04 - jsr L0CBE - bne L0BCC - bcc L0BF0 - bcs L0BEE -L0BCC: lda #$FF - jsr L0CBE - bne L0BD7 - bcc L0BF0 - bcs L0BEE -L0BD7: lda #$FD - sta L0BF4 -L0BDC: dec L0BF4 - lda L0BF4 - beq L0BF0 - jsr L0CBE - bne L0BDC - bcs L0BEE - jmp L0BF0 - -L0BEE: sec - rts - -L0BF0: clc - rts - -L0BF2: .byte 0 -L0BF3: .byte 0 -L0BF4: .byte 0 +.endproc ;;; ============================================================ -L0BF5: ldx $DF21 +.proc L0B5E + ptr1 := $06 + ptr2 := $08 + + ldy #0 + lda (ptr1),y + and #STORAGE_TYPE_MASK ; Active file entry? + bne L0B69 + jmp rtcc + +L0B69: lda (ptr2),y + and #STORAGE_TYPE_MASK ; Active file entry? + bne L0B72 + jmp rtcs + +L0B72: lda selected_file_count + beq L0B7F + lda path_index + beq L0B7F + jmp L0BF5 + +L0B7F: + ldax ptr2 + jsr check_system_file + bcc rtcc + + ldax ptr1 + jsr check_system_file + bcc rtcs + + ldy #0 + lda (ptr2),y + and #STORAGE_TYPE_MASK + sta storage_type2 + + ldy #0 + lda (ptr1),y + and #STORAGE_TYPE_MASK + sta storage_type1 + + ;; Why does this dir-first comparison not just use FT_DIRECTORY ??? + + ;; Is #2 a dir? + lda storage_type2 + cmp #(ST_LINKED_DIRECTORY << 4) + beq dirs ; yep, check #1 + + ;; Is #1 a dir? + lda storage_type1 + cmp #(ST_LINKED_DIRECTORY << 4) + beq rtcs ; yep, but 2 wasn't, so order + bne check_types ; neither are dirs - check types + + ;; #2 was a dir - is #1? +dirs: lda storage_type1 + cmp #(ST_LINKED_DIRECTORY << 4) + bne rtcc + + ;; Both are dirs, order by name + jsr compare_file_entry_names + bcc rtcc + bcs rtcs + + ;; TXT files first +check_types: + lda #FT_TEXT + jsr compare_entry_types_and_names + bne :+ + bcc rtcc + bcs rtcs + + ;; SYS files next +: lda #FT_SYSTEM + jsr compare_entry_types_and_names + bne :+ + bcc rtcc + bcs rtcs + + ;; Then order by type from $FD down +: lda #$FD + sta type +loop: dec type + lda type + beq rtcc + jsr compare_entry_types_and_names + bne loop + bcs rtcs + jmp rtcc + +rtcs: sec + rts + +rtcc: clc + rts + +storage_type2: + .byte 0 +storage_type1: + .byte 0 +type: .byte 0 +.endproc + +;;; ============================================================ + +.proc L0BF5 + ldx selected_file_count L0BF8: dex bmi L0C4A - lda $DF22,x + lda selected_file_list,x asl a tay - lda $DD9F,y - clc - adc #$09 - sta $10 - lda $DDA0,y - adc #$00 - sta $11 + add16 file_table,y, #9, $10 ldy #$00 lda ($10),y sec sbc #$02 sta L0C24 inc16 $10 -L0C1F: lda ($06),y + lda ($06),y and #$0F L0C24 := *+1 @@ -521,16 +573,16 @@ L0C1F: lda ($06),y sta L0C47 L0C2A: iny lda ($10),y - and #$7F - cmp #$61 + and #CHAR_MASK + cmp #'a' bcc L0C35 - and #$DF + and #CASE_MASK ; make upper-case L0C35: sta L0C43 lda ($06),y - and #$7F - cmp #$61 + and #CHAR_MASK + cmp #'a' bcc L0C42 - and #$DF + and #CASE_MASK ; make upper-case L0C43 := *+1 L0C42: cmp #0 @@ -542,26 +594,22 @@ L0C42: cmp #0 bne L0C2A L0C4A: stx L0CBC - ldx $DF21 + ldx selected_file_count L0C50: dex bmi L0CA2 - lda $DF22,x + lda selected_file_list,x asl a tay - lda $DD9F,y - clc - adc #$09 - sta $10 - lda $DDA0,y - adc #$00 - sta $11 + + add16 file_table,y, #9, $10 + ldy #$00 lda ($10),y sec sbc #$02 sta L0C7C inc16 $10 -L0C77: lda ($08),y + lda ($08),y and #$0F L0C7C := *+1 @@ -571,18 +619,20 @@ L0C77: lda ($08),y sta L0C9F L0C82: iny lda ($10),y - and #$7F - cmp #$61 + and #CHAR_MASK + cmp #'a' bcc L0C8D - and #$DF + and #CASE_MASK L0C8D: sta L0C9B lda ($08),y - and #$7F - cmp #$61 + and #CHAR_MASK + cmp #'a' bcc L0C9A - and #$DF + and #CASE_MASK + L0C9B := *+1 L0C9A: cmp #0 + bne L0C50 L0C9F := *+1 @@ -607,100 +657,146 @@ L0CBA: clc L0CBC: .byte 0 L0CBD: .byte 0 -L0CBE: sta L0CFB - ldy #$10 - lda ($08),y - sta L0CF1 - lda ($06),y - sta L0CF2 - lda L0CF1 - cmp L0CFB - beq L0CDF - lda L0CF2 - cmp L0CFB - beq L0CF7 - bne L0CEE -L0CDF: lda L0CF2 - cmp L0CFB - bne L0CF3 - jsr L0D33 - bcc L0CF3 - bcs L0CF7 -L0CEE: return #$FF +.endproc -L0CF1: .byte 0 -L0CF2: .byte 0 -L0CF3: lda #$00 +;;; ============================================================ +;;; Compare file types/names ($06, $08 = ptrs, A=type) +;;; +;;; Output: A=$FF if neither matches type; A=$00 and carry is order + +.proc compare_entry_types_and_names + ptr1 := $06 + ptr2 := $08 + max_length := 16 + + sta type0 + + ldy #max_length + lda (ptr2),y + sta type2 + lda (ptr1),y + sta type1 + + lda type2 + cmp type0 + beq :+ + + lda type1 + cmp type0 + beq rtcs + + bne neither + +: lda type1 + cmp type0 + bne rtcc + jsr compare_file_entry_names + bcc rtcc + bcs rtcs + +neither: + return #$FF + +type2: .byte 0 +type1: .byte 0 + +rtcc: lda #0 clc rts -L0CF7: lda #$00 +rtcs: lda #0 sec rts -L0CFB: .byte 0 -L0CFC: stax $00 - ldy #$10 - lda ($00),y - cmp #$FF - bne L0D29 - ldy #$00 - lda ($00),y - and #$0F +type0: .byte 0 +.endproc + +;;; ============================================================ +;;; Is the file entry a SYS file with .SYSTEM suffix? +;;; Returns carry clear if true, set if false. + +.proc check_system_file + ptr := $00 + + ;; Check for SYS + stax ptr + ldy #FileEntry::file_type + lda (ptr),y + cmp #$FF ; type=SYS + bne fail + + ;; Could name end in .SYSTEM? + ldy #FileEntry::storage_type_name_length + lda (ptr),y + and #NAME_LENGTH_MASK sec - sbc #$06 - bcc L0D29 + sbc #.strlen(".SYSTEM")-1 + bcc fail ; too short tay - ldx #$00 + + ;; Check name suffix + ldx #0 dey -L0D17: iny +loop: iny inx - lda ($00),y - and #$7F - cmp L0D2B,x - bne L0D29 - cpx L0D2B - bne L0D17 + lda (ptr),y + and #CHAR_MASK + cmp str_system,x + bne fail + cpx str_system + bne loop + clc rts -L0D29: sec +fail: sec rts -L0D2B: .byte $07 - rol $5953 - .byte $53 - .byte $54 - eor $4D -L0D33: ldy #$00 - lda ($08),y - and #$0F - sta L0D6B - sta L0D5C - lda ($06),y - and #$0F - sta L0D6C - cmp L0D5C - bcs L0D4E - sta L0D5C -L0D4E: ldy #$00 -L0D50: iny - lda ($08),y - cmp ($06),y - beq L0D5B - bcc L0D69 -L0D59: sec +str_system: + PASCAL_STRING ".SYSTEM" +.endproc + +;;; ============================================================ +;;; Compare file entry names; carry indicates order + +.proc compare_file_entry_names + ptr1 := $06 + ptr2 := $08 + + ldy #0 + lda (ptr2),y + and #NAME_LENGTH_MASK + sta len2 + + sta len + lda (ptr1),y + and #NAME_LENGTH_MASK + sta len1 + cmp len + bcs :+ + sta len + +: ldy #0 +loop: iny + lda (ptr2),y + cmp (ptr1),y + beq next + bcc rtcc +rtcs: sec rts - L0D5C := *+1 -L0D5B: cpy #0 - bne L0D50 - lda L0D6B - cmp L0D6C - beq L0D69 - bcs L0D59 -L0D69: clc + len := *+1 +next: cpy #0 + + bne loop + lda len2 + cmp len1 + beq rtcc + bcs rtcs +rtcc: clc rts -L0D6B: .byte 0 -L0D6C: .byte 0 +len2: .byte 0 +len1: .byte 0 + +.endproc diff --git a/inc/prodos.inc b/inc/prodos.inc index 9a82542..be80b9e 100644 --- a/inc/prodos.inc +++ b/inc/prodos.inc @@ -120,6 +120,77 @@ ERR_OVERRUN_ERROR := $48 ERR_VOLUME_DIR_FULL := $49 ERR_END_OF_FILE := $4C +;;; ============================================================ +;;; Directory Structures +;;; ============================================================ + +STORAGE_TYPE_MASK := $F0 +NAME_LENGTH_MASK := $0F + +;;; Volume Directory Header structure +.struct VolumeDirectoryHeader + prev_block .word + next_block .word + storage_type_name_length .byte + file_name .byte 15 + reserved .byte 8 + creation_date .word + creation_time .word + version .byte + min_version .byte + access .byte + entry_length .byte + entries_per_block .byte + file_count .word + ;; same through here --------- + bit_map_pointer .word + total_blocks .word +.endstruct + .assert .sizeof(VolumeDirectoryHeader) = $2B, error, "incorrect struct size" + +;;; Subdirectory Header structure +.struct SubdirectoryHeader + prev_block .word + next_block .word + storage_type_name_length .byte + file_name .byte 15 + reserved .byte 8 + creation_date .word + creation_time .word + version .byte + min_version .byte + access .byte + entry_length .byte + entries_per_block .byte + file_count .word + ;; same through here --------- + parent_pointer .word + parent_entry_number .byte + parent_entry_length .byte +.endstruct + .assert .sizeof(SubdirectoryHeader) = $2B, error, "incorrect struct size" + +;; File Entry structure +.struct FileEntry + storage_type_name_length .byte + file_name .byte 15 + file_type .byte + key_pointer .word + blocks_used .word + eof .faraddr + creation_date .word + creation_time .word + version .byte + min_version .byte + access .byte + aux_type .word + mod_date .word + mod_time .word + header_pointer .word +.endstruct + .assert .sizeof(FileEntry) = $27, error, "incorrect struct size" + + ;;; ============================================================ ;;; Macros ;;; ============================================================