Volkov: добавить Sprinter Commander

Реализовать двухпанельный Commander от платформенного PoC до этапов P6-P20: EMM-каталог, сортировку и выбор, операции с файлами и деревьями, транзакционное копирование, метаданные, политику конфликтов и предварительную проверку свободного места.

Добавить проектную документацию, HDD/MAME-сценарии и проверенные артефакты. Расширить libc операцией bank_write_page, исправлением режима O_RDONLY и связанными регрессионными проверками.
This commit is contained in:
2026-09-10 10:45:30 +03:00
parent 05bcd8197e
commit 8e389c03f8
870 changed files with 21310 additions and 25 deletions
@@ -0,0 +1,427 @@
# Sprinter Commander: требования к PoC и границы проекта
Статус: требования PoC зафиксированы; gate P1 и ядро P2.1 пройдены в MAME
Целевая платформа: Sprinter Sp2000, Z80, DSS 1.71.57
Инструментарий: SDCC 4.5, `sprinter-cc`, MAME 0.287 / BIOS 3.06
Связанные документы:
[архитектура](commander-architecture.md),
[клавиши и команды](commander-keymap.md),
[план разработки](commander-roadmap.md),
[экранный backend P2](p2-screen-backend.md),
[результаты P2.1](p2-screen-probe-results.md),
[результаты skeleton P2](p2-skeleton-results.md),
[результаты файловых панелей P3](p3-panel-results.md)
## 1. Назначение документа
Документ фиксирует проверяемые требования к первой работающей версии
файлового менеджера для Sprinter. Рабочее имя проекта — **Sprinter
Commander**, рабочее имя исполняемого файла — `SPRCMD.EXE`.
PoC не является портом Volkov Commander. Это новая программа на C,
повторяющая привычную модель двухпанельного файлового менеджера с учётом
архитектуры памяти и API Sprinter.
## 2. Референсы и правила их использования
### 2.1. Volkov Commander 4.05
Используется как минимальный поведенческий образец:
- компоновка двух панелей;
- клавиатурная навигация;
- назначение функциональных клавиш;
- общий сценарий работы пользователя.
### 2.2. Volkov Commander 4.99
Используется как образец декомпозиции и источник функций для дальнейших
версий:
- отдельные подсистемы панелей, экрана, клавиатуры и диалогов;
- отдельные операции копирования, удаления и изменения атрибутов;
- просмотрщик, редактор, поиск и дерево каталогов;
- описания файлов и архивные панели;
- разделение резидентного ядра и загружаемых частей.
### 2.3. Dos Navigator 1.51
Используется только как архитектурный референс:
- единый цикл событий и команды приложения;
- отделение модели панели от её представления;
- абстракция источника файлов;
- длительные операции с прогрессом и отменой;
- виртуальные панели для архивов и результатов поиска;
- история, конфигурация и внешние инструменты.
Объектная система Turbo Vision, DOS overlays, XMS/EMS-код и прикладные
модули DN не переносятся.
Исходный код, строки интерфейса и ресурсы референсов не копируются без
отдельного решения по лицензированию. Реализация проекта должна оставаться
собственной реализацией по описанному поведению.
## 3. Определения версий
**PoC 0.1** доказывает техническую реализуемость панелей, EMM-хранилища,
экранного буфера, копирования и запуска программ.
**Рабочая версия** пригодна для повседневной работы с файлами и включает
безопасные групповые и рекурсивные операции.
**Полная версия 1.0** соответствует основным возможностям VC 4.99, но не
пытается повторить весь набор утилит Dos Navigator.
## 4. Пользовательский сценарий PoC
После запуска программа переключается в текстовый режим 80x32, выделяет
необходимую память и показывает две панели. Обе панели первоначально
открывают текущий каталог запуска.
Пользователь может:
1. Перемещать курсор по активной панели.
2. Переключать активную панель клавишей `Tab`.
3. Входить в каталог клавишей `Enter`.
4. Возвращаться в родительский каталог.
5. Перечитывать содержимое активной панели.
6. Копировать один обычный файл в каталог пассивной панели.
7. Запускать выбранный `.EXE` и возвращаться в Commander.
8. Выйти по `F10` с освобождением всех ресурсов.
## 5. Компоновка экрана PoC
Экран имеет 80 столбцов и 32 строки.
| Строки | Назначение |
|---:|---|
| 0 | Заголовки и текущие пути обеих панелей |
| 1–27 | Списки файлов, по 27 видимых записей |
| 28 | Итоги панелей: число записей и общий размер |
| 29 | Информация о текущей записи активной панели |
| 30 | Строка состояния, ошибок и прогресса |
| 31 | Подсказки функциональных клавиш |
Левая панель занимает столбцы 0–39, правая — 40–79. Точные символы рамок
и палитра не являются контрактом PoC, но все символы должны корректно
отображаться в CP866.
Renderer задаёт смысловые роли атрибутов независимо от конкретной палитры.
P2.2 подтвердил многоцветные планы в MAME: тема сохраняет исходные записи,
задаёт обе FLASH-пары и восстанавливает палитру при выходе. До аппаратного
подтверждения активная и пассивная панели всё равно различаются не только
цветом, но и глифами/маркерами.
Полная перерисовка выполняется из собственного экранного буфера через
`sc_video`. Commander не использует дескрипторы окон BIOS: панели, меню и
диалоги — логические прямоугольники приложения. `sc_video` выводит их в
координаты глобального экрана через ESTEX/BIOS-функции без идентификатора
окна; прямой доступ к VRAM не используется.
Изменение курсора или одной строки панели не должно требовать повторного
чтения каталога.
Прокрутка списка на одну строку может использовать прямоугольный ESTEX
`SCROLL 55h`, как `mdview2`, но рамка и соседняя панель остаются неподвижны,
а экранный EMM-буфер обновляется синхронно. Эта служба не является BIOS-
дескриптором окна; её аппаратная реализация исходниками `mdview2` не
доказана. Псевдографика задаётся raw-кодами CP866 из единого `sc_glyphs.h`.
## 6. Функциональные требования PoC
### REQ-BOOT: запуск и завершение
- **REQ-BOOT-01.** Программа должна явно установить текстовый режим 80x32.
- **REQ-BOOT-02.** Перед изменением видеорежима и текущего каталога должны
быть сохранены исходные значения, если DSS позволяет их получить.
- **REQ-BOOT-03.** При штатном выходе освобождаются все EMM-блоки и закрываются
все открытые файлы.
- **REQ-BOOT-04.** Ошибка инициализации не должна оставлять изменённый
видеорежим или выделенную память.
- **REQ-BOOT-05.** Если обязательные четыре EMM-страницы выделить нельзя,
программа выводит понятную ошибку и завершает работу.
- **REQ-BOOT-06.** `F10` в обычном режиме открывает подтверждение выхода;
положительный ответ запускает штатный cleanup, отрицательный возвращает к
панелям.
### REQ-PANEL: панели
- **REQ-PANEL-01.** Панели имеют независимые пути, курсор и позицию прокрутки.
- **REQ-PANEL-02.** Активная панель визуально отличается от пассивной.
- **REQ-PANEL-03.** Каталоги отображаются перед обычными файлами.
- **REQ-PANEL-04.** Внутри групп записи сортируются по имени без учёта
регистра ASCII.
- **REQ-PANEL-05.** Для записи отображаются имя, размер, дата, время и
атрибут каталога/файла в объёме, который помещается в ширину панели.
- **REQ-PANEL-06.** После перечитывания каталог по возможности сохраняет
курсор на прежнем имени; если оно исчезло — на ближайшей допустимой
позиции.
- **REQ-PANEL-07.** Полный scan DSS использует `*.*`; шаблон `*` не считается
эквивалентным, поскольку не возвращает обычные имена с расширением.
- **REQ-PANEL-08.** Пустой каталог отображается корректно и остаётся
управляемым.
- **REQ-PANEL-09.** Родительский каталог представлен синтетической записью
`..`, кроме корня диска.
- **REQ-PANEL-10.** Записи `.` и `..`, возвращённые DSS, не должны
дублировать синтетическую запись.
- **REQ-PANEL-11.** Во всей линейке 0.1–1.0 панель хранит не более
640 записей, включая синтетическую `..`. При превышении лимита
показывается предупреждение; запись за границу EMM-страницы
запрещена. Многостраничные панели и предел более 640 записей
относятся только к версии 2.0+.
- **REQ-PANEL-12.** Если DSS завершил `F_FIRST/F_NEXT` кодом 35
(`TOO_MANY_FILES_IN_DIR`), уже прочитанные записи остаются доступны, а
последней добавляется красная виртуальная запись `>>> MORE...`. Она
сообщает о недоступном остатке каталога, не сортируется вместе с файлами
и не может быть целью файловой операции.
### REQ-NAV: навигация
- **REQ-NAV-01.** Поддерживаются `Up`, `Down`, `PgUp`, `PgDn`, `Home`, `End`.
- **REQ-NAV-02.** `Tab` переключает активную панель без изменения каталогов.
- **REQ-NAV-03.** `Enter` на каталоге открывает его в активной панели.
- **REQ-NAV-04.** `Ctrl+PgUp` и `Backspace` открывают родительский каталог.
- **REQ-NAV-05.** `Ctrl+R` перечитывает активную панель.
- **REQ-NAV-06.** Навигация внутри уже прочитанной панели не обращается к
файловой системе.
- **REQ-NAV-07.** Операция с активной панелью не должна неожиданно менять
путь пассивной панели.
### REQ-FS: работа с DSS и путями
- **REQ-FS-01.** PoC работает с именами DOS 8.3. Длинные имена не входят в
требования до отдельного подтверждения поддержки DSS.
- **REQ-FS-02.** Максимальный внутренний путь — 255 байт плюс завершающий
ноль.
- **REQ-FS-03.** Склейка пути и имени проверяет переполнение до обращения к
DSS.
- **REQ-FS-04.** Контекст текущего каталога DSS считается глобальным
ресурсом. После временной смены каталога модуль обязан восстановить
ожидаемый каталог приложения.
- **REQ-FS-05.** Одновременно приложение держит не более трёх файловых
дескрипторов; штатная операция копирования использует два.
- **REQ-FS-06.** Конец перебора каталога отличается от настоящей ошибки
`fnext()` по `errno` и контексту операции.
### REQ-COPY: безопасное копирование одного файла
- **REQ-COPY-01.** `F5` копирует выбранный обычный файл в текущий каталог
пассивной панели.
- **REQ-COPY-02.** Копирование каталогов и групп файлов в PoC запрещено с
явным сообщением.
- **REQ-COPY-03.** Если конечное имя уже существует, PoC отказывается от
операции и не изменяет существующий файл.
- **REQ-COPY-04.** Данные копируются блоками, а общий размер и позиция имеют
32-битный тип.
- **REQ-COPY-05.** Поддерживаются файлы больше 64 КБ.
- **REQ-COPY-06.** Целевой файл сначала создаётся под уникальным временным
именем через семантику `O_EXCL`, после успешного закрытия переименовывается
в конечное имя.
- **REQ-COPY-07.** При ошибке или отмене временный файл закрывается и
удаляется.
- **REQ-COPY-08.** Между блоками проверяется `Esc`, а строка состояния
обновляет прогресс.
- **REQ-COPY-09.** Нулевой файл копируется корректно.
- **REQ-COPY-10.** В PoC сохранение времени и атрибутов файла не обязательно,
но должно быть предусмотрено в интерфейсе операции.
- **REQ-COPY-11.** Непосредственно перед переименованием временного файла
конечное имя проверяется повторно. Если оно появилось, операция завершается
без его изменения.
- **REQ-COPY-12.** Данные между открытыми файлами проходят непосредственно
через выделенную EMM-страницу, отображаемую в W3. Полноразмерный блоковый
буфер в W2 и изменяемый буфер внутри банка кода запрещены.
- **REQ-COPY-13.** Начиная с P18 успешно скопированный обычный файл получает
исходные FAT date/time и атрибуты readonly/hidden/system/archive. Время
задаётся temp до `close`, атрибуты — конечному имени после commit.
- **REQ-COPY-14.** Начиная с P19 существующий файл обрабатывается policy
overwrite/skip/rename; варианты overwrite-all и skip-all ограничены одним
F5. Overwrite использует backup в том же каталоге и rollback при отказе
commit, а readonly требует явного повторного решения.
### REQ-EXEC: запуск программ
- **REQ-EXEC-01.** `Enter` на имени с расширением `.EXE` запускает программу
через ESTEX `EXEC`.
- **REQ-EXEC-02.** Перед запуском Commander сохраняет логическое состояние
панелей и закрывает временные ресурсы операции.
- **REQ-EXEC-03.** После возврата восстанавливаются видеорежим, экран и
ожидаемый текущий каталог.
- **REQ-EXEC-04.** Активная панель перечитывается после возврата; пассивная
перечитывается, если запущенная программа могла изменить её каталог.
- **REQ-EXEC-05.** Ошибка загрузки `.EXE` показывается без завершения
Commander.
- **REQ-EXEC-06.** Обычный файл неизвестного типа в PoC не запускается.
### REQ-UI: сообщения и состояние
- **REQ-UI-01.** Ошибки не выводятся поверх структуры панели случайными
вызовами `printf`; они проходят через единый модуль сообщений.
- **REQ-UI-02.** Для каждой ошибки показываются действие, имя объекта и
текст/код ошибки, если они доступны.
- **REQ-UI-03.** `Esc` закрывает сообщение или отменяет текущую длительную
операцию; в обычном состоянии он не завершает программу.
- **REQ-UI-04.** Неподдерживаемые в PoC функциональные клавиши либо не
показаны, либо показаны неактивным цветом.
- **REQ-UI-05.** F6 local rename и F7 mkdir принимают только один проверенный
компонент DOS 8.3; `..`, маркер DSS и неоднозначная группа не передаются
файловой системе.
- **REQ-UI-06.** Rename обязан проверить отсутствие нового имени до DSS
`RENAME`, сохранить CWD и восстановить его после успеха или ошибки.
- **REQ-UI-05.** После закрытия сообщения восстанавливается экран из
логического экранного буфера.
### REQ-MEM: память
- **REQ-MEM-01.** Целевая конфигурация PoC — `--memory big --safe`.
- **REQ-MEM-02.** W2 содержит резидентное ядро, обычные данные, heap и стек;
банковские функции размещаются в W1; W3 используется только для EMM-
данных.
- **REQ-MEM-03.** PoC выделяет четыре 16-КБ страницы: две для панелей, одну
для экранного буфера и одну для рабочей области копирования.
- **REQ-MEM-04.** Прикладной код не хранит указатели в диапазон
`0xC0000xFFFF` между вызовами хранилища.
- **REQ-MEM-05.** Любой модуль, временно меняющий W3, восстанавливает прежнюю
страницу до возврата и до вызова чужого кода.
- **REQ-MEM-06.** Повторное чтение каталогов не выделяет новые блоки.
- **REQ-MEM-07.** Освобождение частично созданного приложения идемпотентно на
уровне состояния приложения: каждый реально выделенный блок освобождается
ровно один раз.
- **REQ-MEM-08.** Рабочая EMM-страница копирования принадлежит общему блоку
`ScApp`; copy job не выделяет и не освобождает её на каждый файл.
## 7. Формат записи каталога PoC
Логический формат записи фиксирован как 24 байта:
```c
typedef struct {
char name[13];
uint32_t size;
uint16_t date;
uint16_t time;
uint8_t attr;
uint8_t flags;
uint8_t reserved;
} ScDirEntry;
```
На этапе реализации обязательна compile-time или build-time проверка
`sizeof(ScDirEntry) == 24`.
Флаги PoC:
- `SC_ENTRY_PARENT` — синтетическая запись `..`;
- `SC_ENTRY_SELECTED` — выбор обычной записи в версии 0.2;
- `SC_ENTRY_DSS_LIMIT` — виртуальная запись о недоступном остатке каталога;
- остальные биты должны быть нулевыми.
В одной странице используется не более 640 записей; последние 1024 байта
остаются резервом и не входят в массив записей. Служебное
состояние панели хранится в W2, а не в начале EMM-страницы.
## 8. Нефункциональные требования
- **REQ-NF-01.** Исходный код и комментарии проекта ведутся на русском.
- **REQ-NF-02.** Сборка выполняется штатным `sprinter-cc` без отдельной
проприетарной цепочки.
- **REQ-NF-03.** После каждого этапа сохраняется отчёт размеров HOME и
банков; переполнение банка является ошибкой сборки.
- **REQ-NF-04.** Реакция на навигационную клавишу в уже прочитанной панели не
должна визуально зависать; целевой ориентир в MAME — менее 100 мс.
- **REQ-NF-05.** Операция дольше 500 мс должна показывать состояние или
прогресс.
- **REQ-NF-06.** Все воспроизводимые дефекты DSS или SDCC подтверждаются
отдельным тестом, `.asm`, дампом или другим артефактом.
- **REQ-NF-07.** Рабочая версия должна проверяться в MAME и на реальном
Sprinter; PoC может быть принят по MAME с обязательным последующим
hardware smoke-test.
## 9. Что не входит в PoC 0.1
- удаление файлов;
- перезапись существующих файлов;
- перемещение и переименование пользователем;
- создание каталогов;
- рекурсивные операции;
- групповое выделение и маски;
- командная строка и история;
- встроенные viewer/editor;
- дерево и поиск;
- архивы и виртуальные панели;
- мышь;
- конфигурационный файл, темы и локализация;
- длинные имена;
- фоновые операции и многозадачность.
## 10. Критерии приёмки PoC
PoC считается завершённым, если одновременно выполнены условия:
1. Программа стабильно запускается в MAME с двухпанельным экраном.
2. Обе панели независимо проходят дерево каталогов и корректно работают с
пустым каталогом.
3. Хранилище панели проверено синтетическим source на границах 640/641 без
выхода за EMM-страницу; на DSS 1.71 превышение его границы 512 физических
FAT-записей даёт управляемый частичный список с красным маркером.
Оба случая подтверждены MAME-пробами в
[результатах P3](p3-panel-results.md).
4. Сто последовательных перечитываний и переходов не меняют число свободных
EMM-страниц.
5. Копируются и побайтно совпадают файлы размеров 0, 1, 4095, 4096, 65535,
65536 байт и более 1 МБ.
6. Отмена и ошибка записи не оставляют временный файл.
7. Существующий целевой файл никогда не меняется.
8. Тестовый `.EXE` запускается, завершается, после чего Commander полностью
восстанавливает экран и продолжает работу.
9. Все пути ошибок возвращают приложение в управляемое состояние.
10. На выходе восстановлен видеорежим, закрыты дескрипторы и освобождены
выделенные EMM-блоки.
## 11. Граница полной версии 1.0
Версия 1.0 должна дополнительно включать:
- групповые и рекурсивные копирование, перемещение и удаление;
- безопасную политику перезаписи;
- сохранение атрибутов и времени;
- независимую для каждой панели сортировку по имени, расширению,
размеру и дате файла в обоих направлениях;
- переключение дисков;
- командную строку, историю, интерактивный полноэкранный
режим псевдооболочки по `Ctrl+O` и ассоциации;
- настраиваемую подсветку имён по расширению;
- просмотрщик и редактор, допустимо отдельными `.EXE`;
- меню, диалоги, помощь и конфигурацию;
- быстрый поиск, дерево и поиск файлов;
- информационную и quick-view панели;
- базовую работу с архивами;
- мышь.
Обязательные детали этих функций:
- групповые `+`, `-` и `*` работают только над файлами и не меняют флаг
каталога, даже если он был установлен отдельным `Insert`;
- `Ctrl+O` не просто скрывает панели, а переключает между ними и
управляемым полноэкранным режимом командной строки;
- полноэкранный режим и однострочный prompt используют один редактор строки и
общую историю; внешние `.EXE` запускаются через ESTEX `EXEC`;
- синтетическая `..` всегда первая, каталоги остаются перед файлами,
а направление применяется внутри этих групп;
- пункт сортировки «дата» использует метку создания/модификации, которую
реально возвращает файловая система; DSS `F_FIRST/F_NEXT` сейчас даёт
метку last-write, поэтому отдельный выбор creation не имитируется
дубликатом даты и требует отдельной платформенной пробы;
- при отсутствии файла цветов каталоги и `..` имеют белый цвет, `.EXE`
жёлтый, остальные файлы — светло-серый;
- предел 640 записей не снимается ни одной из этих функций.
Многостраничное/динамическое хранилище панели, межстраничная сортировка и
показ 1024/2048 или неограниченного числа файлов не входят в 1.0 и
резервируются для 2.0+.
Терминал, модем, CD-плеер, форматирование, восстановление дисков, электронная
таблица, игры и многооконный desktop Dos Navigator не входят в определение
Commander 1.0.