feat(assets): decode research tables and calculate candidate costs
This commit is contained in:
5 files changed
+1981
-23
No files matched your search
@@ -485,16 +485,53 @@ Tag выбирает конкретное правило. Для tag 1 запи
|
||||
|
||||
### TRF и preload-данные
|
||||
|
||||
TRF-файлы проходят структурный разбор. `auto.trf`, `data.trf` и tutorial
|
||||
variants имеют сигнатуру [NRes](../reference/nres.md) и содержат большие
|
||||
таблицы имён игровых прототипов: оружия, башен, сооружений и других объектов.
|
||||
Также найдены preload-записи, ANI и SKE resources.
|
||||
TRF-архивы используют несколько потребителей; один подтверждённый путь ведёт
|
||||
из `Handler(43)` к вычислению стоимости исследования. В проверенной сборке GOG
|
||||
`CalcFullResearchCost` из `ArealMap.dll` получает таблицу, загруженную через
|
||||
`MisLoad.dll`. Для этого пути `TRF0` содержит строки по десять сырых `u32`,
|
||||
`TRF1` — байты флагов, `TRFB` — пары «смещение имени и номер строки», а
|
||||
`TRF6` — пул строк с нулевыми окончаниями. Слово 8 строки связывает её с
|
||||
`TRFB` через младшие 16 бит; старшая половина сохраняется как неизвестное
|
||||
значение. `TRF2` и `TRF3` образуют упорядоченные списки предварительных
|
||||
исследований, которые читает этот путь стоимости. `TRF4`/`TRF5` образуют
|
||||
отдельную пару таблиц, но `CalcFullResearchCost` её не использует. Непрозрачные
|
||||
`TRF7`–`TRFA` остаются в архиве и требуются загрузчику.
|
||||
|
||||
По содержимому, порядку загрузки и consumers TRF с высокой вероятностью
|
||||
предоставляет AI/сценарному слою заранее подготовленную таблицу типов и
|
||||
связанных данных. Framing и имена подтверждены corpus-ом, но полная семантика
|
||||
каждой TRF-записи ещё не закрыта. Имена должны разрешаться через тот же
|
||||
resource registry, что и миссионные объекты.
|
||||
Модуль `fparkan-assets` разбирает этот профиль в `ResearchTrfDocument` и
|
||||
вычисляет пару результатов для одного Unit DAT:
|
||||
|
||||
```rust
|
||||
let table = ResearchTrfDocument::decode(archive_bytes)?;
|
||||
let cost = calc_full_research_cost(&candidate, &table)?;
|
||||
```
|
||||
|
||||
Расчёт проходит компоненты Unit DAT в порядке дерева. Компонент с нулевым
|
||||
`kind` завершает весь свой участок вместе с потомками. Для остальных ключ
|
||||
ресурса ищется среди имён `TRFB`; повтор строки добавляется лишь один раз.
|
||||
После прямых компонентов алгоритм обходит список `TRF2`/`TRF3` в его исходном
|
||||
порядке, углубляясь сразу в найденные предварительные исследования. Общая
|
||||
таблица посещений не даёт повторно добавлять узел и завершает циклы. Два бита
|
||||
флагов `TRF1` управляют включением строки и обходом её зависимостей; остальные
|
||||
сырые биты и слова не получают игровых имён без отдельного доказательства.
|
||||
|
||||
Результат первого native-выхода подписан в отладочной строке как ore и
|
||||
суммирует слово 1 `TRF0`, второй подписан как power и суммирует слово 0. Каждое
|
||||
сложение сохраняется как `f32` в порядке найденной последовательности. В
|
||||
принятом наборе из 23 синтетических тестов оригинальных DLL проверялись
|
||||
`CalcFullResearchCost` и два AI-предиката; именно вызовы `CalcFullResearchCost`
|
||||
подтвердили порядок обхода, дедупликацию, циклы, флаги и отсечение дерева.
|
||||
Две проверки суммы показали чувствительность округления: одна и та же сумма
|
||||
`1, 2^24, -2^24` даёт `0`, а в другом порядке `2^24, -2^24, 1` даёт `1`.
|
||||
|
||||
Эта проверка использовала синтетический исследовательский контекст и заданное
|
||||
для опыта x87-слово управления `0x007f`; она не запускала штатный `Handler(43)`.
|
||||
Локальный Rust-core принимает таблицу и одного Unit DAT, но пока не выбирает
|
||||
кандидата в AI-каталоге и не связывает таблицу с владельцем полного старта
|
||||
миссии. Поэтому `Single.01` всё ещё останавливается на неподдержанном
|
||||
`Handler(43)`. Разбор с настоящими `scream.trf` и `12hel1.dat` проверяет
|
||||
совместимость ресурса с API, но сам по себе не сравнивает стоимость с
|
||||
оригинальным живым контекстом. Проверки границ байтов защищают Rust от плохих
|
||||
входных данных и не приписываются нативному загрузчику.
|
||||
|
||||
### Стабильность AI-слоя
|
||||
|
||||
|
||||
Reference in new issue
Block a user