fix(runtime): load robot Control device tables
Docs Deploy / Build and Deploy MkDocs (push) Successful in 36s
Docs Deploy / Build and Deploy MkDocs (push) Successful in 36s
This commit is contained in:
5 files changed
+264
-34
No files matched your search
@@ -268,9 +268,14 @@ Control для объектов с Unit DAT: корневые записи до
|
||||
|
||||
Control различает добавление устройства и применение одной записи к уже
|
||||
выбранному устройству. Исполнение оригинальной 32-битной DLL на искусственных
|
||||
данных подтверждает общую ветвь переопределения для получателей tags `9`, `15`,
|
||||
`19` и `25`: остаются прежними слот, ключ, ID компонента, множитель и класс,
|
||||
а коэффициенты копируются из новой записи. Искусственный tag `9`-объект создан
|
||||
данных подтверждает общие поля переопределения для получателей tags `2`, `3`,
|
||||
`4`, `5`, `8`, `9`, `10`, `15`, `19`, `21`, `25` и `27`: остаются прежними слот,
|
||||
ключ, ID компонента, множитель и класс, а коэффициенты копируются из новой
|
||||
записи. Обёртка tag `2` по RVA `0x29650` дополнительно пересчитывает два кэша
|
||||
и обнуляет массив состояния map-строк; это выполнено на native DLL, но пока
|
||||
не моделируется в базовой Rust-проекции. Её callback `0x29940` проверен только
|
||||
с неизменной пустой парой ресурсов; стрельба не проверена.
|
||||
Искусственный tag `9`-объект создан
|
||||
без FX-хоста (`+0x3c == 0`), а запись не содержит строк таблицы map; поэтому
|
||||
работа FX-хоста здесь не проверялась. В Rust parser-е
|
||||
`Unsupported { typed_record_index: Some(_) }` означает, что разбор остановился
|
||||
@@ -299,7 +304,9 @@ Global Control getters `1/2` и setter `1` проверены в native x86 orac
|
||||
Control resource у non-geometric prototype и некоторых неразрешённых EXTO node
|
||||
mappings; preview и объекты без Unit DAT root её не строят. Её соответствие
|
||||
полной загрузке игры для всех типов компонентов и factory paths ещё не
|
||||
установлено. Setter `1` меняет multiplier `+0x4c` выбранных строк, но расписание
|
||||
установлено. Полный Rust load AutoDemo проверяет доступность всех восьми таблиц
|
||||
и числа строк `14, 12, 15, 13, 12, 12, 11, 11`; это не сравнение с живой
|
||||
таблицей оригинала. Setter `1` меняет multiplier `+0x4c` выбранных строк, но расписание
|
||||
и lifetime этих объектов после конструктора и в отложенной загрузке остаются
|
||||
непроверенными.
|
||||
|
||||
|
||||
+45
-14
@@ -703,15 +703,43 @@ Rust full-loader теста на оригинальных ресурсах. Ве
|
||||
сбрасывают их. Поэтому «переопределение» здесь означает обновить часть данных
|
||||
того же устройства, с ограничениями конкретного метода.
|
||||
|
||||
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 намеренно не подключён,
|
||||
поэтому его поведение этим опытом не подтверждено.
|
||||
Native x86 oracle для тех же GOG DLL проверяет переопределение получателей
|
||||
factory tags `2`, `3`, `4`, `5`, `8`, `9`, `10`, `15`, `19`, `21`, `25` и `27`.
|
||||
Тест подтверждает сохранение существующего слота, класса/vtable, ключа,
|
||||
component ID и multiplier `2.5` при копировании новых коэффициентов. Для новых
|
||||
получателей конструкторы и начальное слово `+0x50` связаны с такими RVA:
|
||||
|
||||
| Factory tag | Конструктор | Vtable | Начальное `+0x50` |
|
||||
| --- | --- | --- | --- |
|
||||
| `2` | `0x294c0` | `0x3cbd8` | `0` |
|
||||
| `3`, `21` | `0x20800` | `0x3c448` | `5` |
|
||||
| `4` | `0x233d0` | `0x3c720` | `0x200` |
|
||||
| `5` | `0x20800`, затем замена vtable фабрикой | `0x3cdf8` | `5` |
|
||||
| `8` | `0x24310` | `0x3c800` | `5` |
|
||||
| `10` | `0x26470` | `0x3ca20` | `0x2000` |
|
||||
| `27` | `0x218b0` | `0x3c528` | `0` |
|
||||
|
||||
У всех строк таблицы multiplier начинается с `1.0`. Tags `3` и `5` проверены
|
||||
через настоящую фабрику `0x2d4b0`; tag `3` попадает в её default-ветвь.
|
||||
Общий reader `0x21d50` сохраняет переменный хвост: две map-строки `7` и `9`
|
||||
и дополнительная строка `fx` возвращают cursor `record + 0xbf`.
|
||||
Слово CTLD `+0x18 == -1` сохраняет фабричное `+0x50` и при INTO-замене.
|
||||
|
||||
У tag `2` slot `+0x1c` указывает на обёртку `0x29650`. Она вызывает тот же
|
||||
reader, затем сохраняет selector `1` в `+0x120`, округляет selector `0` через
|
||||
x87 `FISTP` в `+0x124` и заново обнуляет массив `+0x12c` по накопленному числу
|
||||
map-строк. Native тест получает `1.25`, округление `3.5 → 4` и четыре нулевых
|
||||
элемента после повторного override. Rust хранит общую проекцию устройства;
|
||||
эти оружейные кэши и дальнейшая стрельба в неё пока не входят. Slot `+0x24`
|
||||
этого класса (`0x29940`) проверен только с неизменной пустой парой ресурсов.
|
||||
Tag `9` проверяется без FX-хоста (`+0x3c == 0`) и без map-строк; его FX-путь
|
||||
этим опытом также не подтверждён.
|
||||
|
||||
Полный Rust loader на исходном `MISSIONS/Autodemo.00/data.tma` строит доступные
|
||||
таблицы для всех восьми объектов: четыре робота содержат `14`, `12`, `15`, `13`
|
||||
устройств, затем два завода по `12` и два генератора по `11`. Это проверка
|
||||
подготовки таблиц на настоящих ресурсах, а не сравнение полного игрового Control
|
||||
с запущенным оригиналом.
|
||||
|
||||
Статический разбор глобального Control interface показывает aggregate getters
|
||||
`1/2` (`FUN_1002b410`, RVA `0x2b410`) и setter `1` (`FUN_1002ba30`, RVA
|
||||
@@ -1050,13 +1078,16 @@ offsets 119–121. В `fr_l_gener.ctl` найдено 35 строк type 4, вк
|
||||
`f_gener_ball` с offset 85.
|
||||
|
||||
Control.dll `+0x8B10` передаёт указатель текущей записи диспетчеру `+0x2D4B0`.
|
||||
Теги 2 и 5 направляются в общий читатель `+0x21D50`: таблица виртуальных методов
|
||||
тега 2 (`+0x3CBD8`) вызывает его через обёртку `+0x29650`, а таблица тега 5
|
||||
(`+0x3CDF8`) указывает прямо на него в позиции `+0x1C`. Читатель потребляет
|
||||
Для tags `2`, `3`, `4`, `5`, `8`, `10`, `21` и `27` подтверждён общий читатель
|
||||
`+0x21D50`: таблица виртуальных методов tag `2` (`+0x3CBD8`) вызывает его через
|
||||
обёртку `+0x29650`, остальные перечисленные vtable указывают прямо на него в
|
||||
позиции `+0x1C`. Читатель потребляет
|
||||
заголовок размером `0xB0` байт со счётчиком `u32` по `+0xAC`, затем `count`
|
||||
значений `u32`, слово длины и, при ненулевой длине, строку с завершающим NUL;
|
||||
указатель возврата указывает на следующую запись. Поэтому для тегов 2 и 5 подтверждён общий
|
||||
структурный формат; смысл их полей пока не назначен.
|
||||
указатель возврата указывает на следующую запись. Rust-тест с tags `3`, `4`,
|
||||
`10`, `27` проверяет переход между записями после непустых values и строк,
|
||||
а также отказ при оборванном завершающем NUL. Это подтверждает структурный
|
||||
формат, но не назначает смысл всем коэффициентам устройств.
|
||||
|
||||
Resolver прототипов хранит явную registry-ссылку на `.cpt` отдельно от ссылки
|
||||
на `.ctl`. Если строки type 4 разобраны и явная ссылка на CPT есть, подготовка
|
||||
|
||||
Reference in new issue
Block a user