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,146 @@
# Sprinter Commander: результаты файловых панелей P3
Дата: 7 сентября 2026 года.
Статус: `PASS` в MAME для навигации, независимых панелей, EMM-store на
границе 640/641, сортировки и явной обработки предела каталога DSS 1.71.
Связанные документы:
[требования](commander-requirements.md),
[архитектура](commander-architecture.md),
[roadmap](commander-roadmap.md),
[большие каталоги DSS](dss-large-directories.md)
## 1. Проверенная граница
В P3 синтетические записи заменены настоящим источником `F_FIRST/F_NEXT`.
Каждая панель имеет собственные путь, cursor/top и физическую EMM-страницу.
Запись панели занимает 24 байта, поэтому одна 16-КБ страница вмещает
жёсткий продуктовый предел 640 записей и оставляет 1024 байта запаса.
Реализованы и проверены:
- шаблон перечисления `*.*` и имена DOS 8.3;
- синтетическая `..` в некорневом каталоге без дублей `.`/`..` от DSS;
- каталоги перед файлами и сортировка имён без учёта регистра ASCII;
- вход в каталог, возврат через `..`/`Ctrl+PgUp`, refresh и независимость
пассивной панели;
- навигация `Up/Down/PgUp/PgDn/Home/End` без повторного scan;
- частичный результат при ошибке DSS 35 и отдельная виртуальная запись
`>>> MORE...`.
## 2. Сборка
Основная команда: `make`.
Конфигурация: `--memory big --safe --max-allocs 3000`.
| Область | Значение |
|---|---:|
| `_CODE` | 7728 байт (`0x8100..0x9F30`) |
| данные | 2281 байт (конец `0xA819`) |
| свободная куча W2 | 4839 байт |
| стек | 1279 байт |
| `_BANK1` — scan/sort | 2299 / 16384 байт (14,0%) |
| `_BANK2` — renderer | 2902 / 16384 байт (17,7%) |
| EXE | 41305 байт |
`check_bank_calls.py` не нашёл прямых вызовов в чужой банк или публикации
указателей на данные банка.
## 3. Прямая диагностика DSS
Образ содержит `BIGDIR` из 680 обычных файлов. Исправленная проба `P3DIR`
получила:
```text
count=512
errno=35
511=B0000598.DAT
512=B0000599.DAT
513=
```
Это подтверждает границу стабильного DSS и отсутствие продолжения за ней.
Конкретные последние имена отражают физический порядок записей, созданный
`mcopy`, и сами по себе не являются контрактом теста.
Артефакт: [экран P3DIR](../artifacts/mame-p3/panels/dss-enum-limit.png).
## 4. Диагностика общего пути Commander
Проба `P3SCAN` использует те же `sc_source_fs`, `sc_store` и `sc_sort`, что
основная программа. Получен результат:
```text
scan: rc=0 errno=35 count=512 trunc=1
first: .. attr=10 flags=01
last : >>> MORE... attr=00 flags=04
```
Ошибка 35 сознательно остаётся в `errno` как причина усечения, но scan
возвращает успешный частичный снимок. Красный маркер занимает последний
элемент снимка и сортируется после файлов.
Артефакт: [экран P3SCAN](../artifacts/mame-p3/panels/scan-marker.png).
## 5. Интеграционный сценарий Commander
Исторические артефакты ниже сняты в MAME 0.287 с FDD `A:`. Текущий
регрессионный сценарий предельного каталога переведён на HDD `D:`:
`make hdd-stress` создаёт `build/hdd/p3_stress.chd`, а
`tests/mame_p3_stress.lua` сначала переключает DSS на `D:`. FDD-сборщик
`tests/make_p3_stress_floppy.sh` оставлен только для smoke-совместимости.
| Действие | Подтверждённое наблюдение | Результат |
|---|---|---|
| Корень | обе панели независимо открыли один реальный каталог | [PASS](../artifacts/mame-p3/panels/root-both-panels.png) |
| Вход и `..` | левая панель вошла в `TESTDIR` и вернулась в корень | [PASS](../artifacts/mame-p3/panels/left-testdir-parent.png), [возврат](../artifacts/mame-p3/panels/enter-parent-return.png) |
| `Ctrl+R` | после refresh сохранён выбор `INNER.TXT` | [PASS](../artifacts/mame-p3/panels/refresh-preserves-inner.png) |
| `Tab` и навигация справа | пути и cursor/top панелей не смешиваются | [PASS](../artifacts/mame-p3/panels/independent-panel-state.png) |
| `Ctrl+PgUp` слева | изменена только активная левая панель | [PASS](../artifacts/mame-p3/panels/ctrl-pgup-left-only.png) |
| Вход в `EMPTY` | единственная запись — синтетическая `..`, count=1 | [PASS](../artifacts/mame-p3/panels/empty-parent.png) |
| Вход в `MANY`, `PgDn`, `Down` | cursor/top меняются до 28/2 без rescan, рамки и соседняя панель сохраняются | [PASS](../artifacts/mame-p3/panels/navigation-scroll.png) |
| Вход в `BIGDIR` | показан частичный снимок, count=512 и признак `entries+` | [PASS](../artifacts/mame-p3/panels/bigdir-partial.png) |
| `End` | выбран последний красный `>>> MORE...`, info показывает `<DSS LIMIT>` | [PASS](../artifacts/mame-p3/panels/dss-marker-selected.png) |
| `Enter` на маркере | выведено сообщение о недоступном остатке DSS; переход или EXEC не выполнен | [PASS](../artifacts/mame-p3/panels/dss-marker-message.png) |
| `F10` | открыт диалог выхода поверх текущего состояния | [PASS](../artifacts/mame-p3/panels/dss-limit-quit-dialog.png) |
| `Enter` в диалоге | выполнен cleanup и возврат в `A:\>` | [PASS](../artifacts/mame-p3/panels/dss-limit-clean-exit.png) |
Скриншот фиксирует только состояние изображения в конкретный момент и не
используется в одиночку для вывода о причине возможного дефекта. Подозрение
на ошибку должно дополнительно подтверждаться соседними кадрами, ожидаемым
состоянием сценария и, при необходимости, отдельной диагностической пробой.
## 6. Синтетическая граница EMM-store
Проба `tests/p3_store_probe/p3store.c` не вызывает DSS и поэтому достигает
продуктового предела, который нельзя получить из реального каталога DSS
1.71. Сборка выполнена с `--max-allocs 3000`.
```text
entry=24 capacity=640 bytes=15360 reserve=1024
write: count=640 first=1 middle=1 last=1
guard: put640=1 get640=1 tail=1
cleanup: free_after=222 restored=1
PASS: store boundary is intact.
```
Проверены записи 0, 319 и 639. Запись и чтение индекса 640 отклонены,
байты в начале и конце 1024-байтового резерва не изменились, EMM-страница
освобождена без утечки.
Артефакт:
[граница 640/641](../artifacts/mame-p3/panels/store-boundary-640-641.png).
## 7. Итог и следующая граница
Функциональный gate файловых панелей P3 закрыт в MAME. Аппаратный прогон на
реальном Sprinter ещё нужен, но не блокирует начало P4.
Следующая работа PoC:
1. копирование одного файла через отдельную EMM-страницу в W3;
2. безопасный временный файл, обработка ошибок и cleanup;
3. запуск `.EXE` через ESTEX с восстановлением экрана после child;
4. регрессионный MAME-сценарий для копирования, файлов больше 64 КБ и EXEC.