feat(runtime): load Behavior profiles for resource queries
Docs Deploy / Build and Deploy MkDocs (push) Successful in 1m14s
Docs Deploy / Build and Deploy MkDocs (push) Successful in 1m14s
This commit is contained in:
7 files changed
+1109
-45
No files matched your search
+66
-16
@@ -755,27 +755,77 @@ NDP, а `FUN_1000a100` (RVA `0xa100`) добавляет их в общую та
|
||||
`FUN_100198e0` (RVA `0x198e0`) суммирует успешные запросы IID `0x204` с selector
|
||||
`0xe00`. В парной `Control.dll` выше `FUN_1002bb40` (RVA `0x2bb40`) для типа
|
||||
`0x1a` вызывает selector `0x300`, описанный в этом разделе. Затем Behavior query
|
||||
`0x1002` (RVA `0xa490`) умножает полученную сумму на текущее значение block
|
||||
`+0x820`, поле `+0x58` `Transfer_Ore_OffBoard` (имя — RVA `0x22e20`, default
|
||||
5.0 — RVA `0x22d90`; config selector 2 загружает блок через RVA `0x0a1a0`).
|
||||
Отдельный query `0x1005` (RVA `0xa490`) возвращает поле `+0x60`
|
||||
`Transfer_Power_Out` (имя — RVA `0x22e20`, default 100.0 — RVA `0x22d90`;
|
||||
setter — RVA `0xaa40`). В полной загрузке FParkan начальные provider-строки
|
||||
хранятся вместе с таблицей Control конкретного `ObjectHandle`. Запрос
|
||||
`0xe00` проходит по ключу устройства в этот снимок и пока поддержан только для
|
||||
текущего descriptor tag `26` с factory tag `26`; для него результат равен
|
||||
`0x1002` (RVA `0xa490`) умножает полученную сумму на поле `+0x58`
|
||||
`Transfer_Ore_OffBoard` блока `+0x820`; отдельный selector `0x1005` возвращает
|
||||
`+0x60` `Transfer_Power_Out`. Имена регистрируются в RVA `0x22e20`, а конструктор
|
||||
RVA `0x22d90` задаёт начальные значения 5.0 и 100.0. Восемнадцать точных class
|
||||
codes выбирают записи `.var` из `behpsp.res`: например, `0x80000004` выбирает
|
||||
`prof_mine.var`, `0x80000002` — `prof_generator.var`, а три кода bunker-класса
|
||||
выбирают `prof_bunker.var`. Таблицу этих соответствий задаёт mapper
|
||||
`FUN_10008a80` (RVA `0x8a80`) в Behavior.dll SHA-256
|
||||
`ddfbdbde07832358fe6e35e01c8dba9b58e7313789498b6049ed51d4ed9baf99`.
|
||||
|
||||
Установленные соответствия mapper-а:
|
||||
|
||||
| Class flags | Запись `behpsp.res` |
|
||||
| --- | --- |
|
||||
| `0x80000004` | `prof_mine.var` |
|
||||
| `0x80000008` | `prof_storage.var` |
|
||||
| `0x80000002` | `prof_generator.var` |
|
||||
| `0x80000010` | `prof_plant.var` |
|
||||
| `0x80000040` | `prof_angar.var` |
|
||||
| `0x80000200` | `prof_mtp.var` |
|
||||
| `0x80000400` | `prof_institute.var` |
|
||||
| `0x80010000`, `0x80020000`, `0x80040000` | `prof_bunker.var` |
|
||||
| `0x80100000`, `0x80200000` | `prof_tower.var` |
|
||||
| `0x01002000` | `prof_trn.var` |
|
||||
| `0x01004000` | `prof_bld.var` |
|
||||
| `0x01008000` | `prof_war.var` |
|
||||
| `0x01010000` | `prof_hq.var` |
|
||||
| `0x01020000` | `prof_hero.var` |
|
||||
| `0x20000000` | `prof_animal.var` |
|
||||
|
||||
У бинарной строки `.var` есть имя, индекс типа, размер и две области данных.
|
||||
Native parser RVA `0x49fa0` читает запись, binder RVA `0x49090` связывает её с
|
||||
зарегистрированным полем, а apply-loop RVA `0x49170` копирует в поле именно
|
||||
вторую область. В профиле используются точные C-string имена
|
||||
`Transfer_Ore_OffBoard` и `Transfer_Power_Out`; регистр учитывается, первый
|
||||
совпавший ряд побеждает. Rust ограничивает чтение исходной записи NRes её
|
||||
границами и сохраняет значения как исходные 32-битные слова у соответствующего
|
||||
`ObjectHandle`. Разбор профиля для полной миссии завершается до создания нового
|
||||
мира: отсутствие или повреждение профиля известного класса прерывает загрузку,
|
||||
не подменяя предыдущую миссию. Если mapper не знает class code, остаются
|
||||
конструкторские значения 5.0 и 100.0; это не догадка о неизвестном профиле.
|
||||
Preview не загружает профили.
|
||||
|
||||
При вычислении `0x1002` native `FUN_100186b0` (RVA `0x186b0`) добавляет в список
|
||||
только текущие Control descriptor-и tag `26`, после чего
|
||||
`FUN_100198e0` (RVA `0x198e0`) суммирует их успешные `0xe00` запросы. FParkan
|
||||
делает то же для загруженной таблицы в её исходном порядке и затем умножает
|
||||
сумму на профильный `Transfer_Ore_OffBoard`. Записи tag `5`, `10` и `21` в общей
|
||||
таблице в этот список не попадают. Запрос `0xe00` проходит по ключу устройства
|
||||
в исходную provider-таблицу и пока поддержан только для текущего descriptor
|
||||
tag `26` с factory tag `26`; для него результат равен
|
||||
`provider * fixed_words[11] * multiplier`. Лицензированный тест загружает
|
||||
оригинальные CTL/NDP и подтверждает, что tag-26 запись с ключом `2` читает
|
||||
начальное значение строки `1.0`. Это проверка начального состояния после
|
||||
конструкторов, не результат живого игрового тика.
|
||||
оригинальные CTL/NDP и полную миссию с этим Unit DAT. В установленном
|
||||
`min_l_n1.dat` class word равен `0x80000004`, поэтому исходный прогон выбирает
|
||||
`prof_mine.var`. Для проверки другого отображения второй прогон оставляет тот же
|
||||
TMA и компоненты, но во временном VFS заменяет слово класса заголовка DAT на
|
||||
`0x80000002`; это тестовая подмена, а не содержимое лицензированного файла.
|
||||
Профиль mine даёт `Transfer_Power_Out` 0.0 и `Transfer_Ore_OffBoard` 1.0;
|
||||
оригинальный профиль генератора — 10.0 и 0.0 соответственно. Для исходного
|
||||
tag-26 ряда получается `1.0` provider × `1.0` coefficient × `1.0` multiplier;
|
||||
профиль mine умножает эту сумму на `1.0`, поэтому selector `0x1002` возвращает
|
||||
`1.0`. Эти запросы используют начальные provider-значения после конструкторов,
|
||||
а не результаты живого игрового тика.
|
||||
|
||||
Поведение provider-строк меняется и после загрузки: например,
|
||||
`Control.dll!FUN_10010f30` (RVA `0x10f30`) обновляет и ограничивает текущее
|
||||
значение, а соседние процедуры распространяют его между связанными строками.
|
||||
Эти изменения пока не отражены в Rust-снимке. Поэтому `0xe00` не является
|
||||
исполнением всего Control tick-а, а Behavior query `0x1002` не подключён к
|
||||
этому API; его множитель `Transfer_Ore_OffBoard` требует отдельного источника
|
||||
текущей конфигурации.
|
||||
Эти изменения пока не отражены в Rust-снимке. Поэтому запрос Control `0xe00` и
|
||||
Behavior selector `0x1002`, который его суммирует, используют исходное состояние
|
||||
полной загрузки. Selector `0x1005` прямо возвращает загруженную ставку профиля.
|
||||
Ни один из них пока не исполняет Control tick или последующие изменения профиля.
|
||||
|
||||
На x87 control word `0x007f` каждое умножение округляет мантиссу до 24 бит,
|
||||
но промежуточная степень может выйти за диапазон `f32` и вернуться в него при
|
||||
|
||||
Reference in new issue
Block a user