# 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). ## Что реализовано сверх голого CORE ABI - **MBR/раздел**: автоматически определяет, есть ли на карте партиция (тип `0x0B`/`0x0C`), или BPB лежит прямо в LBA0; смещение партиции (`ADDTOP`) прибавляется ко всем последующим LBA. - **SDSC/SDHC/SDXC**: сама определяет байтовую или блочную адресацию по биту CCS из CMD8/ACMD41/CMD58, а не считает её заранее известной. - **Защита от выхода за границу LBA**: перед любым чтением сверяет номер сектора с реальным размером тома (посчитанным из BPB) — ошибка в арифметике не уйдёт в CMD17/25 как заведомо неверный адрес. - **Проверка BPB/FAT32**: сигнатура `55 AA`, `BytesPerSector==512`, `FATSz16==0`, `RootEntryCount==0`, `SectorsPerCluster` — степень двойки, прежде чем доверять остальным полям. - **Зеркалирование FAT**: запись FAT-записи дублируется во все копии (`NumFATs`), не только в первую. - **Поиск свободного кластера**: сессионный кэш "куда искать дальше" плюс чтение/запись `FSInfo`-подсказки (`FSI_Nxt_Free`) — не пересканирует FAT с кластера 2 при каждой аллокации на разделах с большим количеством уже занятых кластеров. - **Длинные имена (LFN)**: генерация уникального короткого имени 8.3 с суффиксом `~N` при коллизии, полноценные LFN-записи для MKFILE/MKDIR. - **Дата/время создания**: читает реальные RTC (DS1685-совместимые, порты `#EFF7`/`#DFF7`/`#BFF7`) и проставляет их в создаваемые записи каталога вместо фиксированной заглушки. - **Многокластерные файлы/каталоги**: потоковое чтение и запись (`stream_open`/`stream_read_sector`/`stream_write_sector`) следует цепочке FAT и доращивает её по мере необходимости — не ограничено одним кластером. ## Адресация Драйвер загружается в физическую страницу `#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`).