Реализовать двухпанельный Commander от платформенного PoC до этапов P6-P20: EMM-каталог, сортировку и выбор, операции с файлами и деревьями, транзакционное копирование, метаданные, политику конфликтов и предварительную проверку свободного места. Добавить проектную документацию, HDD/MAME-сценарии и проверенные артефакты. Расширить libc операцией bank_write_page, исправлением режима O_RDONLY и связанными регрессионными проверками.
18 KiB
Sprinter Commander: экранный backend P2
Статус: ядро P2.1 и многоцветная тема P2.2 прошли MAME; аппаратная проверка, восстановление после child и измерение времени ожидаются.
Связанные документы: архитектура, требования, roadmap, результаты P1, результаты P2.1, результаты P2.2
1. Решение
Commander не использует систему оконных дескрипторов BIOS (WIN_OPEN,
WIN_CLOSE, WIN_COPY_WIN, WIN_RESTORE_WIN). Текущий BIOS хранит только
один описатель с идентификатором 0; открытие нового окна уничтожает прежнее
состояние. Диалоги, панели и меню поэтому являются прямоугольниками внутри
собственной модели экрана Commander, а не окнами BIOS.
Целевой backend выводит в координаты полного экрана через системные функции,
но не открывает и не переключает BIOS-окна. Основной пакетный примитив —
ESTEX WINREST; для специальных операций доступны координатные WRCHAR,
CLEAR и SCROLL. Прямой доступ к VRAM не используется.
2. Что уже доказано
P1 и examples/mdview2 подтвердили формат логического буфера:
(char, attr), по строкам, stride = width * 2, без padding
WINREST корректно выводит полный экран, отдельную строку и прямоугольник из
ненулевого смещения EMM-страницы. Эта функция ESTEX не создаёт BIOS-окно и не
использует его идентификатор; слово WIN здесь означает прямоугольную область
текущего экрана.
mdview2 — полезный образец полноэкранного приложения: состояние документа
принадлежит программе, строки материала выводятся из собственного кэша, а
status/menu рисуются координатными примитивами. Commander сохраняет этот
принцип, но выносит способ вывода в отдельный backend.
3. Почему используем системный координатный вывод
- DSS/BIOS уже знают реальное устройство текстового режима, знакогенератора, активной screen page и системной палитры.
WINRESTвыводит сразу прямоугольник из EMM, поэтому не требуется RST на каждую ячейку.- Координатные ESTEX-функции не используют идентификатор глобального окна.
- После возврата из child достаточно снова установить 80x32 и вывести всю экранную модель.
- Один путь работает и в MAME, и на реальном Sprinter без предположений о внутренней раскладке VRAM.
4. Граница между оконными и безоконными функциями
Запрещены функции управления глобальными окнами, где передаётся window ID:
WIN_OPEN, WIN_CLOSE, WIN_COPY_WIN, WIN_RESTORE_WIN, WIN_MOVE_WIN.
Они зависят от единственного поддерживаемого описателя 0.
Разрешены:
- ESTEX
WINREST 5Ah— прямоугольник(row, col, height, width), EMM page и source address, без window ID; - ESTEX
WRCHAR 58h,CLEAR 56h,SCROLL 55h— абсолютные координаты активной screen page; - BIOS
LP_SET_PLACE/LP_PRINT_*/LP_CLS_WIN*— только как пакетные оптимизации для глобального экрана, без открытия новых окон.
Системные вызовы чтения и записи текстовой палитры также разрешены. Их отсутствие в P2.1 — способ изолировать экранный backend, а не архитектурный запрет. Выделенный модуль темы использует их для полного save/set/restore; контракт подтверждён P2.2.
Чтобы renderer не зависел от текущего cursor/place, основным остаётся
WINREST. Если применяется BIOS LP_*, backend всегда сам устанавливает
place непосредственно перед операцией и не оставляет его частью состояния UI.
5. Палитра и FLASH
У Sprinter атрибут — индекс в четыре текстовых палитровых плана: paper, ink, flash-paper и flash-ink. Сигнал FLASH переключает пары глобально. Чтобы тема Commander не мигала, для каждого используемого атрибута normal-paper и flash-paper задаются одинаково, как и normal-ink с flash-ink.
Первый pattern P1 с raw-атрибутами 0x11..0x17 действительно содержал
blue-on-blue. Это ошибка выбора атрибутов, а не нестабильность палитры;
арифметическое построение атрибутов для UI поэтому по-прежнему запрещено.
Прежняя гипотеза о пропадающих цветных строках была вызвана неверным предпросмотром PNG. Проверка декодированных файлов показала, что именованные цветные кадры P1 и три диагностических кадра P2.1 пиксельно идентичны.
P2.2 отдельно проверил шесть цветовых атрибутов:
- сохранены все 24 исходные записи (6 атрибутов × 4 плана);
- установлены одинаковые normal/FLASH-пары;
- обратное чтение дало
PASS (0 mismatches); - пять временных кадров имеют одинаковый viewport Sprinter;
- перед выходом исходные записи восстановлены.
Единственное изменение между двумя полными PNG находилось в служебной панели
MAME: 42 пикселя LED Drive A. Элементы layout вне viewport Sprinter в
экранных сравнениях не учитываются. Подробности — в
результатах P2.2.
6. Интерфейс backend
Минимальный интерфейс не раскрывает ESTEX/BIOS остальным модулям:
int sc_video_init(void);
void sc_video_shutdown(void);
int sc_video_present_full(uint8_t emm_page);
int sc_video_present_rect(uint8_t emm_page, uint16_t offset,
uint8_t row, uint8_t col,
uint8_t height, uint8_t width);
int sc_video_scroll_rect(uint8_t row, uint8_t col,
uint8_t height, uint8_t width,
int8_t delta);
sc_screen строит (char, attr) в EMM и вызывает backend. Он не вызывает
WIN_OPEN, WRCHAR, WINREST или BIOS непосредственно. Единственная
реализация PoC — sc_video_system.c; выбор конкретного системного примитива
остаётся внутри неё.
7. Вертикальный текстовый scroll
mdview2 использует эффективную схему для перемещения на одну строку:
Down: scroll(rect, UP) → нарисовать новую нижнюю строку
Up: scroll(rect, DOWN) → нарисовать новую верхнюю строку
PgUp/PgDn/Home/End → полный redraw области
Его viewport — (col=0, row=1, width=80, height=30). Вызов libc
scroll() обращается к ESTEX SCROLL 55h, который сдвигает прямоугольник
активной screen page на одну строку. Он не использует идентификатор окна
BIOS и совместим с решением не применять window descriptors.
Исходники mdview2 и контракт ESTEX не доказывают, что операция реализована
аппаратным регистром видеоконтроллера: для документации это системный
прямоугольный scroll, пока не появится измерение или исходник DSS. Возможный
глобальный аппаратный сдвиг начала экрана для Commander всё равно неудобен —
он одновременно сдвинет рамки и обе панели. Реализация
sc_video_scroll_rect() делегирует прямоугольник ESTEX; это не создаёт
зависимости от BIOS-окон.
Для Commander эта оптимизация применяется только когда top панели
изменился ровно на один. Прямоугольники — внутренности панелей без рамок:
left: col=1, row=1, width=38, height=27
right: col=41, row=1, width=38, height=27
Точные размеры уточняются renderer-геометрией, но центральный разделитель, заголовок, footer и пассивная панель не должны входить в scroll rectangle.
Экранный EMM-буфер остаётся источником истины. Поэтому
sc_screen_scroll_rows() сначала сдвигает соответствующие (char, attr) в
модели и строит открытую строку, затем вызывает sc_video_scroll_rect() и
выводит эту строку. Системный scroll без синхронизации модели запрещён:
после диалога или EXEC полный redraw иначе вернул бы старые строки.
Fallback при любой неопределённости — present всех 27 строк активной панели. P2.1 должен проверить четыре границы прямоугольника, оба направления, верх и низ списка, 1000 последовательных scroll и неизменность соседней панели.
8. Псевдографика и CP866
mdview2 подтверждает стандартный light box-drawing набор CP866/CP437:
| Имя | Код | Глиф | Имя | Код | Глиф |
|---|---|---|---|---|---|
SC_G_H |
C4 |
─ | SC_G_V |
B3 |
│ |
SC_G_TL |
DA |
┌ | SC_G_TR |
BF |
┐ |
SC_G_BL |
C0 |
└ | SC_G_BR |
D9 |
┘ |
SC_G_TM |
C2 |
┬ | SC_G_BM |
C1 |
┴ |
SC_G_ML |
C3 |
├ | SC_G_MR |
B4 |
┤ |
SC_G_X |
C5 |
┼ |
Стрелки для подсказок, если понадобятся: Up=18, Down=19, Right=1A,
Left=1B. Это управляющий диапазон ASCII, поэтому такие байты нельзя
передавать через API, интерпретирующий CR/LF/BEL/Esc. Они кладутся как raw
glyph непосредственно в ScCell.
Правила Commander:
- все коды сосредоточены в
sc_glyphs.h, чисел0xB3по renderer-модулям быть не должно; - исходная рамка строится из глифов, а не из UTF-8-литералов;
- строки UI хранятся в CP866 или проходят явную build-time конвертацию;
- border test рисует все 11 соединений и четыре стрелки;
- атрибут каждого глифа задаётся через
COLOR(fg, bg); - при координатном raw-выводе символы
<0x20считаются глифами, а не командами.
Для PoC достаточно одинарных рамок. Двойные рамки VC-класса добавляются после проверки полного набора соединений, чтобы не смешивать несовместимые single/double junctions.
Расширенный набор, уже подтверждённый таблицей конвертации mdview2, можно
зарезервировать для прогресса, отметок и будущих тем:
| Имя | Код | Глиф | Назначение |
|---|---|---|---|
SC_G_SHADE_LIGHT |
B0 |
░ | светлая заливка |
SC_G_SHADE_MEDIUM |
B1 |
▒ | средняя заливка |
SC_G_SHADE_DARK |
B2 |
▓ | тёмная заливка |
SC_G_BLOCK |
DB |
█ | полный блок |
SC_G_HALF_UP |
DF |
▀ | верхняя половина |
SC_G_HALF_DOWN |
DC |
▄ | нижняя половина |
SC_G_HALF_LEFT |
DD |
▌ | левая половина |
SC_G_HALF_RIGHT |
DE |
▐ | правая половина |
SC_G_BULLET |
F9 |
∙ | маркер |
SC_G_CHECK |
FB |
√ | отметка |
SC_G_SQUARE |
FE |
■ | квадрат |
mdview2_help.c рисует рамку этими кодами через wrchar() и BIOS fill-
функции. Commander заимствует таблицу глифов и геометрию, но обращается к ним
только через ScCell/sc_video: текущий cursor/place не становится частью
модели интерфейса.
9. Coordinate-screen probe P2.1
Отдельный tests/p2_screen/p2screen.exe выполнен в MAME 0.287 / BIOS 3.06:
- Режим 80x32 и одна EMM-страница экранной модели —
PASS. - Полный экран одним
WINRESTс полной сверкой черезRDCHAR—PASS. - Прямоугольник 20x2 из offset
0x2000—PASS. - Две рамки и таблица CP866-глифов —
PASSвизуально и поRDCHAR. - Левая панель вверх и правая панель вниз —
PASS; рамки и соседние клетки совпали с моделью. - Синхронизация EMM-модели после системного
SCROLL—PASS. - 1000 чередующихся однострочных scroll с итоговой полной сверкой —
PASS. - Сохранение W3 вокруг
WINREST,RDCHARиSCROLL—PASS. - Один системный атрибут стабилен в трёх временных фазах —
PASS, кадры пиксельно идентичны. - Шесть атрибутов и четыре палитровых плана —
PASSотдельной пробой P2.2.
Остались отдельные проверки, не нужные для начала skeleton:
- Повторить полную инициализацию после child, изменившего видеорежим.
- Сравнить время полного, однострочного и scroll-вывода.
- Повторить принятый сценарий на реальном Sprinter.
Подробные значения и кадры приведены в результатах P2.1.
10. Критерий выбора
Системный backend принят для реализации skeleton по результату MAME, потому что:
- совпадает с EMM-моделью по символам и атрибутам;
- изолирует палитру в модуле темы и сохраняет отображение W3;
- частичное обновление не затрагивает соседние клетки;
- scroll прямоугольника не двигает рамку и пассивную панель;
- все псевдографические соединения совпадают с CP866;
- базовый системный атрибут стабилен во времени;
- код не обращается к
RGADR,RGMODи VRAM-банкам напрямую.
До аппаратного принятия backend остаются прогон на реальном Sprinter и повторная инициализация после EXEC. Многоцветность подтверждена отдельным критерием P2.2 и не выводится из результата P2.1.