Реализовать двухпанельный Commander от платформенного PoC до этапов P6-P20: EMM-каталог, сортировку и выбор, операции с файлами и деревьями, транзакционное копирование, метаданные, политику конфликтов и предварительную проверку свободного места. Добавить проектную документацию, HDD/MAME-сценарии и проверенные артефакты. Расширить libc операцией bank_write_page, исправлением режима O_RDONLY и связанными регрессионными проверками.
40 KiB
Sprinter Commander: архитектура
Статус: P1/P2 подтверждены; одностраничная модель панели P3 реализована, проходит граничные проверки DSS
Связанные документы: требования, клавиши и команды, план разработки, платформенные пробы P1, экранный backend P2, результаты P2.1, результаты skeleton P2
1. Цели архитектуры
Архитектура должна позволить получить небольшой технический PoC, не создавая тупиков для полной версии. Главные ограничения задаются не исходным VC, а платформой Sprinter:
- Z80 имеет 64-КБ адресное пространство;
- W0 занят DSS/BIOS;
- стек обязан находиться в W2;
- полный список двух панелей не помещается вместе с кодом в near-память;
- код полной версии потребует банков;
- DSS имеет критический предел в восемь открытых файлов;
- текстовый экран удобно восстанавливать непосредственно из EMM-страницы.
2. Принятые архитектурные решения
ADR-001. Новая реализация, а не перенос
Commander пишется на C для SDCC. VC 4.05/4.99 используются как описание поведения и состава функций, Dos Navigator — как источник архитектурных идей. Зависимости от DOS interrupt API, сегментной модели x86, PSP, DTA, TSR, overlays, XMS и EMS в код проекта не переносятся.
ADR-002. Лёгкий цикл событий вместо оконного framework
Приложение имеет один цикл событий, набор символьных команд и явное состояние экрана. Иерархия объектов наподобие Turbo Vision не используется.
Причины:
- меньше резидентного кода и данных;
- нет виртуальных методов и потоковой сериализации объектов;
- проще анализировать банковские вызовы;
- легче гарантировать освобождение ресурсов.
ADR-003. Целевой режим памяти — big
PoC собирается с --memory big --safe:
- W0
0x0000–0x3FFF— DSS/BIOS; - W1
0x4000–0x7FFF— переключаемые банки кода; - W2
0x8000–0xBFFF— HOME, DATA/BSS, heap и стек; - W3
0xC000–0xFFFF— EMM-страницы данных.
Если первоначальный skeleton временно собирается без банков, это не меняет
контрактов модулей. До принятия PoC должна быть проверена именно сборка big.
ADR-004. Панели, экран и рабочая область копирования хранятся в EMM
Начиная с P4 PoC выделяет один блок из четырёх последовательных 16-КБ страниц.
P2/P3 использовали первые три страницы; четвёртая заранее резервируется текущим
ScApp, чтобы копирование не увеличивало W2 и не меняло схему памяти во время
операции:
| Логическая страница | Назначение | Использование |
|---|---|---|
| 0 | записи левой панели | до 640 ScDirEntry, 1024 байта резерва |
| 1 | записи правой панели | до 640 ScDirEntry, 1024 байта резерва |
| 2 | экранный буфер | первые 5120 байт |
| 3 | рабочая область copy job | первые 4096 байт в PoC |
Допускается выделение четырёх отдельных блоков, если эксперимент покажет проблему с последовательным блоком, но внешний интерфейс хранилища от этого не меняется.
ADR-005. Запрещены долгоживущие указатели на W3
Указатель в диапазон 0xC000–0xFFFF действителен только внутри функции,
которая явно владеет отображением W3. После выхода из неё указатель считается
недействительным.
Ни PanelState, ни ScApp, ни длительная операция не содержат near-указатель
на содержимое EMM. Они хранят физическую страницу и смещение.
ADR-006. Экран строится как модель ячеек
Каждая экранная ячейка представлена двумя байтами (символ, атрибут). Формат
совпадает с подтверждённым форматом ESTEX WINREST:
typedef struct {
uint8_t ch;
uint8_t attr;
} ScCell;
Полный экран занимает 80 * 32 * 2 = 5120 байт. Renderer изменяет EMM-буфер,
помечает строки грязными, а backend выводит либо диапазон строк, либо весь
экран. Backend использует координатные ESTEX/BIOS-функции; основной пакетный
путь — проверенный WINREST. Прямой доступ к VRAM не используется.
Renderer использует смысловые роли атрибутов (frame, title, active,
passive, error), а не числа палитры. Модуль sc_theme, подтверждённый
пробой P2.2, назначает ролям разные атрибуты, сохраняет затрагиваемые записи
четырёх планов и восстанавливает их при cleanup. Это не меняет формат
ScCell или API renderer.
Системные BIOS/ESTEX-вызовы палитры разрешены; запрещён только обход системного
экранного API через прямую адресацию VRAM и оконные дескрипторы BIOS.
Дескрипторы BIOS WIN_OPEN/WIN_CLOSE/WIN_*_WIN не используются: BIOS хранит
только один описатель окна 0. Слово WIN в ESTEX WINREST означает область
экрана и не делает эту функцию частью BIOS window manager.
ADR-007. Источник файлов отделён от панели
Панель не вызывает ffirst/fnext напрямую. Она работает через модуль
источника. В PoC реализован только SC_SOURCE_REAL_FS.
Вместо таблицы виртуальных функций используется kind и обычный диспетчер:
typedef enum {
SC_SOURCE_REAL_FS = 0,
SC_SOURCE_SEARCH,
SC_SOURCE_ARCHIVE
} ScSourceKind;
Такой подход не создаёт near/far function pointers и упрощает размещение
реализаций по банкам. SEARCH и ARCHIVE до соответствующих этапов должны
возвращать внутреннюю ошибку SC_ERR_UNSUPPORTED, которая на границе
платформы при необходимости отображается как ESTEX EUNKOP.
ADR-008. Длительные операции являются jobs
Копирование, а позднее удаление, поиск и подсчёт размеров, оформляются как конечные автоматы:
INIT -> PREPARE -> RUN_CHUNK -> PRE_COMMIT -> COMMIT -> DONE
| | |
+-> CANCEL ----+-----------+
+-> ERROR -----+-----------+
Один шаг не должен надолго захватывать управление. Между блоками приложение
может обновить прогресс и проверить отмену. Даже последний успешно записанный
блок завершает только RUN_CHUNK: отдельный вызов переводит job через
PRE_COMMIT к атомарному rename. Поэтому Esc, полученный после отображения
N/N, всё ещё успевает закрыть и удалить temp до появления целевого файла.
ADR-009. Viewer, editor и setup сначала отдельные программы
Основной Commander отвечает за панели и операции с файлами. Просмотрщик,
редактор и настройка первоначально запускаются через EXEC как отдельные
.EXE. Это уменьшает HOME, число банков и последствия ошибки компонента.
После 1.0 они могут быть интегрированы банками, если измерения покажут реальную пользу.
3. Слои системы
+------------------------------------------------------+
| app: main loop, mode, active panel, command dispatch |
+----------------------+-------------------------------+
| panels/model | UI/dialogs/status |
+----------------------+-------------------------------+
| sources | renderer/screen buffer |
+----------------------+-------------------------------+
| jobs: copy/... | storage: EMM/page access |
+----------------------+-------------------------------+
| platform: ESTEX, keyboard, exec, screen, filesystem |
+------------------------------------------------------+
| libc + Sprinter DSS/BIOS |
+------------------------------------------------------+
Зависимости направлены вниз. platform не знает о панелях; storage не
показывает сообщения; renderer не читает файловую систему.
4. Предлагаемая структура исходников
Makefile
src/
sprcmd.c точка входа и аварийная очистка
sc_app.c главный цикл и состояние приложения
sc_command.c преобразование событий в команды и dispatch
sc_input.c клавиатурные события
sc_screen.c EMM framebuffer и dirty rows
sc_video_system.c координатный вывод ESTEX/BIOS без оконных ID
sc_draw.c рамки, строки, числа, сокращение путей
sc_panel.c состояние и поведение панели
sc_panel_draw.c представление панели
sc_dir_store.c записи каталога в EMM
sc_sort.c сравнение и сортировка записей
sc_source.c диспетчер источников
sc_source_fs.c настоящий каталог DSS
sc_copy_job.c PoC-копирование одного файла
sc_copy_ui.c банковая оркестрация F5 и прогресс
sc_dialog.c сообщения и подтверждения
sc_path.c безопасная работа с путями 8.3
sc_error.c нормализация errno/ESTEX ошибок
sc_platform_exec.c ESTEX EXEC/WAIT
sc_platform_screen.c wrappers WINREST/WRCHAR/SCROLL и screen mode
include/
sc_app.h
sc_command.h
sc_glyphs.h raw-коды CP866 для рамок и стрелок
sc_input.h
sc_screen.h
sc_panel.h
sc_store.h
sc_source.h
sc_job.h
sc_path.h
sc_platform.h
banks/
bank1_panel.c чтение/сортировка/обновление панелей
bank2_fileops.c копирование и диалоги операции
tests/
... target-тесты и данные для MAME
docs/
...
Граница файлов может уточняться по карте линковки. Нельзя объединять всё в один большой модуль: SDCC/линкер должны иметь возможность не тянуть лишний код и разнести холодные функции по банкам.
5. Состояние приложения
5.1. ScApp
В W2 хранится единственный объект состояния:
typedef struct {
ScPanel panels[2];
uint8_t active_panel;
uint8_t running;
uint8_t video_mode_saved;
uint8_t original_video_mode;
uint8_t emm_block;
uint8_t panel_page[2];
uint8_t screen_page;
ScJob job;
int16_t last_error;
} ScApp;
Фактическое определение может отличаться, но следующие инварианты обязательны:
active_panelравен 0 или 1;- обе панели ссылаются на разные EMM-страницы;
jobлибо неактивен, либо является единственным владельцем своих fd;- номера блоков и страниц обнуляются сразу после освобождения;
- cleanup можно вызвать после любой частично завершённой стадии init.
5.2. ScPanel
typedef struct {
char path[256];
uint16_t count;
uint16_t cursor;
uint16_t top;
uint32_t total_size;
uint8_t source_kind;
uint8_t phys_page;
uint8_t truncated;
uint8_t dirty;
} ScPanel;
Ограничения:
cursor < count, еслиcount != 0;cursor == 0, еслиcount == 0;top <= cursor;- видимый курсор лежит в диапазоне
top..top+26; count <= 640для всей линейки 0.1–1.0;pathвсегда завершён нулём.
6. Хранилище каталогов
Публичный интерфейс не возвращает указатель в W3:
int sc_store_get(const ScPanel *panel, uint16_t index, ScDirEntry *out);
int sc_store_put(ScPanel *panel, uint16_t index, const ScDirEntry *entry);
void sc_store_clear(ScPanel *panel);
Для пакетных операций допускается закрытая функция, которая отображает страницу на короткое время. Она должна:
- Сохранить текущую страницу W3.
- Подключить страницу панели.
- Выполнить только вычисления над памятью.
- Не вызывать ESTEX, renderer, банковский dispatch или пользовательский callback.
- Восстановить W3 перед возвратом.
Сортировка PoC должна быть нерекурсивной и не использовать callback qsort,
чтобы избежать лишнего кода и банковских переходов. Предпочтительный первый
вариант — Shell sort над одной отображённой страницей.
7. Чтение настоящего каталога
Последовательность sc_source_fs_scan():
- Проверить и нормализовать путь.
- Сохранить имя записи под курсором, если панель уже заполнена.
- Очистить счётчики панели, но не освобождать её страницу.
- При необходимости добавить синтетическую запись
... - Выполнить
ffirst("*.*")/fnextс одним общим 256-байтовым near-буфером. Шаблон*запрещён: P1 и P3 подтвердили, что DSS считает его именем без расширения и не возвращает обычныеNAME.EXT. - Пропустить
.и..от DSS. - Преобразовать
ffblk_tвScDirEntryи последовательно записать в EMM. - При достижении 640 записей установить
truncatedи немедленно закончить scan: следующийF_FIRSTсам переинициализирует глобальный итератор DSS. - На стабильном DSS 1.71 код 35 означает, что закончилась единственная
16-КБ страница кэша каталога, а не весь каталог. Принять уже прочитанные
записи, установить
truncatedи добавить последней красную виртуальную запись>>> MORE...с флагомSC_ENTRY_DSS_LIMIT. Она занимает один слот, не является файлом и не участвует в файловых операциях. - Отсортировать записи:
.., каталоги, файлы, маркер ограничения; внутри обычных групп применить ключ и направление конкретной панели. - Найти прежнее имя и восстановить курсор.
- Пометить панель и её экранные строки грязными.
Переборы двух панелей никогда не активны одновременно. ffblk_t не хранится
в EMM и не является частью состояния панели. Причина и варианты снятия
предела DSS разобраны в dss-large-directories.md.
Флаг SC_ENTRY_SELECTED хранится в самой 24-байтовой EMM-записи и переезжает
вместе с ней при сортировке. Резидентная ScPanel содержит только счётчик и
32-битную сумму выбранных обычных файлов. .. и виртуальные маркеры никогда
не выбираются; refresh в текущем срезе 0.2 явно сбрасывает выбор и статистику.
Одиночный Insert может менять флаг каталога, но все групповые операции
+, -, * сначала отбрасывают FA_DIREC и никогда не меняют ранее
установленный на каталоге флаг.
Маски +/- используют ASCII case-insensitive matcher с * и ? только
для файлов; специальный DOS-шаблон *.* совпадает также с именами файлов
без точки. Редактор
маски является общей координатной модальной поверхностью в BANK2: он рисует
поле в экранной EMM-модели, поддерживает insertion, Backspace, Delete,
Left/Right/Home/End и не создаёт BIOS-окно.
F6/F7 используют тот же editor и один validator компонента DOS 8.3. Локальный
F6 не передаёт полные пути в DSS RENAME: отдельный банковый helper сохраняет
CWD в резидентный scratch, входит в каталог панели, проверяет отсутствие
target, вызывает rename(old_basename, new_basename) и восстанавливает CWD.
Перезапись существующей записи запрещена до системного вызова.
F8 без выбора удаляет один объект после подтверждения: unlink для файла и
rmdir для пустого каталога. Непустой каталог и виртуальная запись не
запускают разрушительную операцию. При наличии выбора F8 одним
подтверждением сначала удаляет выбранные файлы верхнего уровня, затем
обходит все выбранные directory roots общей BFS-очередью, удаляет найденные
файлы и выполняет rmdir каталогов обратным проходом. При ошибке или Esc
уже выполненные действия не откатываются; CWD и EMM-страница освобождаются.
Групповой F5 проходит EMM-store по индексам и передаёт sc_copy_begin/step
только записи с одновременно установленным SC_ENTRY_SELECTED и снятым
FA_DIREC. Между файлами долговременный указатель W3 не сохраняется. При
ошибке уже committed-файлы остаются, активный temp удаляется прежней job;
это первая зафиксированная политика частично успешной группы.
F5 одного текущего каталога использует sc_tree: на время операции он
выделяет отдельную EMM-страницу с BFS-очередью до 1008 каталогов. Узел хранит
только parent-index, компонент DOS 8.3 и depth; путь восстанавливается перед
действием. Первый 256-байтовый диапазон страницы хранит исходный CWD.
Глубина ограничена 32, а путь — 255 символами. Файлы по-прежнему проходят
через единственную 4-КБ copy-page. Existing target не merge-ится; target
внутри source запрещается до создания root. Групповой F5 добавляет все
выбранные каталоги верхнего уровня как независимые roots той же очереди
после завершения выбранных top-level файлов.
8. Renderer
8.1. Интерфейс
Минимальные операции:
void sc_screen_clear(uint8_t attr);
void sc_screen_cell(uint8_t x, uint8_t y, uint8_t ch, uint8_t attr);
void sc_screen_text(uint8_t x, uint8_t y, const char *s, uint8_t attr,
uint8_t max_width);
void sc_screen_fill(uint8_t x, uint8_t y, uint8_t width,
uint8_t ch, uint8_t attr);
int sc_screen_scroll_rows(uint8_t x, uint8_t y, uint8_t width,
uint8_t height, int8_t delta);
void sc_screen_mark_rows(uint8_t first, uint8_t count);
int sc_screen_flush(void);
Экранный буфер — источник истины. Диалог рисуется в тот же буфер поверх панелей. Для PoC допустима перерисовка панелей после закрытия диалога вместо отдельного стека сохранённых окон.
8.2. Обновление
- Dirty mask занимает 32 бита в W2.
- Изменение курсора помечает старую и новую строку.
- Прокрутка панели помечает строки 1–27 её половины экрана.
- При изменении
topровно на одну строкуsc_screen_scroll_rows()сдвигает одновременно EMM-модель и экранный прямоугольник, затем renderer строит только открытую строку. PgUp/PgDn и большой скачок делают полный redraw области панели. - Смена каталога перерисовывает соответствующую половину и общие строки 29–31.
- Полный
sc_video_present_full()используется после запуска, возврата из.EXEи крупных изменений. sc_video_present_rect()группирует соседние грязные строки.
App-local WINREST wrapper проверен P1-пробой Commander: полный экран 80x32 и
окно 20x2 из offset 0x2000 восстановились корректно. P2.1 затем подтвердил
полную сверку через RDCHAR, оба направления прямоугольного scroll и 1000
операций. Координатный backend принят как основной пакетный способ вывода;
ограничения и артефакты описаны в
результатах P2.1.
9. Ввод и команды
sc_input.c преобразует getkey() и kbd_mod_state() в ScKeyEvent:
typedef struct {
uint8_t ascii;
uint8_t scan;
uint8_t modifiers;
} ScKeyEvent;
Модификаторы хранят только Shift, Ctrl и Alt; состояния CapsLock, NumLock и Rus/Lat не участвуют в выборе команды.
P1 установил особенность DSS: при модифицированной клавише бит 7 raw
scan-кода установлен. Например, Ctrl+R даёт 93, Ctrl+PgUp — D9, Alt+F1
— BB. sc_input нормализует их в 13, 59, 3B через scan & 0x7F,
но только после чтения compact modifiers. Таблица команд никогда не содержит
raw-коды с битом 7.
sc_command.c превращает событие в ScCommand. Остальные модули не должны
сравнивать scan-коды непосредственно. Команды описаны в
commander-keymap.md.
В MAME kbd_mod_state() в момент возврата getkey() сохранил активный
модификатор: compact Ctrl=02, Alt=04, Shift=01. Для переносимости
управляющие ASCII-коды (Ctrl+R и подобные) всё равно имеют явные алиасы,
не зависящие от live-состояния.
10. Копирование как конечный автомат
Состояния PoC:
IDLE
-> VALIDATE
-> CREATE_TEMP
-> OPEN_SOURCE
-> COPY_CHUNK <----+
-> CLOSE_FILES |
-> RENAME_TEMP |
-> REFRESH |
-> DONE |
|
COPY_CHUNK -----------+ пока done < total
|-> CANCEL -> CLEANUP -> DONE
+-> ERROR -> CLEANUP -> DONE
Правила:
- конечное имя проверяется до создания temp;
- temp создаётся в целевом каталоге с
O_CREAT|O_EXCL; - имя temp имеет форму
~SCxxxx.TMPи перебирается с ограниченным числом попыток; - рабочая область находится в отдельной EMM-странице и временно отображается в W3; 4-КБ массива в W2 и изменяемого буфера в банке кода нет;
- начальный логический размер блока — 4096 байт, чтобы между блоками часто обновлять прогресс и проверять отмену; после измерений он может быть увеличен вплоть до размера страницы;
- чтение выполняется существующим
bank_read_page()прямо из открытого fd в страницу; для записи нужен симметричныйbank_write_page(), который сохраняет и восстанавливает отображение W3; - открыто не более двух fd;
- успешность
write()определяется его библиотечным контрактом, а не сырым DE ESTEX; - при short write оставшаяся часть блока дописывается или операция завершается ошибкой;
- после успешного закрытия temp конечное имя проверяется повторно, и только затем temp переименовывается в него;
- FAT date/time задаются temp через
PUT_D_Tперед close; после rename конечное имя получает исходные R/H/S/A черезATTRIB; - ошибка после rename помечается как ошибка финализации уже committed-файла, а не как полное отсутствие результата;
- любое завершение проходит через единый cleanup;
- после успеха перечитывается пассивная панель.
P19 добавляет policy существующего файла. Safe overwrite сначала переводит
старый target в уникальный ~SBxxxx.BAK, затем commit-ит temp. При отказе
второго rename backup возвращается на место вместе с исходными атрибутами;
после успешных метаданных нового target backup удаляется. overwrite all и
skip all — локальное состояние одного F5. Readonly не наследует молча
overwrite all, а повторно показывает choice-dialog.
Для версии 0.2 этот автомат расширяется очередью файлов, обходом каталогов, политиками overwrite/skip/rename и сохранением метаданных.
11. Запуск дочерней программы
Последовательность:
- Завершить или запретить активный job.
- Сформировать проверенный абсолютный путь
.EXE. - Запомнить активную панель, курсоры и ожидаемый CWD; временно сделать путь активной панели текущим каталогом child.
- Выполнить синхронный ESTEX
EXECсB=1и сразу сохранить его результат до других вызовов libc. - Восстановить ожидаемые диск и CWD.
- Повторно установить текстовый режим 80x32 и палитру Commander, не меняя сохранённую палитру для финального shutdown.
- Перечитать обе панели: внешняя программа потенциально могла изменить оба их каталога.
- Полностью вывести экран из screen page.
- При ошибке показать её штатной строкой состояния Commander.
P1 подтвердил контракт wrapper: C-сигнатура
p1_exec(uint8_t path_mode, const char *path) получает mode в A и path в DE,
затем перекладывает их в B и HL для ESTEX. B=0 с коротким именем и B=1
с явным относительным путём работают; probe получил 0x5A. В Commander
низкоуровневый sc_platform_exec(path) фиксирует B=1, принимает путь в HL
по __sdcccall(1) и возвращает код завершения как int в DE.
11.1. Командная строка и Ctrl+O в 1.0
В VC 4.05/4.99 Ctrl+O переключает панели и user screen, а редактор DosBuf
работает вместе с prompt и историей. Dos Navigator дополнительно показывает
самостоятельный TCommandLine с горизонтальной прокруткой и историей. На Sprinter
родительская DSS-shell приостановлена, поэтому её нельзя превратить в интерактивный
фон простым скрытием панелей.
Поэтому 1.0 использует собственный pseudo-shell:
- однострочный prompt на экране панелей и полноэкранный режим делят один редактор, историю и модель текущего каталога;
Ctrl+Oпереключает режимы; возврат к панелям полностью строит их изScPanel, поэтому отдельная копия экрана панелей не нужна;- builtin-команды минимум
cd, смена диска,dir,cls,pwd,help; - внешняя команда запускается через подтверждённый ESTEX
EXEC; после возврата pseudo-shell восстанавливает видеорежим, CWD и свою экранную модель; - вывод и скролл идут через тот же безоконный screen backend; прямой VRAM и BIOS window manager не используются;
- полноэкранные ячейки могут повторно использовать текущую screen page. До
фиксации поведения внешнего
.EXEотдельной пробой проверяетсяWINCOPY.
12. Ошибки и владение ресурсами
Низкий уровень возвращает 0/-1 и устанавливает errno. UI не анализирует
Carry Flag или регистры DSS.
Каждый ресурс имеет одного владельца:
| Ресурс | Владелец |
|---|---|
| общий EMM-блок PoC | ScApp |
| физическая страница панели | ScPanel, без права освобождения блока |
| экранная страница | sc_screen, без права освобождения блока |
| рабочая страница копирования | ScApp/copy job, без права освобождения блока |
| fd источника и temp | активный ScCopyJob |
| исходный видеорежим | ScApp |
| временно отображённая W3 | текущая функция storage/screen |
Cleanup выполняется в обратном порядке инициализации. Нельзя прятать владение fd или EMM-блоком в локальном static-состоянии модуля.
13. Предварительная карта кода
HOME/W2 содержит только постоянно необходимое:
- crt0, банковские трамплины и используемую libc;
- init/cleanup;
- главный цикл;
- ввод и базовый dispatch;
- EMM accessors;
- screen flush;
- критическую обработку ошибок.
Предварительные банки:
| Банк | PoC | Полная версия |
|---|---|---|
| 1 | panel scan, sort, redraw model | панели, сортировки, режимы панели |
| 2 | copy job, operation dialog | копирование/перемещение/удаление |
| 3 | не нужен | меню, конфигурация, история |
| 4 | не нужен | поиск и дерево |
| 5 | не нужен | архивные/виртуальные источники |
Номер банка является деталью сборки, а не публичным ABI. Банковские модули
не должны хранить долгоживущие payload-данные в локальном сегменте банка.
Краткоживущий ffblk_t является обычным near-буфером; закреплять его в хвосте
W1 бессмысленно, поскольку граница больших каталогов находится внутри DSS.
После каждой сборки проверяются:
- размер HOME вместе с DATA/BSS и heap;
- запас каждого банка до 16 КБ;
- отсутствие прямых вызовов в чужой банк;
- расположение трамплинов;
- стек W2 при всех вызовах ESTEX.
14. Эволюция после PoC
Версия 0.2
- одностраничное хранилище остаётся ограничено 640 записями;
- выбранные файлы и маски;
- очередь операций;
- рекурсивный обход;
- local rename, mkdir, recursive group copy/delete выполнены; group move и защитная policy остаются;
- транзакционная перезапись файлов и conflict-policy выполнены; directory merge и delete/move policy остаются;
- атрибуты и время обычных файлов выполнены; метаданные каталогов — позже.
Версия 0.4
- командная строка, история и полноэкранный pseudo-shell по
Ctrl+O; - associations/user menu;
- внешний viewer/editor/setup;
- конфигурационный файл;
- переключение дисков.
Версия 0.6
- quick view и info source;
- дерево и поиск;
- фильтры и сравнение каталогов;
- подсчёт размеров каталогов;
- описания файлов.
Версия 0.8+
SC_SOURCE_SEARCHкак виртуальная панель;SC_SOURCE_ARCHIVE;- протокол внешних helper-программ;
- мышь, помощь, локализация;
- измеренная оптимизация кэшей и renderer.
Версия 2.0+
- динамическое выделение EMM-страниц панели;
- предел 1024/2048 или отсутствие продуктового предела после измерений;
- межстраничная сортировка без полной копии каталога в W2;
- деградация при нехватке EMM и тесты частично выделенных цепочек страниц.
15. Архитектурные запреты
- Нельзя вызывать DSS при стеке вне W2.
- Нельзя держать одновременно восемь файловых дескрипторов.
- Нельзя сохранять W3 pointer в состоянии приложения.
- Нельзя менять W1 вручную из банковской функции.
- Нельзя вызывать чужой код при оставленной временной странице W3.
- Нельзя выполнять разрушительную операцию без известного cleanup-path.
- Нельзя смешивать вывод через
printfс экранной моделью во время работы UI. - Нельзя добавлять функцию DN только потому, что она присутствует в DN; каждая функция должна соответствовать roadmap Commander.