diff options
| author | Valentin Popov <valentin@popov.link> | 2026-10-29 20:20:45 +0300 |
|---|---|---|
| committer | Valentin Popov <valentin@popov.link> | 2026-10-29 20:20:45 +0300 |
| commit | cc5c6414ce68e93a9b7f3c95cc07e9120b400fc1 (patch) | |
| tree | 6932d76d4041901a31415d3412b66271a233f8e9 /docs | |
| parent | 6c079d9457fddf9927d3e2057463d95c502d4673 (diff) | |
| download | fparkan-cc5c6414ce68e93a9b7f3c95cc07e9120b400fc1.tar.xz fparkan-cc5c6414ce68e93a9b7f3c95cc07e9120b400fc1.zip | |
feat(runtime): project native Control object classes
Diffstat (limited to 'docs')
| -rw-r--r-- | docs/appendices/knowledge-boundaries.md | 22 | ||||
| -rw-r--r-- | docs/appendices/script-vm.md | 55 | ||||
| -rw-r--r-- | docs/tomes/06-behavior.md | 14 |
3 files changed, 89 insertions, 2 deletions
diff --git a/docs/appendices/knowledge-boundaries.md b/docs/appendices/knowledge-boundaries.md index e73ba68..be2277a 100644 --- a/docs/appendices/knowledge-boundaries.md +++ b/docs/appendices/knowledge-boundaries.md @@ -202,8 +202,8 @@ Unit DAT создаёт тот же Behavior-компонент во всех ho prototype roots без Unit DAT и отложенные spawn после исходной загрузки вне этой модели. Путь в `ArealMap.dll` (SHA-256 `a25f9254ebb339d70e2e07c8121950191e9584ca0858d8e9c2e2b6c671edf6ea`) к -`CreateObject` по RVA `0x14fd0`/`0x15290` показывает выбор World3D class 3 или 4 -по старшему биту. Для ветки GOG `AniMesh.dll` (SHA-256 +`CreateObject` по RVA `0x14fd0`/`0x15290` показывает выбор World3D factory +selector `3` или `4` по старшему биту. Для ветки GOG `AniMesh.dll` (SHA-256 `65659bf67f20e5be77d67a5b2f59968f61b94293143807fa59ca451c560c4f7e`) RVA `0x2ff0` показывает одну ветку создания: после QueryInterface для IID `0x204` выполняется отдельный импорт `GetQueue()`, а на возвращённом объекте вызывается @@ -247,6 +247,24 @@ CTLD и связанные resources структурно читаются, coun известны. Не названы все секции, shape types, coefficients и точный contact solver. То же относится к редким MSH auxiliary streams и части CTPT/NDPR flags. +### Класс Control при загрузке Unit DAT + +Для двух подтверждённых полных Unit-DAT путей Rust теперь сохраняет класс, +который передаётся конструктору Control, вместе с ветвью-источником. Лицензированный +`min_l_n1.dat` проходит high-bit route и даёт класс `3`; synthetic-тесты покрывают +оба маршрута, известные FourCC и отсутствующие root metadata. Отдельное +исполнение проверило только чистый getter `Terrain.dll+0x33ae0` (SHA-256 и точный +RVA приведены в технической главе). Остальная цепочка через ArealMap, World3D, +Terrain/AniMesh и создание controller восстановлена по статическим инструкциям, +таблицам и конфигурации. Она не означает исполнения оригинального полного +loader-а, Control activation, движения или периодического tick. + +Не моделируются произвольный ненулевой host с неудачным QueryInterface, preview +без полного Unit DAT, отложенный spawn и другие host/factory routes. В частности, +generic failed-query путь native оставляет class `0` и не читает FourCC; это не +эквивалентно canonical no-host lookup корневой registry entry. Остаточные вопросы +об активации и игровом поведении описаны в технической главе. + Одна цепочка Unit DAT → AniMesh descriptor → Control теперь восстановлена статически в [главе о Behavior и Control](../tomes/06-behavior.md): raw `parent_or_link` копируется в descriptor. В non-`EXTO` registry path parent ID diff --git a/docs/appendices/script-vm.md b/docs/appendices/script-vm.md index a1e867d..d47a64d 100644 --- a/docs/appendices/script-vm.md +++ b/docs/appendices/script-vm.md @@ -977,6 +977,61 @@ Ignored Rust-тест также проходит полный неотфильÑ профилю. Это подтверждает декодирование и CPU-проекцию, но не исполнение native полного загрузчика. +#### Входной класс Control при загрузке Unit DAT + +Этот класс задаётся до разбора CTLD и не выводится из device tag или MSH- +геометрии. В GOG `ArealMap.dll` (SHA-256 +`a25f9254ebb339d70e2e07c8121950191e9584ca0858d8e9c2e2b6c671edf6ea`) +`FUN_10014fd0` (RVA `0x14fd0`) вызывает полный путь `FUN_10015290` (RVA +`0x15290`), который читает class word разобранного корня Unit DAT по `+0x78`; +это смещение поля в структуре, а не raw file offset. Установленный старший бит +выбирает `World3D.CreateObject` selector `3`, снятый — selector `4`. В GOG +`World3D.dll` (SHA-256 +`17e4a3089b2583a8cf2356c9db0390b1aba138356a09130d79b4e7e4791da61e`) RVA +`0x7cb0` ведёт к внутренней реализации `0x7a50`, где selectors `3` и `4` +направляются соответственно в registered CID `1` и `3`. +`Comp.ini` (SHA-256 +`3ce88fc077fcc9659d7b87ed0caaa6885ba6d2e2307250cbc0eb75661c295df8`) +связывает CID `1` с `Terrain.LoadBuilding`, а CID `3` — с `AniMesh.LoadAgent`. +Selector, CID и класс Control — разные значения, хотя первый route приводит к +совпадающему числу `3`. + +У маршрута selector `3` внешний host-аргумент `Terrain.LoadBuilding` пуст. +`Terrain.dll` (SHA-256 +`af87d1b2e728a0be73c52be3b44cc196ab46da7799f25a15d40f8c9b0b425ead`) +создаёт `CBuilding` через RVA `0x32490`/`0x324d0`, записывает пустой внешний +родитель в `+0x14`, затем передаёт сам `CBuilding` в `AniMesh.LoadAgent`. +`AniMesh+0x2ff0` вызывает `QueryInterface(6)` и получает обратно primary +указатель `CBuilding`. Его vtable slot `+0x2c` находится по Terrain RVA +`0x65548` и указывает на `Terrain.dll+0x33ae0`. Вызванные отдельно машинные инструкции +этого getter-а — `B8 03 00 00 00 C3`, то есть он возвращает класс `3`. +Постоянный x86 harness проверяет SHA-256, эти байты и прямой вызов getter-а с +`this = null`; это исполненная проверка getter-а. Связь от Unit DAT через +wrapper и vtable восстановлена статически, а не прогнана целиком в оригинальной +игре. + +При selector `4` `AniMesh.LoadAgent` получает пустой host. Конструктор начинает +Agent class field `+0x6d8` с нуля; путь `AniMesh.dll` (SHA-256 +`65659bf67f20e5be77d67a5b2f59968f61b94293143807fa59ca451c560c4f7e`) RVA +`0x2ff0` берёт FourCC из корневой записи NRes registry. Дальше вызов +`LoadControlSystem` по AniMesh RVA `0x32e7` передаёт значение `+0x6d8` в качестве +последнего аргумента; `Control.dll` (SHA-256 +`bcb86318089028548a178b03a21accdce15df0cc85ddd91674cf3c2f55012c6e`) RVA +`0x32280` выбирает для класса `9` конструктор `0x7330`, а для остальных — +`0x31490`. + +Правило прямого no-host пути: `BTLU → 4`, `BULL → 9`, `WPNS → 2`, `STAT → 10`; +другой root FourCC даёт `0`. Источник — NRes registry metadata именно корневой +записи (`EffectivePrototype.source_type`), не первый DWORD CPT payload и не +запись ребёнка. Если заголовок отсутствует, класс Rust оставляет неопределённым +(`None`); при установленном старшем бите выбирается `3`, даже если FourCC нет. +Только в прямом no-host пути отсутствие root FourCC даёт `None`. У произвольного +ненулевого host, который не возвращает +нужный интерфейс, native field также остаётся `0`, но FourCC в этой ветви не +читается; этот generic route не считается одним из двух полных Unit-DAT путей. +Runtime сохраняет класс и источник выбора, не запуская Control clock или +конструкторы gameplay state. + #### Активация и начальные часы Для Control класса `4` oracle вызывает исходный конструктор RVA `0x31490` diff --git a/docs/tomes/06-behavior.md b/docs/tomes/06-behavior.md index 45a6303..68a35e6 100644 --- a/docs/tomes/06-behavior.md +++ b/docs/tomes/06-behavior.md @@ -662,6 +662,20 @@ parent ID через Control IID `0x202`, virtual slot `+0x44`, только еÑ исходный ключ `1` становится `22`. Этот ключ выбирает модельный узел, а не строку Control. Записи корня остаются в исходном виде. +#### Входной класс контроллера + +Таблица устройств и класс самого Control-контроллера выбираются разными +частями загрузки. У полного объекта из Unit DAT старший бит флагов корня решает, +каким путём создать host. В ветви с этим битом объект проходит через Terrain; +эта оболочка передаёт AniMesh native-класс Control `3`. Если бит не установлен, +класс выбирает FourCC записи корневого ресурса: `BTLU` даёт `4`, `BULL` — `9`, +`WPNS` — `2`, `STAT` — `10`, а неизвестный FourCC оставляет класс `0`. + +Например, `min_l_n1.dat` хранит флаги `0x80000004`, поэтому его проекция +получает класс `3`. Это аргумент конструктора Control, а не номер строки +устройства и не само по себе включение движения или обновлений. Техническая +цепочка и границы проверки описаны в [приложении](../appendices/script-vm.md#входной-класс-control-при-загрузке-unit-dat). + ### Как Control добавляет и переопределяет устройства В `Control.dll` (SHA-256 |
