docs(runtime): trace original Control clock delivery
Docs Deploy / Build and Deploy MkDocs (push) Successful in 38s
Docs Deploy / Build and Deploy MkDocs (push) Successful in 38s
This commit is contained in:
3 files changed
+80
-7
No files matched your search
@@ -353,8 +353,15 @@ visibility transition `0x11920` с исходными AniMesh callbacks. Эти
|
|||||||
Control выставлен flag `0x102`, слово флагов ANI `+0x14` и производные байты
|
Control выставлен flag `0x102`, слово флагов ANI `+0x14` и производные байты
|
||||||
`+0x111..+0x113` изначально равны нулю. Вызовы AniMesh `0x93c0` и `0xa2a0` обновляют производную геометрию и
|
`+0x111..+0x113` изначально равны нулю. Вызовы AniMesh `0x93c0` и `0xa2a0` обновляют производную геометрию и
|
||||||
видимость, это отдельная непроверенная граница, а не FX callbacks. Активную
|
видимость, это отдельная непроверенная граница, а не FX callbacks. Активную
|
||||||
clock-ветвь не запускали; внешний источник времени и порядок вызовов в игре
|
clock-ветвь не запускали. Источник времени и доставка прослежены статически:
|
||||||
остаются незакрытыми. Источник контактного коэффициента прослежен статически,
|
World3D RVA `0x6bf0` вычисляет часы из `timeGetTime()` с игровым смещением и
|
||||||
|
поправкой на паузу, затем выполняет первый обход `6/1`, шаг мировой физики и
|
||||||
|
второй обход `6/0x1c`. AniMesh RVA `0x1370` передаёт часы Control; общий
|
||||||
|
обработчик Control RVA `0x7830` численно преобразует unsigned DWORD в `f32`
|
||||||
|
перед primary slot `+0x58`. Фабрика выбирает RVA `0xcbb0` для класса `9` и
|
||||||
|
RVA `0xbcf0` для остальных. Это подтверждает статическую цепочку вызовов, но не
|
||||||
|
её исполнение на миссии: активный путь `0xbcf0` и изменение provider-снимков
|
||||||
|
Rust остаются открытыми. Источник контактного коэффициента прослежен статически,
|
||||||
но не исполнен. Подробные векторы и статические границы приведены в
|
но не исполнен. Подробные векторы и статические границы приведены в
|
||||||
[техническом подразделе о provider-состоянии Control](script-vm.md#изменение-provider-состояния-control).
|
[техническом подразделе о provider-состоянии Control](script-vm.md#изменение-provider-состояния-control).
|
||||||
|
|
||||||
|
|||||||
@@ -640,9 +640,57 @@ oracle вызывает оригинальные `FUN_10010ba0` (RVA `0x10ba0`),
|
|||||||
затем `FMUL` с binary32-константой `0.001` (`0x3a83126f`), после чего результат
|
затем `FMUL` с binary32-константой `0.001` (`0x3a83126f`), после чего результат
|
||||||
сохраняется в `f32`. Код вызывает `FUN_10012a40`, затем `FUN_1002d340` и
|
сохраняется в `f32`. Код вызывает `FUN_10012a40`, затем `FUN_1002d340` и
|
||||||
присваивает `+0xec = +0xe4`. В соседней ветви update packet queue обрабатывается
|
присваивает `+0xec = +0xe4`. В соседней ветви update packet queue обрабатывается
|
||||||
через `FUN_10012ce0`. Активную clock-ветвь oracle не запускал: внешний источник
|
через `FUN_10012ce0`. Активную clock-ветвь oracle не запускал. Источник её
|
||||||
времени и полный порядок вызовов в игре не установлены. Rust продолжает читать
|
входного времени и порядок доставки установлены статически, как описано ниже;
|
||||||
начальные provider snapshots и не моделирует эти изменения.
|
Rust продолжает читать начальные provider snapshots и не моделирует эти изменения.
|
||||||
|
|
||||||
|
#### Доставка игровых часов в Control
|
||||||
|
|
||||||
|
Статическая цепочка относится к GOG-модулям `World3D.dll` (SHA-256
|
||||||
|
`17e4a3089b2583a8cf2356c9db0390b1aba138356a09130d79b4e7e4791da61e`),
|
||||||
|
`AniMesh.dll` (`65659bf67f20e5be77d67a5b2f59968f61b94293143807fa59ca451c560c4f7e`)
|
||||||
|
и `Control.dll` (`bcb86318089028548a178b03a21accdce15df0cc85ddd91674cf3c2f55012c6e`).
|
||||||
|
`World3D!FUN_10006bf0` (RVA `0x6bf0`) получает `timeGetTime()`, прибавляет
|
||||||
|
игровое смещение и вычитает смещение паузы. Младший DWORD результата сохраняется
|
||||||
|
по RVA `0x32a38`. Затем первый обход объектов вызывает их vslot `+0x34` с
|
||||||
|
аргументами `(self, 6, 1, clock)`. После него вызывается world physics vslot
|
||||||
|
`+0x0c(clock)`, а второй обход рассылает `(self, 6, 0x1c, clock)`. Во всех трёх
|
||||||
|
этапах передаётся одно сохранённое значение, а не заново измеренное время.
|
||||||
|
|
||||||
|
В `Comp.ini` CID `3` и `4` назначены `AniMesh.dll!LoadAgent` (RVA `0x16a00`).
|
||||||
|
Его конструктор RVA `0x1000` устанавливает primary vtable RVA `0x201d4`, где
|
||||||
|
слот `+0x34` указывает на обработчик RVA `0x1370`. Для события `6/1` этот
|
||||||
|
обработчик вызывает ненулевые интерфейсы в следующем порядке:
|
||||||
|
|
||||||
|
| Поле AniMesh | Получатель | Подсобытие |
|
||||||
|
|---|---|---|
|
||||||
|
| `+0x17c` | Behavior | `1` |
|
||||||
|
| `+0x178` | Wizard | `1` |
|
||||||
|
| `+0x170` | CollObject | `1` |
|
||||||
|
| `+0x158` | Control | `1` |
|
||||||
|
| `+0x15c` | PhysicalModel | `1` |
|
||||||
|
| `+0x170` | CollObject повторно | `0x1c` |
|
||||||
|
|
||||||
|
Вызовы идут через slot `+0x08`: `ECX` содержит указатель интерфейса, `EDX` —
|
||||||
|
подсобытие, а исходный DWORD часов передаётся на стеке. Связи Control, Behavior,
|
||||||
|
Wizard и CollObject с этими полями видны в загрузчике AniMesh RVA `0x2ff0`.
|
||||||
|
|
||||||
|
Фабрика Control RVA `0x32280` выбирает конструктор RVA `0x7330` для класса `9`
|
||||||
|
и RVA `0x31490` для остальных классов. В первом случае интерфейс объекта `+4`
|
||||||
|
имеет vtable RVA `0x3b888`: его slot `+0x08` ведёт в переходник RVA `0x7fe0`,
|
||||||
|
который вычитает `4` из `ECX` и передаёт вызов RVA `0x7830`. Во втором случае
|
||||||
|
vtable RVA `0x3d254` ведёт через переходник RVA `0x31ae0` в RVA `0x314f0`;
|
||||||
|
для подсобытия `1` этот обработчик также вызывает RVA `0x7830`.
|
||||||
|
Общий обработчик дополняет входной DWORD нулевым старшим словом до qword,
|
||||||
|
выполняет `FILD`, затем `FSTP f32` и вызывает primary slot `+0x58`.
|
||||||
|
Это числовое преобразование беззнаковых миллисекунд в `f32`, а не чтение битов
|
||||||
|
DWORD как float и не передача длительности кадра. Для класса `9` primary
|
||||||
|
vtable RVA `0x3b8cc` направляет этот слот в RVA `0xcbb0`; у остальных классов
|
||||||
|
vtable RVA `0x3d298` направляет его в RVA `0xbcf0`.
|
||||||
|
|
||||||
|
Эта цепочка доказана инструкциями и таблицами исходных модулей. Она не является
|
||||||
|
проверкой исполнения активной ветви `0xbcf0`, её callbacks или изменения
|
||||||
|
provider-состояния в реальной миссии.
|
||||||
|
|
||||||
#### Родители, стадии и видимость provider-узлов
|
#### Родители, стадии и видимость provider-узлов
|
||||||
|
|
||||||
@@ -693,8 +741,9 @@ NDP, Node38 и объект хоста синтетические; слот life
|
|||||||
нулю; поэтому вызовы
|
нулю; поэтому вызовы
|
||||||
`AniMesh.dll!FUN_100093c0` и `FUN_1000a2a0` (пересчёт производной геометрии и
|
`AniMesh.dll!FUN_100093c0` и `FUN_1000a2a0` (пересчёт производной геометрии и
|
||||||
видимости) не покрыты. Эти результаты подтверждают локальные переходы и порядок
|
видимости) не покрыты. Эти результаты подтверждают локальные переходы и порядок
|
||||||
callbacks, но не полный Control update реальной миссии. Активная clock-ветвь,
|
callbacks, но не полный Control update реальной миссии. Источник часов и порядок
|
||||||
внешний источник времени и полный игровой порядок вызовов пока не установлены.
|
их доставки установлены статически выше; исполнение активной clock-ветви и её
|
||||||
|
влияние на состояние реальной миссии остаются непроверенными.
|
||||||
|
|
||||||
### Начальная MSH-часть строки provider
|
### Начальная MSH-часть строки provider
|
||||||
|
|
||||||
|
|||||||
@@ -346,6 +346,23 @@ end-of-render callbacks. Эти callbacks позволяют объектам б
|
|||||||
изменит движение, камеру и сценарные таймеры. Подробности render item и рисков
|
изменит движение, камеру и сценарные таймеры. Подробности render item и рисков
|
||||||
кадровой совместимости вынесены в справочник [Render frame](../reference/render-frame.md).
|
кадровой совместимости вынесены в справочник [Render frame](../reference/render-frame.md).
|
||||||
|
|
||||||
|
У исходного Control источник времени прослежен статически до World3D.
|
||||||
|
World3D берёт миллисекунды `timeGetTime()`, учитывает игровое смещение и паузу,
|
||||||
|
затем передаёт младшие 32 бита результата всем объектам в событии `6/1`.
|
||||||
|
После этого следуют шаг мировой физики и второй обход объектов с событием
|
||||||
|
`6/0x1c`; они получают то же значение часов. Поэтому порядок обновлений имеет
|
||||||
|
значение даже тогда, когда все участники видят одинаковое время.
|
||||||
|
|
||||||
|
Объект AniMesh передаёт первое событие последовательно в Behavior, Wizard,
|
||||||
|
CollObject, Control и PhysicalModel, пропуская отсутствующие интерфейсы, а затем
|
||||||
|
ещё раз в CollObject с подсобытием `0x1c`. Control численно преобразует
|
||||||
|
беззнаковые миллисекунды в `f32` и выбирает обработчик по классу объекта.
|
||||||
|
Это абсолютные часы: длительность шага обработчик вычисляет из сохранённых
|
||||||
|
значений сам. Таблицы, адреса и различие путей классов приведены в
|
||||||
|
[техническом разборе](../appendices/script-vm.md#доставка-игровых-часов-в-control).
|
||||||
|
Статическая цепочка ещё не доказывает исполнение активного Control update на
|
||||||
|
миссии. Rust пока сохраняет начальные provider-снимки и не изменяет их этим путём.
|
||||||
|
|
||||||
## World3D
|
## World3D
|
||||||
|
|
||||||
World3D связывает игровые объекты, события, время, ввод, камеру, сетевые
|
World3D связывает игровые объекты, события, время, ввод, камеру, сетевые
|
||||||
|
|||||||
Reference in new issue
Block a user