Replace closed WDFCVBI2.COD with from-scratch open SD/FAT32 driver

Renamed as zc_sd_driver.asm/zc_sd_driver_body.asm (no relation to Wild
Commander). Fixes a stale-IX bug where core_mkfile's filter_name_to_83
left IX pointing into driver memory instead of restoring it, causing
zifi.asm's save_downloaded_file to read the wrong page/address for
every SAVE512 call after MKFILE. All CORE dispatch entry points now
preserve IX across the call. Also fixes a body/#2000 jump-table
overlap, sdbuf DMA word-alignment, and a load_ram_page staleness race
in zifi.asm's own download bookkeeping.
This commit is contained in:
2026-09-09 20:50:06 +03:00
parent 06c9efa9a8
commit c3c5c7dccc
7 changed files with 5452 additions and 18 deletions
+149 -15
View File
@@ -281,7 +281,13 @@ load_ram_page ld a,0
ex de,hl ; download adress for lists. after "Search:"
1 ld (zipd_adr+1),hl
IF cable_zifi
; snapshot load_ram_page NOW, before the (possibly multi-second)
; network receive below -- see saved_thread_page's own comment for why
; re-reading load_ram_page AFTER the call is wrong.
ld a,(load_ram_page+1)
ld (saved_thread_page),a
IF cable_zifi
ld a,(load_ram_page+1)
ld hl,modem_command
call psb_get
@@ -289,7 +295,6 @@ load_ram_page ld a,0
call zifi_get
ENDIF
; bc: hl - lenght of readed data
ld ix,read_threads
ld a,c
@@ -303,7 +308,7 @@ load_ram_page ld a,0
1 xor a
ld (ix+thread.num),a
ld a,(load_ram_page+1)
ld a,(saved_thread_page)
ld (ix+thread.page),a
call set_page1
ld hl,status_copy ; clear statusbar gfx
@@ -3824,13 +3829,47 @@ sd_init
*/
; on_int_dma/off_int_dma bracket EVERY SD operation (init_sd_card at
; the start, sd_exit at the end -- see their own call sites) -- but
; save_mode alone doesn't cover everything: int_main's pt_play (~line
; 2350) is gated by its OWN SEPARATE music_sw flag, not save_mode, and
; unconditionally repages PAGE0/PAGE1/PAGE3 for the music player
; (set_music_pages_lite) on every single interrupt a track is playing.
; PAGE0 changing mid-execution while our SD driver code is running
; FROM slot 0 (page #0F) crashes the instant the interrupt returns;
; PAGE3 changing mid-LOAD512/SAVE512 silently swaps the transfer's
; real source/dest for whatever the music player last pointed it at.
; wrap_load512/wrap_save512's own di/ei (zc_sd_driver.asm) only
; protects against the CRASH by blocking ALL interrupts for the whole
; multi-block transfer -- but that STARVES pt_play for however long
; the transfer takes (can be several video frames for a large file),
; which is exactly why music glitches/goes to noise and the screen
; flickers when switching tracks during any SD activity: pt_play
; simply never gets to run its own per-frame update while we're mid-
; transfer, then resumes abruptly once di/ei lets it back in. Clearing
; music_sw here too (not just save_mode) means pt_play's own "call
; nz,pt_play" check skips it ENTIRELY during SD operations -- a clean
; pause instead of a starve-then-jump-back-in glitch -- confirmed as
; the real cause of "noise mixed with melody" persisting even after
; the SAVE512 addressing fix (which was a real, separate bug, but not
; the only one). See [[project-zifi-custom-sd-driver]].
; music_sw_saved: off_int_dma saves music_sw's real value here (which
; may already be 0 if the user paused music) before forcing it off, so
; on_int_dma can RESTORE that instead of blindly forcing it back to 1
; -- otherwise an SD operation happening while music is paused would
; incorrectly un-pause it.
music_sw_saved db 0
on_int_dma ld a,1
jr sw_int_dma
off_int_dma xor a
sw_int_dma ld (save_mode+1),a
; ld (analizator_sw+1),a
; ld (mouse_sw+1),a
; jp wait_frame
ld (save_mode+1),a
ld a,(music_sw_saved)
ld (music_sw+1),a
ret
off_int_dma ld a,(music_sw+1)
ld (music_sw_saved),a
xor a
ld (save_mode+1),a
ld (music_sw+1),a
ret
@@ -3968,7 +4007,11 @@ load_ini
CALL FENTRY
JP Z,ini_not_found
LD C,download_page ; page ini
LD HL,#0000
LD HL,#4000 ; LOAD512 uses the SAME slot-1/direct-
; address convention as SAVE512 -- see
; zc_sd_driver_body.asm's core_load512
; comment for why this changed from
; #0000/PAGE3
LD B,#32
CALL LOAD512
CALL SETROOT; возвращаемся в коневой
@@ -3976,8 +4019,8 @@ load_ini
parse_ini ld a,download_page
call set_page3
ld hl,#c000
call set_page1
ld hl,#4000
IF !cable_zifi
ld de,ini_db
call cp_ini
@@ -4691,6 +4734,27 @@ full_len_high byte ;
read_threads thread;ds 6*5
db #ff
; modem_load_file's own private snapshot of load_ram_page, captured
; right before starting the actual network receive (zifi_get/psb_get)
; -- NOT the same as re-reading load_ram_page after the call returns.
; load_ram_page is a single shared global, written from several other
; places (catalog-link clicks, pagination, menu navigation -- see
; loadpage_after_link_list and the download_page writers). zifi_get can
; run for several seconds (WiFi connect/TLS handshake/HTTP wait, many
; wait_frame-yielded interrupt frames), during which the interrupt-
; driven UI can process a DIFFERENT click that overwrites load_ram_page
; before zifi_get returns. Re-reading load_ram_page at that point (the
; old code) stamps thread.page with whatever category was clicked LAST,
; not the one this download actually used. This is a real, still-latent
; hazard (kept as a defensive fix), but turned out NOT to be the cause
; of "every download saves as identical garbage" -- that bug was a
; stale IX left behind by MKFILE (see the wrap_* comment in
; zc_sd_driver.asm), which made save_64 read (ix+thread.page)/(ix+
; thread.adress) from the wrong memory entirely, regardless of what
; read_threads itself held. See [[project-zifi-custom-sd-driver]]
; (2026-09-09).
saved_thread_page db 0
init_zifi
@@ -4722,17 +4786,80 @@ init_zifi
; call wait
; call zifi_check_receive_command
; ret
ld a,wifi_connect_retries_max
ld (wifi_connect_retries_left),a
; wifi_connect_retry: (re)send AT+CWJAP_CUR and wait for "OK" -- up to
; wifi_connect_quanta quanta (~256 frames/quantum, ~5s each) per
; attempt, up to wifi_connect_retries_max attempts total. Was an
; unconditional "jr nz,2b" with NO timeout at all -- a real ESP module
; that never answers (bad credentials, out of range, module wedged)
; hung here forever with zero feedback. See [[project-zifi-custom-sd-driver]].
wifi_connect_retry
ld hl,wifi_try_connect
ld b,2
call zifi_echo
ld hl,cmd_cwjap ; AT+CWJAP_CUR . Connect to AP, for current
call zifi_send
2 call zifi_check_receive_command
ld a,wifi_connect_quanta
ld (wifi_connect_quantum_left),a
wifi_connect_quantum
xor a
ld (wifi_connect_frame_left),a ; 0 wraps to 256 via dec below
wifi_connect_poll
; NOT "call zifi_check_receive_command" -- that goes through
; zifi_input_fifo_check, which BLOCKS INTERNALLY for up to
; 256 frames (its own "call wait_frame / dec e / jr nz,3b")
; whenever the FIFO is empty, only returning immediately
; when data IS already waiting. With nothing new arriving,
; nearly every call to it here would burn a full internal
; 256-frame wait BEFORE this loop's own frame counter even
; gets to react -- confirmed live (wifi_connect_frame_left
; stayed frozen for 6500+ frames: this loop's "iterations"
; were each secretly taking up to 256 frames on their own).
; It also drives zifi_input_fifo_check's OWN separate
; download-timeout/retry state (dl_timeout_left etc, meant
; for actual file downloads, not this WiFi-connect wait) --
; that's what caused the red border flashes. Doing our own
; quick, non-blocking FIFO peek here avoids both problems:
; only call the (bulk-read) fifo_inir when data is actually
; present, so it never falls into the internal wait either.
ld bc,zifi_input_fifo_status
in a,(c)
or a
jr z,wifi_connect_nodata
call fifo_inir
ld de,str_ok
call buffer_cmp
; cp low output_buff+#bf
jr nz,2b
jr z,wifi_connect_ok
wifi_connect_nodata
call wait_frame
ld hl,wifi_connect_frame_left
dec (hl)
jr nz,wifi_connect_poll
ld a,(wifi_connect_quantum_left)
dec a
ld (wifi_connect_quantum_left),a
jr nz,wifi_connect_quantum
; this attempt's quanta are exhausted -- retry if any left
ld a,(wifi_connect_retries_left)
dec a
ld (wifi_connect_retries_left),a
jr nz,wifi_connect_retry
; out of retries -- give up with a real message instead of
; hanging silently forever
ld hl,wifi_connect_failed_msg
ld b,1
call zifi_echo
jr $
wifi_connect_ok
ld hl,wifi_connected
call zifi_echo
ld a,(update_rtc_sw+1) ; "time:" in zifi.ini not "none"?
@@ -4741,6 +4868,13 @@ init_zifi
call rtc_read_date ; name downloads/<date> from the RTC chip either way
call set_download_dir
ret
wifi_connect_quanta equ 4 ; ~5s/quantum * 4 = ~20s per attempt
wifi_connect_retries_max equ 5
wifi_connect_frame_left db 0
wifi_connect_quantum_left db 0
wifi_connect_retries_left db 0
wifi_connect_failed_msg db #0d,#0a,'WiFi connect failed',0,0
; ld b,25
; call wait
; ld hl,cmd_cipsta ; is Set IP address of station ?