feat(runtime): register mission objects with clan distributors
Docs Deploy / Build and Deploy MkDocs (push) Successful in 35s
Docs Deploy / Build and Deploy MkDocs (push) Successful in 35s
This commit is contained in:
5 files changed
+318
-18
No files matched your search
@@ -129,10 +129,41 @@ Rust `load_mission` принимает явный `queue_time_ms`, а не чи
|
||||
host construction phases. Не проверена другая лицензированная миссия с
|
||||
непустым `Init`. Вызов `Behavior.dll!FUN_10019e80` (RVA `0x19e80`, SHA-256
|
||||
`ddfbdbde07832358fe6e35e01c8dba9b58e7313789498b6049ed51d4ed9baf99`) исполнялся
|
||||
на синтетических интерфейсах, но runtime пока не вызывает его в игровом цикле:
|
||||
не доказаны создание реальных записей distributor и интерфейсов ArealMap,
|
||||
которые ему нужны. Остальной Behavior tick flow и общий dispatcher событий
|
||||
также не восстановлены.
|
||||
на синтетических интерфейсах. Путь членства в реальных distributor-списках
|
||||
теперь связан с полями TMA и Unit DAT: `World3D!CreateObject` передаёт selector
|
||||
и class word через дескриптор в Behavior (RVA `0x7e55`, `0x7e62`), а
|
||||
`Behavior.dll!FUN_10005e60` (RVA `0x5e60`) проверяет высокий бит registration
|
||||
key, AI и distributor. Selector из первого DWORD после имени ресурса выбирает
|
||||
слот `GetSuperAI`; таблица этой функции находится в `ai.dll` RVA `0x55398`.
|
||||
Хеши `MisLoad.dll`, `iron3d.dll`, `ArealMap.dll`, `World3D.dll` и
|
||||
`Behavior.dll`, использованных для цепочки, перечислены в
|
||||
[справочнике TMA](../reference/tma.md).
|
||||
|
||||
Отдельный режимный бит Behavior нельзя выводить из `MissionMode`. Конструктор
|
||||
Behavior (`Behavior.dll`, RVA `0x3600`) вызывает `World3D!stdGetGameMode` (RVA
|
||||
`0x14750`), который читает host-global по RVA `0x795130` в `World3D.dll` (SHA-256
|
||||
`17e4a3089b2583a8cf2356c9db0390b1aba138356a09130d79b4e7e4791da61e`). В
|
||||
обычном пути `stdInitGame` (RVA `0x13e90`, запись режима около `0x14040`)
|
||||
формируется отдельное host-значение; в наблюдавшемся запуске AutoDemo getter
|
||||
вернул `4`, и бит `0x2` был снят. Это объясняет соответствующий gate при
|
||||
создании Behavior, но не устанавливает отображение между host-режимом и Rust
|
||||
`MissionMode`.
|
||||
|
||||
Наблюдение обычного запуска лицензированной GOG AutoDemo подтвердило четыре
|
||||
добавления с ключами `0x80000003..0x80000006` в два клановых списка. Полная
|
||||
загрузка Rust сохраняет соответствующие `ObjectHandle` в точном доступном слоте
|
||||
`GetSuperAI` до стартового `Init`; preview не создаёт членств. Лицензированный
|
||||
тест связывает эти записи с TMA ID 4–7, selector и Unit DAT class. Это
|
||||
подтверждает только состав списков, не точную эквивалентность всей загрузки или
|
||||
регулярного шага Behavior.
|
||||
|
||||
Нативный `Behavior.dll!Add` (RVA `0x1aac0`) создаёт для каждого участника запись
|
||||
размером `0x1c` с начальной долей `1 / count`, а `normalize` (RVA `0x1ac90`)
|
||||
перенормирует прежние доли после добавления. Rust пока хранит только членство:
|
||||
поля записи, доли и их изменение ещё не исполняются. Не восстановлено и
|
||||
соединение с реальными интерфейсами ArealMap, необходимыми для регулярного
|
||||
вызова `FUN_10019e80`; остальной Behavior tick flow и общий dispatcher событий
|
||||
также остаются открытыми.
|
||||
|
||||
Для `Handler(30)` отдельно подтверждены обратный вызов `iron3d.dll` RVA
|
||||
`0x611d0` (SHA-256 `d1dc4ea8535e2069b0a05c9e8be2724dd438ba44cca7a83007d8b2e50f9e35fa`),
|
||||
|
||||
@@ -87,6 +87,8 @@ slot `+0x40` в путь выбора AI в Behavior. Поэтому Rust сох
|
||||
`17e4a3089b2583a8cf2356c9db0390b1aba138356a09130d79b4e7e4791da61e` и
|
||||
`Behavior.dll`
|
||||
`ddfbdbde07832358fe6e35e01c8dba9b58e7313789498b6049ed51d4ed9baf99`.
|
||||
Таблица `GetSuperAI` в `ai.dll` находится по RVA `0x55398`; SHA-256 файла —
|
||||
`c19cd6cd31cd2896f8c4ba0f0e700dd3408aec8182daaf4863d98a7d233a2abc`.
|
||||
|
||||
`Property` состоит из четырёх raw `u32` и имени. Typed views разрешены только
|
||||
для доказанных property names и consumers.
|
||||
@@ -215,6 +215,26 @@ MissionObjectDraft {
|
||||
`fparkan-world` не подтверждено. Смещения, условия версий и контрольные суммы исследованных
|
||||
сборок приведены в [справочнике TMA](../reference/tma.md).
|
||||
|
||||
Это слово влияет не только на сценарий. Успешно загруженный пакет клана
|
||||
публикует его `SuperAI` в таблице `GetSuperAI`; World3D передаёт первый DWORD
|
||||
дескриптора создания через Behavior, где он выбирает тот же номер таблицы.
|
||||
Поэтому при создании полного мира можно отнести объект к конкретному клановому
|
||||
диспетчеру, если его номер лежит в диапазоне `0..63` и сценарий этого клана
|
||||
загружен. Rust хранит такую связь отдельно от владельца объекта:
|
||||
|
||||
```text
|
||||
TMA raw_after_resource = 1
|
||||
-> GetSuperAI[1] доступен после загрузки script bundle клана 1
|
||||
-> запись объекта относится к distributor клана 1
|
||||
```
|
||||
|
||||
Для объектов с Unit DAT используется старший бит DWORD по смещению `+4` от
|
||||
начала DAT как общий признак, по которому оригинальный World3D создаёт
|
||||
registration key для Behavior. Это второе 32-битное слово заголовка. Из него
|
||||
нельзя вывести сторону или тип владельца. В AutoDemo это связывает поля TMA,
|
||||
class word из Unit DAT и выбранный клановый AI, не меняя `OwnerId` и хеш
|
||||
игрового состояния.
|
||||
|
||||
Свойства хранятся как ordered property bag:
|
||||
|
||||
```text
|
||||
|
||||
+46
-12
@@ -204,11 +204,47 @@ SuperAI для записей кланов, затем обновляет Behavi
|
||||
не воспроизводит аргумент обратного вызова в `AI+0x3fc`, защиту от повторного
|
||||
входа `AI+0x78`, одноразовую метку `AI+0x8a8` или обновления Behavior на игровых
|
||||
тиках. При этом один конкретный шаг Behavior — распределение ресурсов — уже
|
||||
исполнен на исходной DLL с искусственными объектами; FParkan пока не вызывает
|
||||
его, потому что игровой мир Rust ещё не предоставляет нужные ресурсные
|
||||
интерфейсы. Runtime также не подменяет очередь оригинала: вызывающая сторона
|
||||
сама передаёт время, а локальный генератор Rust пока учитывает только случайные
|
||||
числа восстановленного стартового шага.
|
||||
исполнен на исходной DLL с искусственными объектами. Rust пока не вызывает
|
||||
регулярный шаг: игровой мир ещё не предоставляет нужные ресурсные интерфейсы.
|
||||
При полной загрузке Rust уже восстанавливает членство объектов в клановых
|
||||
списках Behavior, но сами записи распределителя и их доли пока не моделирует.
|
||||
Runtime также не подменяет очередь оригинала: вызывающая сторона сама передаёт
|
||||
время, а локальный генератор Rust пока учитывает только случайные числа
|
||||
восстановленного стартового шага.
|
||||
|
||||
### Откуда берутся объекты распределителя
|
||||
|
||||
Для каждого клана Iron3D создаёт AI независимо от того, найден ли его `.scr`.
|
||||
Таблица `GetSuperAI` получает указатель только для клана, чей пакет сценария
|
||||
успешно загружен. У размещённого объекта первое DWORD после имени ресурса
|
||||
выбирает индекс этой таблицы; второй соседний DWORD для этой цели не используется.
|
||||
World3D получает индекс через дескриптор создания объекта и передаёт его в
|
||||
Behavior. Отдельно DWORD по смещению `+4` от начала Unit DAT задаёт class word
|
||||
объекта. Это второе 32-битное слово файла; его старший бит приводит к созданию
|
||||
registration key, который проходит защиту Behavior вместе с проверками AI и
|
||||
distributor.
|
||||
|
||||
Для обычной полной загрузки Rust сохраняет по одной записи состояния на клан.
|
||||
Каждый размещённый объект с известным Unit DAT и установленным старшим битом
|
||||
получает существующий `ObjectHandle` и попадает в список только при точном
|
||||
совпадении индекса `raw_after_resource` с доступной записью `GetSuperAI`. Индекс
|
||||
не перенумеровывается: например, пакет клана 1 остаётся слотом 1 даже если
|
||||
пакет клана 0 отсутствует. Preview сохраняет свои статические данные, но не
|
||||
создаёт эти связи.
|
||||
|
||||
В лицензированной AutoDemo это даёт четыре членства: TMA объекты 4 и 6 идут
|
||||
в слот 0, а объекты 5 и 7 — в слот 1. У парных записей первого клана raw
|
||||
селектор равен 0, у второго — 1; классы из Unit DAT равны `0x80000010` для
|
||||
`wor_l_n1.dat` и `0x80000002` для `gener01.dat`. Тот же обычный путь в исходном
|
||||
Behavior добавил четыре ключа `0x80000003..0x80000006` в два distributor-а.
|
||||
Rust-тест повторно читает лицензированную миссию, связывает результаты с её
|
||||
TMA-записями и проверяет реальные `ObjectHandle`, но помечен `#[ignore]`, чтобы
|
||||
не требовать оригинальных ресурсов от остальных разработчиков.
|
||||
|
||||
Это пока только перечень участников. Оригинальный `Behavior.dll!Add` создаёт для
|
||||
каждого участника запись размером `0x1c` с долей `1 / count`, после чего
|
||||
нормирует прежние доли. Rust ещё не хранит эти поля и не исполняет их регулярный
|
||||
обмен ресурсами. Поля не выводятся из TMA-соседнего слова или `OwnerId`.
|
||||
|
||||
### Регулярная передача ресурсов
|
||||
|
||||
@@ -227,13 +263,11 @@ Resource Distributor работает со списком зарегистрир
|
||||
исходной `Behavior.dll`, но объекты и ответы интерфейсов заданы тестом; это ещё
|
||||
не воспроизведение реальной миссии.
|
||||
|
||||
Пока мы знаем точные границы интерфейсных запросов и некоторые ветви классов
|
||||
объектов, но не все доменные значения полей записи и не происхождение реальных
|
||||
строк списка. Загрузчик FParkan не должен создавать такие строки из похожих
|
||||
полей миссии: сначала нужно доказать путь регистрации и связать его с типами
|
||||
ресурсных объектов. Технические идентификаторы и численные векторы приведены
|
||||
в [приложении о сценарной машине](../appendices/script-vm.md), а оставшиеся
|
||||
вопросы перечислены в [границах знания](../appendices/knowledge-boundaries.md).
|
||||
Членство списка связано с реальным путём регистрации, но выполнение этой
|
||||
миссии не сравнивалось с тем, как исходная DLL заполняет поля записи `0x1c` и
|
||||
нормирует доли. Rust пока не хранит эти поля, а игровому миру ещё не хватает
|
||||
ресурсных интерфейсов ArealMap для регулярного шага. Открытые вопросы и границы
|
||||
проверки приведены в [границах знания](../appendices/knowledge-boundaries.md).
|
||||
|
||||
Первый часто встречающийся table entry с side effect — `Handler(2)` (176
|
||||
records в corpus). Он берёт active instruction, разрешает семь slots через
|
||||
|
||||
Reference in new issue
Block a user