diff options
Diffstat (limited to 'docs')
| -rw-r--r-- | docs/appendices/knowledge-boundaries.md | 38 | ||||
| -rw-r--r-- | docs/tomes/03-resources.md | 11 | ||||
| -rw-r--r-- | docs/tomes/06-behavior.md | 45 |
3 files changed, 82 insertions, 12 deletions
diff --git a/docs/appendices/knowledge-boundaries.md b/docs/appendices/knowledge-boundaries.md index 5791836..27cf74a 100644 --- a/docs/appendices/knowledge-boundaries.md +++ b/docs/appendices/knowledge-boundaries.md @@ -253,12 +253,26 @@ solver. То же относится к редким MSH auxiliary streams и ч разрешается в индекс устройства и сдвигает локальный индекс только когда parent ID не равен `-1` и IID `0x202` доступен; иначе используется raw локальный индекс. В этом потоке нулевой raw kind пропускает узел вместе с потомками, поэтому общий -assigned ID нельзя получать из preorder-позиции записи. Это закрывает только -передачу полей в native loader-е; Rust ещё должен строить такую же проекцию. - -Control loader также различает добавление устройств и применение одной записи -к уже выбранному устройству. Для tag `19` найденные поля и ветви описаны в -главе, но эффективное слияние пока не реализовано. В Rust parser-е +assigned ID нельзя получать из preorder-позиции записи. Полная загрузка миссии +в FParkan строит упорядоченную базовую проекцию таблицы +Control для объектов с Unit DAT: корневые записи добавляются, `EXTO` добавляет +строки с ключами глобальной MSH-иерархии, а `INTO` обновляет первую строку +выбранного индекса либо добавляет список при sentinel `-1`. Проверка полной +загрузки на оригинальном `min_l_n1.dat` получает 11 строк: 10 корневых записей, +четыре замены `INTO` и одну добавленную строку дочернего `EXTO`. Ветви C4/C8 и +добавление `EXTO` подтверждены машинными инструкциями оригинальных модулей, но +полный результат FParkan не сравнивался с таблицей из запущенной игры. Тест на +искусственном дереве также проверяет ID после пропущенного поддерева с raw kind +`0`. Проекция хранит общие поля и происхождение записей; она не исполняет все +обработчики Control. + +Control различает добавление устройства и применение одной записи к уже +выбранному устройству. Исполнение оригинальной 32-битной DLL на искусственных +данных подтверждает общую ветвь переопределения для получателей tags `9`, `15`, +`19` и `25`: остаются прежними слот, ключ, ID компонента, множитель и класс, +а коэффициенты копируются из новой записи. Искусственный tag `9`-объект создан +без FX-хоста (`+0x3c == 0`), а запись не содержит строк таблицы map; поэтому +работа FX-хоста здесь не проверялась. В Rust parser-е `Unsupported { typed_record_index: Some(_) }` означает, что разбор остановился внутри списка typed records; без индекса остановки unsupported может относиться к effect-tail после уже разобранного списка. Эти случаи нужно различать. @@ -269,10 +283,14 @@ Control loader также различает добавление устройс трактоваться как пустой список. Глобальные Control selectors `1/2` и setter selector `1` по tag `19` описаны -там же только по статическому разбору `Control.dll`; execution oracle для этих -глобальных вызовов нет. Остаются открытыми проверка effective merge на живых -объектах, полный охват registry types и host factory paths, а также runtime -жизненный цикл множителя `+0x4c`. +там же только по статическому разбору `Control.dll`; их вызовы отдельно не +исполнялись. Проекция полного mission load недоступна для неполного списка +typed records, Control resource у non-geometric prototype и некоторых +неразрешённых EXTO node mappings; preview и объекты без Unit DAT root её не +строят. Её соответствие полной загрузке игры для всех типов компонентов и +factory paths ещё не установлено. Не восстановлен и жизненный цикл множителя +`+0x4c` после конструктора и переопределения; также неизвестно, когда эти +объекты создаются при отложенной загрузке. Для `Control.dll` (SHA-256 `bcb86318089028548a178b03a21accdce15df0cc85ddd91674cf3c2f55012c6e`) tag-26 diff --git a/docs/tomes/03-resources.md b/docs/tomes/03-resources.md index a11ad55..a349a79 100644 --- a/docs/tomes/03-resources.md +++ b/docs/tomes/03-resources.md @@ -477,8 +477,15 @@ struct UnitDatRecord112 { При построении mission prototype graph FParkan сохраняет для каждого root упорядоченный список этих raw records. Список передаётся в -`MissionObjectDraft` с исходными `kind`, `parent_or_link`, description и tails; -эти данные пока не объединяются в таблицу эффективных устройств Control. +`MissionObjectDraft` с исходными `kind`, `parent_or_link`, description и tails. +Во время полного mission load runtime использует дерево и подготовленные CTL +resources, чтобы построить для такого объекта упорядоченную базовую таблицу +Control: корневые строки добавляются, дочерний `INTO` может обновить выбранную +строку или добавить записи при sentinel `-1`, а `EXTO` добавляет строки с +переведёнными ключами глобальной MSH-иерархии. Результат хранит исходный factory +tag и provenance; неизвестные tag-specific callbacks он не выполняет. Preview +режим эту таблицу не строит, а неполная typed-record list оставляет состояние +явно unavailable. Каждый graph edge от `UnitDatRoot` к effective component и далее к его MSH dependency также несёт `unit_component_index`. Это индекс исходной записи в diff --git a/docs/tomes/06-behavior.md b/docs/tomes/06-behavior.md index 9d7b01e..0bd00df 100644 --- a/docs/tomes/06-behavior.md +++ b/docs/tomes/06-behavior.md @@ -593,6 +593,28 @@ parent ID через Control IID `0x202`, virtual slot `+0x44`, только еÑ нужно проверить это поведение явно. `EXTO` проходит отдельную ветвь, поэтому это правило нельзя распространять на все registry types. +Ветка `EXTO` заполняет другие поля. В `FUN_10003760` RVA `0x3760` и mount +`C4`, и target `C8` сначала равны `-1`. Ветка `EXTO` вычисляет mount и +записывает его только в `C4`; `C8` остаётся `-1`. Поэтому Control добавляет +все typed records такого компонента в конец общей таблицы. Raw +`parent_or_link` здесь выбирает mount-узел, а не строку Control. + +`AniMesh.dll` (SHA-256 +`65659bf67f20e5be77d67a5b2f59968f61b94293143807fa59ca451c560c4f7e`) +собирает глобальную нумерацию MSH-узлов: обычная корневая модель добавляет все +`N` узлов, `EXTO`-дочерняя модель добавляет `N - 1`, начиная со своего узла `1`, +а `INTO`-компонент не добавляет узлов. `FUN_1000a460` (RVA `0xa460`) выполняет +эту загрузку MSH; `FUN_10005780` (RVA `0x5780`) находит первый глобальный узел +с заданным component ID. Если у `EXTO`-модели только один узел, она не добавляет +глобальных узлов, и поиск первого узла возвращает `-1`. + +При добавлении `EXTO` Control отдельно переводит ключи CTLD в пространство +глобальной MSH-иерархии: нулевой ключ заменяется mount-узлом `C4`; ненулевой +ключ сдвигается относительно первого глобального узла компонента только при +`C4 != -1`. Например, если компонент начинается с глобального узла `22`, его +исходный ключ `1` становится `22`. Этот ключ выбирает модельный узел, а не +строку Control. Записи корня остаются в исходном виде. + ### Как Control добавляет и переопределяет устройства В `Control.dll` (SHA-256 @@ -609,6 +631,19 @@ override path применяет первую typed record и не добавлÑ путь `0x20800`, поэтому такой результат парсера сам по себе не доказывает отказ оригинального loader-а и не позволяет объявить Rust merge полным. +FParkan строит базовую проекцию этой таблицы во время полного mission load для +объектов с Unit DAT. Корневые typed records добавляются в исходном порядке; +`EXTO` тоже добавляет все свои записи с remapped MSH-ключами; `INTO` обновляет +одну строку по `C8`, а при sentinel `-1` добавляет весь список. Preview таблицу +не создаёт. Проекция хранит исходный factory tag, текущий typed record и их +provenance, но не исполняет все tag-specific callbacks и не заменяет полный +Control runtime. Лицензированный `UNITS/BUILDS/MINE/min_l_n1.dat` подтверждает +10 исходных устройств, четыре `INTO`-override по индексам `0..3` и добавление +одной дочерней записи `EXTO` с ключом `22`, всего 11 устройств. Это результат +Rust full-loader теста на оригинальных ресурсах. Ветви C4/C8 и добавление +`EXTO` подтверждены статически по native ASM; отдельный native full-load oracle +для всей таблицы не запускался. + Для tag `19` фабрика создаёт объект с его исходными классом и vtable. Базовый конструктор `FUN_100218b0` задаёт multiplier `+0x4c = 1.0`. Override через `FUN_1002d890` вызывает у выбранного объекта vtable slot `+0x1c`, то есть @@ -621,6 +656,16 @@ override path применяет первую typed record и не добавлÑ сбрасывают их. Поэтому «переопределение» здесь означает обновить часть данных того же устройства, с ограничениями конкретного метода. +Native x86 oracle для тех же GOG DLL выполняет конструкторы и этот общий setter +на уже созданных получателях factory tags `9`, `15`, `19` и `25` (размеры +объектов `0x120`, `0x98`, `0x94` и `0xa4`). У всех проверенных vtable slot +`+0x1c` указывает на RVA `0x21d50`; тест подтверждает, что override сохраняет +существующий слот, класс/vtable, ключ, component ID и multiplier `2.5`, копируя +новые коэффициенты. Slot `+0x24` у tag `9` указывает на отдельный обработчик +`0x25600`, а у остальных трёх — на no-op `0xbcd0`. Tag `9` проверяется с +нулевым pointer `+0x3c` и записью без map rows: FX host намеренно не подключён, +поэтому его поведение этим опытом не подтверждено. + Статический разбор глобального Control interface показывает aggregate getters `1/2` (`FUN_1002b410`, RVA `0x2b410`) и setter `1` (`FUN_1002ba30`, RVA `0x2ba30`) для устройств tag `19`. Для конечных значений getter `1` вычисляет |
