8e389c03f8
Реализовать двухпанельный Commander от платформенного PoC до этапов P6-P20: EMM-каталог, сортировку и выбор, операции с файлами и деревьями, транзакционное копирование, метаданные, политику конфликтов и предварительную проверку свободного места. Добавить проектную документацию, HDD/MAME-сценарии и проверенные артефакты. Расширить libc операцией bank_write_page, исправлением режима O_RDONLY и связанными регрессионными проверками.
428 lines
30 KiB
Markdown
428 lines
30 KiB
Markdown
# 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.** Прикладной код не хранит указатели в диапазон
|
||
`0xC000–0xFFFF` между вызовами хранилища.
|
||
- **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.
|