diff options
| author | Valentin Popov <valentin@popov.link> | 2026-10-22 14:30:41 +0300 |
|---|---|---|
| committer | Valentin Popov <valentin@popov.link> | 2026-10-22 14:30:41 +0300 |
| commit | 83db371742ad3865bf4dc534ae38429c07a936d3 (patch) | |
| tree | abb39dd412c6dd3bada1125d2a3c7ba78284cc1b /docs/tomes | |
| parent | 29b81b87237d0e6a3b7ffac913a0b882738eed7c (diff) | |
| download | fparkan-83db371742ad3865bf4dc534ae38429c07a936d3.tar.xz fparkan-83db371742ad3865bf4dc534ae38429c07a936d3.zip | |
feat(runtime): load Behavior profiles for resource queriestrunk
Diffstat (limited to 'docs/tomes')
| -rw-r--r-- | docs/tomes/06-behavior.md | 82 |
1 files changed, 66 insertions, 16 deletions
diff --git a/docs/tomes/06-behavior.md b/docs/tomes/06-behavior.md index 7dc6d66..bcb7320 100644 --- a/docs/tomes/06-behavior.md +++ b/docs/tomes/06-behavior.md @@ -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` и вернуться в него при |
