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:
@@ -51,8 +51,7 @@ AT+CIPSNTPTIME? — получить текущее врем
|
|||||||
- теперь DMA-очистка под индикатор громкости дожидается завершения перед тем, как CPU начинает рисовать поверх той же области (была гонка записи);
|
- теперь DMA-очистка под индикатор громкости дожидается завершения перед тем, как CPU начинает рисовать поверх той же области (была гонка записи);
|
||||||
- исправил переполнение буфера имени файла (`create_filename`): при скачивании имя файла из ссылки копировалось в 48-байтный буфер без проверки длины, и если оно было длиннее — переполнение затирало соседние переменные (`zifi.ini`, имена служебных папок) прямо в памяти. Теперь копирование корректно обрезается на 48 символах. Проверено на железе: создание папки и файла с длинными именами (в т.ч. ровно 48 символов) и последующее чтение содержимого — всё работает штатно, никакой драйверной обрезки до 8 символов нет.
|
- исправил переполнение буфера имени файла (`create_filename`): при скачивании имя файла из ссылки копировалось в 48-байтный буфер без проверки длины, и если оно было длиннее — переполнение затирало соседние переменные (`zifi.ini`, имена служебных папок) прямо в памяти. Теперь копирование корректно обрезается на 48 символах. Проверено на железе: создание папки и файла с длинными именами (в т.ч. ровно 48 символов) и последующее чтение содержимого — всё работает штатно, никакой драйверной обрезки до 8 символов нет.
|
||||||
|
|
||||||
> [!CAUTION]
|
**Заменил драйвер SD-карты.** Штатный `_sd/WDFCVBI2.COD` (закрытый бинарник без исходников, автор — "Hacker VBI") был заменён на собственный, открытый SD/FAT32-драйвер (`_sd/zc_sd_driver.asm` + `_sd/zc_sd_driver_body.asm`) — реализует те же ~15 функций CORE-таблицы, которые реально использует ZiFi. Заодно исправлена и порча имён папок на FAT32 (короткие имена 8.3 иногда совпадали с уже существующей записью в каталоге). Подробнее — `_sd/README.md`.
|
||||||
> **Известная серьёзная проблема (пока не исправлена): порча имён папок на FAT32.** Штатный драйвер SD-карты (`_sd/WDFCVBI2.COD`, закрытый бинарник без исходников, автор — "Hacker VBI") при создании папки/файла с длинным именем иногда генерирует короткое имя 8.3, совпадающее с уже существующей записью в каталоге — получаются две разные папки с одинаковым коротким именем на диске. Windows chkdsk потом это обнаруживает и переименовывает вторую запись в `<имя>.--N`, а по факту это два разных физических каталога, которые должны были быть одним (например, файлы за один день оказываются раскиданы между `2026_09_01` и `2026_0~1.--0`). Нашёл и подтвердил дизассемблированием конкретный баг в алгоритме генерации числового суффикса `~N` внутри драйвера, но исправить сам драйвер нельзя — исходников нет, только бинарник. Сейчас пишу отдельный, открытый SD/FAT32-драйвер на замену (реализует только те ~15 функций, которые реально использует ZiFi) — работа в процессе, ещё не готово к использованию.
|
|
||||||
|
|
||||||
**Известная нерешённая мелочь:** курсор мыши (аппаратный спрайт TSU) обрывается по фиксированной строке экрана прямо над нижней панелью управления — похоже на границу, завязанную на тайминг переключения видеорежима или на аппаратный бордюр, а не на что-то, что двигается вместе с содержимым панели. Я не нашёл способ поправить это без риска сломать что-то ещё, оставил как есть.
|
**Известная нерешённая мелочь:** курсор мыши (аппаратный спрайт TSU) обрывается по фиксированной строке экрана прямо над нижней панелью управления — похоже на границу, завязанную на тайминг переключения видеорежима или на аппаратный бордюр, а не на что-то, что двигается вместе с содержимым панели. Я не нашёл способ поправить это без риска сломать что-то ещё, оставил как есть.
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,50 @@
|
|||||||
|
# zc_sd_driver
|
||||||
|
|
||||||
|
Открытый SD/FAT32-драйвер для ZiFi, замена закрытого `WDFCVBI2.COD`.
|
||||||
|
Реализует ту же CORE-таблицу (`CORE equ #2002` в `zifi.asm`), что и
|
||||||
|
оригинальный драйвер, но с открытыми исходниками.
|
||||||
|
|
||||||
|
## Файлы
|
||||||
|
|
||||||
|
- `zc_sd_driver.asm` — резидентная часть: таблица переходов CORE,
|
||||||
|
di/ei-обёртки над каждой точкой входа, распаковщик тела.
|
||||||
|
- `zc_sd_driver_body.asm` — основная логика: SPI/SD-протокол, DMA,
|
||||||
|
разбор FAT32 (BPB, цепочки кластеров, FAT), поиск по имени с LFN,
|
||||||
|
создание/удаление файлов и каталогов. Хранится в сжатом виде и
|
||||||
|
распаковывается в резидентную часть во время выполнения `DOS_SWP`.
|
||||||
|
- `body_syms.inc` — адреса функций/переменных тела, сгенерированные
|
||||||
|
из символьной таблицы сборки `zc_sd_driver_body.asm`, подключаются
|
||||||
|
в `zc_sd_driver.asm` как константы.
|
||||||
|
|
||||||
|
## Реализованные функции CORE
|
||||||
|
|
||||||
|
`DEV_INI`, `HDD`, `LOAD512`, `SAVE512`, `DOS_SWP`, `MKFILE`, `MKDIR`,
|
||||||
|
`DELFL`, `RENAME`, `FENTRY`, `LOADNON`, `NXTETY`, `SETDIR`, `SETROOT`,
|
||||||
|
`SEEK0`. Остальные точки входа таблицы — заглушки (не используются
|
||||||
|
ZiFi).
|
||||||
|
|
||||||
|
## Адресация
|
||||||
|
|
||||||
|
Драйвер загружается в физическую страницу `#0F`, отображается в CPU
|
||||||
|
слот 0 (`#0000-#3FFF`). `CORE` (`#2002`) — фиксированный адрес внутри
|
||||||
|
этого слота. Резидентная часть собирается с `ORG #2000`; тело
|
||||||
|
распаковывается в адреса `#0000..body_end` той же страницы —
|
||||||
|
`body_end` обязан оставаться в пределах `#2002` (граница проверяется
|
||||||
|
на этапе сборки).
|
||||||
|
|
||||||
|
`LOAD512`/`SAVE512` используют прямой DMA между SD-картой и указанной
|
||||||
|
вызывающим физической страницей/смещением, не затрагивая пейджинг
|
||||||
|
CPU.
|
||||||
|
|
||||||
|
## Сборка
|
||||||
|
|
||||||
|
```
|
||||||
|
cd _sd
|
||||||
|
sjasmplus.exe zc_sd_driver_body.asm --sym=body_syms_new.txt
|
||||||
|
# упаковать zc_sd_driver_body.bin -> zc_sd_driver_body.pb (PackBits)
|
||||||
|
# обновить body_syms.inc из body_syms_new.txt (без DATA/CONF)
|
||||||
|
sjasmplus.exe zc_sd_driver.asm
|
||||||
|
```
|
||||||
|
|
||||||
|
Результат (`zc_sd_driver.bin`) копируется в `_spg/` и подключается
|
||||||
|
через `_spg/spgbld.ini` (`Block = #e000, #0f, zc_sd_driver.bin`).
|
||||||
@@ -0,0 +1,861 @@
|
|||||||
|
DEVICE ZXSPECTRUM48
|
||||||
|
|
||||||
|
; From-scratch open SD/FAT32 driver for ZiFi, replacing the closed
|
||||||
|
; WDFCVBI2.COD -- built and hardware-tested incrementally in
|
||||||
|
; D:\ST\sjasmplus\sdtest\sdtest.asm across this whole investigation
|
||||||
|
; (see [[project-zifi-custom-sd-driver]]), this file assembles the
|
||||||
|
; SAME proven code into the jump-table shape zifi.asm's CORE equ #2002
|
||||||
|
; expects.
|
||||||
|
;
|
||||||
|
; Table layout confirmed by cross-referencing WC's own KERNEL.ASM
|
||||||
|
; START table (E:\zx-evo-master\pentevo\soft\WC\source\core32\
|
||||||
|
; KERNEL.ASM) -- byte-for-byte matching offsets (DEV_INI=+3, HDD=+9,
|
||||||
|
; LOAD512=+21, SAVE512=+24, DOS_SWP=+27, MKFILE=+57, MKDIR=+60,
|
||||||
|
; DELFL=+63, RENAME=+66, FENTRY=+78, LOADNON=+84, NXTETY=+87) for the
|
||||||
|
; first 31 entries, PLUS three more (SETDIR=+93, SETROOT=+96, SEEK0=
|
||||||
|
; +99) that WC's own core32 table does NOT have -- WDFCVBI2.COD's own
|
||||||
|
; table is a superset/independent implementation, not a live reference
|
||||||
|
; into whatever WC happens to be installed (confirmed by the user
|
||||||
|
; directly: Wild-Commander-Improved, which has the LFN bug already
|
||||||
|
; fixed in ITS OWN core32, did NOT fix ZiFi's bug -- so ZiFi's driver
|
||||||
|
; is definitely self-contained, not calling into WC's shared kernel).
|
||||||
|
;
|
||||||
|
; Loaded via spgbld's Block directive at #E000/page matching the
|
||||||
|
; original WDFCVBI2.COD placement -- the exact mechanism by which that
|
||||||
|
; maps to the fixed #2002 jump-table address is still not 100% proven
|
||||||
|
; (see [[project-zifi-custom-sd-driver]] for the open question), but
|
||||||
|
; the original driver's own DOS_SWP/LOAD512-real-address evidence
|
||||||
|
; found earlier in this investigation, PLUS this file being structured
|
||||||
|
; identically (jump table at the very start of the loaded block),
|
||||||
|
; should reproduce whatever that mechanism is. THIS IS THE FIRST REAL
|
||||||
|
; HARDWARE TEST of that hypothesis -- expect to iterate.
|
||||||
|
;
|
||||||
|
; Entries zifi.asm never calls (grepped for every CORE+n EQU it
|
||||||
|
; actually uses) are safe no-op/stub implementations: RDD/SDD/GIPAG/
|
||||||
|
; GLSTCAT/TLSTCAT/SRHFCL/MKSG/RFRH/GENTRY/TENTRY/DLSG/CHTOSE/LOAD256/
|
||||||
|
; NXTETY2/REINI, and the three raw "Z0" slots WC's own table leaves
|
||||||
|
; unimplemented too. NXTETY (directory enumeration, a different job
|
||||||
|
; from FENTRY's single-name search) is ALSO a stub for now -- zifi.asm's
|
||||||
|
; only reference to it (VYGREB/VYG) is commented-out dead code
|
||||||
|
; ("Выгребаем каталог, чисто по приколу" -- "just for fun"), never
|
||||||
|
; actually called by the real running program.
|
||||||
|
|
||||||
|
; NOTE: this code is invoked via zifi.asm's init_sd_card (line ~4134),
|
||||||
|
; which does "ld a,sd_driver_page(#0f) / jp set_page0" -- i.e. maps
|
||||||
|
; page #0F into PAGE0 (CPU slot 0, addresses #0000-#3FFF), NOT slot 3.
|
||||||
|
; CORE=#2002 is a slot-0 address, so every internal absolute JP/CALL in
|
||||||
|
; this file must be assembled as if it lives at #2002, not #E000 --
|
||||||
|
; otherwise the driver hangs the instant it's entered (confirmed on
|
||||||
|
; hardware: first attempt used ORG #E000 and hung on the boot banner).
|
||||||
|
;
|
||||||
|
; spgbld's Block directive only accepts 512-byte-aligned addresses, and
|
||||||
|
; #2002 isn't one -- so we can't just tell it to load at offset #2002
|
||||||
|
; directly (Block = #e002 -> "Block address is not a 512 multiple!").
|
||||||
|
; Instead we load at the aligned #e000 (page-offset #2000, same as the
|
||||||
|
; original WDFCVBI2.COD placement) and pad 2 bytes here so the actual
|
||||||
|
; jump table lands exactly on #2002 once loaded. This is almost
|
||||||
|
; certainly what WDFCVBI2.COD's own "DOS_SWP; DEPACK Driver" call was
|
||||||
|
; really doing at runtime (relocating itself those same 2 bytes) --
|
||||||
|
; padding at assembly time is simpler and needs no runtime relocator.
|
||||||
|
ORG #2000
|
||||||
|
DS 2 ; pad offset #2000-#2001; jump table
|
||||||
|
; below starts at #2002 = CORE
|
||||||
|
|
||||||
|
CONF EQU #77
|
||||||
|
DATA EQU #57
|
||||||
|
|
||||||
|
; Body-routine addresses (sdinit, dma_set_addr, sdread_lba, parse_bpb,
|
||||||
|
; core_fentry, get_next_cluster, write_fat_entry, find_by_name,
|
||||||
|
; sdwrite_lba, cur_cluster_hi/lo, target_name, dot_name,
|
||||||
|
; clear_dir_entry, and everything else from zc_sd_driver_body.asm) --
|
||||||
|
; imported here as plain EQU constants (generated from that file's own
|
||||||
|
; --sym dump by build.ps1) so every JP/CALL/reference below resolves
|
||||||
|
; correctly even though the actual body code isn't present in this
|
||||||
|
; file -- it's compressed and depacked at runtime by drv_dos_swp
|
||||||
|
; instead. See the fuller comment further down and
|
||||||
|
; [[project-zifi-custom-sd-driver]].
|
||||||
|
INCLUDE "body_syms.inc"
|
||||||
|
|
||||||
|
;--- Build-time guard: the depacked body (ORG #0000..body_end, written
|
||||||
|
;--- by drv_dos_swp at runtime) MUST stay strictly under #2002 (CORE
|
||||||
|
;--- itself, this file's own resident jump table) -- otherwise depacking
|
||||||
|
;--- silently overwrites the START of THIS file's own resident code,
|
||||||
|
;--- every single time it runs. This isn't hypothetical: body growth
|
||||||
|
;--- crossed #2000 by 198 bytes in this exact project (body_end reached
|
||||||
|
;--- #20C6) and every CORE dispatch call (DEV_INI, HDD, FENTRY,
|
||||||
|
;--- everything) silently jumped to garbage as a result -- diagnosed
|
||||||
|
;--- the hard way via PEEKPHYS/checkpoint instrumentation after
|
||||||
|
;--- "zifi.ini not found" started happening. The threshold is #2002, not
|
||||||
|
;--- #2000: the 2 bytes at #2000-#2001 (see "DS 2" above) are pure
|
||||||
|
;--- alignment padding, never read by anything, so the depacked body may
|
||||||
|
;--- safely fill them too -- body_end==#2002 means the last byte written
|
||||||
|
;--- is at #2001, one below CORE. Never remove this check; if it fires,
|
||||||
|
;--- shrink zc_sd_driver_body.asm (or increase this IF condition's
|
||||||
|
;--- threshold together with confirming real headroom exists all the way
|
||||||
|
;--- to code_end below #4000) before doing anything else. See
|
||||||
|
;--- [[project-zifi-custom-sd-driver]]. ---
|
||||||
|
IF body_end > #2002
|
||||||
|
DEFB 1/0 ; BODY OVERLAPS RESIDENT CODE -- FIX THIS, see comment above
|
||||||
|
ENDIF
|
||||||
|
|
||||||
|
;=====================================================================
|
||||||
|
; Jump table -- 34 entries x 3 bytes (JP nnnn), offsets 0..99, must
|
||||||
|
; stay in this exact order/spacing to match every CORE+n EQU in
|
||||||
|
; zifi.asm.
|
||||||
|
;=====================================================================
|
||||||
|
JP drv_seldev ; +0
|
||||||
|
JP wrap_dev_init ; +3
|
||||||
|
JP drv_stub_ok ; +6 REINI
|
||||||
|
JP wrap_hdd ; +9
|
||||||
|
JP drv_stub_fail ; +12 RDD
|
||||||
|
JP drv_stub_fail ; +15 SDD
|
||||||
|
JP drv_stub_fail ; +18 GIPAG
|
||||||
|
JP wrap_load512 ; +21
|
||||||
|
JP wrap_save512 ; +24
|
||||||
|
JP wrap_dos_swp ; +27
|
||||||
|
JP drv_stub_fail ; +30 GLSTCAT
|
||||||
|
JP drv_stub_fail ; +33 TLSTCAT
|
||||||
|
JP drv_stub_fail ; +36 SRHFCL
|
||||||
|
JP drv_stub_fail ; +39 Z0
|
||||||
|
JP drv_stub_fail ; +42 MKSG
|
||||||
|
JP drv_stub_fail ; +45 Z0
|
||||||
|
JP drv_stub_fail ; +48 RFRH
|
||||||
|
JP drv_stub_fail ; +51 GENTRY
|
||||||
|
JP drv_stub_fail ; +54 TENTRY
|
||||||
|
JP wrap_mkfile ; +57
|
||||||
|
JP wrap_mkdir ; +60
|
||||||
|
JP wrap_delfl ; +63 DELFL
|
||||||
|
JP wrap_renam ; +66 RENAM
|
||||||
|
JP drv_stub_fail ; +69 DLSG
|
||||||
|
JP drv_stub_fail ; +72 CHTOSE
|
||||||
|
JP drv_stub_fail ; +75 Z0
|
||||||
|
JP wrap_fentry ; +78
|
||||||
|
JP drv_stub_fail ; +81 LOAD256
|
||||||
|
JP wrap_loadnon ; +84
|
||||||
|
JP drv_nxtety ; +87
|
||||||
|
JP drv_stub_fail ; +90 NXTETY2
|
||||||
|
JP wrap_setdir ; +93
|
||||||
|
JP wrap_setroot ; +96
|
||||||
|
JP wrap_seek0 ; +99
|
||||||
|
|
||||||
|
;=====================================================================
|
||||||
|
; di/ei wrappers around every entry point that does real work while
|
||||||
|
; executing from CPU slot 0 (this whole driver only exists there while
|
||||||
|
; PAGE0 points at page #0F -- see the ORG note above). Found on
|
||||||
|
; hardware: zifi.asm's own "off_int_dma"/save_mode flag (which init_sd_
|
||||||
|
; card/sd_exit toggle around SD operations) does NOT cover everything --
|
||||||
|
; int_main's pt_play (zifi.asm ~line 2350, gated by a SEPARATE "music_sw"
|
||||||
|
; flag, not save_mode) calls set_music_pages_lite EVERY interrupt
|
||||||
|
; whenever a track is playing, which repages PAGE0 *and* PAGE1 *and*
|
||||||
|
; PAGE3 for the music player's own use. If that fires while we're mid-
|
||||||
|
; CORE-call: PAGE0 changing while we're actively EXECUTING CODE FROM
|
||||||
|
; SLOT 0 crashes/jumps to garbage the instant the interrupt returns
|
||||||
|
; (next instruction fetch reads the wrong page); PAGE3 changing mid-
|
||||||
|
; LOAD512/SAVE512 silently swaps the transfer's source/dest to whatever
|
||||||
|
; the music player last pointed it at instead of the real caller data --
|
||||||
|
; confirmed on hardware as the cause of downloaded files playing back as
|
||||||
|
; a constant garbage pattern instead of the real track. Wrapping the
|
||||||
|
; real logic in a plain di/ei critical section (bodies below are
|
||||||
|
; UNCHANGED, just called instead of jumped to) closes both holes
|
||||||
|
; regardless of music_sw/save_mode state. The original hardware-tested
|
||||||
|
; function bodies keep their own names/all internal early-return paths
|
||||||
|
; exactly as they were -- only the outer entry/exit changed.
|
||||||
|
;=====================================================================
|
||||||
|
; Every wrap_* below preserves IX across the real call (push/pop around
|
||||||
|
; it) -- ZiFi.asm's own CORE-ABI convention relies on IX surviving a
|
||||||
|
; CORE call unmolested (save_downloaded_file sets "ld ix,read_threads"
|
||||||
|
; ONCE, then keeps using (ix+thread.n) addressing across MULTIPLE CORE
|
||||||
|
; calls, including AFTER MKFILE returns, with no re-load in between).
|
||||||
|
; filter_name_to_83 (zc_sd_driver_body.asm, used by core_mkfile/
|
||||||
|
; core_mkdir's short-name generation) uses IX internally as a plain
|
||||||
|
; scratch pointer (ld ix,sn_base / ld ix,sn_ext) and never restores it
|
||||||
|
; -- so a caller relying on IX surviving MKFILE was silently reading
|
||||||
|
; save_64's (ix+thread.page)/(ix+thread.adress) from wherever sn_base/
|
||||||
|
; sn_ext happened to leave IX pointing (this driver's own low, #0000-
|
||||||
|
; based body addresses, still mapped into slot 0 at that point) instead
|
||||||
|
; of zifi's real read_threads struct -- confirmed as the actual root
|
||||||
|
; cause of "every download saves as identical, page/track-independent
|
||||||
|
; garbage" (2026-09-09): read_threads.page/adress were correct the
|
||||||
|
; WHOLE time, SAVE512 was just told to read from the wrong place by a
|
||||||
|
; stale IX. See [[project-zifi-custom-sd-driver]]. ---
|
||||||
|
wrap_dev_init di
|
||||||
|
push ix
|
||||||
|
call drv_dev_init
|
||||||
|
pop ix
|
||||||
|
ei
|
||||||
|
ret
|
||||||
|
wrap_hdd di
|
||||||
|
push ix
|
||||||
|
call drv_hdd
|
||||||
|
pop ix
|
||||||
|
ei
|
||||||
|
ret
|
||||||
|
;--- NO di/ei needed here, matching what a real disassembly of the
|
||||||
|
;--- ORIGINAL closed WDFCVBI2.COD driver's own SAVE512/LOAD512 turned
|
||||||
|
;--- out to do (hand-verified: zero real DI/EI opcodes anywhere in its
|
||||||
|
;--- transfer routine at #22DB). That disassembly also showed WHY it
|
||||||
|
;--- didn't need any: its transfer uses the TS-Conf DMA controller, not
|
||||||
|
;--- a CPU-driven page1_port+LDIR loop. core_save512/core_load512 (in
|
||||||
|
;--- zc_sd_driver_body.asm) now do the same -- DMA straight between the
|
||||||
|
;--- SD card and the caller's page, addressed by physical page number,
|
||||||
|
;--- never touching the CPU's slot mapping at all. Two di/ei variants
|
||||||
|
;--- around the OLD LDIR-based version were tried first and both made
|
||||||
|
;--- things WORSE on real hardware (di/ei around the whole transfer:
|
||||||
|
;--- audio noise + hangs on track switch; di/ei only around the brief
|
||||||
|
;--- PAGE1-touch+LDIR: full hangs with garbage on screen) -- di/ei
|
||||||
|
;--- was never going to fix it, since the LDIR's dependence on PAGE1
|
||||||
|
;--- staying stable across the whole copy was the real hazard, not a
|
||||||
|
;--- timing race di/ei could close (a write-only page port can't be
|
||||||
|
;--- restored after set_music_pages_lite clobbers it mid-transfer,
|
||||||
|
;--- di/ei or not). See [[project-zifi-custom-sd-driver]]. ---
|
||||||
|
wrap_load512 push ix
|
||||||
|
call core_load512
|
||||||
|
pop ix
|
||||||
|
ret
|
||||||
|
wrap_save512 push ix
|
||||||
|
call core_save512
|
||||||
|
pop ix
|
||||||
|
ret
|
||||||
|
wrap_mkfile di
|
||||||
|
push ix
|
||||||
|
call core_mkfile
|
||||||
|
pop ix
|
||||||
|
ei
|
||||||
|
ret
|
||||||
|
wrap_mkdir di
|
||||||
|
push ix
|
||||||
|
call core_mkdir
|
||||||
|
pop ix
|
||||||
|
ei
|
||||||
|
ret
|
||||||
|
wrap_fentry di
|
||||||
|
push ix
|
||||||
|
call drv_fentry
|
||||||
|
pop ix
|
||||||
|
ei
|
||||||
|
ret
|
||||||
|
wrap_loadnon di
|
||||||
|
push ix
|
||||||
|
call drv_loadnon
|
||||||
|
pop ix
|
||||||
|
ei
|
||||||
|
ret
|
||||||
|
wrap_setdir di
|
||||||
|
push ix
|
||||||
|
call core_setdir
|
||||||
|
pop ix
|
||||||
|
ei
|
||||||
|
ret
|
||||||
|
wrap_setroot di
|
||||||
|
push ix
|
||||||
|
call core_setroot
|
||||||
|
pop ix
|
||||||
|
ei
|
||||||
|
ret
|
||||||
|
wrap_seek0 di
|
||||||
|
push ix
|
||||||
|
call stream_open
|
||||||
|
pop ix
|
||||||
|
ei
|
||||||
|
ret
|
||||||
|
wrap_delfl di
|
||||||
|
push ix
|
||||||
|
call core_delfl
|
||||||
|
pop ix
|
||||||
|
ei
|
||||||
|
ret
|
||||||
|
wrap_renam di
|
||||||
|
push ix
|
||||||
|
call core_renam
|
||||||
|
pop ix
|
||||||
|
ei
|
||||||
|
ret
|
||||||
|
; DOS_SWP now does real work (depacking the body -- see drv_dos_swp
|
||||||
|
; below), unlike every other entry here it previously had NO di/ei
|
||||||
|
; protection at all (harmless when it was a no-op). Real interrupts
|
||||||
|
; MUST stay off for the whole unpack: page #0F is mapped into slot 0
|
||||||
|
; the entire time, and zifi.asm's pt_play interrupt handler repages
|
||||||
|
; PAGE0/1/3 for the music player if it fires mid-CORE-call (see the
|
||||||
|
; header comment above) -- exactly the same risk this wrapping already
|
||||||
|
; protects every other substantive entry against.
|
||||||
|
; No `ei` here (unlike every other wrap_*): DOS_SWP is ALWAYS
|
||||||
|
; immediately followed by another di-guarded CORE call in zifi.asm's
|
||||||
|
; own fixed sequence (sd_init: CALL DOS_SWP; CALL DEV_INI; ...) -- so
|
||||||
|
; re-enabling interrupts here just to have the very next call disable
|
||||||
|
; them again is pointless, and genuinely risky while depacking: an
|
||||||
|
; interrupt landing in the gap would fire with PAGE0 still pointing at
|
||||||
|
; page #0F, jumping to #0038 (IM1 vector) which -- mid-depack -- can
|
||||||
|
; be anything from still-compressed garbage to not-yet-written body
|
||||||
|
; code, not a real ROM/interrupt handler. Confirmed by direct testing:
|
||||||
|
; this exact gap crashed a standalone depack test (wild PC, eventual
|
||||||
|
; HALT) until `ei` was removed here.
|
||||||
|
wrap_dos_swp di
|
||||||
|
call drv_dos_swp
|
||||||
|
ret
|
||||||
|
|
||||||
|
;--- drv_stub_ok / drv_stub_fail: safe stubs for every CORE-table slot
|
||||||
|
;--- zifi.asm never actually calls (confirmed via its own CORE+n EQU
|
||||||
|
;--- list) -- Z (success-shaped) or NZ (not-found/error-shaped)
|
||||||
|
;--- respectively, whichever is the safer default for a function
|
||||||
|
;--- nothing should ever invoke. ---
|
||||||
|
drv_stub_ok xor a
|
||||||
|
ret
|
||||||
|
drv_stub_fail xor a
|
||||||
|
inc a
|
||||||
|
ret
|
||||||
|
|
||||||
|
drv_seldev xor a
|
||||||
|
ret
|
||||||
|
|
||||||
|
;--- drv_dev_init: CORE+3, DEV_INI -- raw SD card init only (matches
|
||||||
|
;--- zifi.asm's own "CALL DEV_INI:JP NZ,ER0" -- HDD/partition search is
|
||||||
|
;--- a separate, later call). Z=ok, NZ=fail. ---
|
||||||
|
drv_dev_init call sdinit
|
||||||
|
ret
|
||||||
|
|
||||||
|
;--- drv_hdd: CORE+9, HDD ("SEARCH PARTITION" per WC's own naming) --
|
||||||
|
;--- reads sector 0, detects/validates the partition (detect_partition
|
||||||
|
;--- already does its own verify_fat32 check internally, falling back
|
||||||
|
;--- to sector 0 itself if no MBR partition table is present), then
|
||||||
|
;--- parses the real BPB. Z=ok, NZ=fail. ---
|
||||||
|
drv_hdd ld hl,0
|
||||||
|
ld de,0
|
||||||
|
call set_lba32
|
||||||
|
call sdread_lba
|
||||||
|
ret nz
|
||||||
|
|
||||||
|
call detect_partition
|
||||||
|
ret nz
|
||||||
|
|
||||||
|
call parse_bpb
|
||||||
|
|
||||||
|
; Pre-warm the RTC read HERE, during sd_init's quiet pre-EI
|
||||||
|
; window (zifi.asm calls sd_init at line ~56, then "ei" at
|
||||||
|
; line 57 -- HDD runs before interrupts are even on and
|
||||||
|
; before any active UI/video updates). rtc_to_fat_datetime's
|
||||||
|
; own caching means every LATER call (from core_mkdir/
|
||||||
|
; core_mkfile during the active WiFi-connect/download phase)
|
||||||
|
; just reuses this result instead of touching the RTC chip
|
||||||
|
; again. This matters because [[project-zifi-rtc-time-sync]]
|
||||||
|
; already found -- the hard way, on this exact board -- that
|
||||||
|
; touching #EFF7 (which this RTC read also does, to select
|
||||||
|
; the CMOS/RTC register space) during an active UI phase can
|
||||||
|
; cause real corruption even with correct di/ei and a proper
|
||||||
|
; read-modify-write, for reasons never fully root-caused;
|
||||||
|
; the only fix that actually worked there was moving WHEN
|
||||||
|
; the touch happens, not how. Doing it here avoids the same
|
||||||
|
; class of risk instead of re-discovering it the hard way.
|
||||||
|
call rtc_to_fat_datetime
|
||||||
|
|
||||||
|
xor a
|
||||||
|
ret
|
||||||
|
|
||||||
|
;--- drv_dos_swp: CORE+27, DOS_SWP ("SELDEVnDRIVERinit" / "DEPACK
|
||||||
|
;--- Driver" per WC's/zifi's own naming) -- the original closed driver
|
||||||
|
;--- was compressed and self-relocated here; this driver now does the
|
||||||
|
;--- same thing for real, not just in spirit: the "body" (everything
|
||||||
|
;--- from sdinit onward -- DMA/SD/FAT32/CORE-ABI logic, built and
|
||||||
|
;--- hardware-tested as zc_sd_driver_body.asm) is compressed and stored
|
||||||
|
;--- as body_packed_start..body_packed_end below. Decompressing it to
|
||||||
|
;--- its true addresses (#0000-body_end, see body_syms.inc) is what
|
||||||
|
;--- makes those addresses (and every JP/CALL into them from this
|
||||||
|
;--- resident half, including the jump table indirectly via wrap_hdd
|
||||||
|
;--- etc, and DELFL/RENAM below) valid -- this MUST run before any
|
||||||
|
;--- other CORE entry point does real work, matching zifi.asm's own
|
||||||
|
;--- fixed call order (sd_init: CALL DOS_SWP; DEPACK Driver -- always
|
||||||
|
;--- immediately after paging page #0F into slot 0, always before
|
||||||
|
;--- DEV_INI/HDD/etc).
|
||||||
|
;---
|
||||||
|
;--- Hrust1, not ZX0: ZX0 (both the "standard" forward AND backward
|
||||||
|
;--- Z80 decoders, dzx0_standard(_back).asm by Einar Saukas) was tried
|
||||||
|
;--- first and, after extensive isolated Z80-harness testing (see
|
||||||
|
;--- [[project-zifi-custom-sd-driver]]), both directions turned out to
|
||||||
|
;--- decompress small/simple payloads (even ones with real
|
||||||
|
;--- back-references) correctly but produce garbage specifically on
|
||||||
|
;--- this driver's full 8027-byte body -- root cause never found
|
||||||
|
;--- despite real effort, abandoned as too large a time sink for an
|
||||||
|
;--- optional space optimization.
|
||||||
|
;---
|
||||||
|
;--- Chased a real, never-root-caused bug here for a long time: every
|
||||||
|
;--- attempt to fix load_ini's address-0 collision FROM THIS SIDE
|
||||||
|
;--- (padding the body with a sacrifice_buf, later an ORG shift to
|
||||||
|
;--- #0200 with zero added bytes) reliably broke BOTH Z80 Hrust
|
||||||
|
;--- decoders tried (hand-transcribed classic dehst.asm DEHRUST,
|
||||||
|
;--- confirmed byte-for-byte correct against source via automated
|
||||||
|
;--- diff; and hrust13.exe's own "-depacker" self-relocating output)
|
||||||
|
;--- the instant core_load512's fix (in zc_sd_driver_body.asm) grew
|
||||||
|
;--- the body by its own ~53 bytes, regardless of padding/positioning
|
||||||
|
;--- -- see [[project-zifi-custom-sd-driver]] for the full history.
|
||||||
|
;--- Root cause in either decoder never found under real time
|
||||||
|
;--- pressure. Fixed properly instead: zifi.asm's load_ini/parse_ini
|
||||||
|
;--- now use LOAD512's SAME slot-1/#4000/PAGE1 convention as SAVE512
|
||||||
|
;--- (see core_load512's own comment in zc_sd_driver_body.asm), so
|
||||||
|
;--- load_ini never touches address 0 at all anymore.
|
||||||
|
;---
|
||||||
|
;--- Hrust1 fully abandoned at this point (both the classic hand-
|
||||||
|
;--- transcribed dehst.asm DEHRUST -- confirmed byte-for-byte correct
|
||||||
|
;--- against source via automated diff, TWICE -- and hrust13.exe's own
|
||||||
|
;--- "-depacker" output kept producing wrong Z80 decompression results
|
||||||
|
;--- on data that a PC-side reference tool, dehrust1.exe, decoded
|
||||||
|
;--- correctly every single time, on EVERY size/content tried,
|
||||||
|
;--- including this exact 8018-byte body with no changes at all except
|
||||||
|
;--- core_load512's own content -- so dehrust1.exe was never actually
|
||||||
|
;--- validating what was assumed; root cause never found under real
|
||||||
|
;--- time pressure -- see [[project-zifi-custom-sd-driver]]).
|
||||||
|
;---
|
||||||
|
;--- Replaced with a trivial, self-written, fully-verified PackBits-
|
||||||
|
;--- style RLE (round-tripped byte-for-byte on the PC first, in
|
||||||
|
;--- PowerShell, before ever touching Z80 code): control byte C,
|
||||||
|
;--- C=128 is the end marker; C<128 is a literal run of C+1 bytes
|
||||||
|
;--- (copied verbatim); C>128 is a repeat run of (257-C) copies of the
|
||||||
|
;--- single byte that follows (257-C covers 2..128 for C=255..129; C=1
|
||||||
|
;--- unused/invalid, C=128 reserved as the terminator instead of a
|
||||||
|
;--- literal-run-of-1 encoding). Only ~12.5% compression is actually
|
||||||
|
;--- needed here (8018-byte body must fit under ~7076 bytes to leave
|
||||||
|
;--- room for the #2000-#3FFF dispatcher) -- this achieves 5929 bytes
|
||||||
|
;--- (~74%), comfortable margin, on real driver code (long runs of
|
||||||
|
;--- identical bytes are common in data tables/padding). ---
|
||||||
|
drv_dos_swp ld ix,body_packed_start
|
||||||
|
ld de,0
|
||||||
|
call PB_DECODE
|
||||||
|
xor a
|
||||||
|
ret
|
||||||
|
|
||||||
|
;=====================================================================
|
||||||
|
; PB_DECODE: PackBits-style RLE decoder (see drv_dos_swp's comment for
|
||||||
|
; the format). IX=source, DE=dest. Doesn't touch SP.
|
||||||
|
;=====================================================================
|
||||||
|
PB_DECODE
|
||||||
|
PB_LOOP ld a,(ix+0)
|
||||||
|
inc ix
|
||||||
|
cp 128
|
||||||
|
ret z ; terminator
|
||||||
|
bit 7,a
|
||||||
|
jr z,PB_LITERAL
|
||||||
|
|
||||||
|
neg ; a = 256-ctrl (ctrl in 129..255)
|
||||||
|
inc a ; a = 257-ctrl (mod 256) = repeat count (2..128)
|
||||||
|
ld b,a
|
||||||
|
ld a,(ix+0)
|
||||||
|
inc ix
|
||||||
|
PB_REP_LOOP ld (de),a
|
||||||
|
inc de
|
||||||
|
djnz PB_REP_LOOP
|
||||||
|
jr PB_LOOP
|
||||||
|
|
||||||
|
PB_LITERAL inc a ; a = ctrl+1 = literal count (1..128)
|
||||||
|
ld b,a
|
||||||
|
PB_LIT_LOOP ld a,(ix+0)
|
||||||
|
inc ix
|
||||||
|
ld (de),a
|
||||||
|
inc de
|
||||||
|
djnz PB_LIT_LOOP
|
||||||
|
jr PB_LOOP
|
||||||
|
|
||||||
|
;--- drv_fentry: CORE+78, FENTRY -- real ABI is HL -> {flag(1),
|
||||||
|
;--- name(1-255),0} (flag = file-vs-dir attribute filter, not yet
|
||||||
|
;--- implemented -- see [[project-zifi-custom-sd-driver]] Next steps).
|
||||||
|
;--- On a match, automatically opens a stream on the found entry's
|
||||||
|
;--- cluster (matching the real ABI's own doc: "SEEK0 is automatically
|
||||||
|
;--- called") so a caller can go straight into LOAD512/SAVE512/LOADNON
|
||||||
|
;--- without any extra setup, exactly like zifi.asm's own real call
|
||||||
|
;--- sites do (FENTRY then LOAD512, nothing in between). Z=NOT FOUND,
|
||||||
|
;--- NZ=FOUND + [DE,HL]=length. ---
|
||||||
|
drv_fentry inc hl ; skip the flag byte (filter not
|
||||||
|
; implemented yet -- matches by name
|
||||||
|
; only)
|
||||||
|
call core_fentry
|
||||||
|
or a
|
||||||
|
ret z ; not found
|
||||||
|
|
||||||
|
ld hl,(fbn_cluster_hi)
|
||||||
|
ld (cur_cluster_hi),hl
|
||||||
|
ld hl,(fbn_cluster_lo)
|
||||||
|
ld (cur_cluster_lo),hl
|
||||||
|
call stream_open
|
||||||
|
|
||||||
|
ld de,(fbn_size_hi)
|
||||||
|
ld hl,(fbn_size_lo)
|
||||||
|
ld a,1
|
||||||
|
or a ; NZ (A=1, nonzero) -- found
|
||||||
|
ret
|
||||||
|
|
||||||
|
;--- drv_loadnon: CORE+84, LOADNON -- advances the CURRENTLY OPEN
|
||||||
|
;--- stream (opened by the last drv_fentry match) by B sectors without
|
||||||
|
;--- reading/writing data. Real ABI doesn't document a return value
|
||||||
|
;--- beyond implicit success. ---
|
||||||
|
drv_loadnon ld a,b
|
||||||
|
or a
|
||||||
|
ret z
|
||||||
|
dln_loop push bc
|
||||||
|
call strm_advance
|
||||||
|
pop bc
|
||||||
|
djnz dln_loop
|
||||||
|
xor a
|
||||||
|
ret
|
||||||
|
|
||||||
|
;--- drv_nxtety: CORE+87, NXTETY -- real ABI is a directory-listing
|
||||||
|
;--- iterator (GetNextEntryFromActiveDir), a genuinely different job
|
||||||
|
;--- from FENTRY's single-name search -- NOT YET BUILT. Stubbed as
|
||||||
|
;--- "always EndOfDir" (Z) since zifi.asm's only reference to it
|
||||||
|
;--- (VYGREB/VYG) is commented-out dead code, never actually called by
|
||||||
|
;--- the real running program -- revisit if that changes. ---
|
||||||
|
drv_nxtety xor a
|
||||||
|
ret
|
||||||
|
|
||||||
|
; CORE+99, SEEK0 (per FENTRY's own doc, "SEEK0 is automatically
|
||||||
|
; called" by FENTRY -- nothing in zifi.asm calls this directly) is
|
||||||
|
; wired straight to stream_open via wrap_seek0 in the jump-table
|
||||||
|
; wrapper block above -- no separate drv_seek0 needed.
|
||||||
|
|
||||||
|
;=====================================================================
|
||||||
|
; Everything that used to live inline below this point (ported,
|
||||||
|
; hardware-tested code from D:\ST\sjasmplus\sdtest\sdtest.asm -- DMA/
|
||||||
|
; SD/FAT32/CORE-ABI logic) now lives in zc_sd_driver_body.asm instead,
|
||||||
|
; compiled to its own true addresses (#0000 upward), compressed with
|
||||||
|
; ZX0 and depacked here at runtime by drv_dos_swp (see above) -- this
|
||||||
|
; is what freed enough room in this #2000-#3FFF half for DELFL/RENAM
|
||||||
|
; to fit alongside everything already here. body_syms.inc (included
|
||||||
|
; near the top of this file) supplies every body label as a plain EQU
|
||||||
|
; constant. See [[project-zifi-custom-sd-driver]].
|
||||||
|
;=====================================================================
|
||||||
|
|
||||||
|
;=====================================================================
|
||||||
|
; CORE ABI: DELFL/RENAM -- never actually called by zifi.asm (grepped
|
||||||
|
; the whole file for CALL DELFL/CALL RENAM, zero hits), but built
|
||||||
|
; anyway per explicit user request ("для полноты драйвера"). Both need
|
||||||
|
; to know exactly which directory entries to mark deleted (0xE5) --
|
||||||
|
; the short entry AND any preceding LFN run -- so find_by_name now
|
||||||
|
; tracks fbn_match_index_lo/fbn_match_run_start_lo (see above) for
|
||||||
|
; this purpose.
|
||||||
|
;=====================================================================
|
||||||
|
|
||||||
|
;--- core_free_chain: (cur_cluster_hi,cur_cluster_lo) -> frees every
|
||||||
|
;--- cluster in this FAT chain (FAT entry := 0, mirrored to all copies
|
||||||
|
;--- via write_fat_entry) by following get_next_cluster until chain_
|
||||||
|
;--- ended. A=0 ok, A=1 fail (disk error -- chain may be partially
|
||||||
|
;--- freed). ---
|
||||||
|
cfc_cur_hi dw 0
|
||||||
|
cfc_cur_lo dw 0
|
||||||
|
cfc_next_hi dw 0
|
||||||
|
cfc_next_lo dw 0
|
||||||
|
cfc_has_next db 0
|
||||||
|
|
||||||
|
core_free_chain
|
||||||
|
ld hl,(cur_cluster_hi)
|
||||||
|
ld (cfc_cur_hi),hl
|
||||||
|
ld hl,(cur_cluster_lo)
|
||||||
|
ld (cfc_cur_lo),hl
|
||||||
|
|
||||||
|
cfc_loop ld hl,(cfc_cur_hi)
|
||||||
|
ld (cur_cluster_hi),hl
|
||||||
|
ld hl,(cfc_cur_lo)
|
||||||
|
ld (cur_cluster_lo),hl
|
||||||
|
call get_next_cluster
|
||||||
|
ld a,(chain_ended)
|
||||||
|
or a
|
||||||
|
jr nz,cfc_nonext
|
||||||
|
ld hl,(cur_cluster_hi)
|
||||||
|
ld (cfc_next_hi),hl
|
||||||
|
ld hl,(cur_cluster_lo)
|
||||||
|
ld (cfc_next_lo),hl
|
||||||
|
ld a,1
|
||||||
|
ld (cfc_has_next),a
|
||||||
|
jr cfc_free_this
|
||||||
|
cfc_nonext xor a
|
||||||
|
ld (cfc_has_next),a
|
||||||
|
|
||||||
|
cfc_free_this ld hl,(cfc_cur_hi)
|
||||||
|
ld (cur_cluster_hi),hl
|
||||||
|
ld hl,(cfc_cur_lo)
|
||||||
|
ld (cur_cluster_lo),hl
|
||||||
|
ld hl,0
|
||||||
|
ld (new_val_hi),hl
|
||||||
|
ld (new_val_lo),hl
|
||||||
|
call write_fat_entry
|
||||||
|
or a
|
||||||
|
jr nz,cfc_fail
|
||||||
|
|
||||||
|
ld a,(cfc_has_next)
|
||||||
|
or a
|
||||||
|
jr z,cfc_done
|
||||||
|
ld hl,(cfc_next_hi)
|
||||||
|
ld (cfc_cur_hi),hl
|
||||||
|
ld hl,(cfc_next_lo)
|
||||||
|
ld (cfc_cur_lo),hl
|
||||||
|
jr cfc_loop
|
||||||
|
|
||||||
|
cfc_done xor a
|
||||||
|
ret
|
||||||
|
cfc_fail xor a
|
||||||
|
inc a
|
||||||
|
ret
|
||||||
|
|
||||||
|
;--- core_mark_deleted_range: (cur_cluster_hi,cur_cluster_lo already
|
||||||
|
;--- set by caller to the directory) + cmdr_start_lo/cmdr_end_lo
|
||||||
|
;--- (logical 32-byte-entry-index range, inclusive) -> marks each
|
||||||
|
;--- entry's first byte 0xE5 (deleted). A=0 ok, A=1 fail (disk error). ---
|
||||||
|
cmdr_start_lo dw 0
|
||||||
|
cmdr_end_lo dw 0
|
||||||
|
cmdr_cur_index_lo dw 0
|
||||||
|
cmdr_entptr dw 0
|
||||||
|
cmdr_dirty db 0
|
||||||
|
cmdr_this_sec_hi dw 0
|
||||||
|
cmdr_this_sec_lo dw 0
|
||||||
|
|
||||||
|
core_mark_deleted_range
|
||||||
|
call stream_open
|
||||||
|
ld hl,0
|
||||||
|
ld (cmdr_cur_index_lo),hl
|
||||||
|
|
||||||
|
cmdr_sector_loop
|
||||||
|
ld a,(stream_eoc)
|
||||||
|
or a
|
||||||
|
jp nz,cmdr_done
|
||||||
|
|
||||||
|
call strm_calc_sector
|
||||||
|
ld hl,(strm_sector_hi)
|
||||||
|
ld (cmdr_this_sec_hi),hl
|
||||||
|
ld hl,(strm_sector_lo)
|
||||||
|
ld (cmdr_this_sec_lo),hl
|
||||||
|
ld hl,(strm_sector_hi)
|
||||||
|
ld de,(strm_sector_lo)
|
||||||
|
call set_lba32
|
||||||
|
call sdread_lba
|
||||||
|
or a
|
||||||
|
jr nz,cmdr_fail
|
||||||
|
|
||||||
|
xor a
|
||||||
|
ld (cmdr_dirty),a
|
||||||
|
ld hl,sdbuf
|
||||||
|
ld (cmdr_entptr),hl
|
||||||
|
ld b,16
|
||||||
|
|
||||||
|
cmdr_entloop ld hl,(cmdr_cur_index_lo)
|
||||||
|
ld de,(cmdr_start_lo)
|
||||||
|
or a
|
||||||
|
sbc hl,de
|
||||||
|
jr c,cmdr_notinrange
|
||||||
|
|
||||||
|
ld hl,(cmdr_cur_index_lo)
|
||||||
|
ld de,(cmdr_end_lo)
|
||||||
|
or a
|
||||||
|
sbc hl,de
|
||||||
|
jr c,cmdr_inrange
|
||||||
|
jr nz,cmdr_notinrange
|
||||||
|
|
||||||
|
cmdr_inrange ld hl,(cmdr_entptr)
|
||||||
|
ld (hl),#e5
|
||||||
|
ld a,1
|
||||||
|
ld (cmdr_dirty),a
|
||||||
|
|
||||||
|
cmdr_notinrange
|
||||||
|
ld hl,(cmdr_cur_index_lo)
|
||||||
|
inc hl
|
||||||
|
ld (cmdr_cur_index_lo),hl
|
||||||
|
ld hl,(cmdr_entptr)
|
||||||
|
ld de,32
|
||||||
|
add hl,de
|
||||||
|
ld (cmdr_entptr),hl
|
||||||
|
djnz cmdr_entloop
|
||||||
|
|
||||||
|
ld a,(cmdr_dirty)
|
||||||
|
or a
|
||||||
|
jr z,cmdr_skip_write
|
||||||
|
ld hl,(cmdr_this_sec_hi)
|
||||||
|
ld de,(cmdr_this_sec_lo)
|
||||||
|
call set_lba32
|
||||||
|
call sdwrite_lba
|
||||||
|
or a
|
||||||
|
jr nz,cmdr_fail
|
||||||
|
cmdr_skip_write
|
||||||
|
|
||||||
|
ld hl,(cmdr_cur_index_lo)
|
||||||
|
ld de,(cmdr_end_lo)
|
||||||
|
or a
|
||||||
|
sbc hl,de
|
||||||
|
jr c,cmdr_continue
|
||||||
|
jr nz,cmdr_done
|
||||||
|
|
||||||
|
cmdr_continue call strm_advance
|
||||||
|
jp cmdr_sector_loop
|
||||||
|
|
||||||
|
cmdr_done xor a
|
||||||
|
ret
|
||||||
|
cmdr_fail xor a
|
||||||
|
inc a
|
||||||
|
ret
|
||||||
|
|
||||||
|
;--- core_delfl: HL -> {flag(1),name(1-255),0} -> finds the entry (via
|
||||||
|
;--- find_by_name in the active directory), frees its FAT chain, and
|
||||||
|
;--- marks its short entry + any preceding LFN run deleted. Z=NOT
|
||||||
|
;--- FOUND, NZ=FILE DELETED -- matches real DELFL's documented ABI
|
||||||
|
;--- (note the inverted sense vs MKDIR/MKFILE's Z=success). ---
|
||||||
|
|
||||||
|
core_delfl inc hl ; skip flag byte
|
||||||
|
ld (cmk_name_ptr),hl
|
||||||
|
|
||||||
|
ld hl,(active_dir_hi)
|
||||||
|
ld (cur_cluster_hi),hl
|
||||||
|
ld hl,(active_dir_lo)
|
||||||
|
ld (cur_cluster_lo),hl
|
||||||
|
ld hl,(cmk_name_ptr)
|
||||||
|
call find_by_name
|
||||||
|
or a
|
||||||
|
ret z ; not found -- Z, matches real DELFL
|
||||||
|
|
||||||
|
ld hl,(fbn_cluster_hi)
|
||||||
|
ld (cur_cluster_hi),hl
|
||||||
|
ld hl,(fbn_cluster_lo)
|
||||||
|
ld (cur_cluster_lo),hl
|
||||||
|
call core_free_chain
|
||||||
|
|
||||||
|
ld hl,(fbn_match_run_start_lo)
|
||||||
|
ld (cmdr_start_lo),hl
|
||||||
|
ld hl,(fbn_match_index_lo)
|
||||||
|
ld (cmdr_end_lo),hl
|
||||||
|
ld hl,(active_dir_hi)
|
||||||
|
ld (cur_cluster_hi),hl
|
||||||
|
ld hl,(active_dir_lo)
|
||||||
|
ld (cur_cluster_lo),hl
|
||||||
|
call core_mark_deleted_range
|
||||||
|
|
||||||
|
xor a
|
||||||
|
inc a ; NZ -- FILE DELETED
|
||||||
|
ret
|
||||||
|
|
||||||
|
;--- core_renam: HL -> {flag(1),oldname(1-255),0}, DE -> {newname
|
||||||
|
;--- (1-255),0} -> renames an entry in the active directory, preserving
|
||||||
|
;--- its cluster/size/attr (re-stamps date/time fresh). Z=NOT FOUND,
|
||||||
|
;--- NZ=SUCCESS -- matches real RENAM's documented ABI. Not
|
||||||
|
;--- transactional: the old entry is marked deleted before the new one
|
||||||
|
;--- is written, matching this driver's existing failure-mode
|
||||||
|
;--- conventions elsewhere (no rollback attempted) -- the real ABI has
|
||||||
|
;--- no code for "found but couldn't rename" to report anyway. ---
|
||||||
|
crn_newname_ptr dw 0
|
||||||
|
crn_old_attr db 0
|
||||||
|
crn_old_size_hi dw 0
|
||||||
|
crn_old_size_lo dw 0
|
||||||
|
crn_old_run_start_lo dw 0
|
||||||
|
crn_old_match_index_lo dw 0
|
||||||
|
|
||||||
|
core_renam inc hl ; skip flag byte -- oldname starts here
|
||||||
|
ld (cmk_name_ptr),hl
|
||||||
|
ld (crn_newname_ptr),de
|
||||||
|
|
||||||
|
ld hl,(active_dir_hi)
|
||||||
|
ld (cur_cluster_hi),hl
|
||||||
|
ld hl,(active_dir_lo)
|
||||||
|
ld (cur_cluster_lo),hl
|
||||||
|
ld hl,(cmk_name_ptr)
|
||||||
|
call find_by_name
|
||||||
|
or a
|
||||||
|
ret z ; not found -- Z, matches real RENAM
|
||||||
|
|
||||||
|
ld hl,(fbn_cluster_hi)
|
||||||
|
ld (cmk_cluster_hi),hl
|
||||||
|
ld hl,(fbn_cluster_lo)
|
||||||
|
ld (cmk_cluster_lo),hl
|
||||||
|
ld a,(fbn_attr)
|
||||||
|
ld (crn_old_attr),a
|
||||||
|
ld hl,(fbn_size_hi)
|
||||||
|
ld (crn_old_size_hi),hl
|
||||||
|
ld hl,(fbn_size_lo)
|
||||||
|
ld (crn_old_size_lo),hl
|
||||||
|
ld hl,(fbn_match_run_start_lo)
|
||||||
|
ld (crn_old_run_start_lo),hl
|
||||||
|
ld hl,(fbn_match_index_lo)
|
||||||
|
ld (crn_old_match_index_lo),hl
|
||||||
|
|
||||||
|
; refuse if the NEW name already exists -- generate_unique_
|
||||||
|
; shortname only avoids SHORT-name collisions, so without this
|
||||||
|
; explicit check RENAM could create a SECOND entry displaying
|
||||||
|
; the same long name as an existing one (confirmed on hardware:
|
||||||
|
; renaming into an already-used name did exactly that -- same
|
||||||
|
; bug class as core_mkdir/core_mkfile's own duplicate-guard,
|
||||||
|
; just missed here originally). Checked BEFORE touching the
|
||||||
|
; old entry at all, so a refusal here leaves everything as-is.
|
||||||
|
ld hl,(active_dir_hi)
|
||||||
|
ld (cur_cluster_hi),hl
|
||||||
|
ld hl,(active_dir_lo)
|
||||||
|
ld (cur_cluster_lo),hl
|
||||||
|
ld hl,(crn_newname_ptr)
|
||||||
|
call find_by_name
|
||||||
|
or a
|
||||||
|
ret nz ; new name already exists -- refuse
|
||||||
|
; (Z, matching RENAM's two-outcome ABI)
|
||||||
|
|
||||||
|
ld hl,(crn_old_run_start_lo)
|
||||||
|
ld (cmdr_start_lo),hl
|
||||||
|
ld hl,(crn_old_match_index_lo)
|
||||||
|
ld (cmdr_end_lo),hl
|
||||||
|
ld hl,(active_dir_hi)
|
||||||
|
ld (cur_cluster_hi),hl
|
||||||
|
ld hl,(active_dir_lo)
|
||||||
|
ld (cur_cluster_lo),hl
|
||||||
|
call core_mark_deleted_range
|
||||||
|
|
||||||
|
call rtc_to_fat_datetime
|
||||||
|
call clear_dir_entry
|
||||||
|
call stamp_dir_entry_datetime
|
||||||
|
ld a,(crn_old_attr)
|
||||||
|
ld (dir_entry_buf+11),a
|
||||||
|
ld hl,(cmk_cluster_hi)
|
||||||
|
ld (dir_entry_buf+20),hl
|
||||||
|
ld hl,(cmk_cluster_lo)
|
||||||
|
ld (dir_entry_buf+26),hl
|
||||||
|
ld hl,(crn_old_size_lo)
|
||||||
|
ld (dir_entry_buf+28),hl
|
||||||
|
ld hl,(crn_old_size_hi)
|
||||||
|
ld (dir_entry_buf+30),hl
|
||||||
|
|
||||||
|
ld hl,(active_dir_hi)
|
||||||
|
ld (cur_cluster_hi),hl
|
||||||
|
ld hl,(active_dir_lo)
|
||||||
|
ld (cur_cluster_lo),hl
|
||||||
|
ld hl,(crn_newname_ptr)
|
||||||
|
call filter_name_to_83
|
||||||
|
call generate_unique_shortname
|
||||||
|
or a
|
||||||
|
jr nz,crn_done ; degenerate failure -- old entry
|
||||||
|
; already deleted, nothing sane left
|
||||||
|
; to roll back to; ABI has no code
|
||||||
|
; for this anyway (see header comment)
|
||||||
|
|
||||||
|
ld hl,(crn_newname_ptr)
|
||||||
|
call build_lfn_entries
|
||||||
|
|
||||||
|
ld hl,(active_dir_hi)
|
||||||
|
ld (cur_cluster_hi),hl
|
||||||
|
ld hl,(active_dir_lo)
|
||||||
|
ld (cur_cluster_lo),hl
|
||||||
|
call find_free_run
|
||||||
|
or a
|
||||||
|
jr nz,crn_done
|
||||||
|
|
||||||
|
ld hl,(active_dir_hi)
|
||||||
|
ld (cur_cluster_hi),hl
|
||||||
|
ld hl,(active_dir_lo)
|
||||||
|
ld (cur_cluster_lo),hl
|
||||||
|
call write_name_entries
|
||||||
|
|
||||||
|
crn_done xor a
|
||||||
|
inc a ; NZ -- SUCCESS (per the real ABI's
|
||||||
|
; two-outcome contract; see header
|
||||||
|
; comment about the no-rollback
|
||||||
|
; degenerate case)
|
||||||
|
ret
|
||||||
|
|
||||||
|
;--- The PackBits-compressed body blob (see drv_dos_swp's comment for
|
||||||
|
;--- the format and PB_DECODE for the decoder). Produced by
|
||||||
|
;--- packbits_encode.ps1 (D:\Temp\claude\E--Claude\
|
||||||
|
;--- a54de7f1-2eb7-418e-8cf2-9a46028fb01b\scratchpad) -- no header, no
|
||||||
|
;--- footer, just the encoded stream ending in its own 0x80 terminator
|
||||||
|
;--- byte, so PB_DECODE needs no extra length/tail parameters at all. ---
|
||||||
|
body_packed_start:
|
||||||
|
INCBIN "zc_sd_driver_body.pb"
|
||||||
|
body_packed_end:
|
||||||
|
|
||||||
|
code_end:
|
||||||
|
|
||||||
|
SAVEBIN "zc_sd_driver.bin",#2000,code_end-#2000
|
||||||
File diff suppressed because it is too large
Load Diff
Binary file not shown.
+12
-1
@@ -10,7 +10,18 @@ Pager = 0
|
|||||||
;Block = #e000, 5,violent.bin
|
;Block = #e000, 5,violent.bin
|
||||||
Block = #c000, 2,zifi.bin
|
Block = #c000, 2,zifi.bin
|
||||||
Block = #c000, 3,ptplay.bin
|
Block = #c000, 3,ptplay.bin
|
||||||
Block = #e000, #0f,WDFCVBI2.COD ; sd driver
|
;Block = #e000, #0f,WDFCVBI2.COD ; sd driver -- OLD, closed driver
|
||||||
|
; (backed up in _backup_old_driver/),
|
||||||
|
; disabled while testing the from-
|
||||||
|
; scratch replacement below
|
||||||
|
Block = #e000, #0f,zc_sd_driver.bin ; sd driver (from-scratch replacement,
|
||||||
|
; see [[project-zifi-custom-sd-driver]]) --
|
||||||
|
; driver is entered via PAGE0 (CPU slot 0,
|
||||||
|
; #0000-#3FFF) where CORE=#2002 lives; the
|
||||||
|
; .asm pads 2 bytes at its own #2000 so the
|
||||||
|
; jump table lands exactly on #2002 once
|
||||||
|
; loaded here (spgbld needs a 512-aligned
|
||||||
|
; Block address, #e002 is rejected)
|
||||||
Block = #c000, #10,cursor.tga.pix4
|
Block = #c000, #10,cursor.tga.pix4
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -281,7 +281,13 @@ load_ram_page ld a,0
|
|||||||
ex de,hl ; download adress for lists. after "Search:"
|
ex de,hl ; download adress for lists. after "Search:"
|
||||||
1 ld (zipd_adr+1),hl
|
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 a,(load_ram_page+1)
|
||||||
ld hl,modem_command
|
ld hl,modem_command
|
||||||
call psb_get
|
call psb_get
|
||||||
@@ -289,7 +295,6 @@ load_ram_page ld a,0
|
|||||||
call zifi_get
|
call zifi_get
|
||||||
ENDIF
|
ENDIF
|
||||||
|
|
||||||
|
|
||||||
; bc: hl - lenght of readed data
|
; bc: hl - lenght of readed data
|
||||||
ld ix,read_threads
|
ld ix,read_threads
|
||||||
ld a,c
|
ld a,c
|
||||||
@@ -303,7 +308,7 @@ load_ram_page ld a,0
|
|||||||
|
|
||||||
1 xor a
|
1 xor a
|
||||||
ld (ix+thread.num),a
|
ld (ix+thread.num),a
|
||||||
ld a,(load_ram_page+1)
|
ld a,(saved_thread_page)
|
||||||
ld (ix+thread.page),a
|
ld (ix+thread.page),a
|
||||||
call set_page1
|
call set_page1
|
||||||
ld hl,status_copy ; clear statusbar gfx
|
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
|
on_int_dma ld a,1
|
||||||
jr sw_int_dma
|
ld (save_mode+1),a
|
||||||
off_int_dma xor a
|
ld a,(music_sw_saved)
|
||||||
sw_int_dma ld (save_mode+1),a
|
ld (music_sw+1),a
|
||||||
; ld (analizator_sw+1),a
|
ret
|
||||||
; ld (mouse_sw+1),a
|
off_int_dma ld a,(music_sw+1)
|
||||||
; jp wait_frame
|
ld (music_sw_saved),a
|
||||||
|
xor a
|
||||||
|
ld (save_mode+1),a
|
||||||
|
ld (music_sw+1),a
|
||||||
ret
|
ret
|
||||||
|
|
||||||
|
|
||||||
@@ -3968,7 +4007,11 @@ load_ini
|
|||||||
CALL FENTRY
|
CALL FENTRY
|
||||||
JP Z,ini_not_found
|
JP Z,ini_not_found
|
||||||
LD C,download_page ; page ini
|
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
|
LD B,#32
|
||||||
CALL LOAD512
|
CALL LOAD512
|
||||||
CALL SETROOT; возвращаемся в коневой
|
CALL SETROOT; возвращаемся в коневой
|
||||||
@@ -3976,8 +4019,8 @@ load_ini
|
|||||||
|
|
||||||
|
|
||||||
parse_ini ld a,download_page
|
parse_ini ld a,download_page
|
||||||
call set_page3
|
call set_page1
|
||||||
ld hl,#c000
|
ld hl,#4000
|
||||||
IF !cable_zifi
|
IF !cable_zifi
|
||||||
ld de,ini_db
|
ld de,ini_db
|
||||||
call cp_ini
|
call cp_ini
|
||||||
@@ -4691,6 +4734,27 @@ full_len_high byte ;
|
|||||||
read_threads thread;ds 6*5
|
read_threads thread;ds 6*5
|
||||||
db #ff
|
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
|
init_zifi
|
||||||
@@ -4722,17 +4786,80 @@ init_zifi
|
|||||||
; call wait
|
; call wait
|
||||||
; call zifi_check_receive_command
|
; call zifi_check_receive_command
|
||||||
; ret
|
; 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 hl,wifi_try_connect
|
||||||
ld b,2
|
ld b,2
|
||||||
call zifi_echo
|
call zifi_echo
|
||||||
ld hl,cmd_cwjap ; AT+CWJAP_CUR . Connect to AP, for current
|
ld hl,cmd_cwjap ; AT+CWJAP_CUR . Connect to AP, for current
|
||||||
call zifi_send
|
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
|
ld de,str_ok
|
||||||
call buffer_cmp
|
call buffer_cmp
|
||||||
; cp low output_buff+#bf
|
jr z,wifi_connect_ok
|
||||||
jr nz,2b
|
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
|
ld hl,wifi_connected
|
||||||
call zifi_echo
|
call zifi_echo
|
||||||
ld a,(update_rtc_sw+1) ; "time:" in zifi.ini not "none"?
|
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 rtc_read_date ; name downloads/<date> from the RTC chip either way
|
||||||
call set_download_dir
|
call set_download_dir
|
||||||
ret
|
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
|
; ld b,25
|
||||||
; call wait
|
; call wait
|
||||||
; ld hl,cmd_cipsta ; is Set IP address of station ?
|
; ld hl,cmd_cipsta ; is Set IP address of station ?
|
||||||
|
|||||||
Reference in New Issue
Block a user