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