aboutsummaryrefslogtreecommitdiff
path: root/docs/appendices/script-vm.md
diff options
context:
space:
mode:
Diffstat (limited to 'docs/appendices/script-vm.md')
-rw-r--r--docs/appendices/script-vm.md59
1 files changed, 54 insertions, 5 deletions
diff --git a/docs/appendices/script-vm.md b/docs/appendices/script-vm.md
index 0f5994b..c4c0255 100644
--- a/docs/appendices/script-vm.md
+++ b/docs/appendices/script-vm.md
@@ -640,9 +640,57 @@ oracle вызывает оригинальные `FUN_10010ba0` (RVA `0x10ba0`),
затем `FMUL` с binary32-константой `0.001` (`0x3a83126f`), после чего результат
сохраняется в `f32`. Код вызывает `FUN_10012a40`, затем `FUN_1002d340` и
присваивает `+0xec = +0xe4`. В соседней ветви update packet queue обрабатывается
-через `FUN_10012ce0`. Активную clock-ветвь oracle не запускал: внешний источник
-времени и полный порядок вызовов в игре не установлены. Rust продолжает читать
-начальные provider snapshots и не моделирует эти изменения.
+через `FUN_10012ce0`. Активную clock-ветвь oracle не запускал. Источник её
+входного времени и порядок доставки установлены статически, как описано ниже;
+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-узлов
@@ -693,8 +741,9 @@ NDP, Node38 и объект хоста синтетические; слот life
нулю; поэтому вызовы
`AniMesh.dll!FUN_100093c0` и `FUN_1000a2a0` (пересчёт производной геометрии и
видимости) не покрыты. Эти результаты подтверждают локальные переходы и порядок
-callbacks, но не полный Control update реальной миссии. Активная clock-ветвь,
-внешний источник времени и полный игровой порядок вызовов пока не установлены.
+callbacks, но не полный Control update реальной миссии. Источник часов и порядок
+их доставки установлены статически выше; исполнение активной clock-ветви и её
+влияние на состояние реальной миссии остаются непроверенными.
### Начальная MSH-часть строки provider