aboutsummaryrefslogtreecommitdiff
path: root/docs/appendices/script-vm.md
diff options
context:
space:
mode:
authorValentin Popov <valentin@popov.link>2026-10-29 19:26:15 +0300
committerValentin Popov <valentin@popov.link>2026-10-29 19:26:15 +0300
commitba7cb7f0f9f572bf587824cc5816ed933fe74f12 (patch)
tree184a58c08f2b8c393bc3edf6a6c83dee5e91e67f /docs/appendices/script-vm.md
parent1d20509b052c0b3e2db2a8bd86756f007041ab21 (diff)
downloadfparkan-ba7cb7f0f9f572bf587824cc5816ed933fe74f12.tar.xz
fparkan-ba7cb7f0f9f572bf587824cc5816ed933fe74f12.zip
feat(runtime): support tag-26 Control resource budgets
Diffstat (limited to 'docs/appendices/script-vm.md')
-rw-r--r--docs/appendices/script-vm.md69
1 files changed, 53 insertions, 16 deletions
diff --git a/docs/appendices/script-vm.md b/docs/appendices/script-vm.md
index 5fb0cd0..84bb4b9 100644
--- a/docs/appendices/script-vm.md
+++ b/docs/appendices/script-vm.md
@@ -792,23 +792,19 @@ provider getter и изменение количества не подменен
Rust предоставляет явный CPU-вызов
`advance_loaded_mission_control_budget(engine, handle, dt)`. Он переносит
-исходные callbacks factory tags `9`, `15`, `19` и общий default callback, а
-категории выбирает по текущему descriptor tag. Native map подтверждён только
-для префикса тегов `0..=34`; неизвестная категория, специализированный
-callback, provider или численный диапазон возвращает ошибку без публикации
-частичных изменений. Ставки `+0x5dc/+0x5e0` сохраняются отдельно, а сам вызов
-ещё не включён в Control clock.
+исходные callbacks factory tags `9`, `15`, `19`, `26` и общий default callback,
+а категории выбирает по текущему descriptor tag. Native map подтверждён только
+для префикса тегов `0..=34`; неизвестная категория, неподдержанный
+специализированный callback, provider или численный диапазон возвращает ошибку
+без публикации частичных изменений. Ставки `+0x5dc/+0x5e0` сохраняются отдельно,
+а сам вызов ещё не включён в Control clock.
Нативный oracle проверяет пустую таблицу с отрицательным нулём в обеих выходных
ставках, невырожденную пару исходных устройств tag 19/tag 15 при `dt = 0.375`
и tag 9 с шестью значениями и шестью накопителями изменений. Rust-тесты
повторяют их по битам, включая положительное и отрицательное обновления tag 9.
-В лицензированном `min_l_n1.dat` предварительная проверка распознаёт категории,
-но находит неподдержанный factory tag `26` и отклоняет бюджет до расчёта ставок
-или вызова устройств; транзакционный тест подтверждает, что исходная таблица
-не меняется. Полный бюджетный проход на реальной миссии пока не выполнен. Rust также отклоняет нулевой знаменатель
-обновления tag 19; тест вызывает эту ошибку после изменения provider
-потребителем и подтверждает откат всей таблицы.
+Rust также отклоняет нулевой знаменатель обновления tag 19; тест вызывает эту
+ошибку после изменения provider потребителем и подтверждает откат всей таблицы.
#### Генератор tag 19 в том же бюджетном проходе
@@ -911,10 +907,51 @@ Descriptor category lookup `0x2c3a0` возвращает следующие зÐ
Именно текущий descriptor выбирает категорию; callback остаётся у исходного
factory-класса. В Rust неизвестный текущий тег за концом префикса и
-специализированный factory callback не подменяются общей формулой. На
-лицензированном Unit DAT полный проход доходит до factory `26` и возвращает
-ошибку без частичного изменения таблицы. Ни этот CPU-вызов, ни локальные
-векторы не означают включения бюджетного шага в Control clock.
+неподдержанный специализированный factory callback не подменяются общей
+формулой. Tag `26` поддержан отдельной парой callbacks, описанной ниже. Ни этот
+CPU-вызов, ни локальные векторы не означают включения бюджетного шага в Control
+clock.
+
+#### Фабричный tag 26: изменяемая добавка
+
+В этой сборке `Control.dll` SHA-256
+`bcb86318089028548a178b03a21accdce15df0cc85ddd91674cf3c2f55012c6e` фабричный
+tag `26` обрабатывается в функции-фабрике RVA `0x2d4b0`: её ветка вызывает общий
+конструктор `0x20800`, обнуляет поле устройства `+0xa4` и устанавливает vtable
+`0x3ce38`. Rate
+callback RVA `0x2e540` сначала проходит проверку доступности provider, затем
+считает `-((descriptor[+0x20] + device[+0xa4]) * dt)`; прибавление до умножения
+важно для битового результата. Update slot `+0x18` ведёт на RVA `0x21890` и
+сохраняет выделенную долю как обычный multiplier `+0x4c`, не трогая `+0xa4`.
+
+Vtable slot `+0x1c` ведёт на общий reader `0x21d50`. Native override RVA
+`0x2d890` через этот reader заменяет descriptor и коэффициенты, сохраняя
+изменяемую добавку. Oracle проверяет сам slot и повторный rate после `INTO`.
+Rust теперь включает factory tag `26` в projection guard для `INTO` по этой
+проверке; границы для фабричных тегов `1`, `17` и `30` остаются закрытыми.
+
+Отдельный Control setter RVA `0x2c2b0` поддерживает selector `0x500`: только
+при текущем descriptor tag `26` он записывает переданные биты в `+0xa4` и
+возвращает успех. Behavior.dll с SHA-256
+`ddfbdbde07832358fe6e35e01c8dba9b58e7313789498b6049ed51d4ed9baf99` вызывает
+его через RVA `0x19880`. Callers `0x29910` и `0x2f400` передают ноль, а
+`0x29ba0` передаёт поле `+0x64` рядом с кодом `NewfOreCost`; смысл последнего
+значения не установлен, поэтому Rust пока не запускает этот Behavior путь.
+
+При `B = 0.2`, добавке `0.3` и `dt = 0.7` исходная rate имеет биты
+`0xbeb33333`. Смешанная проверка использует оригинальный tag-19 генератор
+(`B = 0.625`, `C0 = 1`, provider `0.4`) и tag-26 потребитель (`B = 0.2`,
+добавка `0.3`) при `dt = 0.5`: первый даёт `0.125`, второй запрашивает `0.25`.
+Native dispatcher выделяет tag `26` половину, сохраняет множители
+`0x3f300000`/`0x3f000000`, а ставки `+0x5dc/+0x5e0` получают
+`0x80000000`/`0x3e800000`. Постоянный x86 oracle вызывает исходные callbacks и
+Rust-тест повторяет этот вектор.
+
+Ignored Rust-тест также проходит полный неотфильтрованный Control budget по
+одиннадцати исходным устройствам `min_l_n1.dat` при `dt = 0.5`; выходы равны
+`0x3c23d70a`/`0x3c23d70a`, первые два множителя tag `19` — `0x3f7fd70a`.
+Это проверка CPU-проекции реальной таблицы, а не сравнение целой миссии с
+оригиналом.
#### Активация и начальные часы