aboutsummaryrefslogtreecommitdiff
path: root/docs
diff options
context:
space:
mode:
Diffstat (limited to 'docs')
-rw-r--r--docs/appendices/knowledge-boundaries.md43
-rw-r--r--docs/appendices/script-vm.md49
-rw-r--r--docs/tomes/06-behavior.md28
3 files changed, 95 insertions, 25 deletions
diff --git a/docs/appendices/knowledge-boundaries.md b/docs/appendices/knowledge-boundaries.md
index 9869581..dcc14fe 100644
--- a/docs/appendices/knowledge-boundaries.md
+++ b/docs/appendices/knowledge-boundaries.md
@@ -358,10 +358,18 @@ API `distribute_loaded_mission_control_provider_amount` переносит
`+0x10` получает фактическую разницу amount. После распределения обязателен
`0x11130(root, true)`.
-Оба API работают только с CPU-проекцией и не подключены к GPU/window path или
-игровому Control clock. Gate `+0x618` изначально выключен; событие `7` задаёт его
-по правилу `gate = (arg == 2)` и вызывает `0x2dc20`, только если gate изменился.
-События Control в Rust пока не исполняются.
+Три API работают только с CPU-проекцией и не подключены к GPU/window path или
+игровому Control clock. Отдельный
+`advance_loaded_mission_control_budget` переносит `0x2d340` для factory
+callbacks `15/19` и current descriptor tags `15/19` (категории `0/1`); ставки сохраняются
+в текущих полях `+0x5dc/+0x5e0`. Он выполняется транзакционно, а неизвестный
+callback, provider или диапазон числа возвращает ошибку без частичного
+изменения. Тест с нулевым знаменателем генератора подтверждает откат после уже
+выполненного изменения потребителем. Пустая таблица всё равно записывает в оба поля отрицательный ноль;
+неактивный callback не требует provider lookup. Gate `+0x618` изначально
+выключен; событие `7` задаёт его по правилу `gate = (arg == 2)` и вызывает
+`0x2dc20`, только если gate изменился. События Control в Rust пока не
+исполняются, поэтому ресурсный шаг вызывается явно и не подключён к часам.
Capacity aggregate выведен при подтверждённых единичных множителях Unit DAT;
изменение масштабов `0x9ee0`/`0x9f90` не реализовано. Из-за округления `+0x590`
может стать больше сохранённого `+0x58c`; распределение сохраняет этот signed
@@ -394,8 +402,8 @@ Rust query обращается к загруженному объекту и п
текущего descriptor tag `26` с factory tag `26`; другие активные typed tags и
factory paths остаются явными границами. Запрос читает текущее type-1 значение.
Licensed `min_l_n1.dat` подтверждает изменение `0xe00` и Behavior `0x1002` с
-`1.0` до `0.5` после явного уменьшения количества вдвое; это ещё не
-автоматический бюджетный цикл.
+`1.0` до `0.5` после явного уменьшения количества вдвое; чтение получает
+текущее значение provider, который также меняет явный бюджетный шаг.
Native oracle проверил изолированные пути распределения, обновления класса `4`,
стадийную арифметику `0x11220`, обход дочерних provider-строк `0x11130` на
interleaved parents `[-1, 0, 0, 1, 3]` с callback-порядком `1, 3, 4, 2` и
@@ -406,15 +414,28 @@ visibility transition `0x11920` с исходными AniMesh callbacks. ОтдÐ
в этом векторе подставлен mock-ом. Отдельный вектор с исходным генератором
tag `19` (`0x22980`, `0x229a0`, `0x22a60`) проверяет полную и ограниченную
rate, изменение provider и собственного множителя генератора; отрицательные
-параметры и нулевой знаменатель не проверены. Эти сценарии
-используют синтетические NDP/Node38-строки; они подтверждают локальные переходы
-и порядок вызовов, но не полную загрузку или выполнение Control на миссии. Вызовы
-`0x11220` используют `updateEffects = false`, что исключает ветвь Control FX и
+параметры и нулевой знаменатель не проверены. Native-векторы бюджетного шага
+подтверждают текущие ставки `+0x5dc/+0x5e0`, включая значения `0.2`/`0.4` у
+потребителя tag 15, пустой результат `-0.0` и невырожденную пару исходных
+устройств tag 19/tag 15 при `dt = 0.375`; Rust-тест повторяет поля этой пары
+на синтетической таблице. Реализация принимает только описанные factory и
+category tags; остальные callbacks и состояния остаются явными ошибками.
+Лицензированный `min_l_n1.dat` содержит исходные factory/current tags
+`[19, 19, 9, 15, 12, 12, 13, 13, 26, 25, 21]`. Публичный API оставляет всю
+таблицу без изменений при не конечном интервале и при первом неподдержанном
+current tag `9`; полный бюджетный проход для этой реальной таблицы поэтому не
+проверен. Успешные бюджетные native-векторы используют синтетические
+NDP/Node38-строки и подтверждают локальные переходы и порядок вызовов, а не
+полный Control tick на миссии. Прямые oracle-вызовы `0x11220` для одиночной
+строки используют `updateEffects = false`, что исключает ветвь Control FX и
`0x11af0`; в отдельном сценарии класса `9` `0xfca0` возвращается сразу после
смены видимости, поэтому связанное с ним движение не проверено. Хотя у строки
Control выставлен flag `0x102`, слово флагов ANI `+0x14` и производные байты
`+0x111..+0x113` изначально равны нулю. Вызовы AniMesh `0x93c0` и `0xa2a0` обновляют производную геометрию и
-видимость, это отдельная непроверенная граница, а не FX callbacks. Бюджетная
+видимость, это отдельная непроверенная граница, а не FX callbacks. Распределение
+и бюджетный шаг вызывают обязательный `0x11130(root, true)`, но их проверенные
+векторы имеют одну строку без смены стадии; они не доказывают исполнение FX или
+`0x11af0`. Бюджетная
часть активного `0xbcf0` исполнена на синтетическом хосте класса `10`:
при периоде `500` и нулевом RNG проверены пропуск до deadline и на равенстве
`437.5`, затем ресурсный `dt = 0.5` при времени `500`. На том же ограниченном
diff --git a/docs/appendices/script-vm.md b/docs/appendices/script-vm.md
index b658348..a362b73 100644
--- a/docs/appendices/script-vm.md
+++ b/docs/appendices/script-vm.md
@@ -752,8 +752,8 @@ amount, accumulator, aggregate или stage изменений.
Поле `+0x618` изначально выключено; обработчик события `7` задаёт gate по
правилу `gate = (arg == 2)` и вызывает пересчёт `0x2dc20`, только если gate
изменился. Проекция сохраняет начальное состояние и уважает установленную
-suspension-метку. События Control пока не исполняются,
-поэтому это API остаётся явным CPU-шагом и не подключено к игровому clock.
+suspension-метку. События Control пока не исполняются, а ресурсный budget API
+вызывается явно и пока не подключён к игровому clock.
Тесты Rust повторяют пропорциональный вектор, накопитель `+0x10`, округление
`2^24`, sequential capacity boundary, достижимый negative capacity и откат при
unsupported FX/lifecycle.
@@ -776,18 +776,37 @@ descriptor `+0x20`. Исходная rate-функция возвращает `-
вклад `0.1` или `0.5` и записывает аргументы своего update. Функции tag 15,
provider getter и изменение количества не подменены.
-| Бюджет | Коэффициент tag 15 | Amount / processed / total, биты | Доля, биты |
-|---|---|---|---|
-| `0.1` | `0.5` | `0x42206666` (`40.1`) | `0x3ecd4fdf` |
-| `0.5` | `1` | `0x4220cccd` (`40.2`) | `0x3ecdd2f2` |
+| Бюджет | Коэффициент tag 15 | Amount / processed / total, биты | Доля, биты | `+0x5dc` / `+0x5e0`, биты |
+|---|---|---|---|---|
+| `0.1` | `0.5` | `0x42206666` (`40.1`) | `0x3ecd4fdf` | `0x3e4ccccd` / `0x3e4ccccd` (`0.2`) |
+| `0.5` | `1` | `0x4220cccd` (`40.2`) | `0x3ecdd2f2` | `0x3ecccccd` / `0x3ecccccd` (`0.4`) |
Сравнение идёт по битам при x87 control word `0x007f`. Реальный update
вызывает RVA `0x10ba0` и публикует новую долю одним callback selector `0x200`.
Хотя генератор стоит первым в массиве, его update уже видит изменённое
количество: категория tag 15 обслуживается раньше. Проверены также интервал
и коэффициент, переданные mock-генератору. Его собственная генерация, другие
-категории и выполнение миссии этим не проверены.
-Rust пока не переносит этот изменяемый бюджетный цикл.
+категории и выполнение миссии этим не проверены. Исходные выходные ставки
+`+0x5dc` и `+0x5e0` также записываются на каждом вызове; при пустой таблице
+оба поля получают битовый отрицательный ноль.
+
+Rust предоставляет явный CPU-вызов
+`advance_loaded_mission_control_budget(engine, handle, dt)`. Он переносит
+диспетчер и callbacks исходных factory tags `15` и `19`, если текущий
+descriptor tag равен `15` или `19` (native categories `0` или `1`). Rates `+0x5dc/+0x5e0`
+сохраняются отдельно. Вызов работает на копии полного состояния: неизвестный
+descriptor, factory callback, provider или численный диапазон возвращает
+ошибку без публикации частичных изменений. Вызов ещё не включён в Control clock;
+нативный oracle также проверяет пустую таблицу с отрицательным нулём в обеих
+выходных ставках и невырожденную пару исходных устройств tag 19/tag 15 при
+`dt = 0.375`. Этот парный вектор проверяет изменения amount, processed amount,
+накопителя, доли, обоих множителей и ставок `+0x5dc/+0x5e0` по битам. Rust-тест
+повторяет его на синтетической provider-таблице. Для лицензированного
+`min_l_n1.dat` отдельный тест подтверждает состав factory/current tags и то, что
+первый неподдержанный current tag `9` отклоняет весь шаг без изменений; полного
+успешного бюджетного прохода для реальной миссионной таблицы пока нет.
+Rust также отклоняет нулевой знаменатель обновления tag 19; тест вызывает эту
+ошибку после изменения provider потребителем и подтверждает откат всей таблицы.
#### Генератор tag 19 в том же бюджетном проходе
@@ -814,8 +833,18 @@ provider уже после потребителя tag `15`, повторно вÑ
собственный множитель. Это не запись коэффициента выделения в `+0x4c`, как у
tag `15`: смысл изменения этого поля зависит от фабричного класса.
Векторы проверяют конечные положительные значения при x87 CW `0x007f`;
-нулевой знаменатель, отрицательные параметры и другие классы устройств ими
-не покрыты. Перенос общего бюджетного цикла в Rust ещё не завершён.
+нативный oracle дополнительно фиксирует невырожденный случай, в котором
+коэффициенты различаются и поле `+0x20` ненулевое. Нулевой знаменатель,
+отрицательные параметры и другие классы устройств остаются непокрытыми.
+В этом дополнительном native-векторе `dt = 0.375`, provider `40/100`, tag 19
+имеет `B = 1`, `C0 = 0.25`, а tag 15 — `B = 0.125`, `C0 = 0.75`, `C1 = 1.25`
+и начальный множитель `0.8`. Получены rate генератора `0x3dcccccd`, rate
+потребителя `0xbe400000`, amount `0x42202b85`, ratio `0x3ecd0481`, накопитель
+`+0x10 = 0x3d2e1400`, множитель tag 15 `0x3f088889`, множитель tag 19 `0`, а
+обе выходные ставки равны `0x3e88888a`. Это проверяет раздельное чтение
+коэффициента `C1` и множителя `+0x4c`, а также ненулевую базовую стоимость.
+Поддержанные Rust-векторы не означают, что любой Control descriptor или
+полный миссионный цикл уже работает.
#### Активация и начальные часы
diff --git a/docs/tomes/06-behavior.md b/docs/tomes/06-behavior.md
index 452f577..6406307 100644
--- a/docs/tomes/06-behavior.md
+++ b/docs/tomes/06-behavior.md
@@ -1051,6 +1051,26 @@ Rust переносит этот порядок, сохраняет native наÐ
реализованные FX или lifecycle-вызовы, таблица остаётся без изменений. Эти
операции обновляют только CPU-снимок и пока не подключены к игровым часам Control.
+Распределение по бюджету тоже доступно как отдельный CPU-вызов
+`advance_loaded_mission_control_budget`. Он сначала собирает положительные
+ставки, затем обслуживает категории в исходном порядке и передаёт каждому
+устройству его долю. Например, при запасе `40/100`, доле `0.4` и интервале
+`0.5` секунды tag 19 может принести `0.1`, а tag 15 запросить `0.2`.
+Потребитель получает половину запроса: запас становится `40.1`, доля — `0.401`,
+а множитель генератора уменьшается до `0.75`. Хотя генератор может стоять раньше
+в массиве, его обновление перечитывает уже изменённую долю после обслуживания
+категории tag 15. Этот явный вызов хранит также две выходные ставки `+0x5dc` и
+`+0x5e0`, но сам по себе ещё не запускается игровыми часами.
+Поддержаны factory callbacks `15/19` и текущие descriptor tags `15/19`
+(категории `0/1`); неизвестное устройство,
+недоступные данные provider или нулевой знаменатель останавливают весь шаг без
+частичных изменений.
+Другие категории и полный миссионный цикл пока не подтверждены. В лицензированном
+`min_l_n1.dat` рядом с тегами `19` и `15` есть также factory tags `9`, `12`,
+`13`, `21`, `25` и `26`; поэтому его полный проход пока явно отклоняется на
+первой неподдержанной категории `9`. Проверка сохраняет всю таблицу без
+изменений и не доказывает успешный бюджетный шаг на реальной миссии.
+
Отдельный путь объекта класса `4` умножает интервал на контактный коэффициент и
передаёт изменение строке. В проверенном примере коэффициент `1`, интервал `2`,
и значение строки уменьшается на `2`; этот коэффициент не является ставкой
@@ -1064,10 +1084,10 @@ Control заново разыгрывает срок обновления, даÐ
исходная DLL пропустила времена `500` и `501`, затем выполнила ресурсный шаг
на `502`. Выбрать случайный срок один раз и ждать его было бы неверно.
Принудительный шаг тоже расходует RNG; неактивный объект синхронизирует часы
-без такого расхода. Это локальные native проверки, а не работающий Rust
-Control: запросы Rust `0xe00` и `0x1002` читают текущее состояние строк,
-которое меняют явные API одной строки и распределения, а `0x1005` — загруженную
-ставку профиля.
+без такого расхода. Это локальные native проверки, а не автоматический Rust
+Control tick: запросы Rust `0xe00` и `0x1002` читают текущее состояние строк,
+которое меняют явные API одной строки, распределения и бюджетного шага, а
+`0x1005` — загруженную ставку профиля.
Точные нативные векторы и открытые границы описаны в [приложении](../appendices/script-vm.md#изменение-provider-состояния-control).
На x87 control word `0x007f` каждое умножение округляет мантиссу до 24 бит,