From d76bcc5bd156f56fb008a5358770c84597bcf40d Mon Sep 17 00:00:00 2001 From: Alex Date: Mon, 5 Oct 2026 09:17:33 +0300 Subject: [PATCH] Fix CMD58 OCR read during SD initialization --- _sd/body_syms.inc | 840 +++++++++++++++++++------------------- _sd/zc_sd_driver_body.asm | 53 +-- _spg/ZIFI/zifi.spg | Bin 44544 -> 44544 bytes 3 files changed, 430 insertions(+), 463 deletions(-) diff --git a/_sd/body_syms.inc b/_sd/body_syms.inc index 2ac3446..ac31808 100644 --- a/_sd/body_syms.inc +++ b/_sd/body_syms.inc @@ -1,406 +1,403 @@ -body_end: EQU 0x00002002 -mkdir_sec_lo: EQU 0x00001FF2 -mkdir_sec_hi: EQU 0x00001FF0 -cmkf_open_stream: EQU 0x00001FC9 -cmkf_final: EQU 0x00001FB3 -cmkf_buildlfn: EQU 0x00001F97 -cmkf_entry: EQU 0x00001F55 -cmkf_havecl: EQU 0x00001F27 -cmkf_alloc: EQU 0x00001F11 -cmkf_havelen: EQU 0x00001EF8 -cmkf_lendone: EQU 0x00001EEF -cmkf_lenloop: EQU 0x00001EE2 -core_mkfile: EQU 0x00001EC7 -cmkf_len_lo: EQU 0x00001EC5 -cmkf_len_hi: EQU 0x00001EC3 -cmkd_final: EQU 0x00001EAE -cmkd_buildlfn: EQU 0x00001E92 -cmkd_ownentry: EQU 0x00001E5F -dotdot_name: EQU 0x00001FE5 -cmkd_dot_ok: EQU 0x00001E13 -dot_name: EQU 0x00001FDA -clear_dir_entry: EQU 0x00001FF4 -cmkd_dots: EQU 0x00001DBF -cmkd_zf: EQU 0x00001DA9 -cmkd_have_cl: EQU 0x00001D7B -cmkd_alloc: EQU 0x00001D65 -cmkd_toolong: EQU 0x00001D44 -cmkd_lendone: EQU 0x00001D48 -core_mkdir: EQU 0x00001D37 -cmk_sec_lo: EQU 0x00001D35 -cmk_sec_hi: EQU 0x00001D33 -cmk_cluster_lo: EQU 0x00001D31 -cmk_cluster_hi: EQU 0x00001D2F -cmk_name_ptr: EQU 0x00001D2D -sv512_nowrap: EQU 0x00001D29 -lv512_nowrap: EQU 0x00001CFC -lv512_advance: EQU 0x00001CE6 -lv512_eoc: EQU 0x00001D09 -lv512_done: EQU 0x00001D00 -lv512_loop: EQU 0x00001CC5 -core_load512: EQU 0x00001CBA -lv512_count: EQU 0x00001CB9 -lv512_off: EQU 0x00001CB7 -lv512_page: EQU 0x00001CB6 -sv512_advance: EQU 0x00001D13 -sv512_eoc: EQU 0x00001CAC -sv512_done: EQU 0x00001CA3 -sv512_loop: EQU 0x00001C82 -core_save512: EQU 0x00001C77 -sv512_count: EQU 0x00001C76 +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 page1_port: EQU 0x000011AF -core_fentry: EQU 0x00001C62 -core_setdir: EQU 0x00001C55 -core_setroot: EQU 0x00001C48 -active_dir_lo: EQU 0x00001C46 -active_dir_hi: EQU 0x00001C44 -fbn_tm_yes: EQU 0x00001C06 -fbn_tm_short: EQU 0x00001BF4 -fbn_acc_null: EQU 0x00001BC6 -fbn_acc_pad: EQU 0x00001BD1 -fbn_acc_charloop: EQU 0x00001B9A -fbn_acc_mul: EQU 0x00001B8A -fbn_acc_mul_done: EQU 0x00001B90 -fbn_matched_setrun: EQU 0x00001B5B -fbn_matched_norun: EQU 0x00001B58 -fbn_accumulate_lfn: EQU 0x00001B61 -fbn_lfn_cont: EQU 0x00001B22 -fbn_next: EQU 0x00001B2D -fbn_matched: EQU 0x00001B46 -fbn_try_match: EQU 0x00001BD4 -fbn_is_lfn: EQU 0x00001B14 -fbn_deleted: EQU 0x00001B27 -fbn_notfound_pop: EQU 0x00001B43 -fbn_entloop: EQU 0x00001AF3 -fbn_notfound: EQU 0x00001B44 -fbn_sector_loop: EQU 0x00001AD3 -find_by_name: EQU 0x00001AC3 -fbn_match_run_start_lo: EQU 0x00001AC1 -fbn_match_index_lo: EQU 0x00001ABF -fbn_run_start_lo: EQU 0x00001ABD -fbn_cur_index_lo: EQU 0x00001ABB -fbn_render_buf: EQU 0x00001AAE -fbn_attr: EQU 0x00001AAD -fbn_size_lo: EQU 0x00001AAB -fbn_size_hi: EQU 0x00001AA9 -fbn_cluster_hi: EQU 0x00001AA5 -fbn_acc_dest: EQU 0x00001AA3 -fbn_lfn_seen: EQU 0x00001AA2 -fbn_lfn_checksum: EQU 0x00001AA1 -fbn_lfn_buf: EQU 0x00001A38 -fbn_name_ptr: EQU 0x00001A36 -rsn_ext: EQU 0x00001A28 -rsn_done: EQU 0x00001A32 -rsn_ext_prep: EQU 0x00001A1D -rsn_base_skip: EQU 0x00001A1A -rsn_base: EQU 0x00001A0E -render_shortname: EQU 0x00001A0B -seci_eq: EQU 0x00001A09 -seci_ne: EQU 0x00001A06 -str_eq_ci: EQU 0x000019F3 -to_upper: EQU 0x000019EA -wne_w_skip_write: EQU 0x000019E1 -wne_w_notinrange: EQU 0x000019B3 -wne_w_entloop: EQU 0x0000197D -wne_w_fail: EQU 0x000019E7 -wne_w_continue: EQU 0x00001948 -wne_w_done: EQU 0x00001946 -wne_w_sector_loop: EQU 0x00001931 -write_name_entries: EQU 0x00001928 -wne_w_this_sec_lo: EQU 0x00001926 -wne_w_this_sec_hi: EQU 0x00001924 -wne_w_dirty: EQU 0x00001923 -wne_w_entcount: EQU 0x00001922 -wne_w_entptr: EQU 0x00001920 -ffr_no_hi_carry: EQU 0x000018A0 -ffr_free_cont: EQU 0x00001869 -ffr_advance_index: EQU 0x0000188A -ffr_free: EQU 0x00001853 -ffr_entloop: EQU 0x00001844 -ffr_fail: EQU 0x000018AD -ffr_grow_dir: EQU 0x000018B0 -ffr_have_sector: EQU 0x0000182C -ffr_sector_loop: EQU 0x0000181D -find_free_run: EQU 0x0000180D -wne_free_index_lo: EQU 0x0000180B -wne_free_index_hi: EQU 0x00001809 -cmkd_lenloop: EQU 0x00001D3C -wne_cur_index_lo: EQU 0x00001807 -wne_cur_index_hi: EQU 0x00001805 -wne_run_start_lo: EQU 0x00001803 -wne_run_start_hi: EQU 0x00001801 -wne_run_len: EQU 0x00001800 -ble_char_nextk: EQU 0x000017CD -ble_char_hi0: EQU 0x000017CB -ble_char_have: EQU 0x000017B1 -ble_char_isreal: EQU 0x000017A7 -ble_char_isnull: EQU 0x000017B0 -ble_lfn_next: EQU 0x000017D0 -ble_charloop: EQU 0x00001788 -ble_mul13done: EQU 0x00001783 -ble_mul13: EQU 0x00001778 -ble_seqset: EQU 0x0000175A -ble_notlast: EQU 0x00001759 -ble_lfn_done: EQU 0x000017D7 -ble_lfn_loop: EQU 0x00001722 -ble_divdone: EQU 0x0000170B -ble_divloop: EQU 0x00001700 -ble_multi: EQU 0x000016F7 -build_lfn_entries: EQU 0x000016D2 -ble_entry_ptr: EQU 0x000016D0 -ble_charpos: EQU 0x000016CE -ble_j: EQU 0x000016CD -ble_checksum: EQU 0x000016CC -ble_lfn_count: EQU 0x000016CB -ble_name_ptr: EQU 0x000016C9 -lfn_char_dest: EQU 0x000016BC -wne_slot_count: EQU 0x000016BB -wne_entries_buf: EQU 0x0000159B +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 wne_max_lfn: EQU 0x00000008 -btd_done: EQU 0x0000158F -btd_loop: EQU 0x00001586 -gus_have_candidate: EQU 0x00001565 -bin_to_2dig: EQU 0x00001584 -gus_try_1digit: EQU 0x0000154D -gus_try: EQU 0x00001528 -gus_ok: EQU 0x00001582 -gus_needs_suffix: EQU 0x00001523 -generate_unique_shortname: EQU 0x00001504 -gus_suffix: EQU 0x00001503 -fn83_ext_full: EQU 0x000014F5 -fn83_ext_bad: EQU 0x000014FC -fn83_ext_loop: EQU 0x000014D7 -fn83_ext_go: EQU 0x000014C0 -fn83_base_full: EQU 0x000014A5 -fn83_base_bad: EQU 0x000014AC -fn83_ext: EQU 0x000014B3 -fn83_base_loop: EQU 0x00001486 -fn83_have_baselen: EQU 0x0000147B -fn83_scan_next: EQU 0x00001439 -fn83_scandone: EQU 0x0000143D -fn83_scan: EQU 0x0000142D -filter_name_to_83: EQU 0x00001422 -fn83_charbuf: EQU 0x00001421 -sn_base_len: EQU 0x0000141F -sn_dot_pos: EQU 0x0000141D -sn_name_len: EQU 0x0000141B -sn_needs_lfn: EQU 0x0000141A -sn_ext: EQU 0x00001417 -sn_base: EQU 0x0000140F -cc_symyes: EQU 0x0000140A -cc_no: EQU 0x0000140D -cc_symloop: EQU 0x00001400 -cc_sym: EQU 0x000013FC -cc_yes: EQU 0x0000140B -cc_dig: EQU 0x000013F4 -cc_up: EQU 0x000013EC -classify_char: EQU 0x000013E2 -cc_symbols: EQU 0x000013D1 -lfnck_loop: EQU 0x000013CB -lfn_checksum: EQU 0x000013C8 -stamp_dir_entry_datetime: EQU 0x000011B1 -rtc_to_fat_datetime: EQU 0x00001135 -rtc_cached: EQU 0x00001134 -fat_time: EQU 0x00001132 -fat_date: EQU 0x00001130 -bcd_to_bin: EQU 0x0000111B -rtc_field_to_bin: EQU 0x0000110F -rtc_dm: EQU 0x0000110E -rtc_year: EQU 0x0000109D -rtc_month: EQU 0x0000109C -rtc_date: EQU 0x0000109B -rtc_hour: EQU 0x0000109A -rtc_min: EQU 0x00001099 -rtc_sec: EQU 0x00001098 -sv512_off: EQU 0x00001C74 -sv512_page: EQU 0x00001C73 -strm_write_have2: EQU 0x00001083 -stream_write_sector_from: EQU 0x0000101F -read_rtc_datetime: EQU 0x0000109E -strm_write_have: EQU 0x0000100A -stream_write_sector: EQU 0x00000F9C -stream_read_sector_to: EQU 0x00000D81 -stream_data_save: EQU 0x00000D9C -strm_read_eoc: EQU 0x00000D7E -stream_read_sector: EQU 0x00000D4B -strm_adv_same: EQU 0x00000D45 -strm_adv_cross: EQU 0x00000D1E -strm_adv_test_z: EQU 0x00000D16 -strm_advance: EQU 0x00000D09 -strm_calc_sector: EQU 0x00000CE1 -strm_open_nz: EQU 0x00000CCD -stream_open: EQU 0x00000CB3 -strm_sector_lo: EQU 0x00000CB1 -strm_sector_hi: EQU 0x00000CAF -stream_eoc: EQU 0x00000CAE -stream_sec_in_cluster: EQU 0x00000CAD -stream_cluster_lo: EQU 0x00000CAB -stream_cluster_hi: EQU 0x00000CA9 -wde_next: EQU 0x00000C78 -wde_slot: EQU 0x00000C89 -wde_entloop: EQU 0x00000C58 -wde_fail: EQU 0x00000CA6 -wde_sec_loop: EQU 0x00000C43 -wde_cluster: EQU 0x00000C2E -write_dir_entry: EQU 0x00000C2E -wde_slotptr: EQU 0x00000C2C -wde_sector_lo: EQU 0x00000C2A -wde_sector_hi: EQU 0x00000C28 -wde_remaining: EQU 0x00000C27 -dir_entry_buf: EQU 0x00000C07 -zfc_loop: EQU 0x00000BF5 -zfc_fail: EQU 0x00000C04 -zero_fill_cluster: EQU 0x00000BCF -zfc_remaining: EQU 0x00000BCE -ffc_nowrap: EQU 0x00000BBF -ffc_nsv2: EQU 0x00000B99 -ffc_nsv: EQU 0x00000B93 -ffc_entnext: EQU 0x00000BA3 -ffc_entloop: EQU 0x00000B5C -ffc_fail: EQU 0x00000BCB -ffc_from2: EQU 0x00000B12 -ffc_scan: EQU 0x00000B21 -ffc_use_hint: EQU 0x00000AF8 -find_free_cluster: EQU 0x00000ADD -next_search_valid: EQU 0x00000AD8 -ffc_sectors_read: EQU 0x00000AD6 -ffc_count: EQU 0x00000AD5 -ffc_ptr: EQU 0x00000AD3 -free_cluster_lo: EQU 0x00000AD1 -free_cluster_hi: EQU 0x00000ACF -next_search_hi: EQU 0x00000AD9 -next_search_lo: EQU 0x00000ADB -wfi_skip_count: EQU 0x00000AB3 -write_fsinfo_hint: EQU 0x00000A78 -read_fsinfo_hint: EQU 0x00000A19 -fsinfo_valid: EQU 0x00000A18 -fsinfo_hint_lo: EQU 0x00000A16 -fsinfo_hint_hi: EQU 0x00000A14 -wfe_loop: EQU 0x000009DD -wfe_fail: EQU 0x00000A0F -write_fat_entry: EQU 0x0000098E -wfe_sector_lo: EQU 0x0000098C -wfe_sector_hi: EQU 0x0000098A -wfe_remaining: EQU 0x00000989 -new_val_lo: EQU 0x00000987 -new_val_hi: EQU 0x00000985 -gnc_have_next: EQU 0x00000974 -gnc_end: EQU 0x0000096E -nxt_hi: EQU 0x00000927 -nxt_lo: EQU 0x00000925 -ctf_bad: EQU 0x00000921 -ctf_shr: EQU 0x000008D2 -cluster_to_fatpos: EQU 0x000008C4 -gnc_inoff: EQU 0x000008C3 -gnc_fatsec_lo: EQU 0x000008C1 -gnc_fatsec_hi: EQU 0x000008BF -gnc_lo: EQU 0x000008BD -gnc_hi: EQU 0x000008BB -c2s_loop: EQU 0x00000881 -c2s_done: EQU 0x0000089A -cur_cluster_hi: EQU 0x000008B7 -cur_cluster_lo: EQU 0x000008B9 -c2s_prod_hi: EQU 0x00000854 -c2s_prod_lo: EQU 0x00000852 -c2s_hi: EQU 0x00000850 -c2s_lo: EQU 0x0000084E -chain_ended: EQU 0x00000924 -get_next_cluster: EQU 0x00000929 -fza_next: EQU 0x00000838 -fza_inc_loop: EQU 0x00000830 -fza_done: EQU 0x0000084B -fza_stop: EQU 0x00000849 -fza_loop: EQU 0x0000081A -fza_sector_lo: EQU 0x00000856 -fza_sector_hi: EQU 0x00000858 -cluster_to_sector: EQU 0x0000085A -fza_cluster: EQU 0x00000807 -find_zifi_all: EQU 0x00000807 -fza_remaining: EQU 0x00000806 -fz_found: EQU 0x000007D1 -fz_cmpfail: EQU 0x000007C4 -fz_cmp: EQU 0x000007B8 -fz_skip: EQU 0x000007C6 -fz_end: EQU 0x000007CE -fz_loop: EQU 0x000007A9 -find_zifi: EQU 0x000007A4 -target_name: EQU 0x00000799 -zifi_size: EQU 0x00000797 -fbn_acc_nocs: EQU 0x00001B75 -zifi_size_hi: EQU 0x00000795 -zifi_cluster: EQU 0x00000793 -zifi_cluster_hi: EQU 0x00000791 -root_dir_hi: EQU 0x0000078F -root_dir_lo: EQU 0x0000078D -mul2_loop: EQU 0x0000070E -mul2_done: EQU 0x00000727 -prod2_hi: EQU 0x0000078B -prod2_lo: EQU 0x00000789 -rc2_hi: EQU 0x00000787 -rc2_lo: EQU 0x00000785 -data_start_hi: EQU 0x00000783 -data_start_lo: EQU 0x00000781 -mul1_loop: EQU 0x000006AF -mul1_done: EQU 0x000006C8 -prod_hi: EQU 0x0000077F -prod_lo: EQU 0x0000077D -root_cluster_lo: EQU 0x00000779 -root_cluster_hi: EQU 0x0000077B -fatsz32_lo: EQU 0x00000775 -fatsz32_hi: EQU 0x00000777 -sectors_per_cluster: EQU 0x00000774 -num_fats: EQU 0x00000773 -fsinfo_sector: EQU 0x00000A12 -reserved_sectors: EQU 0x00000771 -total_sectors_hi: EQU 0x0000076B -total_sectors_lo: EQU 0x00000769 -parse_bpb: EQU 0x00000635 -diag_buf: EQU 0x00000621 -vf_ok: EQU 0x0000061C -vf_bad: EQU 0x0000061E -verify_fat32: EQU 0x000005DC -dp_fallback: EQU 0x000005C0 -dp_found: EQU 0x00000591 -dp_entry: EQU 0x000005DA -dp_loop: EQU 0x00000577 -dp_none: EQU 0x0000058F -detect_partition: EQU 0x0000054C -sec0_copy: EQU 0x0000034C -add_addtop: EQU 0x0000033C -addtop_lo: EQU 0x0000033A -addtop_hi: EQU 0x00000338 -cmdx: EQU 0x00000305 -do_cmd55: EQU 0x000002DF -cmdo: EQU 0x000002FF -send_frame: EQU 0x000002E7 -cmd16: EQU 0x000002BF -cmd08: EQU 0x000002B9 -cmd00: EQU 0x000002B3 -sdwrite_lba_from: EQU 0x0000022E -sdwrite_lba: EQU 0x0000022B -sdwrite_multi_stop: EQU 0x00000216 -sdwrite_multi_block_from: EQU 0x000001F1 -sdwrite_multi_block: EQU 0x000001EE -csl: EQU 0x00000252 -wait: EQU 0x00000267 -sdwrite_multi_start: EQU 0x000001A9 -wtdo: EQU 0x0000027C -sdread_fail: EQU 0x000001A0 -resp: EQU 0x00000292 -sdread_common: EQU 0x00000187 -sdread_lba_oob: EQU 0x000001A6 -send_cmd_lba: EQU 0x000001C1 -cmdlba_op: EQU 0x000001C0 -sdread_lba_to: EQU 0x0000017C -sdread_lba: EQU 0x00000179 -dma_send_ext: EQU 0x00000159 -dma_wait: EQU 0x00000173 -dma_recv_ext: EQU 0x0000013D -dma_set_addr_ext: EQU 0x00000127 -sdbuf: EQU 0x000011C8 -set_dma_sdbuf: EQU 0x0000011B -dma_xfer_page: EQU 0x0000011A -dma_xfer_off: EQU 0x00000118 +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 +gnc_inoff: EQU 0x00000874 +gnc_fatsec_lo: EQU 0x00000872 +gnc_fatsec_hi: EQU 0x00000870 +gnc_lo: EQU 0x0000086E +gnc_hi: EQU 0x0000086C +c2s_loop: EQU 0x00000832 +c2s_done: EQU 0x0000084B +cur_cluster_hi: EQU 0x00000868 +cur_cluster_lo: EQU 0x0000086A +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 +fza_next: EQU 0x000007E9 +fza_inc_loop: EQU 0x000007E1 +fza_done: EQU 0x000007FC +fza_stop: EQU 0x000007FA +fza_loop: EQU 0x000007CB +fza_sector_lo: EQU 0x00000807 +fza_sector_hi: EQU 0x00000809 +cluster_to_sector: EQU 0x0000080B +fza_cluster: EQU 0x000007B8 +find_zifi_all: EQU 0x000007B8 +fza_remaining: EQU 0x000007B7 +fz_found: EQU 0x00000782 +fz_cmpfail: EQU 0x00000775 +fz_cmp: EQU 0x00000769 +fz_skip: EQU 0x00000777 +fz_end: EQU 0x0000077F +fz_loop: EQU 0x0000075A +find_zifi: EQU 0x00000755 +target_name: EQU 0x0000074A +zifi_size: EQU 0x00000748 +fbn_acc_nocs: EQU 0x00001B25 +zifi_size_hi: EQU 0x00000746 +zifi_cluster: EQU 0x00000744 +zifi_cluster_hi: EQU 0x00000742 +root_dir_hi: EQU 0x00000740 +root_dir_lo: EQU 0x0000073E +mul2_loop: EQU 0x000006D2 +mul2_done: EQU 0x000006EB +prod2_hi: EQU 0x0000073C +prod2_lo: EQU 0x0000073A +rc2_hi: EQU 0x00000738 +rc2_lo: EQU 0x00000736 +data_start_hi: EQU 0x00000734 +data_start_lo: EQU 0x00000732 +mul1_loop: EQU 0x0000067B +mul1_done: EQU 0x00000694 +prod_hi: EQU 0x00000730 +prod_lo: EQU 0x0000072E +root_cluster_lo: EQU 0x0000072A +root_cluster_hi: EQU 0x0000072C +fatsz32_lo: EQU 0x00000726 +fatsz32_hi: EQU 0x00000728 +sectors_per_cluster: EQU 0x00000725 +num_fats: EQU 0x00000724 +fsinfo_sector: EQU 0x000009C3 +reserved_sectors: EQU 0x00000722 +total_sectors_hi: EQU 0x0000071C +total_sectors_lo: EQU 0x0000071A +parse_bpb: EQU 0x0000062F +vf_ok: EQU 0x0000062A +vf_bad: EQU 0x0000062C +verify_fat32: EQU 0x000005EA +dp_fallback: EQU 0x000005CE +dp_found: EQU 0x0000059F +dp_entry: EQU 0x000005E8 +dp_loop: EQU 0x00000585 +dp_none: EQU 0x0000059D +detect_partition: EQU 0x0000055A +sec0_copy: EQU 0x0000035A +add_addtop: EQU 0x0000034A +addtop_lo: EQU 0x00000348 +addtop_hi: EQU 0x00000346 +cmdx: EQU 0x00000313 +do_cmd55: EQU 0x000002ED +cmdo: EQU 0x0000030D +send_frame: EQU 0x000002F5 +cmd16: EQU 0x000002C5 +cmd08: EQU 0x000002BF +cmd00: EQU 0x000002B9 +sdwrite_lba_from: EQU 0x00000234 +sdwrite_lba: EQU 0x00000231 +sdwrite_multi_stop: EQU 0x0000021C +sdwrite_multi_block_from: EQU 0x000001F7 +sdwrite_multi_block: EQU 0x000001F4 +csl: EQU 0x00000258 +wait: EQU 0x0000026D +sdwrite_multi_start: EQU 0x000001AF +wtdo: EQU 0x00000282 +sdread_fail: EQU 0x000001A6 +resp: EQU 0x00000298 +sdread_common: EQU 0x0000018D +sdread_lba_oob: EQU 0x000001AC +send_cmd_lba: EQU 0x000001C7 +cmdlba_op: EQU 0x000001C6 +sdread_lba_to: EQU 0x00000182 +sdread_lba: EQU 0x0000017F +dma_send_ext: EQU 0x0000015F +dma_wait: EQU 0x00000179 +dma_recv_ext: EQU 0x00000143 +dma_set_addr_ext: EQU 0x0000012D +sdbuf: EQU 0x00001178 +set_dma_sdbuf: EQU 0x00000121 +dma_xfer_page: EQU 0x00000120 +dma_xfer_off: EQU 0x0000011E dma_ctr: EQU 0x000027AF dma_num: EQU 0x000028AF dma_len: EQU 0x000026AF @@ -411,26 +408,27 @@ dma_daddrx: EQU 0x00001FAF dma_daddrh: EQU 0x00001EAF dma_daddrl: EQU 0x00001DAF own_page: EQU 0x0000000F -cca_shift: EQU 0x000000EE -compute_card_arg: EQU 0x000000DC -card_arg: EQU 0x000000D8 -sd_lba_max_hi: EQU 0x0000076F -sd_lba_max_lo: EQU 0x0000076D -lba_guard_check: EQU 0x000000B9 -lba_arg: EQU 0x000000B5 -set_lba32: EQU 0x000000A4 -sd_block_addressed: EQU 0x000000D7 -sd_v2_ocr_rest: EQU 0x00000093 -sdinit_ok: EQU 0x00000099 -do_cmd16: EQU 0x000002D1 -do_cmd1: EQU 0x000002D7 +cca_shift: EQU 0x000000F4 +compute_card_arg: EQU 0x000000E2 +card_arg: EQU 0x000000DE +sd_lba_max_hi: EQU 0x00000720 +sd_lba_max_lo: EQU 0x0000071E +lba_guard_check: EQU 0x000000BF +lba_arg: EQU 0x000000BB +set_lba32: EQU 0x000000AA +sd_block_addressed: EQU 0x000000DD +sd_v2_ocr_rest: EQU 0x00000099 +do_cmd58: EQU 0x000002DD +sdinit_ok: EQU 0x0000009F +do_cmd16: EQU 0x000002D7 +do_cmd1: EQU 0x000002E5 sd_fbs: EQU 0x0000005D -do_acmd41: EQU 0x00000318 +do_acmd41: EQU 0x00000326 sd_v2: EQU 0x00000067 -do_cmd8: EQU 0x000002CB -do_cmd0: EQU 0x000002C5 -sdinit_fail: EQU 0x0000009E -cycl: EQU 0x000002A6 -csh: EQU 0x0000023F +do_cmd8: EQU 0x000002D1 +do_cmd0: EQU 0x000002CB +sdinit_fail: EQU 0x000000A4 +cycl: EQU 0x000002AC +csh: EQU 0x00000245 sdinit: EQU 0x00000000 -fbn_cluster_lo: EQU 0x00001AA7 +fbn_cluster_lo: EQU 0x00001A57 diff --git a/_sd/zc_sd_driver_body.asm b/_sd/zc_sd_driver_body.asm index 78f05c4..7d0fdc6 100644 --- a/_sd/zc_sd_driver_body.asm +++ b/_sd/zc_sd_driver_body.asm @@ -114,12 +114,17 @@ sd_v2 ld de,#01aa or a jr nz,sdinit_fail - ; ACMD41 just succeeded (card left the busy state) -- read - ; its OCR (4 more bytes, MSB-first) for the REAL CCS bit + ; ACMD41 just succeeded (card left the busy state). CMD58 is + ; mandatory here: without it the following four reads only sample + ; idle SPI bytes (#ff) and falsely turn every v2 card into SDHC. + ; Read its OCR (4 bytes, MSB-first) for the REAL CCS bit ; (bit 30 = bit 6 of the first byte) instead of assuming ; every card that speaks the v2 protocol is block-addressed. ; A genuine SDv2 card can still be an SDSC (<=2GB) card. See ; [[project-zifi-custom-sd-driver]]. + call do_cmd58 + or a + jr nz,sdinit_fail ld bc,DATA in a,(c) bit 6,a @@ -668,6 +673,9 @@ do_cmd8 ld hl,cmd08 jp send_frame do_cmd16 ld hl,cmd16 jp send_frame +do_cmd58 ld a,%01000000+58 + call cmdo + jp resp do_cmd1 ld a,%01000000+1 call cmdo jp resp @@ -910,7 +918,7 @@ vf_bad xor a ;--- parse_bpb: reads BPB fields out of sdbuf (offsets per the standard ;--- FAT32 BPB layout), computes DataStartSector and RootDirSector as -;--- true 32-bit values, and fills diag_buf for on-screen display. +;--- true 32-bit values. ;--- FATSz32 alone can be tens of thousands of sectors on a real card ;--- (30MB+ FAT tables are normal) -- ReservedSectorCount + NumFATs* ;--- FATSz32 overflowed 16 bits on the first try (32 + 2*59430 = @@ -918,8 +926,6 @@ vf_bad xor a ;--- that just happened to read back as all zeroes. All the sector- ;--- number math below uses ADC HL,DE across (hi,lo) 16-bit halves. --- -diag_buf ds 20 - parse_bpb ld hl,(sdbuf+32) ; TotalSectors32 low16 (u32 @ offset 32) ld (total_sectors_lo),hl ld hl,(sdbuf+34) ; TotalSectors32 high16 @@ -927,47 +933,25 @@ parse_bpb ld hl,(sdbuf+32) ; TotalSectors32 low16 (u32 @ offset 32) ld hl,(sdbuf+14) ; ReservedSectorCount (u16) ld (reserved_sectors),hl - ld a,h - ld (diag_buf+0),a - ld a,l - ld (diag_buf+1),a ld hl,(sdbuf+48) ; FSInfoSector (u16, sector # within volume) ld (fsinfo_sector),hl ld a,(sdbuf+16) ; NumFATs (u8) ld (num_fats),a - ld (diag_buf+2),a ld a,(sdbuf+13) ; SectorsPerCluster (u8) ld (sectors_per_cluster),a - ld (diag_buf+3),a ld hl,(sdbuf+38) ; FATSz32 high16 ld (fatsz32_hi),hl - ld a,h - ld (diag_buf+4),a - ld a,l - ld (diag_buf+5),a ld hl,(sdbuf+36) ; FATSz32 low16 ld (fatsz32_lo),hl - ld a,h - ld (diag_buf+6),a - ld a,l - ld (diag_buf+7),a ld hl,(sdbuf+46) ; RootCluster high16 ld (root_cluster_hi),hl - ld a,h - ld (diag_buf+8),a - ld a,l - ld (diag_buf+9),a ld hl,(sdbuf+44) ; RootCluster low16 ld (root_cluster_lo),hl - ld a,h - ld (diag_buf+10),a - ld a,l - ld (diag_buf+11),a ; NumFATs * FATSz32 (32-bit product via repeated 32-bit add -- ; NumFATs is always tiny, 1 or 2, so this is at most 2 iterations) @@ -998,10 +982,6 @@ mul1_done ld de,(prod_hi) adc hl,de ld (data_start_hi),hl - ld a,h - ld (diag_buf+12),a - ld a,l - ld (diag_buf+13),a ; RootCluster - 2 (32-bit) ld hl,(root_cluster_lo) @@ -1043,15 +1023,6 @@ mul2_done ld de,(prod2_hi) adc hl,de ld (root_dir_hi),hl - ld a,h - ld (diag_buf+14),a - ld a,l - ld (diag_buf+15),a - ld hl,(root_dir_lo) - ld a,h - ld (diag_buf+16),a - ld a,l - ld (diag_buf+17),a ; sd_lba_max = ADDTOP + TotalSectors32 -- one past the last ; valid absolute LBA on this card/partition. Computed here @@ -4382,8 +4353,6 @@ cmkf_open_stream dot_name db ". " ; 11 bytes dotdot_name db ".. " ; 11 bytes -mkdir_sec_hi dw 0 -mkdir_sec_lo dw 0 clear_dir_entry ld hl,dir_entry_buf diff --git a/_spg/ZIFI/zifi.spg b/_spg/ZIFI/zifi.spg index 5b05450e6e22a5cc6a61cd3af5311d86eaa11a4e..f65bca6ce541ceda97ba3be54f28c4b5ba221694 100644 GIT binary patch delta 4365 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 delta 4426 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