diff --git a/_sd/body_syms.inc b/_sd/body_syms.inc index ac31808..2e1de26 100644 --- a/_sd/body_syms.inc +++ b/_sd/body_syms.inc @@ -1,294 +1,294 @@ -body_end: EQU 0x00001FAE -cmkf_open_stream: EQU 0x00001F79 -cmkf_final: EQU 0x00001F63 -cmkf_buildlfn: EQU 0x00001F47 -cmkf_entry: EQU 0x00001F05 -cmkf_havecl: EQU 0x00001ED7 -cmkf_alloc: EQU 0x00001EC1 -cmkf_havelen: EQU 0x00001EA8 -cmkf_lendone: EQU 0x00001E9F -cmkf_lenloop: EQU 0x00001E92 -core_mkfile: EQU 0x00001E77 -cmkf_len_lo: EQU 0x00001E75 -cmkf_len_hi: EQU 0x00001E73 -cmkd_final: EQU 0x00001E5E -cmkd_buildlfn: EQU 0x00001E42 -cmkd_ownentry: EQU 0x00001E0F -dotdot_name: EQU 0x00001F95 -cmkd_dot_ok: EQU 0x00001DC3 -dot_name: EQU 0x00001F8A -clear_dir_entry: EQU 0x00001FA0 -cmkd_dots: EQU 0x00001D6F -cmkd_zf: EQU 0x00001D59 -cmkd_have_cl: EQU 0x00001D2B -cmkd_alloc: EQU 0x00001D15 -cmkd_toolong: EQU 0x00001CF4 -cmkd_lendone: EQU 0x00001CF8 -core_mkdir: EQU 0x00001CE7 -cmk_sec_lo: EQU 0x00001CE5 -cmk_sec_hi: EQU 0x00001CE3 -cmk_cluster_lo: EQU 0x00001CE1 -cmk_cluster_hi: EQU 0x00001CDF -cmk_name_ptr: EQU 0x00001CDD -sv512_nowrap: EQU 0x00001CD9 -lv512_nowrap: EQU 0x00001CAC -lv512_advance: EQU 0x00001C96 -lv512_eoc: EQU 0x00001CB9 -lv512_done: EQU 0x00001CB0 -lv512_loop: EQU 0x00001C75 -core_load512: EQU 0x00001C6A -lv512_count: EQU 0x00001C69 -lv512_off: EQU 0x00001C67 -lv512_page: EQU 0x00001C66 -sv512_advance: EQU 0x00001CC3 -sv512_eoc: EQU 0x00001C5C -sv512_done: EQU 0x00001C53 -sv512_loop: EQU 0x00001C32 -core_save512: EQU 0x00001C27 -sv512_count: EQU 0x00001C26 +body_end: EQU 0x00001FAA +cmkf_open_stream: EQU 0x00001F75 +cmkf_final: EQU 0x00001F5F +cmkf_buildlfn: EQU 0x00001F43 +cmkf_entry: EQU 0x00001F01 +cmkf_havecl: EQU 0x00001ED3 +cmkf_alloc: EQU 0x00001EBD +cmkf_havelen: EQU 0x00001EA4 +cmkf_lendone: EQU 0x00001E9B +cmkf_lenloop: EQU 0x00001E8E +core_mkfile: EQU 0x00001E73 +cmkf_len_lo: EQU 0x00001E71 +cmkf_len_hi: EQU 0x00001E6F +cmkd_final: EQU 0x00001E5A +cmkd_buildlfn: EQU 0x00001E3E +cmkd_ownentry: EQU 0x00001E0B +dotdot_name: EQU 0x00001F91 +cmkd_dot_ok: EQU 0x00001DBF +dot_name: EQU 0x00001F86 +clear_dir_entry: EQU 0x00001F9C +cmkd_dots: EQU 0x00001D6B +cmkd_zf: EQU 0x00001D55 +cmkd_have_cl: EQU 0x00001D27 +cmkd_alloc: EQU 0x00001D11 +cmkd_toolong: EQU 0x00001CF0 +cmkd_lendone: EQU 0x00001CF4 +core_mkdir: EQU 0x00001CE3 +cmk_sec_lo: EQU 0x00001CE1 +cmk_sec_hi: EQU 0x00001CDF +cmk_cluster_lo: EQU 0x00001CDD +cmk_cluster_hi: EQU 0x00001CDB +cmk_name_ptr: EQU 0x00001CD9 +sv512_nowrap: EQU 0x00001CD5 +lv512_nowrap: EQU 0x00001CA8 +lv512_advance: EQU 0x00001C92 +lv512_eoc: EQU 0x00001CB5 +lv512_done: EQU 0x00001CAC +lv512_loop: EQU 0x00001C71 +core_load512: EQU 0x00001C66 +lv512_count: EQU 0x00001C65 +lv512_off: EQU 0x00001C63 +lv512_page: EQU 0x00001C62 +sv512_advance: EQU 0x00001CBF +sv512_eoc: EQU 0x00001C58 +sv512_done: EQU 0x00001C4F +sv512_loop: EQU 0x00001C2E +core_save512: EQU 0x00001C23 +sv512_count: EQU 0x00001C22 page1_port: EQU 0x000011AF -core_fentry: EQU 0x00001C12 -core_setdir: EQU 0x00001C05 -core_setroot: EQU 0x00001BF8 -active_dir_lo: EQU 0x00001BF6 -active_dir_hi: EQU 0x00001BF4 -fbn_tm_yes: EQU 0x00001BB6 -fbn_tm_short: EQU 0x00001BA4 -fbn_acc_null: EQU 0x00001B76 -fbn_acc_pad: EQU 0x00001B81 -fbn_acc_charloop: EQU 0x00001B4A -fbn_acc_mul: EQU 0x00001B3A -fbn_acc_mul_done: EQU 0x00001B40 -fbn_matched_setrun: EQU 0x00001B0B -fbn_matched_norun: EQU 0x00001B08 -fbn_accumulate_lfn: EQU 0x00001B11 -fbn_lfn_cont: EQU 0x00001AD2 -fbn_next: EQU 0x00001ADD -fbn_matched: EQU 0x00001AF6 -fbn_try_match: EQU 0x00001B84 -fbn_is_lfn: EQU 0x00001AC4 -fbn_deleted: EQU 0x00001AD7 -fbn_notfound_pop: EQU 0x00001AF3 -fbn_entloop: EQU 0x00001AA3 -fbn_notfound: EQU 0x00001AF4 -fbn_sector_loop: EQU 0x00001A83 -find_by_name: EQU 0x00001A73 -fbn_match_run_start_lo: EQU 0x00001A71 -fbn_match_index_lo: EQU 0x00001A6F -fbn_run_start_lo: EQU 0x00001A6D -fbn_cur_index_lo: EQU 0x00001A6B -fbn_render_buf: EQU 0x00001A5E -fbn_attr: EQU 0x00001A5D -fbn_size_lo: EQU 0x00001A5B -fbn_size_hi: EQU 0x00001A59 -fbn_cluster_hi: EQU 0x00001A55 -fbn_acc_dest: EQU 0x00001A53 -fbn_lfn_seen: EQU 0x00001A52 -fbn_lfn_checksum: EQU 0x00001A51 -fbn_lfn_buf: EQU 0x000019E8 -fbn_name_ptr: EQU 0x000019E6 -rsn_ext: EQU 0x000019D8 -rsn_done: EQU 0x000019E2 -rsn_ext_prep: EQU 0x000019CD -rsn_base_skip: EQU 0x000019CA -rsn_base: EQU 0x000019BE -render_shortname: EQU 0x000019BB -seci_eq: EQU 0x000019B9 -seci_ne: EQU 0x000019B6 -str_eq_ci: EQU 0x000019A3 -to_upper: EQU 0x0000199A -wne_w_skip_write: EQU 0x00001991 -wne_w_notinrange: EQU 0x00001963 -wne_w_entloop: EQU 0x0000192D -wne_w_fail: EQU 0x00001997 -wne_w_continue: EQU 0x000018F8 -wne_w_done: EQU 0x000018F6 -wne_w_sector_loop: EQU 0x000018E1 -write_name_entries: EQU 0x000018D8 -wne_w_this_sec_lo: EQU 0x000018D6 -wne_w_this_sec_hi: EQU 0x000018D4 -wne_w_dirty: EQU 0x000018D3 -wne_w_entcount: EQU 0x000018D2 -wne_w_entptr: EQU 0x000018D0 -ffr_no_hi_carry: EQU 0x00001850 -ffr_free_cont: EQU 0x00001819 -ffr_advance_index: EQU 0x0000183A -ffr_free: EQU 0x00001803 -ffr_entloop: EQU 0x000017F4 -ffr_fail: EQU 0x0000185D -ffr_grow_dir: EQU 0x00001860 -ffr_have_sector: EQU 0x000017DC -ffr_sector_loop: EQU 0x000017CD -find_free_run: EQU 0x000017BD -wne_free_index_lo: EQU 0x000017BB -wne_free_index_hi: EQU 0x000017B9 -cmkd_lenloop: EQU 0x00001CEC -wne_cur_index_lo: EQU 0x000017B7 -wne_cur_index_hi: EQU 0x000017B5 -wne_run_start_lo: EQU 0x000017B3 -wne_run_start_hi: EQU 0x000017B1 -wne_run_len: EQU 0x000017B0 -ble_char_nextk: EQU 0x0000177D -ble_char_hi0: EQU 0x0000177B -ble_char_have: EQU 0x00001761 -ble_char_isreal: EQU 0x00001757 -ble_char_isnull: EQU 0x00001760 -ble_lfn_next: EQU 0x00001780 -ble_charloop: EQU 0x00001738 -ble_mul13done: EQU 0x00001733 -ble_mul13: EQU 0x00001728 -ble_seqset: EQU 0x0000170A -ble_notlast: EQU 0x00001709 -ble_lfn_done: EQU 0x00001787 -ble_lfn_loop: EQU 0x000016D2 -ble_divdone: EQU 0x000016BB -ble_divloop: EQU 0x000016B0 -ble_multi: EQU 0x000016A7 -build_lfn_entries: EQU 0x00001682 -ble_entry_ptr: EQU 0x00001680 -ble_charpos: EQU 0x0000167E -ble_j: EQU 0x0000167D -ble_checksum: EQU 0x0000167C -ble_lfn_count: EQU 0x0000167B -ble_name_ptr: EQU 0x00001679 -lfn_char_dest: EQU 0x0000166C -wne_slot_count: EQU 0x0000166B -wne_entries_buf: EQU 0x0000154B +core_fentry: EQU 0x00001C0E +core_setdir: EQU 0x00001C01 +core_setroot: EQU 0x00001BF4 +active_dir_lo: EQU 0x00001BF2 +active_dir_hi: EQU 0x00001BF0 +fbn_tm_yes: EQU 0x00001BB2 +fbn_tm_short: EQU 0x00001BA0 +fbn_acc_null: EQU 0x00001B72 +fbn_acc_pad: EQU 0x00001B7D +fbn_acc_charloop: EQU 0x00001B46 +fbn_acc_mul: EQU 0x00001B36 +fbn_acc_mul_done: EQU 0x00001B3C +fbn_matched_setrun: EQU 0x00001B07 +fbn_matched_norun: EQU 0x00001B04 +fbn_accumulate_lfn: EQU 0x00001B0D +fbn_lfn_cont: EQU 0x00001ACE +fbn_next: EQU 0x00001AD9 +fbn_matched: EQU 0x00001AF2 +fbn_try_match: EQU 0x00001B80 +fbn_is_lfn: EQU 0x00001AC0 +fbn_deleted: EQU 0x00001AD3 +fbn_notfound_pop: EQU 0x00001AEF +fbn_entloop: EQU 0x00001A9F +fbn_notfound: EQU 0x00001AF0 +fbn_sector_loop: EQU 0x00001A7F +find_by_name: EQU 0x00001A6F +fbn_match_run_start_lo: EQU 0x00001A6D +fbn_match_index_lo: EQU 0x00001A6B +fbn_run_start_lo: EQU 0x00001A69 +fbn_cur_index_lo: EQU 0x00001A67 +fbn_render_buf: EQU 0x00001A5A +fbn_attr: EQU 0x00001A59 +fbn_size_lo: EQU 0x00001A57 +fbn_size_hi: EQU 0x00001A55 +fbn_cluster_hi: EQU 0x00001A51 +fbn_acc_dest: EQU 0x00001A4F +fbn_lfn_seen: EQU 0x00001A4E +fbn_lfn_checksum: EQU 0x00001A4D +fbn_lfn_buf: EQU 0x000019E4 +fbn_name_ptr: EQU 0x000019E2 +rsn_ext: EQU 0x000019D4 +rsn_done: EQU 0x000019DE +rsn_ext_prep: EQU 0x000019C9 +rsn_base_skip: EQU 0x000019C6 +rsn_base: EQU 0x000019BA +render_shortname: EQU 0x000019B7 +seci_eq: EQU 0x000019B5 +seci_ne: EQU 0x000019B2 +str_eq_ci: EQU 0x0000199F +to_upper: EQU 0x00001996 +wne_w_skip_write: EQU 0x0000198D +wne_w_notinrange: EQU 0x0000195F +wne_w_entloop: EQU 0x00001929 +wne_w_fail: EQU 0x00001993 +wne_w_continue: EQU 0x000018F4 +wne_w_done: EQU 0x000018F2 +wne_w_sector_loop: EQU 0x000018DD +write_name_entries: EQU 0x000018D4 +wne_w_this_sec_lo: EQU 0x000018D2 +wne_w_this_sec_hi: EQU 0x000018D0 +wne_w_dirty: EQU 0x000018CF +wne_w_entcount: EQU 0x000018CE +wne_w_entptr: EQU 0x000018CC +ffr_no_hi_carry: EQU 0x0000184C +ffr_free_cont: EQU 0x00001815 +ffr_advance_index: EQU 0x00001836 +ffr_free: EQU 0x000017FF +ffr_entloop: EQU 0x000017F0 +ffr_fail: EQU 0x00001859 +ffr_grow_dir: EQU 0x0000185C +ffr_have_sector: EQU 0x000017D8 +ffr_sector_loop: EQU 0x000017C9 +find_free_run: EQU 0x000017B9 +wne_free_index_lo: EQU 0x000017B7 +wne_free_index_hi: EQU 0x000017B5 +cmkd_lenloop: EQU 0x00001CE8 +wne_cur_index_lo: EQU 0x000017B3 +wne_cur_index_hi: EQU 0x000017B1 +wne_run_start_lo: EQU 0x000017AF +wne_run_start_hi: EQU 0x000017AD +wne_run_len: EQU 0x000017AC +ble_char_nextk: EQU 0x00001779 +ble_char_hi0: EQU 0x00001777 +ble_char_have: EQU 0x0000175D +ble_char_isreal: EQU 0x00001753 +ble_char_isnull: EQU 0x0000175C +ble_lfn_next: EQU 0x0000177C +ble_charloop: EQU 0x00001734 +ble_mul13done: EQU 0x0000172F +ble_mul13: EQU 0x00001724 +ble_seqset: EQU 0x00001706 +ble_notlast: EQU 0x00001705 +ble_lfn_done: EQU 0x00001783 +ble_lfn_loop: EQU 0x000016CE +ble_divdone: EQU 0x000016B7 +ble_divloop: EQU 0x000016AC +ble_multi: EQU 0x000016A3 +build_lfn_entries: EQU 0x0000167E +ble_entry_ptr: EQU 0x0000167C +ble_charpos: EQU 0x0000167A +ble_j: EQU 0x00001679 +ble_checksum: EQU 0x00001678 +ble_lfn_count: EQU 0x00001677 +ble_name_ptr: EQU 0x00001675 +lfn_char_dest: EQU 0x00001668 +wne_slot_count: EQU 0x00001667 +wne_entries_buf: EQU 0x00001547 wne_max_lfn: EQU 0x00000008 -btd_done: EQU 0x0000153F -btd_loop: EQU 0x00001536 -gus_have_candidate: EQU 0x00001515 -bin_to_2dig: EQU 0x00001534 -gus_try_1digit: EQU 0x000014FD -gus_try: EQU 0x000014D8 -gus_ok: EQU 0x00001532 -gus_needs_suffix: EQU 0x000014D3 -generate_unique_shortname: EQU 0x000014B4 -gus_suffix: EQU 0x000014B3 -fn83_ext_full: EQU 0x000014A5 -fn83_ext_bad: EQU 0x000014AC -fn83_ext_loop: EQU 0x00001487 -fn83_ext_go: EQU 0x00001470 -fn83_base_full: EQU 0x00001455 -fn83_base_bad: EQU 0x0000145C -fn83_ext: EQU 0x00001463 -fn83_base_loop: EQU 0x00001436 -fn83_have_baselen: EQU 0x0000142B -fn83_scan_next: EQU 0x000013E9 -fn83_scandone: EQU 0x000013ED -fn83_scan: EQU 0x000013DD -filter_name_to_83: EQU 0x000013D2 -fn83_charbuf: EQU 0x000013D1 -sn_base_len: EQU 0x000013CF -sn_dot_pos: EQU 0x000013CD -sn_name_len: EQU 0x000013CB -sn_needs_lfn: EQU 0x000013CA -sn_ext: EQU 0x000013C7 -sn_base: EQU 0x000013BF -cc_symyes: EQU 0x000013BA -cc_no: EQU 0x000013BD -cc_symloop: EQU 0x000013B0 -cc_sym: EQU 0x000013AC -cc_yes: EQU 0x000013BB -cc_dig: EQU 0x000013A4 -cc_up: EQU 0x0000139C -classify_char: EQU 0x00001392 -cc_symbols: EQU 0x00001381 -lfnck_loop: EQU 0x0000137B -lfn_checksum: EQU 0x00001378 -stamp_dir_entry_datetime: EQU 0x00001162 -rtc_to_fat_datetime: EQU 0x000010E6 -rtc_cached: EQU 0x000010E5 -fat_time: EQU 0x000010E3 -fat_date: EQU 0x000010E1 -bcd_to_bin: EQU 0x000010CC -rtc_field_to_bin: EQU 0x000010C0 -rtc_dm: EQU 0x000010BF -rtc_year: EQU 0x0000104E -rtc_month: EQU 0x0000104D -rtc_date: EQU 0x0000104C -rtc_hour: EQU 0x0000104B -rtc_min: EQU 0x0000104A -rtc_sec: EQU 0x00001049 -sv512_off: EQU 0x00001C24 -sv512_page: EQU 0x00001C23 -strm_write_have2: EQU 0x00001034 -stream_write_sector_from: EQU 0x00000FD0 -read_rtc_datetime: EQU 0x0000104F -strm_write_have: EQU 0x00000FBB -stream_write_sector: EQU 0x00000F4D -stream_read_sector_to: EQU 0x00000D32 -stream_data_save: EQU 0x00000D4D -strm_read_eoc: EQU 0x00000D2F -stream_read_sector: EQU 0x00000CFC -strm_adv_same: EQU 0x00000CF6 -strm_adv_cross: EQU 0x00000CCF -strm_adv_test_z: EQU 0x00000CC7 -strm_advance: EQU 0x00000CBA -strm_calc_sector: EQU 0x00000C92 -strm_open_nz: EQU 0x00000C7E -stream_open: EQU 0x00000C64 -strm_sector_lo: EQU 0x00000C62 -strm_sector_hi: EQU 0x00000C60 -stream_eoc: EQU 0x00000C5F -stream_sec_in_cluster: EQU 0x00000C5E -stream_cluster_lo: EQU 0x00000C5C -stream_cluster_hi: EQU 0x00000C5A -wde_next: EQU 0x00000C29 -wde_slot: EQU 0x00000C3A -wde_entloop: EQU 0x00000C09 -wde_fail: EQU 0x00000C57 -wde_sec_loop: EQU 0x00000BF4 -wde_cluster: EQU 0x00000BDF -write_dir_entry: EQU 0x00000BDF -wde_slotptr: EQU 0x00000BDD -wde_sector_lo: EQU 0x00000BDB -wde_sector_hi: EQU 0x00000BD9 -wde_remaining: EQU 0x00000BD8 -dir_entry_buf: EQU 0x00000BB8 -zfc_loop: EQU 0x00000BA6 -zfc_fail: EQU 0x00000BB5 -zero_fill_cluster: EQU 0x00000B80 -zfc_remaining: EQU 0x00000B7F -ffc_nowrap: EQU 0x00000B70 -ffc_nsv2: EQU 0x00000B4A -ffc_nsv: EQU 0x00000B44 -ffc_entnext: EQU 0x00000B54 -ffc_entloop: EQU 0x00000B0D -ffc_fail: EQU 0x00000B7C -ffc_from2: EQU 0x00000AC3 -ffc_scan: EQU 0x00000AD2 -ffc_use_hint: EQU 0x00000AA9 -find_free_cluster: EQU 0x00000A8E -next_search_valid: EQU 0x00000A89 -ffc_sectors_read: EQU 0x00000A87 -ffc_count: EQU 0x00000A86 -ffc_ptr: EQU 0x00000A84 -free_cluster_lo: EQU 0x00000A82 -free_cluster_hi: EQU 0x00000A80 -next_search_hi: EQU 0x00000A8A -next_search_lo: EQU 0x00000A8C -wfi_skip_count: EQU 0x00000A64 -write_fsinfo_hint: EQU 0x00000A29 -read_fsinfo_hint: EQU 0x000009CA -fsinfo_valid: EQU 0x000009C9 -fsinfo_hint_lo: EQU 0x000009C7 -fsinfo_hint_hi: EQU 0x000009C5 -wfe_loop: EQU 0x0000098E -wfe_fail: EQU 0x000009C0 -write_fat_entry: EQU 0x0000093F -wfe_sector_lo: EQU 0x0000093D -wfe_sector_hi: EQU 0x0000093B -wfe_remaining: EQU 0x0000093A -new_val_lo: EQU 0x00000938 -new_val_hi: EQU 0x00000936 -gnc_have_next: EQU 0x00000925 -gnc_end: EQU 0x0000091F -nxt_hi: EQU 0x000008D8 -nxt_lo: EQU 0x000008D6 -ctf_bad: EQU 0x000008D2 -ctf_shr: EQU 0x00000883 -cluster_to_fatpos: EQU 0x00000875 +btd_done: EQU 0x0000153B +btd_loop: EQU 0x00001532 +gus_have_candidate: EQU 0x00001511 +bin_to_2dig: EQU 0x00001530 +gus_try_1digit: EQU 0x000014F9 +gus_try: EQU 0x000014D4 +gus_ok: EQU 0x0000152E +gus_needs_suffix: EQU 0x000014CF +generate_unique_shortname: EQU 0x000014B0 +gus_suffix: EQU 0x000014AF +fn83_ext_full: EQU 0x000014A1 +fn83_ext_bad: EQU 0x000014A8 +fn83_ext_loop: EQU 0x00001483 +fn83_ext_go: EQU 0x0000146C +fn83_base_full: EQU 0x00001451 +fn83_base_bad: EQU 0x00001458 +fn83_ext: EQU 0x0000145F +fn83_base_loop: EQU 0x00001432 +fn83_have_baselen: EQU 0x00001427 +fn83_scan_next: EQU 0x000013E5 +fn83_scandone: EQU 0x000013E9 +fn83_scan: EQU 0x000013D9 +filter_name_to_83: EQU 0x000013CE +fn83_charbuf: EQU 0x000013CD +sn_base_len: EQU 0x000013CB +sn_dot_pos: EQU 0x000013C9 +sn_name_len: EQU 0x000013C7 +sn_needs_lfn: EQU 0x000013C6 +sn_ext: EQU 0x000013C3 +sn_base: EQU 0x000013BB +cc_symyes: EQU 0x000013B6 +cc_no: EQU 0x000013B9 +cc_symloop: EQU 0x000013AC +cc_sym: EQU 0x000013A8 +cc_yes: EQU 0x000013B7 +cc_dig: EQU 0x000013A0 +cc_up: EQU 0x00001398 +classify_char: EQU 0x0000138E +cc_symbols: EQU 0x0000137D +lfnck_loop: EQU 0x00001377 +lfn_checksum: EQU 0x00001374 +stamp_dir_entry_datetime: EQU 0x0000115D +rtc_to_fat_datetime: EQU 0x000010E1 +rtc_cached: EQU 0x000010E0 +fat_time: EQU 0x000010DE +fat_date: EQU 0x000010DC +bcd_to_bin: EQU 0x000010C7 +rtc_field_to_bin: EQU 0x000010BB +rtc_dm: EQU 0x000010BA +rtc_year: EQU 0x00001049 +rtc_month: EQU 0x00001048 +rtc_date: EQU 0x00001047 +rtc_hour: EQU 0x00001046 +rtc_min: EQU 0x00001045 +rtc_sec: EQU 0x00001044 +sv512_off: EQU 0x00001C20 +sv512_page: EQU 0x00001C1F +strm_write_have2: EQU 0x0000102F +stream_write_sector_from: EQU 0x00000FCB +read_rtc_datetime: EQU 0x0000104A +strm_write_have: EQU 0x00000FB6 +stream_write_sector: EQU 0x00000F48 +stream_read_sector_to: EQU 0x00000D2D +stream_data_save: EQU 0x00000D48 +strm_read_eoc: EQU 0x00000D2A +stream_read_sector: EQU 0x00000CF7 +strm_adv_same: EQU 0x00000CF1 +strm_adv_cross: EQU 0x00000CCA +strm_adv_test_z: EQU 0x00000CC2 +strm_advance: EQU 0x00000CB5 +strm_calc_sector: EQU 0x00000C8D +strm_open_nz: EQU 0x00000C79 +stream_open: EQU 0x00000C5F +strm_sector_lo: EQU 0x00000C5D +strm_sector_hi: EQU 0x00000C5B +stream_eoc: EQU 0x00000C5A +stream_sec_in_cluster: EQU 0x00000C59 +stream_cluster_lo: EQU 0x00000C57 +stream_cluster_hi: EQU 0x00000C55 +wde_next: EQU 0x00000C24 +wde_slot: EQU 0x00000C35 +wde_entloop: EQU 0x00000C04 +wde_fail: EQU 0x00000C52 +wde_sec_loop: EQU 0x00000BEF +wde_cluster: EQU 0x00000BDA +write_dir_entry: EQU 0x00000BDA +wde_slotptr: EQU 0x00000BD8 +wde_sector_lo: EQU 0x00000BD6 +wde_sector_hi: EQU 0x00000BD4 +wde_remaining: EQU 0x00000BD3 +dir_entry_buf: EQU 0x00000BB3 +zfc_loop: EQU 0x00000BA1 +zfc_fail: EQU 0x00000BB0 +zero_fill_cluster: EQU 0x00000B7B +zfc_remaining: EQU 0x00000B7A +ffc_nowrap: EQU 0x00000B6B +ffc_nsv2: EQU 0x00000B45 +ffc_nsv: EQU 0x00000B3F +ffc_entnext: EQU 0x00000B4F +ffc_entloop: EQU 0x00000B08 +ffc_fail: EQU 0x00000B77 +ffc_from2: EQU 0x00000AC1 +ffc_scan: EQU 0x00000AD0 +ffc_use_hint: EQU 0x00000AA7 +find_free_cluster: EQU 0x00000A8C +next_search_valid: EQU 0x00000A87 +ffc_sectors_read: EQU 0x00000A85 +ffc_count: EQU 0x00000A84 +ffc_ptr: EQU 0x00000A82 +free_cluster_lo: EQU 0x00000A80 +free_cluster_hi: EQU 0x00000A7E +next_search_hi: EQU 0x00000A88 +next_search_lo: EQU 0x00000A8A +wfi_skip_count: EQU 0x00000A62 +write_fsinfo_hint: EQU 0x00000A27 +read_fsinfo_hint: EQU 0x000009C8 +fsinfo_valid: EQU 0x000009C7 +fsinfo_hint_lo: EQU 0x000009C5 +fsinfo_hint_hi: EQU 0x000009C3 +wfe_loop: EQU 0x0000098C +wfe_fail: EQU 0x000009BE +write_fat_entry: EQU 0x00000940 +wfe_sector_lo: EQU 0x0000093E +wfe_sector_hi: EQU 0x0000093C +wfe_remaining: EQU 0x0000093B +new_val_lo: EQU 0x00000939 +new_val_hi: EQU 0x00000937 +gnc_have_next: EQU 0x00000926 +gnc_end: EQU 0x00000920 +nxt_hi: EQU 0x000008DC +nxt_lo: EQU 0x000008DA +ctf_bad: EQU 0x000008D6 +ctf_shr: EQU 0x00000884 +cluster_to_fatpos: EQU 0x00000876 gnc_inoff: EQU 0x00000874 gnc_fatsec_lo: EQU 0x00000872 gnc_fatsec_hi: EQU 0x00000870 @@ -302,8 +302,8 @@ c2s_prod_hi: EQU 0x00000805 c2s_prod_lo: EQU 0x00000803 c2s_hi: EQU 0x00000801 c2s_lo: EQU 0x000007FF -chain_ended: EQU 0x000008D5 -get_next_cluster: EQU 0x000008DA +chain_ended: EQU 0x000008D9 +get_next_cluster: EQU 0x000008DE fza_next: EQU 0x000007E9 fza_inc_loop: EQU 0x000007E1 fza_done: EQU 0x000007FC @@ -324,7 +324,7 @@ fz_loop: EQU 0x0000075A find_zifi: EQU 0x00000755 target_name: EQU 0x0000074A zifi_size: EQU 0x00000748 -fbn_acc_nocs: EQU 0x00001B25 +fbn_acc_nocs: EQU 0x00001B21 zifi_size_hi: EQU 0x00000746 zifi_cluster: EQU 0x00000744 zifi_cluster_hi: EQU 0x00000742 @@ -348,7 +348,7 @@ fatsz32_lo: EQU 0x00000726 fatsz32_hi: EQU 0x00000728 sectors_per_cluster: EQU 0x00000725 num_fats: EQU 0x00000724 -fsinfo_sector: EQU 0x000009C3 +fsinfo_sector: EQU 0x000009C1 reserved_sectors: EQU 0x00000722 total_sectors_hi: EQU 0x0000071C total_sectors_lo: EQU 0x0000071A @@ -394,7 +394,7 @@ dma_send_ext: EQU 0x0000015F dma_wait: EQU 0x00000179 dma_recv_ext: EQU 0x00000143 dma_set_addr_ext: EQU 0x0000012D -sdbuf: EQU 0x00001178 +sdbuf: EQU 0x00001174 set_dma_sdbuf: EQU 0x00000121 dma_xfer_page: EQU 0x00000120 dma_xfer_off: EQU 0x0000011E @@ -431,4 +431,4 @@ sdinit_fail: EQU 0x000000A4 cycl: EQU 0x000002AC csh: EQU 0x00000245 sdinit: EQU 0x00000000 -fbn_cluster_lo: EQU 0x00001A57 +fbn_cluster_lo: EQU 0x00001A53 diff --git a/_sd/tests/test_fat_offsets.py b/_sd/tests/test_fat_offsets.py new file mode 100644 index 0000000..6bf9bf3 --- /dev/null +++ b/_sd/tests/test_fat_offsets.py @@ -0,0 +1,153 @@ +"""Run assembled driver routines with an in-memory block device. + +Requires Python package z80 and a fresh body build with --sym=body_syms_new.txt. +Run: python tests/test_fat_offsets.py +SPI/DMA sector I/O is intercepted; FAT traversal and LOAD512 execute as Z80 code. +""" +from pathlib import Path +import re +import z80 + +ROOT = Path(__file__).resolve().parents[1] +SYMS = dict((name, int(value, 16)) for name, value in re.findall( + r"^(\w+): EQU 0x([0-9A-Fa-f]+)$", + (ROOT / 'body_syms_new.txt').read_text(), re.M)) +BODY = (ROOT / 'zc_sd_driver_body.bin').read_bytes() + + +class Driver: + def __init__(self): + self.m = z80.Z80Machine() + self.m.set_memory_block(0, BODY) + self.disk = {} + self.ram = bytearray(256 * 16384) + self.hooks = {SYMS[n]: n for n in + ('sdread_lba', 'sdread_lba_to', 'sdwrite_lba', 'write_fsinfo_hint')} + for address in [0xff00, *self.hooks]: + self.m.set_breakpoint(address) + self.put('reserved_sectors', 32) + self.put('fatsz32_lo', 64) + self.put('addtop_lo', 17) + self.put('data_start_lo', 1000) + self.put('sectors_per_cluster', 2, 1) + self.put('num_fats', 2, 1) + + def put(self, name, value, size=2): + self.m.set_memory_block(SYMS[name], value.to_bytes(size, 'little')) + + def get(self, name, size=2): + return int.from_bytes(self.m.memory[SYMS[name]:SYMS[name]+size], 'little') + + def cluster(self, value): + self.put('cur_cluster_lo', value & 65535) + self.put('cur_cluster_hi', value >> 16) + + def fat(self, cluster, value): + sector, offset = divmod(cluster * 4, 512) + block = self.disk.setdefault(49 + sector, bytearray(512)) + block[offset:offset+4] = value.to_bytes(4, 'little') + + def call(self, name): + self.m.sp = 0xfef0 + self.m.set_memory_block(self.m.sp, b'\x00\xff') + self.m.pc = SYMS[name] + for _ in range(10000): + self.m.ticks_to_stop = 100000 + self.m.run() + if self.m.pc == 0xff00: + return self.m.a + hook = self.hooks.get(self.m.pc) + if not hook: + continue + if hook != 'write_fsinfo_hint': + lba = int.from_bytes(self.m.memory[SYMS['lba_arg']:SYMS['lba_arg']+4], 'big') + if hook == 'sdwrite_lba': + p = SYMS['sdbuf'] + self.disk[lba] = bytearray(self.m.memory[p:p+512]) + elif hook == 'sdread_lba': + self.m.set_memory_block(SYMS['sdbuf'], self.disk[lba]) + # Real sdread_lba resets the DMA destination to sdbuf. + self.put('dma_xfer_page', 15, 1) + self.put('dma_xfer_off', SYMS['sdbuf']) + else: + dest = self.get('dma_xfer_page', 1)*16384 + (self.get('dma_xfer_off') & 16383) + self.ram[dest:dest+512] = self.disk[lba] + self.m.af = 0x0040 # A=0, Z=1 (successful sector I/O) + self.m.pc = int.from_bytes(self.m.memory[self.m.sp:self.m.sp+2], 'little') + self.m.sp += 2 + raise AssertionError(f'{name}: execution did not return') + + +def test_offsets_and_links(): + d = Driver() + for n in range(128): + d.fat(256+n, 2000+n) + for n in range(128): + d.cluster(256+n) + assert d.call('cluster_to_fatpos') == 0 + assert d.get('gnc_fatsec_lo') == 34 + assert d.get('gnc_inoff') == n*4, n + d.call('get_next_cluster') + assert d.get('chain_ended', 1) == 0 + assert d.get('cur_cluster_lo') == 2000+n, n + for n in (65535, 65536, 0x123456): + d.put('fatsz32_lo', 65535) + d.cluster(n) + assert d.call('cluster_to_fatpos') == 0 + sector = d.get('gnc_fatsec_lo') | d.get('gnc_fatsec_hi') << 16 + assert sector == 32 + n//128 + assert d.get('gnc_inoff') == (n % 128)*4 + + +def test_write_and_allocation(): + for n in range(128): + d = Driver() + original = bytearray(b'\x55\x55\x55\xa5'*128) + d.disk[51] = original[:] + d.cluster(256+n) + d.put('new_val_lo', 0x3456) + d.put('new_val_hi', 0x0123) + assert d.call('write_fat_entry') == 0 + expected = original[:] + expected[n*4:n*4+4] = b'\x56\x34\x23\xa1' + assert d.disk[51] == expected, n + assert d.disk[115] == expected, n + for start, free in ((319, 320), (320, 321), (356, 357), (383, 384)): + d = Driver() + for n in range(256, 512): + d.fat(n, 0x0fffffff) + d.fat(free, 0) + d.put('next_search_valid', 1, 1) + d.put('next_search_lo', start) + assert d.call('find_free_cluster') == 0 + assert d.get('free_cluster_lo') == free, (start, free) + + +def test_fragmented_load(): + d = Driver() + chain = [319, 500, 320, 1023, 384, 383, 356, 256] * 1 + # 40 non-adjacent clusters, 40 KiB: crosses FAT sectors and RAM pages. + chain += [1300 + n*137 for n in range(32)] + expected = bytearray() + for index, cluster in enumerate(chain): + d.fat(cluster, chain[index+1] if index+1 < len(chain) else 0x0fffffff) + for sector in range(2): + data = bytearray((index*19 + sector*71 + i) % 256 for i in range(512)) + d.disk[1017+(cluster-2)*2+sector] = data + expected.extend(data) + d.cluster(chain[0]) + d.call('stream_open') + d.m.c, d.m.hl = 32, 0x4000 + for count in (13, 27, 40): + d.m.b = count + assert d.call('core_load512') == 0 + assert d.ram[32*16384:32*16384+len(expected)] == expected + assert (d.m.c, d.m.hl) == (34, 0x6000) + d.m.b = 1 + assert d.call('core_load512') == 15 + + +if __name__ == '__main__': + for test in (test_offsets_and_links, test_write_and_allocation, test_fragmented_load): + test() + print(f'PASS: {test.__name__}') diff --git a/_sd/zc_sd_driver_body.asm b/_sd/zc_sd_driver_body.asm index 7d0fdc6..61f862a 100644 --- a/_sd/zc_sd_driver_body.asm +++ b/_sd/zc_sd_driver_body.asm @@ -1278,7 +1278,7 @@ gnc_hi dw 0 gnc_lo dw 0 gnc_fatsec_hi dw 0 gnc_fatsec_lo dw 0 -gnc_inoff db 0 +gnc_inoff dw 0 ; FAT32 entry offset: 0..508, needs 9 bits cluster_to_fatpos ld hl,(cur_cluster_hi) @@ -1317,9 +1317,11 @@ ctf_shr ld hl,(gnc_hi) ld hl,(cur_cluster_lo) ld a,l and #7f - add a,a - add a,a - ld (gnc_inoff),a + ld l,a + ld h,0 + add hl,hl + add hl,hl + ld (gnc_inoff),hl xor a ret @@ -1350,9 +1352,7 @@ get_next_cluster or a jr nz,gnc_end - ld a,(gnc_inoff) - ld l,a - ld h,0 + ld hl,(gnc_inoff) ld de,sdbuf add hl,de ld a,(hl) @@ -1435,9 +1435,7 @@ write_fat_entry or a jr nz,wfe_fail - ld a,(gnc_inoff) - ld l,a - ld h,0 + ld hl,(gnc_inoff) ld de,sdbuf add hl,de ld a,(new_val_lo) @@ -1693,9 +1691,7 @@ ffc_scan call cluster_to_fatpos inc hl ld (ffc_sectors_read),hl - ld a,(gnc_inoff) - ld l,a - ld h,0 + ld hl,(gnc_inoff) ld de,sdbuf add hl,de ld (ffc_ptr),hl diff --git a/_spg/ZIFI/zifi.spg b/_spg/ZIFI/zifi.spg index f65bca6..2f6d1a9 100644 Binary files a/_spg/ZIFI/zifi.spg and b/_spg/ZIFI/zifi.spg differ