Реализовать двухпанельный Commander от платформенного PoC до этапов P6-P20: EMM-каталог, сортировку и выбор, операции с файлами и деревьями, транзакционное копирование, метаданные, политику конфликтов и предварительную проверку свободного места. Добавить проектную документацию, HDD/MAME-сценарии и проверенные артефакты. Расширить libc операцией bank_write_page, исправлением режима O_RDONLY и связанными регрессионными проверками.
18 KiB
Sprinter Commander: платформенные пробы P1
Статус: MAME 0.287 / BIOS 3.06 — PASS; проверка на реальном Sprinter ожидается
Связанные документы: требования, архитектура, клавиши, roadmap, экранный backend P2
1. Назначение
Программа p1probe.exe объединяет платформенные проверки, которые должны
быть завершены до реализации UI Commander. Она не является ранней версией
Commander и не определяет его пользовательский интерфейс.
Исходники находятся в tests/p1_platform/.
Вторая программа, p1child.exe, используется только для проверки ESTEX
EXEC, возврата к родителю и кода завершения.
2. Ограничения безопасности
- Пробы не создают, не изменяют и не удаляют файлы.
- Каталожная проба выполняет только
getcwd,chdir(".")иffirst/fnext. - EMM-проба пишет только в выделенный ей блок из трёх страниц.
- Screen-проба пишет только в отдельную выделенную EMM-страницу.
- Дочерняя программа меняет видеорежим, но не пишет на диск.
- Проба не открывает файловые дескрипторы приложения напрямую.
- MAME не запускается целями
makeиmake all.
Первый MAME-прогон выполнен 6 сентября 2026 года после отдельного согласования.
Все запуски использовали автоматически пересоздаваемый mc.img; исходные
дисковые образы не изменялись программами-пробами.
3. Состав
| Файл | Назначение |
|---|---|
p1probe.c |
меню, общие сообщения, последовательность тестов |
p1_sys.c |
app-local wrappers DSKINFO, EXEC, WAIT, WINREST |
p1_emm.c |
выделение трёх страниц и проверка границ |
p1_dir.c |
CURDIR/CHDIR/F_FIRST/F_NEXT и DSKINFO output |
p1_screen.c |
полный и частичный WINREST с ненулевым offset |
p1_keyboard.c |
вывод ascii/scan/live modifiers |
p1_exec_test.c |
два режима EXEC и проверка состояния родителя |
p1child.c |
дочерний EXE, меняющий режим на 40x32 и возвращающий 0x5A |
mame_dump_keys.lua |
вывод карты полей AT-клавиатуры MAME |
mame_p1_keyboard.lua |
воспроизводимый ввод стрелок, F1–F10 и сочетаний |
Makefile |
сборка обоих EXE |
4. Сборка
cd applications/Volkov/tests/p1_platform
make
Диагностическая программа собирается в режиме small --safe. Это сделано
намеренно: P1 проверяет платформенные ABI и не должен одновременно отлаживать
банковую topology Commander. Сборка big --safe является критерием P2.
Дочерняя программа собирается как tiny --safe.
Результат текущей сборки
p1probe.exe:
_CODE: 11 062 байта;- данные: 2 741 байт;
- файл EXE: 11 835 байт;
- heap после статики: 17 429 байт;
- стек: 1 279 байт.
p1child.exe:
_CODE: 3 907 байт;- данные: 849 байт;
- файл EXE: 4 453 байта;
- heap после статики: 10 092 байта;
- стек: 1 279 байт.
Компиляция выполнена без ошибок. Значения относятся к текущей диагностической сборке и не являются бюджетом Commander.
5. Статическая проверка ABI
5.1. DSKINFO
Сигнатура:
int p1_disk_info(uint8_t disk, P1DiskInfo *out);
Сгенерированный вызов передаёт disk в A, out в DE. Wrapper сохраняет IX,
а после RST сохраняет:
- A — sectors per cluster;
- HL — total clusters;
- DE — free clusters;
- BC — bytes per sector.
Размер P1DiskInfo проверяется typedef-assert и равен семи байтам.
5.2. EXEC
Сигнатура намеренно имеет 8-битный аргумент первым:
int p1_exec(uint8_t path_mode, const char *path);
Для этого порядка SDCC передаёт path_mode в A и path в DE. Wrapper
перекладывает их в B и HL соответственно. Вариант
p1_exec(const char *path, uint8_t mode) был отвергнут после просмотра
сгенерированного ASM: второй 8-битный аргумент SDCC помещал на стек, а не в
DE.
На успехе A сохраняется как p1_exec_exit_code; на ошибке код из A проходит
через __errno_set.
5.3. WINREST
Wrapper повторяет уже подтверждённую раскладку tests/winrest и mdview2:
A row
L column
SP+2 height
SP+3 width
SP+4 physical page
SP+5..6 offset in 16-KB page
IX сохраняется, перед RST устанавливается в 0xC000 + offset. Сгенерированный
вызов проверен для полного экрана 32x80 и окна 2x20 с offset 0x2000.
6. Меню p1probe.exe
| Клавиша | Проба | Автоматическая оценка |
|---|---|---|
1 |
Каталог и F_FIRST/F_NEXT | да, плюс наблюдаемые коды |
2 |
EMM: три страницы | да |
3 |
WINREST full/partial | только завершение; изображение оценивается визуально |
4 |
Клавиатурные коды | сбор наблюдений |
5 |
EXEC и возврат | да для режима B=1 |
6 |
DSKINFO текущего диска | да |
A |
Пробы 1, 2 и 6 | да |
0/Esc |
Выход | — |
7. Ожидаемые проверки
7.1. Каталог
Проба дважды перечисляет каталог по маскам *.* и *, печатает первые 20
записей и итоговые значения:
- число записей;
- наличие
.; - наличие
..; errnoпоследнегоfnext();- совпадение результатов двух масок;
- сохранение CWD после
chdir(".").
Фактический результат DSS различается: *.* вернул обе записи с расширением,
а * завершился как пустой список с ENOENT. Поэтому *.* принят как
обязательный шаблон полного scan; совпадение масок не предполагается.
MAME-прогон установил фактическое завершение перечисления: fnext()
возвращает ошибку с errno=3 (ENOENT). Код 0x0F из старого описания DSS
для этой операции не подтверждён. Проба после измерения принимает только
ENOENT, чтобы возможная смена поведения не осталась незамеченной.
7.2. EMM
Проверяются:
mem_alloc_pages(3);- три различных физических номера;
- первые 64 байта каждой страницы;
- последние 64 байта каждой страницы;
- независимые patterns страниц;
- восстановление
mem_info.free_pagesпосле освобождения блока.
7.3. Screen/WINREST
Первый вызов должен показать полный экран 80x32 с рамкой и цветными строками.
После клавиши второй вызов должен наложить окно 20x2 в позиции row 14,
column 30. Данные второго окна лежат по offset 0x2000, поэтому тест
одновременно проверяет корректность IX.
Тест не открывает окно через BIOS: ESTEX WINREST здесь только копирует
прямоугольник в текущий текстовый экран. Повтор со снимками в t=20 и t=24
без промежуточных вызовов подтвердил, что фон вне прямоугольника сохранён.
Первая версия pattern использовала арифметически полученные атрибуты
0x11..0x17. Верхняя граница 0x11 была обычным blue-on-blue, а часть
остальных сочетаний выглядела неоднозначно в разных моментах палитрового
цикла. Замечание о синих символах на синем фоне подтвердилось; raw-арифметика
атрибутов в UI запрещается.
После замены на именованные COLOR(LIGHTBLUE..WHITE, BLUE) полный экран и
частичное окно были видимы на кадрах t=20 и t=24. Повторная проверка
исходных PNG установила, что их декодированные RGB-пиксели полностью
идентичны. Прежнее сообщение о чередовании P2 было ошибкой встроенного
предпросмотра, а не поведением MAME.
Отдельная проба P2.2 сохранила, установила, прочитала обратно и восстановила
шесть атрибутов во всех четырёх планах; многоцветная сцена осталась стабильной.
Строка P1-SCR-03 ниже подтверждена как PASS. Детали — в
результатах P2.2.
7.4. Keyboard
Для 24 событий печатаются:
ascii, scan, полное kbd_mod_state, compact Shift/Ctrl/Alt
Esc печатается последним и завершает сбор. В автоматическом MAME-сценарии
использован следующий набор из 24 событий:
- стрелки, Home/End, PgUp/PgDn;
- F1–F10;
- Insert/Delete;
- Ctrl+R;
- Ctrl+PgUp;
- Alt+F1;
- Esc.
7.5. EXEC
Выполняются два случая:
B=0,P1CHILD.EXE— наблюдение short-name/PATH semantics.B=1,.\\P1CHILD.EXE— обязательный случай PoC.
Дочерняя программа:
- переключается в 40x32;
- показывает свои W1/W2/W3 и CWD;
- ждёт клавишу;
- возвращает
0x5A.
После возврата родитель проверяет:
- результат непосредственного EXEC;
- результат WAIT;
- восстановление W1/W2/W3;
- восстановление CWD;
- возможность вернуть 80x32 и продолжить работу.
Ошибка случая B=0 записывается как наблюдение и не проваливает PoC. Ошибка B=1 проваливает тест.
8. Выполненный порядок первого прогона
2— EMM.6— DSKINFO.1— каталог.3— WINREST.4— клавиатура.5— EXEC последним.- Повторно
2в том же процессе после EXEC, чтобы проверить EMM. - Возврат в меню; независимые запуски дополнительно подтвердили повторный старт программы.
Такой порядок сначала проверяет неразрушительные примитивы и оставляет наиболее сложное переключение контекста на конец.
9. Таблица runtime-результатов
Окружение MAME: mame.arm 0.287 (b0c4527c), машина sprinter, BIOS v3.06, запуск
p1probe.exe с дискеты A:. PENDING в аппаратной колонке означает только
отсутствие прогона на реальном Sprinter и не отменяет результата MAME.
| ID | Проверка | MAME 0.287 / BIOS 3.06 | Реальный Sprinter | Артефакт |
|---|---|---|---|---|
| P1-DIR-01 | CWD и chdir(".") |
PASS | PENDING | результат |
| P1-DIR-02 | *.* против * |
PASS: 2 против 0; полный scan использует только *.* |
PENDING | результат |
| P1-DIR-03 | Код конца F_NEXT | PASS, ENOENT=3 |
PENDING | строгая проверка |
| P1-EMM-01 | Блок 3 страницы | PASS, страницы EF/F0/F1 |
PENDING | результат |
| P1-EMM-02 | Границы страниц | PASS | PENDING | результат |
| P1-EMM-03 | Счётчик после free | PASS, 221 → 221 |
PENDING | результат |
| P1-SCR-01 | Полный WINREST 80x32 | PASS, визуально | PENDING | контрастный экран |
| P1-SCR-02 | Offset WINREST | PASS, row 14 / col 30 / 0x2000 |
PENDING | фон и окно вместе |
| P1-SCR-03 | Цветные атрибуты в двух моментах цикла | PASS, RGB кадров идентичен; P2.2 подтвердил 6 атрибутов × 4 плана | PENDING | кадр 1, кадр 2, P2.2 |
| P1-SCR-04 | Raw-атрибуты 0x11..0x17 |
OBSERVED, raw-арифметика запрещена | PENDING | неудачный исходный pattern |
| P1-KBD-01 | Базовые scan-коды | PASS | PENDING | таблица |
| P1-KBD-02 | Ctrl/Alt modifiers | PASS | PENDING | сочетания |
| P1-EXE-01 | EXEC B=0 | PASS | PENDING | результат |
| P1-EXE-02 | EXEC B=1 | PASS | PENDING | результат |
| P1-EXE-03 | Exit/WAIT 0x5A |
PASS / PASS | PENDING | результат |
| P1-EXE-04 | Восстановление W1/W2/W3 | PASS, F3/F2/FF |
PENDING | результат |
| P1-EXE-05 | EMM после двух EXEC | PASS | PENDING | контроль |
| P1-DSK-01 | DSKINFO | PASS | PENDING | результат |
9.1. Зафиксированные значения
- DSKINFO: 1 сектор на кластер, 512 байт на сектор, 2847 кластеров всего, 2814 свободно.
- EMM до выделения: 256 страниц всего, 221 свободна; после освобождения снова 221.
- Оба режима EXEC:
rc=0,errno=0, непосредственный exit=5A, WAIT=5A. - CWD до и после child:
\; страницы W1/W2/W3 до и после:F3/F2/FF. - Модифицированная клавиша приходит с установленным битом 7 scan-кода:
Ctrl+R=
93, Ctrl+PgUp=D9, Alt+F1=BB. Послеscan & 0x7Fполучаются базовые коды13,59,3B; compact modifiers равны02,02,04. - Esc:
ascii=1B,scan=01.
10. Условия завершения P1
MAME-часть P1 завершена: все обязательные строки имеют PASS, фактические
клавиатурные коды перенесены в keymap, завершение fnext() уточнено,
EXEC B=1/WAIT и EMM после child подтверждены, артефакты сохранены.
Проверка на реальном Sprinter остаётся желательной аппаратной валидацией, но не блокирует переход к P2 и реализацию platform API PoC. Если реальное железо даст расхождение, оно оформляется отдельным репро и не маскируется адаптацией UI.