aboutsummaryrefslogtreecommitdiff
path: root/docs/appendices/knowledge-boundaries.md
diff options
context:
space:
mode:
Diffstat (limited to 'docs/appendices/knowledge-boundaries.md')
-rw-r--r--docs/appendices/knowledge-boundaries.md131
1 files changed, 94 insertions, 37 deletions
diff --git a/docs/appendices/knowledge-boundaries.md b/docs/appendices/knowledge-boundaries.md
index 3d97927..a31b561 100644
--- a/docs/appendices/knowledge-boundaries.md
+++ b/docs/appendices/knowledge-boundaries.md
@@ -10,6 +10,10 @@ authoring API без динамического подтверждения.
Не доказаны символами точные имена renderer vtable slots, полный набор CShade
state transitions и окончательный порядок части transparent/FX/shadow subpasses.
+Свободная камера превью удерживается в XY-границах поверхностей карты и над
+рельефом. Она пока не проверяет стены и проёмы строений; эти ограничения не
+подтверждают поведение стратегической камеры или камеры робота оригинала.
+
Закрывающий эксперимент: запустить оригинал в совместимой Windows/DirectX
среде, перехватить DirectDraw/Direct3D calls и surface flips, сохранить state
log на минимальных сценах с одним типом материала.
@@ -478,20 +482,35 @@ Control выставлен flag `0x102`, слово флагов ANI `+0x14` и
пересчитывается при каждом принятом активном вызове. Проверены также точное
равенство с ненулевым RNG, расход RNG при принудительном `+0xd4` и сохранение
RNG/счётчика в неактивной ветви. Движение и очереди исключены условиями этих
-векторов; активация `+0xe0` задана явно. Отдельный вектор
-класса `4` исполняет событие `4` через `0x31ae0` → `0x314f0`, проверяя
-активность, начальные часы `time - 100`, округление DWORD в `f32` и одну
-начальную команду. Геометрические callbacks подставлены явно, таблицы
-устройств и shapes пусты; полный загрузочный путь не проверен. Источник времени
-и доставка прослежены статически:
+векторов; активация `+0xe0` задавалась явно. Отдельный native-вектор класса `4`
+вызывает `0x314f0` через синтетический owner `+4` и переходник `0x31ae0`.
+Он сравнивает raw `f32` слова абсолютных часов и baseline, вычисленный до
+округления `u32` в `f32`: для `16777217` это `0x4b800000/0x4b7fff9d`, для
+`16777219` — `0x4b800002/0x4b7fff9f`. Последовательность `100`, `101` оставляет
+`+0xe4` нулём после первого вызова, поэтому старое условие `+0xe4 == 0` добавляет
+начальную команду повторно: счётчик `+0x370` переходит с `1` на `2`. Это путь
+тестового интерфейса owner `+4`; статическая цепочка AniMesh `Agent+0x158`
+ведёт к primary Control owner slot `+0x08` напрямую в `0x314f0`. Геометрические
+callbacks подставлены явно, матрица identity и масштаб единичный, таблицы
+устройств и shapes пусты. Вектор подтверждает ABI/арифметику часов, но не
+реальную матрицу и callbacks из миссии или полный Unit DAT loader.
+
+Источник времени и доставка прослежены статически:
World3D RVA `0x6bf0` вычисляет часы из `timeGetTime()` с игровым смещением и
поправкой на паузу, затем выполняет первый обход `6/1`, шаг мировой физики и
-второй обход `6/0x1c`. AniMesh RVA `0x1370` передаёт часы Control; общий
-обработчик Control RVA `0x7830` численно преобразует unsigned DWORD в `f32`
-перед primary slot `+0x58`. Фабрика выбирает RVA `0xcbb0` для класса `9` и
-RVA `0xbcf0` для остальных. Это подтверждает статическую цепочку вызовов, но не
-её исполнение на миссии: связывание интерфейсов, активация устройств и shapes,
-остальные ветви `0xbcf0` и
+второй обход `6/0x1c`. При создании объекта World3D RVA `0x7cb0` вызывает slot
+`+0x38` с literal-null payload в `0x7d1a`, а затем передаёт в тот же slot DWORD
+из `DATWorld+0x32a38` в `0x7e6e`; RVA `0x7ea0` повторяет передачу часов в
+`0x80a9`. Setter RVA `0x5140` записывает этот DWORD в `DATWorld+0x32a38`.
+AniMesh RVA `0x2ff0` получает для `Agent+0x158` Control base owner по QI selector
+`0xa`, после чего `Agent` RVA `0x1a80` dispatch-ит событие `4` через его primary
+slot `+0x08` прямо в `Control.dll+0x314f0`. Это и отдельный синтетический вызов
+через owner `+4` — подтверждённые интерфейсные пути, но пока не единая трасса
+игрового старта. Control RVA `0x7830` численно преобразует unsigned DWORD в
+`f32` перед primary slot `+0x58`; фабрика выбирает RVA `0xcbb0` для класса `9` и
+RVA `0xbcf0` для остальных. Статические вызовы не подтверждают их исполнение на
+миссии: связывание реальных интерфейсов, активация устройств и shapes, остальные
+ветви `0xbcf0` и
автоматическое изменение provider через clock и бюджет Rust остаются открытыми. Источник контактного коэффициента прослежен статически,
но не исполнен. Подробные векторы и статические границы приведены в
[техническом подразделе о provider-состоянии Control](script-vm.md#изменение-provider-состояния-control).
@@ -569,23 +588,52 @@ resource-device значения во время игры.
и mirror-варианты передают свой transform-вектор setter-у; это отдельная
граница, как и более поздние placement/tick.
-Полный Rust loader теперь вызывает FAC0 при построении
-`build_control_device_projection` и публикует результат в
-`MissionControlOwnerProfile::load_projection`. Игнорируемый corpus-тест
-`full_load_builds_effective_control_device_table_for_mine_unit_dat` на лицензированном
-`min_l_n1.dat` проверяет 11 устройств, все 25 соответствий provider ordinal
-модели и упорядоченные значения `row +0x20`. Его агрегаты —
-`0x470833fc/0x4897e712/0x4d9452cb` для `+0x530/+0x534/+0x538`; исходный и
-начальный mutable word `26` равны `0x7f7fffff`. Это подтверждает Rust full-load
-результат на оригинальных ресурсах, но не совпадение с полным нативным load
-оригинала. Поведение позже при placement/tick и физический смысл raw-полей
-остаётся неизвестным. Точные RVA, owner layout и векторы приведены в
-[описании изолированного прохода FAC0](script-vm.md#изолированный-проход-fac0).
-
-Остаётся сравнить этот полный mine load с original loader при тех же входных
-данных и продолжить трассировку `LoadControlSystem`, `LoadPhysicalModel`,
-`CreateCollManager` и collision objects, если потребуется связать profile words
-с shapes, contacts или реакцией на движение.
+Полный Rust loader теперь выполняет FAC0, затем FCA0 при построении
+`build_control_device_projection_with_class`. `MissionControlOwnerProfile::load_projection`
+сохраняет отдельный результат FAC0, а `fca0_projection` — статус следующего
+прохода. FCA0 проверяет класс **владельца** `owner +0x50`: класс `9` сразу
+возвращает неизменённую копию; это не условие по device factory tag `9`. Любой
+известный класс, отличный от `9`, включая `0`, проходит общий расчёт. В Rust
+`MissingNativeControlClass` означает, что проекция не восстановила метаданные
+класса, а не то, что оригинальная DLL не содержит класс. `Fac0Unavailable`
+применяется только к не-классу-9 ветви, потому что класс `9` выходит до проверки
+FAC0.
+
+FCA0 суммирует selector `0xe00` в обратном порядке по устройствам с текущим
+descriptor tag `5`. Изолированный x86-вектор исполняет оригинальный reader
+`0x21d00` и FCA0. Статическая проверка двух factory vtables подтверждает общий
+reader `0x21d00` и setter `0x21d50` для tags `5`/`26`; provider getter `0x0dc40`
+использует `owner +4`, а canonical `QueryInterface(0x204)` задаёт
+`owner +0x38 -> owner +0x0c`.
+В каноническом constructor/event-4 пути scalar `+0x1a8` и means `+0x354/+0x358`
+равны `1.0`. На исходном Control.dll с SHA-256
+`bcb86318089028548a178b03a21accdce15df0cc85ddd91674cf3c2f55012c6e` FCA0
+подтверждена по RVA `0x0fca0` при x87 control word `0x007f`. Слова
+`[0,1,2,6,7,8,9,10,11]` в canonical-default векторе имеют биты
+`40200000 c0a00000 40c00000 3f800000 40000000 41200000 41e70000 c22d4000 40e70000`.
+
+Лицензированный тест `full_load_builds_effective_control_device_table_for_mine_unit_dat`
+настоящего `min_l_n1.dat` теперь проверяет class `3`, `fca0_projection = Ok(())`,
+11 устройств и все 25 provider rows. Его девять target words
+`[0,1,2,6,7,8,9,10,11]` равны
+`40000000 40000000 40000000 00000000 00000000 00000000 00000000 00000000 00000000`;
+word `26` после FAC0 остаётся `0x7f7fffff`, а оригинальный блок, FAC0 агрегаты
+`0x470833fc/0x4897e712/0x4d9452cb` и 25 значений строк сохраняются. Это Rust
+full-load результат на оригинальных ресурсах, а не сравнение полного native
+Unit DAT loader-а или gameplay. Rust helper поддерживает только конечные входы
+и промежуточные значения домена `normal-or-zero`; прочие битовые случаи остаются
+вне заявленного диапазона.
+
+Полный динамический жизненный цикл после начальной загрузки не подтверждён:
+поздние изменения owner scalar/means, activation, игровые часы, Control tick и
+placement не сведены в одну проверенную трассу и не включены в Rust-проекцию.
+Отдельные constructor, setter и loader-пути уже прослежены; физические единицы
+слов профиля и накопителей остаются неизвестны. Для закрытия границы нужны
+динамическая трассировка и сравнение полного Unit DAT load с оригинальным
+loader-ом при одинаковых ресурсах и условиях.
+Подробные RVA, QI/provider layout, арифметика и пределы векторов приведены в
+[описании изолированного прохода FAC0](script-vm.md#изолированный-проход-fac0)
+и [разборе FCA0](script-vm.md#изолированный-проход-fca0).
## DirectPlay wire
@@ -600,14 +648,23 @@ Native interoperability подтверждается только успешны
Граница shell подтверждена exports `createShell/getIShell`, `IGUIServer`,
верхнеуровневым UI-pass и файлами `ui/*.cfg`, `DATA/TextRes.cfg`,
-`gamefont.rlb` и `sprites.lib`. RsLi framing библиотек закрыт, но widget tree,
-layout rules, glyph metrics, sprite command semantics, focus/navigation и HUD
-state machine пока не восстановлены до field-level спецификации.
-
-Закрывающий эксперимент: трассировать загрузку `shell_ctrls.cfg`,
-`menu_resources.cfg`, `cursor.cfg`, `game_resources.cfg` и `hq.cfg`, сопоставить
-GUI object factories и снять command/event captures для меню, HUD, briefing и
-диалогов.
+`gamefont.rlb` и `sprites.lib`. Для полной GOG-сборки подтверждены раздельные
+форматы: `gamefont.rlb` читается общим RsLi reader, но его native consumer этим
+не установлен; для меню подтверждена цепочка `menu_resources.cfg` → NRes
+`font.lib` → native lookup `MENU_FONT` с получением реального font-объекта.
+Reader `fparkan-font` разбирает 20-байтовый Tfnt prefix, 256 записей фиксированного
+шага и передаёт вложенный Texm общему reader-у. Native consumer подтверждает
+два целочисленных параметра, per-byte spacing и signed advance; смысл трёх glyph DWORD
+и поля заголовка по `0x0c` пока не установлен. Это не реализует выбор шрифта, текстовый
+layout или glyph drawing. `menu_resources.cfg` и шесть вариантов
+`MENU_FONT`/`GAME_FONT` сопоставлены с NRes-записями в
+[разборе shell и шрифтов](ui-shell.md). Также остаются открытыми выбор dimension
+на фактическом дисплее `1280x1024`, widget tree, layout rules, sprite command
+semantics, focus/navigation и HUD state machine.
+
+Закрывающий эксперимент: сопоставить оставшиеся детали `shell_ctrls.cfg`,
+`cursor.cfg`, `game_resources.cfg` и `hq.cfg` с GUI object factories и снять
+command/event captures для меню, HUD, briefing и диалогов.
## Research, economy and properties