aboutsummaryrefslogtreecommitdiff
path: root/docs
diff options
context:
space:
mode:
authorValentin Popov <valentin@popov.link>2026-10-22 13:19:25 +0300
committerValentin Popov <valentin@popov.link>2026-10-22 13:19:25 +0300
commitb9a4d1b478d9ff6dff457617f7296c54db70532e (patch)
treee839d5892f2bf09092cd09a79ab47582719c3517 /docs
parent40e43921385740b6e2cb502f1cb5e3d8347dc2d7 (diff)
downloadfparkan-b9a4d1b478d9ff6dff457617f7296c54db70532e.tar.xz
fparkan-b9a4d1b478d9ff6dff457617f7296c54db70532e.zip
feat(runtime): query and update loaded Control resources
Diffstat (limited to 'docs')
-rw-r--r--docs/appendices/knowledge-boundaries.md29
-rw-r--r--docs/tomes/06-behavior.md45
2 files changed, 57 insertions, 17 deletions
diff --git a/docs/appendices/knowledge-boundaries.md b/docs/appendices/knowledge-boundaries.md
index 27cf74a..f389b03 100644
--- a/docs/appendices/knowledge-boundaries.md
+++ b/docs/appendices/knowledge-boundaries.md
@@ -282,15 +282,26 @@ Control различает добавление устройства и прим
подготовленного CTL должно оставаться явным unavailable result, а не
трактоваться как пустой список.
-Глобальные Control selectors `1/2` и setter selector `1` по tag `19` описаны
-там же только по статическому разбору `Control.dll`; их вызовы отдельно не
-исполнялись. Проекция полного mission load недоступна для неполного списка
-typed records, Control resource у non-geometric prototype и некоторых
-неразрешённых EXTO node mappings; preview и объекты без Unit DAT root её не
-строят. Её соответствие полной загрузке игры для всех типов компонентов и
-factory paths ещё не установлено. Не восстановлен и жизненный цикл множителя
-`+0x4c` после конструктора и переопределения; также неизвестно, когда эти
-объекты создаются при отложенной загрузке.
+Global Control getters `1/2` и setter `1` проверены в native x86 oracle для
+искусственных factory/descriptor pairs `9`, `15` и `19`, а в Rust реализованы
+для текущего descriptor tag `19` с factory tags `9`, `15`, `19` и `25`. Для tag
+`25` общий getter slot `+0x10` подтверждён чтением vtable, но агрегатный вызов
+этого класса native oracle не запускал. Rust API обращается к строкам проекции
+конкретного живого `ObjectHandle`; это запрос к уже загруженной таблице, а не
+исполнение Control или Behavior tick. Setter `17`, остальные factory tags и
+внешние эффекты их методов не включены. Для tag `9` selector `0` использует
+отдельный scale `+0x11c`; остальные поддержанные классы используют коэффициент
+напрямую. Пустой набор и нулевой знаменатель остаются native no-result, а
+неподдержанный factory tag и расчётный диапазон произведения/отношения за
+нормальным диапазоном `f32` становятся явной ошибкой Rust.
+
+Проекция полного mission load недоступна для неполного списка typed records,
+Control resource у non-geometric prototype и некоторых неразрешённых EXTO node
+mappings; preview и объекты без Unit DAT root её не строят. Её соответствие
+полной загрузке игры для всех типов компонентов и factory paths ещё не
+установлено. Setter `1` меняет multiplier `+0x4c` выбранных строк, но расписание
+и lifetime этих объектов после конструктора и в отложенной загрузке остаются
+непроверенными.
Для `Control.dll` (SHA-256
`bcb86318089028548a178b03a21accdce15df0cc85ddd91674cf3c2f55012c6e`) tag-26
diff --git a/docs/tomes/06-behavior.md b/docs/tomes/06-behavior.md
index 0bd00df..2b26f62 100644
--- a/docs/tomes/06-behavior.md
+++ b/docs/tomes/06-behavior.md
@@ -668,14 +668,43 @@ Native x86 oracle для тех же GOG DLL выполняет конструк
Статический разбор глобального Control interface показывает aggregate getters
`1/2` (`FUN_1002b410`, RVA `0x2b410`) и setter `1` (`FUN_1002ba30`, RVA
-`0x2ba30`) для устройств tag `19`. Для конечных значений getter `1` вычисляет
-`sum(base * multiplier) / sum(base)`, а getter `2` — `sum(base)`. При встрече
-отрицательного base selector `1` сразу возвращает `1.0`, а selector
-`2` — этот base. Если подходящих записей нет или сумма base неположительна,
-getter возвращает неуспех без записи результата. Setter пишет multiplier `+0x4c`
-только устройствам tag `19` с положительным selector-0 значением; пустой набор
-возвращает успех. Это вывод статического анализа для конечных входных значений,
-без отдельного native execution oracle для глобальных selectors.
+`0x2ba30`) для текущего descriptor tag `19`. Getter `1` складывает ответы
+виртуального selector `0x200` в числитель и selector `0` в знаменатель; getter
+`2` возвращает сумму selector `0`. Для обычного factory tag `19` эти ответы
+равны `coefficient * multiplier` и `coefficient`, то есть отношение сводится к
+`sum(coefficient * multiplier) / sum(coefficient)`. У factory tag `9` selector
+`0` умножает коэффициент на отдельное поле `+0x11c`, тогда как selector `0x200`
+использует коэффициент и multiplier; эта особая база меняет знаменатель.
+Обработчик factory tag `9` расположен в Control RVA `0x255c0`, а его конструктор
+RVA `0x25460` задаёт `+0x11c = 1.0`. При встрече отрицательного ответа selector
+`0` getter `1` сразу возвращает `1.0`, а getter `2` — этот ответ. Если подходящих
+записей нет или сумма базы неположительна, getter возвращает неуспех без записи
+результата. Setter пишет multiplier `+0x4c` только устройствам с текущим
+descriptor tag `19` и положительным selector-0 ответом; пустой набор возвращает
+успех. Фильтр использует **текущий descriptor tag**, который может измениться
+при `INTO`, а виртуальный вызов остаётся методом исходного factory-класса.
+
+Этот путь проверяется native x86 oracle на оригинальной `Control.dll` указанной
+выше: искусственные factory/descriptor пары `9`, `15` и `19` покрывают setter,
+отрицательные ответы, округление и тег `9` с scale `0.5`. Для factory tag `25`
+его vtable slot `+0x10` статически указывает на общий getter RVA `0x21d00`, но
+отдельный aggregate oracle этот класс не запускал. Rust хранит начальный scale
+factory `9` и предоставляет `query_loaded_mission_control_resource` для selector
+`1`/`2` и `set_loaded_mission_control_multiplier` для setter-а `1`. Вызовы
+сначала проверяют живой `ObjectHandle`, затем обращаются к таблице этого объекта
+из полной загрузки миссии. Синтетические тесты проверяют границы пустой таблицы,
+нулевого знаменателя, неподдержанных factory tags и чисел за диапазоном
+нормального `f32`; лицензированный тест сверяет реальные descriptor tags и
+получает для `min_l_n1.dat` сумму `16` и отношение `1` до setter-а.
+
+В этом API пока реализованы только getter selectors `1`/`2` и setter `1`.
+Отдельный native setter selector `17`, tag-specific методы прочих factory tags,
+их внешние эффекты и вызов из регулярного шага Behavior здесь не моделируются.
+Числа должны оставаться конечными и нормальными либо точным нулём; произведения
+и отношения за поддерживаемым диапазоном `f32` возвращают явную ошибку, а не
+подменяются нулём или `None`. При проверке диапазона Rust оценивает операцию в
+`f64`, затем выполняет её в `f32`; это ограниченная проверка диапазона, а не
+эмуляция полного x87 accumulator-а.
Отдельная ветка того же GOG `AniMesh.dll` показывает, когда создаётся Behavior
для host object. В `FUN_10002ff0` (RVA `0x2ff0`, SHA-256