21 KiB
Wild Commander — Обзор Системы Плагинов
Версия документа: 2.0 — дополнена по результатам анализа исходников
Источники:inc/wc_api.h,asm/wc_api.s,asm/crt0.s,DiskRef/Help.txt,DiskRef/WC_History.txt
Введение
Wild Commander (WC) — файловый менеджер с системой плагинов для платформы TS-Configuration (ZX Spectrum Evo). Выполняет роль основной оболочки и загрузчика для работы с FAT32-дисками, SD-картами и IDE.
WC запускается из BootROM / vDOS и предоставляет:
- Двухпанельный интерфейс (80 × 25/30/36 TXT-режим)
- FAT32 (длинные и короткие имена до 255 символов)
- Систему плагинов (.WMF) с горячей загрузкой/выгрузкой
- Поддержку устройств: SD (Z-Controller), IDE NEMO, IDE SMUC, NeoGS SD
- Встроенный просмотрщик (F3): TXT, HEX, TGA, SCR, Gigascreen, MGS — до 1 МБ
- Мультиязычность (ENG / RUS, переключение CTRL+SHIFT)
Версии
| Компонент | Версия | Примечание |
|---|---|---|
| WC | 1.10 (03.08.2025) | Последняя из WC_History.txt |
| Plugin System | #10 | Формат заголовка .WMF |
| Идентификатор | WildCommanderMDL |
16 байт, offset +16 в заголовке |
Общая концепция
Плагины WC (.WMF файлы) — модульные расширения, выполняемые в адресном пространстве Z80. Поддерживают до 64 страниц (1 МБ) кода/данных.
Типичные области применения:
- Просмотр файлов различных форматов (BMP, GIF, ILBM, SCR)
- Воспроизведение музыки и видео (VGM, MOD, WAV, MP3/GS)
- Редактирование файлов (TXT Editor с подсветкой синтаксиса)
- Работа с ROM/Flash (ROM_PROG)
- Монтирование образов дисков (MOUNTER: TRD, TAP, FDI)
- Утилиты (часы, скринсейвер, компилятор, дамп памяти)
Типы запуска плагинов
При запуске плагина, в регистр A передается тип вызова:
| Код | Константа (C) | Описание |
|---|---|---|
| #00 | WC_PCOND_EXT_ONLY |
По расширению файла (ENTER / F3) |
| #01 | WC_PCOND_ON_LOAD |
При первой загрузке плагина (ENTER) |
| #02 | WC_PCOND_TIMER |
По таймеру скринсейвера + меню F10 |
| #03 | WC_PCOND_F10 |
Из меню запуска плагинов (F10) |
| #04 | WC_PCOND_VIEWER |
Из меню вьювера (SHIFT+F3 / SHIFT+ENTER) |
| #05 | WC_PCOND_F10_VIEW |
F10 + SHIFT+F3 |
| #11 | WC_PCOND_F10_F2 |
F10 + F2 |
| #12 | WC_PCOND_F2 |
По нажатию F2 |
| #13 | WC_PCOND_F10_F4 |
F10 + F4 |
| #14 | WC_PCOND_F4 |
По нажатию F4 |
| #15 | WC_PCOND_F10_V_F4 |
F10 + SHIFT+F3 + F4 |
Примечание: Все плагины также вызываются по расширению, если расширения указаны в блоке расширений заголовка (offset +64). ENTER и F3 разделены начиная с WC v1.00 — флаг +63 определяет, какой из них запускает плагин.
Входные параметры при запуске
WC делает CALL #8000. В crt0.s (SDCC) входные регистры сохраняются
в глобальные переменные автоматически.
; Входные параметры:
A - тип вызова (см. таблицу выше)
[DE,HL] - длина файла в байтах (DE=hi16, HL=lo16)
BC - адрес строки с именем файла (для типов #00, #04, #14)
формат: name(1-255), 0 (длинное FAT имя)
IX - адрес структуры активной панели
; Альтернативные регистры (только для #00,#04,#12,#14):
A' - номер расширения (0-31) для типа #00
DE' - количество файлов/каталогов в панели (включая "..")
HL' - номер объекта из панели (от 1)
В SDCC-плагине (crt0.s автоматически):
extern uint8_t wc_file_ext; // ← A' (номер расширения)
extern char * wc_file_name; // ← BC (указатель на имя)
extern uint32_t wc_file_size; // ← [DE,HL] (32-бит размер)
Коды возврата из плагина
При выходе из плагина регистр A определяет действие WC:
| A | Константа (C) | Действие |
|---|---|---|
| 0 | WC_EXIT_ESC |
Просто выход (ESC) |
| 1 | WC_EXIT_UNRECOGNIZED |
Файл не опознан → передать другому плагину (тип #00) |
| 2 | WC_EXIT_NEXT |
Перейти на следующий файл (тип #00) |
| 3 | WC_EXIT_RELOAD_DIR |
Перечитать каталог |
| 4 | WC_EXIT_PREV |
Перейти на предыдущий файл (тип #00) |
В SDCC-плагине: wc_exit_code = 0; return 0; — crt0.s считывает
wc_exit_code в A перед RET обратно в WC.
Код 2/4 (NEXT/PREV): WC вызывает тот же плагин повторно с другим файлом.
crt0.sзаново обнуляет BSS (_DATA) и копирует инициализаторы (_INITIALIZER → _INITIALIZED), поэтому всеstaticпеременные сбросятся.
Системные адреса
Источник:
src_sdcc/inc/wc_api.h, раздел «СИСТЕМНЫЕ ПЕРЕМЕННЫЕ WC»
| Адрес | Константа | Размер | Описание |
|---|---|---|---|
#6000 |
WC_SYS_PG0 |
1 | Текущая страница в окне #0000 |
#6001 |
WC_SYS_PG4 |
1 | Текущая страница в окне #4000 |
#6002 |
WC_SYS_PG8 |
1 | Текущая страница в окне #8000 |
#6003 |
WC_SYS_PGC |
1 | Текущая страница в окне #C000 |
#6004 |
WC_SYS_ABT |
1 | 1 = был нажат ESC |
#6005 |
WC_SYS_ENT |
1 | 1 = был нажат ENTER |
#6006 |
WC_SYS_FUN |
3 | Точка входа WC API (JP к диспетчеру) |
#6009 |
WC_SYS_TMN |
2 | Таймер INT (uint16_t, ++/кадр ≈50 Гц) |
#600B |
WC_SYS_FEP |
1 | Страница FAT-движка в окне 0 |
#600C |
WC_SYS_XPP |
1 | Сохранённая страница |
#600D |
WC_SYS_CNFV |
1 | ЦАП: 0=PWM, 1=3bit, 2=4bit, 3=5bit, 7=VDAC2/FT812 |
#600E |
WC_SYS_HEI |
1 | Высота TXT-экрана: 25 / 30 / 36 |
#600F |
WC_SYS_TXTMD |
1 | Текущий видеорежим WC (0=TXT) |
#6010 |
WC_SYS_INIFLG |
1 | Флаг загрузки INI-конфигурации |
#6011 |
WC_SYS_RSQBC |
2 | RSQ буфер-счётчик |
#6013 |
WC_SYS_RSQB2 |
2 | RSQ буфер 2 |
#6015 |
WC_SYS_SDBSF |
1 | Состояние SD1 драйвера |
#6016 |
WC_SYS_SDBSF2 |
1 | Состояние SD2 драйвера |
#6017 |
WC_SYS_F3ENTFL |
1 | Флаг F3/ENTER для файловых операций |
#6018 |
WC_SYS_FEP2 |
2 | FAT engine page extra |
#6020 |
WC_SYS_PLRESAD |
8 | Резидент перехода: A=страница, HL=адрес → JP(HL) |
#6028 |
WC_SYS_PLRESCALL |
8 | Резидент вызова: A=страница, HL=адрес → CALL(HL) |
#8000 |
— | — | Точка входа плагина (WC делает CALL #8000) |
Чтение из C:
#define WC_SYS_ABT (*(volatile uint8_t*)0x6004)
#define WC_SYS_TMN (*(volatile uint16_t*)0x6009)
#define WC_SYS_HEI (*(volatile uint8_t*)0x600E)
// Или через макросы wc_api.h:
uint8_t h = wc_get_height(); // 25/30/36
uint16_t t = wc_get_timer(); // кадровый счётчик
uint8_t esc = wc_get_abt(); // 1 = ESC нажат
Вызов API функций
Все функции WC вызываются через точку доступа #6006:
WLD EQU #6006
; Пример вызова функции PRWOW (вывод окна)
PRWOW LD A,1
JP WLD
; Пример вызова ESC (проверка нажатия ESC)
ESC LD A,#17
JP WLD
Регистровые соглашения WC API:
- Вход: A = номер функции, остальные параметры в регистрах (см. справочник)
- Некоторые функции используют A' (альтернативный A через
EX AF,AF') - Портит: AF, BC, DE, HL, IX
- Сохраняет: IY, AF', BC', DE', HL', SP
⚠️ IX сохраняется диспетчером P8000, но AF, BC, DE, HL портятся при каждом вызове
CALL #6006.
Карта памяти (физические страницы)
Источник:
wc_api.h— полная таблицаWC_PAGE_*
| Страницы | Константа | Назначение |
|---|---|---|
#00 |
WC_PAGE_MTXPG |
Основной текстовый экран (TXT) |
#01 |
WC_PAGE_FONT0 |
Шрифт основного TXT + Hrust/MegaLZ |
#02 |
WC_PAGE_CODE |
Код WC (ядро) |
#05 |
WC_PAGE_FAT_ENGINE |
FAT движок + стек + данные |
#08 |
WC_PAGE_BUFPG |
2-й текстовый экран / буфер |
#09 |
WC_PAGE_FONT1 |
Шрифт для 2-го TXT |
#0B–#13 |
WC_PAGE_CAT_LEFT |
Каталог левой панели (9 стр.) |
#14–#1C |
WC_PAGE_CAT_RIGHT |
Каталог правой панели (9 стр.) |
#1D |
WC_PAGE_RESB |
Буфер сохранения окон (RESB) |
#1E |
WC_PAGE_CPPG1 |
Позиции левой панели |
#1F |
WC_PAGE_CPPG2 |
Позиции правой панели |
| #20–#5F | WC_PAGE_TVBPG |
Мегабуфер (64 стр. = 1 МБ), он же видео: |
#20–#2F |
WC_PAGE_GV1 |
— видеобуфер 1 (16 стр.) |
#30–#3F |
WC_PAGE_GV2 |
— видеобуфер 2 |
#40–#4F |
WC_PAGE_GV3 |
— видеобуфер 3 |
#50–#5F |
WC_PAGE_GV4 |
— видеобуфер 4 |
#60 |
WC_PAGE_PLHPG |
Заголовки плагинов |
| #61–#A0 | WC_PAGE_PLGPG |
Код/данные плагинов (до 64 стр.) |
#A1–#BF |
WC_PAGE_TAP_START |
TAP-область (31 стр. = 496 КБ) |
#C0–#E7 |
WC_PAGE_VDOS_RAM |
vDOS RAM-диск (40 стр. = 640 КБ) |
#E8–#EF |
WC_PAGE_VDOS_FREE |
Свободные страницы |
#F0 |
WC_PAGE_PNLPG |
Поток левой панели |
#F1 |
WC_PAGE_PNL_RIGHT |
Поток правой панели |
#F2 |
WC_PAGE_INIPG |
INI-поток (плагин #00) |
#F3 |
WC_PAGE_STRPG |
Поток плагина #01 |
#F4–#F7 |
— | SPG loader, boot pages (5,2), panel paths |
#F8–#FB |
WC_PAGE_VROM_START |
Виртуальный ROM (4 стр.) |
#FC–#FF |
— | vDOS: таблицы, драйверы, трапы |
Плагин видит: свои заказанные страницы (0..N) через
wc_mngc_pl()/wc_mng0_pl()/wc_mng8_pl(). Физическая нумерация скрыта — WC маппит логическую страницу N плагина вWC_PAGE_PLGPG + N.
Поддерживаемые устройства хранения
| Код | Константа | Устройство |
|---|---|---|
| 0 | WC_DEV_SD_ZC |
SD-карта (Z-Controller) |
| 1 | WC_DEV_IDE_NEMO_M |
IDE Nemo — Master |
| 2 | WC_DEV_IDE_NEMO_S |
IDE Nemo — Slave |
| 3 | WC_DEV_SD_NGS |
SD-карта (NeoGS) |
| 4 | WC_DEV_IDE_SMUC_M |
IDE SMUC — Master |
| 5 | WC_DEV_IDE_SMUC_S |
IDE SMUC — Slave |
| 6 | WC_DEV_SD2_ZC |
Вторая SD (Z-Controller SD2) |
Работа со страницами памяти
Логическая нумерация
Плагин запрашивает N страниц в заголовке (offset +34). WC выделяет их
из пула #61–#A0. Плагин обращается по логическому номеру 0..N−1.
Окна CPU и функции маппинга
| Окно | Адреса | Функция ASM | Функция C | Примечание |
|---|---|---|---|---|
| Win 0 | #0000–#3FFF |
MNG0_PL (#4E) |
wc_mng0_pl(page) |
⚠ Данные для WC API нельзя класть сюда |
| Win 2 | #8000–#BFFF |
MNG8_PL (#4F) |
wc_mng8_pl(page) |
Код плагина — обычно стартовая страница |
| Win 3 | #C000–#FFFF |
MNGC_PL (#00) |
wc_mngc_pl(page) |
⚠ Сбрасывается после КАЖДОГО вызова WC API |
Специальные значения для MNGC_PL:
#FF— шрифтовая страница (нельзя писать в#E000–#FFFF!)#FE— первый текстовый экран (с панелями WC)
Резидент перехода (#6020)
Переключает страницу плагина и делает безвозвратный JP:
// C: никогда не вернётся в вызывающий код
void wc_resident_jump(uint8_t page, uint16_t addr);
; ASM: A = страница (0..N-1), HL = адрес (#8000–#BFFF)
LD A,1
LD HL,#8000
CALL #6020 ; → WC переключает Win2 на стр.1, JP (HL)
Резидент вызова (#6028)
Вызывает код в другой странице плагина с возвратом:
void wc_resident_call(uint8_t page, uint16_t addr);
; ASM: A = страница, HL = адрес. Сохраняет всё кроме A,HL.
LD A,2
LD HL,#A000
CALL #6028 ; → WC переключает, CALL (HL), возвращает стр. назад
Добавлено в WC v1.09 (31.07.2024). До этого многостраничные плагины требовали прямой OUT в порт Page2 (#12AF).
Важные замечания
-
При входе в плагин может быть любой экран! Обязательно вызывайте
GEDPL(#0F) /wc_gedpl()для переключения на текстовый режим. -
Вызывать GEDPL лучше после анализа файла, когда убедились что файл подходит для плагина (и вернули
wc_exit_code = 1если нет). -
Обязательно сохраняйте IX при входе в плагин, если планируете использовать файловые функции.
-
⚠ Win3 (#C000) сбрасывается после каждого вызова WC API!
ВнутриCALL #6006WC переключает окно#C000на текстовую страницу и не восстанавливает его. Если плагин работал черезmngcvpl()/mngc_pl(), он обязан повторить маппинг после любого UI-вызова (gedpl,prwow,txtpr,rresb,load512и т.д.). -
GEDPL затирает #1000–#1447 в окне 0 — нельзя хранить данные в этой области.
-
Буферы и строки для файловых функций (
load512,fentry,findnext, и т.д.) обязаны быть в#8000–#FFFF. WC ремапит#0000–#7FFFпод FAT-движок внутри каждого файлового вызова. -
FindNext портит #0000–#1FFF на странице драйвера — не хранить данные там при итерации по каталогу.
-
WC API портит регистры: AF, BC, DE, HL, IX. Сохраняет: IY, AF', BC', DE', HL', SP. Это верно для всех функций через
CALL #6006. -
Стек не настраивается — плагин использует стек WC (в Win 1,
#4000–#7FFF). Стек WC достаточно глубокий для обычных плагинов, но рекурсия требует осторожности.
Горячие клавиши WC (для пользователя)
Источник:
DiskRef/Help.txt
| Клавиша | Действие |
|---|---|
| ENTER | Войти в каталог / запустить .WMF / просмотреть файл |
| F3 | Встроенный просмотрщик (TXT/HEX/TGA/SCR/MGS, до 1 МБ) |
| SHIFT+F3/SHIFT+ENTER | Меню выбора вьювера (плагин с WC_PCOND_VIEWER) |
| F2 | Пользовательское меню (из wc.mnu) |
| F4 | Редактирование / выбор текстового редактора |
| F5 | Копирование отмеченных файлов в другую панель |
| F6 | Переименование файла/каталога |
| F7 | Создание каталога |
| F8 / DEL | Удаление отмеченных файлов |
| F9 | Настройки INI (авто-создаёт каталог WC на загрузочном устройстве) |
| F10 | Меню запуска/удаления плагинов |
| TAB | Переключение между панелями |
| SPACE / INSERT | Отметить файл/каталог |
| * | Инвертировать выделение |
| ALT+F1/F2 | Выбор диска для левой/правой панели |
| CTRL+F3 | Сортировка по имени |
| CTRL+F4 | Сортировка по расширению |
| CTRL+F6 | Сортировка по размеру |
| CTRL+R | Обновить каталог |
| CTRL+A | Выделить все объекты |
| CTRL+SHIFT | Переключение ENG/RUS |
Примеры плагинов
В каталоге DiskRef/WC/ находятся скомпилированные плагины WC:
| Файл | Назначение |
|---|---|
GSPLAYER.WMF |
Плеер для GS (MP3, MOD, WAV) |
WPLAYER.WMF |
Музыкальный плеер с плейлистами |
VGMPLAY.WMF |
VGM плеер (OPL3/AY/SAA) — этот проект |
TXTEDIT.WMF |
Текстовый редактор с подсветкой синтаксиса |
BMPV.WMF |
Просмотрщик BMP |
GIFVIEW.WMF |
Просмотрщик GIF |
ILBMVIEW.WMF |
Просмотрщик IFF/ILBM |
FTVIEW.WMF |
Просмотрщик FT-шрифтов |
MOUNTER.WMF |
Монтирование TRD/TAP/FDI образов |
ROM_PROG.WMF |
Программатор ROM/Flash |
SCRSAVER.WMF |
Скринсейвер (тип вызова WC_PCOND_TIMER) |
CLOCK.WMF |
Часы |
SETIME.WMF |
Установка времени |
COMPILER.WMF |
Компилятор |
RE.WMF |
Ассемблер/отладчик |
Ссылки на другие разделы документации
- 02_Plugin_Header_Structure.md — формат 512-байтного заголовка
- 03_WC_API_Reference.md — полный справочник функций
- 04_TSConfig_Platform.md — аппаратная платформа, порты, регистры
- 06_Example_Plugin.md — примеры плагинов на ASM и SDCC C