chore: simplify project to engine docs and tests

Remove planning and acceptance scaffolding while retaining the native Vulkan mission preview, format readers, runtime algorithms, and ordinary Rust tests. Keep the book aligned with the runnable project and validate checked-in shaders without generated tool metadata.
This commit is contained in:
2026-09-06 05:22:12 +04:00
parent da03e77f53
commit aa51f3574d
167 changed files with 667 additions and 23705 deletions
+22 -225
View File
@@ -1,115 +1,19 @@
# I. Путеводитель и методика
# I. Путеводитель
Первый том задаёт язык и правила всей документации. Он объясняет, как читать
технические главы, какие термины используются для игрового runtime, как
разделяются уровни уверенности и какие требования предъявляются к реализации,
которая должна работать с оригинальными данными без потери информации.
Игра выглядит как непрерывное движение, но компьютер строит её из отдельных
шагов. Он читает ввод, обновляет мир, вычисляет положение моделей и рисует
очередной кадр. Чтобы воспроизвести старую игру, нужно понять как её файлы,
так и правила этих шагов.
Документация рассчитана на разработчика, который уже умеет читать C/C++,
байтовые форматы, PE-модули и графические pipeline, но не обязательно знаком с
Iron3D. Поэтому этот том не описывает один конкретный crate, package или
физическое деление будущего кода. Он фиксирует контракты: что должно быть
прочитано, сохранено, рассчитано и показано.
Книга не требует опыта игровой разработки. Ниже объясняются основные понятия,
а последующие главы показывают их на конкретных данных «Паркана».
Подробные таблицы адресов и байтов полезны при реализации; при первом чтении
их можно пропустить.
## Назначение книги
Книга ведёт от общей архитектуры Iron3D к точным форматам данных и алгоритмам
исполнения. Практическая цель -- реализация, способная открыть оригинальный
каталог *Parkan: Iron Strategy*, загрузить миссию, создать мир, провести
игровой шаг и сформировать кадр.
Форматы в главах описываются как байтовые контракты. Если указано поле
`+0x10`, это означает расположение в потоке или структуре данных, а не
разрешение читать файл прямым `reinterpret_cast`. Для постоянных layouts
используются offsets, проверки размеров, bounded cursor и явное сохранение
неизвестных байтов. Для versioned и variable-length записей приоритет имеет
последовательный parser с контролем границ.
Игровое поведение описывается не только размером структур. Совместимая
реализация должна учитывать порядок событий, время, fallback-правила,
идентификаторы объектов, численные ограничения, состояние материалов,
границы кадра и правила завершения операций.
## Маршруты чтения
**Читатель, новый для игровой разработки**, начинает с базовых понятий этого
тома, затем переходит к архитектуре, игровому циклу и вводу в рендер. После
этого имеет смысл читать главы о миссиях, мире и ресурсных форматах.
**Разработчик совместимого движка** читает тома II-VII линейно. Технические
главы имеют одинаковую логику: назначение подсистемы, данные на диске,
представление в памяти, алгоритм работы, проверки и требования к новой
реализации.
**Аналитик оригинальной программы** использует этот том вместе с разделами о
доказательной базе, ABI, результатах корпусных проверок и границах знания.
Факты, согласованные выводы и открытые вопросы должны оставаться разделёнными:
это позволяет расширять реализацию без подмены проверенных контрактов
удобными догадками.
## Состав документации
1. **Путеводитель и методика** -- язык предметной области, правила чтения и
процедура проверки.
2. [**Запуск, архитектура и игровой цикл**](02-architecture.md) -- от
`iron_3d.exe` до расчёта и вывода кадра.
3. [**Ресурсная система и форматы**](03-resources.md) -- архивы, кэши, реестры
и служебные данные.
4. [**Мир, миссии и игровой runtime**](04-world.md) -- TMA, ландшафт, ареалы и
создание объектов.
5. [**Геометрия, материалы и рендер**](05-render.md) -- от вершины модели до
изображения на экране.
6. [**Поведение, управление, звук и сеть**](06-behavior.md) -- интерактивные
подсистемы.
7. [**Руководство по полной реализации**](07-implementation.md) -- предлагаемая
архитектура и порядок работ.
8. [**Справочник и доказательная база**](08-evidence.md) -- ABI,
конфигурация, статистика и открытые вопросы.
Дополнительные краткие определения собраны в
[глоссарии](../appendices/glossary.md). Технические области, где контракт ещё
не закрыт полностью, перечислены в
[границах знания](../appendices/knowledge-boundaries.md).
## Условные обозначения
`+0x10` означает смещение поля относительно начала структуры или записи.
`RVA 0x13B60` -- адрес относительно базы PE-модуля. `u16`, `u32`, `i16` и
`float32` обозначают типы фиксированной ширины. `LE` означает little-endian.
`payload` -- полезные данные записи после метаданных контейнера. `EOF` -- точное
завершение файла или ограниченного блока.
Если в тексте указан hash, RVA или ordinal, значение относится к явно
обозначенному binary profile. Адреса разных сборок не объединяются по имени
функции. При публикации функции нужны минимум модуль, SHA-256 сборки и RVA.
Размеры структур выражаются в байтах. Счётчики и offsets считаются частью
формата, даже когда их можно восстановить из длины файла. Padding, reserved
поля, неизвестные хвосты и gaps не нормализуются без доказанного правила.
## Совместимость
Слово "совместимость" в этой книге имеет несколько уровней.
**Reader** умеет открыть файл, проверить границы, извлечь известные поля и
сохранить неизвестные bytes так, чтобы данные можно было записать обратно.
**Viewer** умеет показать ресурс: модель, texture, material, эффект или карту.
Viewer может быть полезен для анализа, но он не доказывает поведение runtime.
**Runtime** умеет создать мир, зарегистрировать объекты, исполнять события,
обновлять время, применять контроллеры, выбирать видимое состояние и передавать
его рендеру.
**Полноценный движок** дополнительно воспроизводит порядок операций, численные
правила, fallback-поведение, resource lifetime, reference ownership, pause,
manual input, сетевые идентификаторы, boundaries кадра и состояние
интерактивных подсистем.
Поэтому файл может быть "прочитан правильно", но всё ещё не быть реализованным
на уровне движка. Например, reader MSH может восстановить вершины и индексы,
viewer может нарисовать mesh, а runtime обязан ещё сохранить material slots,
animation state, bounds, LOD, visibility, collision и связи с объектом мира.
`+0x10` означает смещение в байтах от начала записи. `RVA` — адрес относительно
начала загруженной DLL. `u16`, `u32`, `i16`, `float32` — числа фиксированного
размера. `LE` означает little-endian: младший байт числа записан первым.
`EOF` — конец файла. Неизвестные поля сохраняются без изменений.
## Движок как программа длительного действия
@@ -250,122 +154,15 @@ Writer пересчитывает только производные значе
записей, сортировочные таблицы и padding, если правило доказано. Unknown fields
и reserved ranges сохраняются побайтно.
## Иерархия доказательств
Документация использует четыре уровня уверенности.
## Проверка предположений
**Прямое наблюдение** -- поле, значение или последовательность видны в
инструкции программы, таблице PE, экспорте, строке, обработчике файла или в
самом ресурсе. Это самый сильный уровень.
Формат подтверждается тем, как оригинальная программа читает запись, и тем,
какие значения встречаются в игровых ресурсах. Изображение из стороннего
просмотрщика помогает заметить ошибку, но само по себе не доказывает формулу.
Для восстановленного поведения оставляем небольшой тест с конкретным входом
и ожидаемым результатом. Для неопределённого поля прямо пишем, что его смысл
неизвестен.
**Корпусное подтверждение** -- правило проверено на всех подходящих файлах
одного или нескольких явно названных наборов: демоверсии, Части 1 и Части 2.
Например, базовый корпус содержит 435 моделей MSH, 518 textures Texm и 923
эффекта FXID, прошедших структурные проверки без ошибок; полные части расширяют
эту матрицу вариантов.
**Согласованный вывод** -- назначение восстановлено по нескольким независимым
признакам: вызывающим функциям, vtable slots, строкам ошибок, диапазонам
значений и связям между форматами. Такой вывод пригоден для реализации, но его
численные детали следует проверять тестами.
**Открытый вопрос** -- данные можно читать и сохранять, однако предметный смысл
поля или редкой ветки не доказан. Такие bytes нельзя обнулять,
переупорядочивать или превращать в authoring API.
Уровень уверенности должен быть виден из формулировки. "Поле равно" означает
проверенный layout или значение. "Вероятно отвечает за" означает согласованный
вывод. "Неизвестно" означает сохранять без изменения и не строить вокруг этого
публичный контракт.
## Проверенные материалы
Локальный набор проверки включает демоверсию, полные каталоги Частей 1 и 2,
исполняемые файлы, 15 DLL каждой сборки и игровые ресурсы. DLL из
первоначального архива и DLL демоверсии совпали по SHA-256: `15/15`, поэтому
выводы по этому коду и demo-ресурсам образуют один доказательный профиль.
Исполняемый файл демоверсии `iron_3d.exe` имеет размер 36 864 байта, PE32/x86,
entry RVA `0x141E`, image base `0x400000` и SHA-256
`b0a8b0db1c3a8698c4d4604d89c655496bd91ac1f8859a455e8a45838aebfbd6`.
Исполняемые файлы Частей 1 и 2 также имеют размер 36 864 байта и побайтно
совпадают между собой, но относятся к другому binary profile: entry RVA
`0x147E`, SHA-256
`f476af85c034a4b4f34f49d0806e4dff397b5da0ee26d382a7674231144979f7`.
Полные каталоги Частей 1 и 2 суммарно включают 60 TMA, 1 101 unit DAT, 254
NRes-файла и 14 975 NRes entries. Все контейнеры и TMA прошли bounded parser до
точного EOF; полный достижимый граф обеих частей разрешился без ошибок.
## Процедура проверки
Проверка строится как воспроизводимая цепочка:
1. Снять PE-метаданные, хэши, импорты, экспорты, ordinals, RTTI и строки.
2. Построить граф вызовов между модулями и отметить фабрики подсистем.
3. Разобрать функции запуска, загрузчики файлов, главный цикл и критические
vtable-вызовы.
4. Проверить форматы независимыми reader-скриптами с контролем границ и точного
завершения файла.
5. Построить цепочку миссия -> объект -> прототип -> модель -> материал ->
texture.
6. Сравнить счётчики, диапазоны, ссылки и размеры на всём доступном корпусе.
Ключевой результат сквозной проверки демо-миссий: все 201 объектов шести
миссий разрешились в 501 запрос прототипов, затем в 501 модель, 501 таблицу
WEAR, 3 879 слотов материалов и 5 085 ссылок на textures или lightmaps. Ошибок
в фактически исполняемом пути нет.
## Что не считается доказательством
Удобное имя поля не доказывает его назначение. Совпадение layout с текущей
реализацией не доказывает поведение оригинального runtime. Успешный viewer не
доказывает writer. Успешный reader одного файла не доказывает формат всего
корпуса. Совпадение ABI не доказывает побайтную идентичность всех сборок.
Если локальные данные и предположение расходятся, приоритет имеют исполняемый
код, реальные ресурсы и взаимные invariants между форматами. Неизвестное поле
лучше оставить без имени, чем дать ему ложное предметное значение.
## Требования к воспроизводимости
Каждая новая реализация должна иметь strict parser mode, lossless roundtrip
mode и набор corpus tests. Неизвестные поля сохраняются побайтно. Любое
присвоенное полю имя должно сопровождаться наблюдаемым поведением или тестом.
Численные правила -- округление, порядок умножения, RNG и время -- считаются
частью формата исполнения, даже если файл читается правильно.
Минимальный отчёт проверки должен фиксировать:
1. build profile и hashes модулей;
2. путь или ключ ресурса;
3. размер входного файла и hash входных bytes;
4. версию parser-а или commit реализации;
5. список включённых quirks;
6. число прочитанных записей и точку EOF;
7. ошибки, предупреждения и unknown ranges;
8. результат roundtrip, если writer участвует в проверке.
Для runtime-проверок дополнительно нужны mission key, configuration, device
profile, начальное состояние, input/time script и trace значимых callbacks.
## Разделение профилей
Binary profile описывает исполняемый код: PE-метаданные, exports/imports,
ordinals, hashes, RVA и layout функций. Corpus profile описывает набор файлов:
каталог, миссии, ресурсы, размеры, counts, variants и статистику parser-а.
Эти профили нельзя смешивать без явной пометки. Один и тот же формат может
иметь общий смысл в разных сборках, но отличаться редкими ветками, адресами
функций или набором встреченных вариантов. Один и тот же address может иметь
смысл только внутри конкретного module hash.
При расширении документации новое утверждение должно отвечать на три вопроса:
1. Где это видно напрямую?
2. На каком корпусе это проверено?
3. Что должна сделать реализация, если правило нарушено?
Если на один из вопросов нет ответа, утверждение остаётся согласованным выводом
или открытым вопросом, а не закрытым контрактом.
RVA зависит от сборки DLL. Сравнивая инструкции, сначала сверяют соответствующий
файл с [таблицей оригинальных модулей](../reference/original-binaries.md).
-15
View File
@@ -484,21 +484,6 @@ Visual dependency expansion наследует этот индекс на edges
diffuse texture и lightmap. Поэтому ошибка или asset в любой из этих фаз
сохраняет путь до конкретной записи unit DAT, а не только до миссионного object.
Для воспроизводимой проверки используется `fparkan-cli prototype inspect`.
Схема JSON `fparkan-prototype-inspect-v2` содержит lossless hex каждого
32-byte поля unit record и materialized graph edges с `unit_component_index`.
Например, для GOG AutoDemo:
```powershell
cargo run -p fparkan-cli -- prototype inspect `
--root 'C:\GOG Games\Parkan - Iron Strategy' `
--key 'UNITS\UNITS\AutoDEMO\w_m_wlk2.dat' --format json
```
Вывод фиксирует 18 component records, их MSH/WEAR/MAT0/Texm dependencies и
точные parent edges. JSON предназначен для анализа и regression evidence, а
не для интерпретации `kind`, links или opaque tails как готовой game logic.
## Вспомогательные форматы
MSH, материал и текстура отвечают за видимую форму. Полноценный прототип
+62 -1091
View File
File diff suppressed because it is too large Load Diff
-18
View File
@@ -447,24 +447,6 @@ Licensed test на GOG `Autodemo.00` запускает этот путь для
доказывает связывание current runtime data, но не доказывает семантику
оригинального движения.
Путь доступен и через самостоятельный composition root:
```powershell
fparkan-headless --root "C:\GOG Games\Parkan - Iron Strategy" `
--mission MISSIONS/Autodemo.00/data.tma `
--move-object 0 419.10318 717.433 0.25 --ticks 1
```
`--move-object` принимает original object ID, target X/Y и maximum step;
требует `--root` и `--mission`, допускается один раз за запуск и отвергает
non-finite/неположительный шаг ещё при разборе аргументов. Приложение печатает
`reached`, затем normal headless tick/hash. Проверка на GOG 18 июля 2026 года
загрузила 8 objects, 343 areals и 3 174 terrain surfaces без graph failures;
команда для объекта `0` вернула `reached=false`, что подтверждает именно
ограниченный шаг, а не телепортацию к цели.
### Различия Control в Части 2
`Control.dll` пересобрана при неизменных размере, imports и пяти именах/ordinals
exports; RVA всех пяти exports изменились. Форматы и cross-module boundary
сохранились, но точное physical/collision behavior нельзя считать побайтно тем
+67 -711
View File
@@ -1,711 +1,67 @@
# VII. Руководство по полной реализации
Этот том описывает инженерный путь к совместимому движку FParkan. Он опирается
на доказанные форматы и runtime-контракты, но не требует повторять физическое
деление оригинала на пятнадцать DLL. Повторить нужно наблюдаемое поведение:
форматы, имена, fallback, object IDs, порядок событий, численную политику,
границы кадра, сохранения и воспроизводимость прохождения.
Предложенные ниже modules, handles, snapshots, queues и scheduler phases являются
целевой архитектурой новой реализации, а не восстановленным внутренним layout
оригинального Iron3D. Главная практическая цель: запускаться из неизменённого
оригинального каталога игры, проходить corpus gates для демоверсии, Части 1 и
Части 2, а затем измеримо двигаться от archive compatibility к полной игровой
совместимости.
## Целевая архитектура
Практичная форма новой реализации -- модульный монолит с узкими интерфейсами и
отдельными platform adapters. Внутренние границы должны соответствовать ролям
Iron3D, а не обязательно его DLL. Это упрощает перенос на современные платформы
и оставляет возможность поддерживать разные compatibility profiles для разных
сборок данных.
```text
application запуск, окно, конфигурация, shutdown
platform filesystem, clocks, input, threads, dynamic libraries
resources NRes, RsLi, paths, archives, cache and diagnostics
assets MSH, WEAR, MAT0, Texm, FXID and auxiliary formats
mission TMA, unit DAT, prototype graph, scenario data
world ObjectId, queue, lifecycle, time, messages, mirrors
terrain Land.msh, Land.map, surface and spatial queries
navigation areals, graph search, corridors
behavior unit state machines, target and path requests
physics control systems, collision proxies and contacts
animation pose sampling, hierarchy and blending
audio sample cache, sources, listener and buses
render immutable frame contracts and modern backend
network game message schema plus transport adapters
tools validators, extractors, viewers, captures and editors
```
Каждый модуль зависит от нижележащих интерфейсов, а не от concrete managers.
Behavior видит `INavigation` и `IPhysicsCommandSink`, но не включает headers
renderer-а. Render получает immutable snapshot, а не mutable world. Network
receive не меняет мир напрямую: validated messages попадают в очередь следующей
calculation boundary.
### Центральные идентичности
Resource identity хранит и исходное написание, и нормализованный ASCII-key для
поиска:
```c
struct ResourceKey {
NormalizedRelativePath archive;
FixedAsciiName name;
uint32_t type_id;
};
```
Normalization сохраняет исходную строку для diagnostics и roundtrip, а отдельный
ASCII-casefold key используется только для lookup. Эта граница важна для
архивов [NRes](../reference/nres.md), таблиц [RsLi](../reference/rsli.md),
prototype references и fallback-путей материалов.
Object identity разделяет внутреннюю защиту от dangling references и исходную
сетевую/script-семантику:
```c
struct ObjectHandle { uint32_t generation; uint32_t slot; };
struct OriginalObjectId { uint32_t raw; };
```
`ObjectHandle` нужен для безопасного внутреннего владения, deferred deletion и
weak references. `OriginalObjectId` сохраняет наблюдаемую семантику исходной
игры: scripts, mirrors, network messages и savegame references должны видеть
логический ID, а не адрес объекта или номер slot в новом allocator-е.
Frame snapshot отделяет simulation от render. Simulation пишет mutable state;
renderer читает опубликованное состояние или строго ограниченную фазу
`in_render`. Deferred deletion применяется между фазами, а не во время traversal.
Командный контур renderer-а должен сверяться с [описанием кадра](../reference/render-frame.md)
до pixel comparison.
### Владение ресурсами
Ресурс проходит несколько уровней:
```text
ArchiveHandle -> EntryView -> DecodedBlob -> ParsedAsset -> RuntimeResource
```
`EntryView` ссылается на metadata архива, `DecodedBlob` владеет подготовленными
bytes, `ParsedAsset` является CPU-представлением, `RuntimeResource` может
дополнительно владеть GPU/audio objects. Eviction верхнего уровня не закрывает
архив, если он ещё нужен другому entry. Ссылки идут вниз только через явные
handles.
Для shared objects допустимы reference counting или generation handles.
Intrusive refcount нужен только в ABI-shim; внутренний современный код
предпочтительно держит понятное владение и weak handles. Архивы, decoded blobs,
CPU assets и GPU resources имеют отдельные бюджеты и отдельные diagnostics.
### Backend adapters
Render, audio, input и network получают отдельные adapters. Compatibility state
живёт вне Vulkan, D3D11 или Metal backend; DirectPlay compatibility живёт
отдельно от modern transport. Так можно заменить платформу, не меняя форматы,
игровую семантику и regression corpus.
Backend adapter не должен быть местом, где исправляются данные. Если
[MSH](../reference/msh.md), [MAT0](../reference/materials.md) или
[Texm](../reference/texm.md) требуют fallback, это фиксируется в asset/runtime
слое и попадает в trace. Backend получает уже выбранные resources, states и
draw items.
### Scheduler phases
```text
collect_platform_events
build_input_snapshot
advance_game_clock
calculate_world_queue
apply_deferred_operations
update_navigation_physics_animation_fx
publish_render_snapshot
render_world
render_ui
end_frame_callbacks
maintenance_and_eviction
```
Фазы имеют стабильный порядок и запрещённые операции. Registry mutation
запрещена во время world traversal, GPU upload не изменяет simulation state, а
maintenance не влияет на gameplay. Script timers, material animation и FX
lifetime относятся к game time, если обратное не доказано.
Сначала реализуется однопоточный эталон. Параллелизм добавляется только внутри
фаз с детерминированным merge: decoding независимых assets, culling chunks или
подготовка immutable draw items. Это снижает риск скрытых race conditions и
расхождений replay.
### Структурированные ошибки
Каждая ошибка должна содержать фазу, путь, archive entry, object/prototype key,
offset и цепочку причины.
```text
MissionLoadError
mission: Campaign.00/Mission.02
object: 17
resource_name: UNITS/.../unit.dat
component: e_tur_...
prototype: objects.rlb::e_tur_...
cause: model archive missing
```
Логическое отсутствие необязательного lightmap, отсутствующий entry в архиве,
неизвестное opaque поле, выход ссылки за диапазон и повреждённый offset имеют
разный severity и разные способы исправления. Ошибка данных должна быть
actionable chain, а не строка вида `failed to load resource`.
## Порядок работ
Движок строится от данных к поведению и от детерминированных CPU-компонентов к
аппаратным. Каждый этап заканчивается исполняемым инструментом и тестовым
критерием. Нельзя начинать полноценный gameplay, пока ресурсный граф и
model/material path не дают воспроизводимый результат.
### Этап 0. Corpus harness
- индексировать оригинальный каталог и вычислить hashes;
- реализовать bounded binary cursor и structured diagnostics;
- создать CLI для массового запуска parser-ов;
- сохранять JSON-отчёт с counts, variants, warnings и failures;
- зафиксировать демоверсию, Часть 1 и Часть 2 как независимые baselines.
Готовность: повторный запуск на каждом неизменённом каталоге даёт идентичный
отчёт. Любой parser умеет завершиться контролируемой ошибкой с offset и
контекстом, а не crash или allocation по непроверенному count.
### Этап 1. Архивы и пути
- реализовать strict/lossless [NRes](../reference/nres.md) reader/writer;
- реализовать [RsLi](../reference/rsli.md) mapping, table transform, lookup,
LZSS и Deflate;
- добавить адаптивный decoder для методов `0x080` и `0x0A0`;
- воспроизвести overlay и известные compatibility quirks;
- реализовать archive-handle cache и ASCII name policy.
Готовность: неизменённые архивы проходят byte-identical roundtrip; поиск всех
имён совпадает с каталогом; malformed corpus отклоняется без выхода за память.
NRes с ненулевым unindexed region обязательно остаётся regression case.
### Этап 2. Граф ресурсов
- разобрать `objects.rlb` и unit DAT;
- построить resolver прямой MSH, рекурсивного parent prototype через
`objects.rlb` и отдельного BASE payload;
- реализовать dependency graph с reachability от миссии;
- добавить parsers CTPT, NDPR и остальных служебных форматов в lossless-режиме;
- создать инспектор прототипа, показывающий все связанные ресурсы.
Готовность: 201 demo-объект раскрывается в 501 прототип. Затем все миссии
Частей 1 и 2 дают 4 701 и 5 845 prototype requests без failures. Недостижимые
отсутствующие ресурсы отмечаются отдельно от критических ошибок в reachable
graph.
### Этап 3. Статический asset viewer
- реализовать [MSH](../reference/msh.md) core streams, slots и batches;
- декодировать Texm во все подтверждённые pixel formats;
- разобрать WEAR и [MAT0](../reference/materials.md) с точными fallback;
- построить современный renderer compatibility layer;
- добавить wireframe, normals, bounds, LOD/group и material debug views.
Готовность: открываются 435/511 моделей, 518/631 textures и 905/1 127 materials
Частей 1/2; batch/index bounds не нарушаются; viewer показывает корректно
текстурированную статическую модель из исходного архива. Красивый viewer всё ещё
означает только asset compatibility, а не готовую игру.
Текущее состояние репозитория нужно формулировать строже. `apps/fparkan-viewer`
сейчас является inspection CLI и synthetic command producer, а не live Vulkan
asset viewer. Реальный Vulkan в репозитории сегодня доказан только через
Stage 0 smoke triangle path; Stage 3 GPU vertical slice для оригинального
`MSH` + `Texm` + `WEAR/MAT0` + terrain остаётся блокером. Для различения
smoke, planning и live GPU путей используйте [таблицу правды renderer paths](../rendering/renderer_truth_table.md).
### Этап 4. Анимация и эффекты
- реализовать MSH type 8/type 19 sampling и hierarchy;
- добавить x87-compatible reference path для чувствительных формул;
- реализовать material phase animation;
- разобрать FXID header/commands и runtime instances;
- сначала поддержать все opcodes, встречающиеся в корпусе, сохраняя raw body;
- добавить deterministic RNG stream и effect capture.
Готовность: frame-by-frame poses совпадают с golden reference своей части; все
923/1 065 FXID создаются без parser errors; перезапуск одинакового effect seed
даёт идентичный список emitted primitives.
Текущее состояние репозитория опять же уже, чем целевой этап. В коде есть
portable reference sampler и детерминированный FX reference stub, но нет
runtime-captured parity для lifecycle/opcode semantics и нет Stage 4 rendered
acceptance поверх live Vulkan asset renderer. Поэтому rendered Stage 4 следует
считать заблокированным входным gate Stage 3, а parallel Stage 4 work вести
через captures, schemas и backend-neutral snapshots.
### Этап 5. Карта и мир
- реализовать `Land.msh` и corrected `TerrainFace28` layout;
- построить terrain rendering и CPU surface queries;
- реализовать `Land.map`, cell grid и graph links;
- визуализировать areals и найденные маршруты;
- разобрать [TMA](../reference/tma.md) и выполнять staged mission loading;
- создать World3D queue, ObjectId и deferred deletion.
Готовность: 65 карт и 60 TMA Частей 1 и 2 загружаются до EOF; все areal links
валидны; objects появляются в правильных transforms; мир выдерживает расчётные
шаги без рендера.
### Этап 6. Gameplay controllers
- подключить input snapshot и camera controller;
- реализовать navigation corridor, Behavior state machine и Wizard boundary;
- создать physical controller и collision manager;
- загрузить control resources в lossless typed model;
- внедрить game time, pause, event queue и end-of-frame callbacks;
- подключить AI layer и symbol/event layer сценариев.
Готовность: юнит получает цель, строит маршрут, движется по terrain, реагирует
на collision и исполняет базовые миссионные события в детерминированном replay.
На этом этапе вводится differential branch для изменённых `AniMesh`, `Control` и
`Effect`; неизменённые DLL используют общий reference path.
### Этап 7. Полный кадр, звук и UI
- реализовать render phases, sorting, lighting, shadows и atmosphere;
- подключить 3D listener, sample cache, FX sounds и mission audio;
- воспроизвести shell/UI loading и post-world pass;
- добавить frame capture до UI и после UI;
- зафиксировать capability fallback profiles.
Готовность: миссия визуально и звуково проходима; каждый draw и sound event
имеет trace; одинаковый replay создаёт одинаковые command lists. На этом этапе
вводится differential branch для `iron3d` и `services`.
### Этап 8. Сеть, сохранения и динамическая совместимость
- реализовать modern transport над versioned game-message schema;
- отдельно исследовать DirectPlay wire и `netZipData` для native compatibility;
- добавить mirrors, ownership transfer и disconnect cleanup;
- восстановить save/campaign state и dispatcher;
- выполнить динамические captures оригинала для render states, script VM и
physics edge cases.
Готовность: одиночная кампания запускается из оригинального каталога,
сохраняется и продолжается; multiplayer replay согласован между peers; full
corpus не создаёт новых parser variants без явной регистрации.
## Тестовый контур
Совместимость нельзя подтвердить одним screenshot. Нужны тесты на уровне bytes,
структур, ссылок, simulation state, команд renderer-а и конечного изображения.
Каждый слой локализует свой класс ошибки.
```text
unit tests
-> parser/property tests
-> corpus validation
-> cross-resource integration
-> deterministic simulation replay
-> render/audio command captures
-> pixel and gameplay parity
```
Failure верхнего уровня всегда должен позволять спуститься к меньшему тесту и
понять причину.
### Unit, property и fuzz tests
Для каждого binary primitive проверяются little-endian чтение, bounded strings,
checked arithmetic и cursor boundaries. Для структур -- минимальный размер,
максимальные counts, пустые arrays, нулевые варианты и редкие branches.
Property tests генерируют случайные корректные NRes/RsLi/WEAR records,
выполняют encode -> decode и сравнивают семантику. Fuzz tests изменяют длины,
offsets, counts и termination bytes и требуют контролируемой ошибки без crash и
чрезмерного выделения памяти.
Критические алгоритмы имеют отдельные vectors: ASCII casefold, NRes permutation
search, RsLi byte transform, LZSS backreferences, quaternion shortest path,
matrix composition и terrain mask remap.
### Corpus validation
Каждый файл оригинального каталога проходит parser своего семейства. Отчёт
содержит hash, variant, counts, warnings, errors и точный offset сбоя. Baseline
демоверсии:
```text
MSH 435
MAT0 905
Texm 518
FXID 923
WEAR 457
Land.msh 6
Land.map 6
TMA 6
unit DAT 425
errors 0
```
Изменение parser-а принимается только если baseline остаётся стабильной либо
новый variant зарегистрирован с образцом и объяснением. Warnings должны быть
именованными: «неизвестное opaque поле» не равно «выход ссылки за диапазон».
### Cross-resource integration
Интеграционный тест начинается с миссии и проходит весь dependency graph:
object -> prototype -> MSH -> WEAR -> MAT0 -> Texm/lightmap/FXID. Он не
ограничивается тем, что файлы существуют: material slot должен указывать на
допустимый MAT0, phase -- на допустимую texture, model batch -- на существующий
WEAR index.
Demo mission total: 201 objects -> 501 prototypes -> 501 object MSH/WEAR.
Чистый object graph даёт 3 873 material slots и 5 049 texture requests; после
включения environment WEAR итог равен 3 879 material slots, 5 067 textures и
18 lightmaps, failures 0. Такой тест ловит ошибки casefold, suffix, fallback и
путей, которые отдельный parser не замечает.
Для каждого отсутствующего узла отчёт хранит полный parent chain, чтобы
различать broken global archive и реально достижимый mission failure.
### Deterministic simulation replay
#### Mission transform state in the world contract
`fparkan-world` now carries a `TransformState` for every live object: the
three TMA position words, three orientation words and three scale words are
preserved as exact IEEE-754 bit patterns. This stores source identity before a
movement or physics controller interprets axes, units or Euler order.
`WorldSnapshot` publishes transforms in stable object-handle order and the
canonical SHA-256 state hash includes every transform word.
Mission loading assigns this state after construction and before registration.
A headless licensed GOG AutoDemo run on 2026-07-18 loaded eight objects, 343
areals and 3,174 terrain surfaces with zero graph failures, then completed two
deterministic ticks. This is the state foundation for a future route/movement
controller; it does not claim recovered velocity, collision or original
behavior-controller semantics.
The ordinary planning renderer now consumes this snapshot state before falling
back to a mission draft. Its current transform bridge applies the preserved
position and non-uniform scale only; raw orientation remains uninterpreted in
this backend-neutral path. A GOG AutoDemo planning run on 2026-07-18 completed
two ticks with eight objects, 66 draws and state hash
`a54855a4f47ffa380911228f295dd49a9a7b88d6ff271a23db48ba318b1fbbb4`.
Записывается начальная миссия, seed, input events, network messages и значения
внешних часов. На контрольных ticks сохраняется canonical state hash:
```text
sorted ObjectId list
transforms and velocities
critical properties and owners
AI/behavior state IDs
active effect state
game clock and RNG states
```
Pointer addresses, allocator order и GPU handles в hash не входят. Два запуска с
одинаковым log должны давать одинаковый state hash на каждом checkpoint. Первое
расхождение гораздо информативнее финального разного результата миссии.
### Render command parity
До pixel comparison сравнивается command list:
```text
camera matrices and viewport
visible ObjectIds
render phase and stable order
model/node/slot/batch IDs
material phase and texture handles
legacy pipeline states
index ranges and transforms
```
Если command lists совпадают, но pixels различаются, проблема находится в
shader/backend, sampling или численной точности. Если command lists уже
различаются, pixel diff лишь скрывает более раннюю ошибку.
Golden captures следует хранить отдельно для статической модели, анимации,
terrain, transparent FX, shadows, lightmap и atmosphere.
### Pixel, audio и network tests
Pixel tests используют фиксированное разрешение, camera, device profile, seed и
timeline. Сравниваются exact pixels для CPU/reference path и tolerance metrics
для GPU path, но tolerance не должна скрывать переставленные прозрачные
primitives.
Audio tests сравнивают список sound events, sample IDs, positions, loop flags и
gains; waveform зависит от mixer/device и является вторичным уровнем. Network
tests воспроизводят captured message sequences, проверяют mirrors, ownership и
disconnect. Для native DirectPlay compatibility дополнительно нужен packet-level
corpus.
## Regression baselines
Corpus validation формирует три независимых отчёта: демоверсия, Часть 1 и
Часть 2. Каждый сохраняет manifest файлов, hashes executable/DLL, variants,
warnings, global archive health и mission reachability.
Ключевые corpus gates:
```text
NRes: 120 файлов / 6 804 entries и 134 / 8 171 для Частей 1/2
TMA: 29 миссий / 864 objects / 28 extras и 31 / 885 / 41
MSH: 435 и 511 моделей
MAT0: 905 и 1 127 материалов
Texm: 518 и 631 текстура
FXID: 923 и 1 065 эффектов
full reachability: 4 701 и 5 845 prototype requests, failures 0
```
Расширенные mission-reachability totals:
```text
Часть 1: 29 TMA, 864 objects, 4 701 prototypes,
36 954 materials, 48 806 textures, 139 lightmaps, failures 0
Часть 2: 31 TMA, 885 objects, 5 845 prototypes,
50 888 materials, 68 603 textures, 214 lightmaps, failures 0
```
Обязательные regression cases:
- NRes с ненулевым unindexed region;
- prototype inheritance через `objects.rlb`;
- unit DAT `description[32]` без NUL;
- TMA epilogue и `extra_count` 0--4;
- empty SWAV entry;
- stale save-slot metadata без payload;
- build-scoped RVA lookup.
Byte-identical asset comparison выполняется только внутри одного корпуса. Между
Частями 1 и 2 сравниваются semantic invariants и decoded representation,
поскольку многие assets пересобраны.
## Точность, скорость и повторяемость
Совместимый движок должен быть корректным, повторяемым и достаточно быстрым.
Эти свойства нельзя получать одним и тем же приёмом. Сначала создаётся простой
эталонный путь, затем он измеряется и оптимизируется без изменения результата.
Главные источники расхождений: x87 extended precision, преобразование float в
integer, порядок операций, старые SIMD implementations, нестабильная сортировка,
RNG и использование разных часов.
### x87 и округление
Оригинальный x86-код мог хранить промежуточные значения в 80-битных регистрах
x87, а в память записывать 32-битный float. Современный compiler чаще использует
SSE с округлением после каждой операции. Различие заметно на границах animation
frame, culling plane и collision threshold.
Для критических формул нужен reference mode:
- фиксированный порядок операций без reassociation;
- запрещённый fast-math;
- явные преобразования и проверенный режим округления;
- тесты возле half-integer и epsilon boundaries;
- при необходимости extended intermediate через `long double` на проверенной
платформе.
Не требуется эмулировать x87 во всём движке. Нужно локализовать функции, где
малое отличие меняет дискретное решение, и держать для них scalar reference path.
### RNG как часть состояния
FX, atmosphere и, вероятно, AI используют случайные значения. Один глобальный
RNG легко расходится, если новая реализация запрашивает дополнительное число для
визуальной оптимизации. Для трассировки полезны именованные streams:
```text
world/gameplay RNG
AI/script RNG
FX instance RNG
atmosphere RNG
non-deterministic cosmetic RNG
```
Для native parity может потребоваться один общий алгоритм и точная sequence. До
подтверждения capture каждый stream хранит seed и счётчик вызовов в trace.
Cosmetic stream не входит в simulation hash.
### Стабильный порядок
Коллекции не должны зависеть от адресов, unordered containers или порядка
завершения worker threads. Для объектов, collision pairs, opaque/transparent
draws и network messages задаются явные stable keys:
- objects -- queue insertion sequence или OriginalObjectId;
- collision pairs -- упорядоченная пара IDs;
- opaque draws -- phase, pipeline key, material, stable insertion ID;
- transparent draws -- layer, quantized distance, stable insertion ID;
- network messages -- sequence и sender.
Даже когда математический результат коммутативен, side effects, cache accesses и
RNG делают порядок наблюдаемым.
### Часы и fixed-step
Monotonic platform clock хранится отдельно от game clock. Pause и time scaling
применяются к game clock. Simulation работает с фиксированным или точно
воспроизводимым шагом, а render может интерполировать presentation state, не
изменяя authoritative world.
Maintenance timers кэшей используют реальные часы или отдельную подтверждённую
шкалу; их срабатывание не должно менять gameplay. При перегрузке лучше выполнить
ограниченное число simulation steps и явно зафиксировать dropped presentation
frames, чем передать огромный `dt` в AI/physics.
### Оптимизация без потери эталона
1. Сохранить scalar reference implementation.
2. Добавить profiler counters на decoding, culling, sorting, animation, upload
и draw.
3. Оптимизировать только измеренный bottleneck.
4. Сравнить SIMD/parallel результат с reference на полном corpus.
5. Оставить runtime switch для отключения оптимизации при диагностике.
`g_FastProc` удобно моделировать как таблицу function objects: все slots сначала
указывают на scalar path, затем безопасные slots заменяются SIMD-вариантами
после self-test на старте.
### Кэш и память
Архивы, decoded blobs, CPU assets и GPU resources имеют отдельные budgets.
Eviction разрешена только для объектов с нулевым external refcount и после
безопасной frame fence. Original delayed cleanup порядка десятков секунд можно
воспроизвести policy-параметрами, не сканируя все entries каждый кадр.
Основные показатели: число открытых архивов, decoded bytes, resident
textures/lightmaps, models, active FX, draw items и deferred-delete size. Любой
неограниченно растущий счётчик является regression. Производительность считается
достаточной только после корректности: стабильные 60 FPS с неверным LOD или
пропущенными эффектами не являются успехом.
## Release gates
Версия не выпускается, если:
- появился новый corpus error;
- изменился byte roundtrip неизменённых ресурсов;
- dependency graph получил failure в достижимом пути;
- deterministic replay расходится;
- command capture изменился без ожидаемого changelog;
- parser допускает allocation по непроверенному count;
- новая оптимизация не имеет scalar reference comparison.
Каждое исправление регистрирует минимальный regression asset или synthetic
vector. Если новый behavior намеренно отличается от предыдущего, изменение
должно иметь compatibility profile, corpus sample и объяснение, почему старый
baseline был неполным или неверным.
## Уровни совместимости
Слово «совместимый» используется только с уровнем:
1. **Archive-compatible** -- открывает и сохраняет контейнеры.
2. **Asset-compatible** -- декодирует модели, материалы, текстуры и эффекты.
3. **Mission-compatible** -- загружает карту и создаёт все объекты.
4. **Runtime-compatible** -- исполняет время, события, поведение и физику.
5. **Presentation-compatible** -- воспроизводит рендер и звук.
6. **Game-compatible** -- позволяет пройти миссии, сохраняться и продолжать.
7. **Native-interoperable** -- взаимодействует с оригинальной сетью и внешним
ABI.
Viewer с красивой моделью находится только на втором уровне.
### Обязательные критерии запуска и данных
- приложение запускается из неизменённого оригинального каталога;
- относительные пути, регистр и legacy encodings разрешаются по исходным
правилам;
- все требуемые NRes/RsLi открываются без предварительной конвертации;
- parsers проверяют границы и не используют неопределённые bytes как указатели;
- неизвестные поля сохраняются lossless;
- все mission-reachable prototype, model, material, texture, lightmap и effect
references разрешаются;
- отсутствие необязательного ресурса следует документированному fallback, а не
случайному default.
### Обязательные критерии мира
- TMA разбирается до точного EOF;
- `Land.msh` и `Land.map` создают корректную поверхность и areal graph;
- ObjectId, owner и mirror semantics устойчивы;
- queue traversal и deferred deletion безопасны;
- pause, game time и simulation steps повторяемы;
- AI/Behavior/Wizard/Control взаимодействуют через заданные границы;
- collision и navigation не подменяют друг друга;
- script events используют logical IDs и переживают удаление объектов;
- deterministic replay совпадает на контрольных ticks.
### Обязательные критерии presentation
- static и animated MSH используют правильные slots, batches и transforms;
- WEAR/MAT0/Texm fallback и phase timing совпадают;
- mip-skip, palettes, Page atlases и lightmaps работают;
- render phases, depth/cull/blend state и transparent order подтверждены
captures;
- FXID commands и RNG дают устойчивый результат;
- camera и 3D sound listener синхронизированы;
- atmosphere, тени, солнце и flares не являются декоративными заглушками;
- UI и world rendering имеют правильную границу;
- golden command captures стабильны, pixel parity измеряется на фиксированных
сценах.
### Обязательные критерии полной игры
- все доступные миссии стартуют, завершаются и корректно сообщают
success/failure;
- campaign dispatcher сохраняет прогресс;
- savegame восстанавливает world, script, AI, RNG и clocks, а не только
placement;
- input remapping, pause, camera modes, sound и настройки работают из UI;
- длительный прогон не накапливает objects, resources или audio sources;
- ошибки данных показывают actionable chain;
- производительность приемлема без отключения подсистем;
- демоверсия, Часть 1 и Часть 2 проходят один и тот же тестовый контур с
раздельными manifests и эталонами.
### Native interoperability
Самый строгий уровень дополнительно требует совпадения x86 ABI экспортов, vtable
slots и calling conventions для подключаемых оригинальных модулей, а также
DirectPlay wire/framing и compression. Этот уровень независим от возможности
играть в новом standalone runtime.
Проект может честно заявлять game compatibility без native DLL/network
interoperability, но это должно быть явно указано. Аналогично pixel-perfect режим
может быть отдельным compatibility profile поверх функционально корректного
renderer-а.
### Совместимость нескольких наборов данных
Критерий полной совместимости применяется отдельно к демоверсии, Части 1 и
Части 2. Прохождение одного набора не позволяет заявлять поддержку остальных.
Обязательное различие:
- **format compatibility** -- один parser принимает все три набора;
- **content compatibility** -- конкретная миссия разрешает весь reachable graph;
- **behavior compatibility** -- runtime совпадает с соответствующей сборкой
изменённых DLL;
- **cross-version support** -- один новый движок выбирает корректные данные и
defaults по fingerprint установки.
Content fingerprint включает hashes executable/DLL и manifest ключевых архивов.
Он не используется для запрета модификаций, но выбирает compatibility profile и
делает отклонение диагностируемым.
## Definition of done
Полное документирование и реализация считаются завершёнными только когда каждый
критерий связан с главой спецификации, executable test и хотя бы одним
corpus/golden case. Утверждение без проверяемого критерия остаётся
исследовательской заметкой, а не контрактом.
# VII. Работа над движком
FParkan развивается небольшими законченными изменениями. Для нового поведения
сначала нужен пример из оригинала и Rust-тест, затем реализация и объяснение
в соответствующей главе. Если меняется видимый результат, проверка заканчивается
запуском приложения на настоящих игровых ресурсах.
## Где находится код
Библиотеки в `crates/` читают архивы и форматы, связывают ресурсы миссии,
вычисляют геометрию и хранят мир. Они не создают окно и не обращаются к GPU.
Окно находится в адаптере winit, графические ресурсы — в адаптере Vulkan.
`fparkan-game` связывает их в приложение.
У файла на диске и объекта в игре разные сроки жизни. Одна модель может быть
прочитана однажды и использоваться многими объектами, у каждого из которых
свои положение и время анимации. Материалы и текстуры тоже разделяются между
экземплярами. Владение этими данными видно из Rust-структур; отдельный сервис
или интерфейс добавляется, когда появляется реальная потребность.
## Один тест на правило
Для бинарного формата полезен короткий массив байтов: тест проверяет значения
полей и отказ при обрыве записи или неправильной ссылке. Для преобразования
координат удобны точки и повороты, результат которых легко посчитать вручную.
Тесты находятся рядом с соответствующим алгоритмом и запускаются через
`cargo test --workspace`.
Оригинальные ресурсы остаются в установленной игре. Локальные тесты с ними
помечены `#[ignore]`, чтобы обычная проверка работала без коммерческих файлов.
Сообщение об ошибке должно назвать ресурс и причину: например, какой материал
сослался на отсутствующую текстуру. Отдельный отчёт для каждого запуска не нужен.
## Числа и порядок вычислений
Порядок умножения матриц имеет значение: поворот объекта вокруг своей оси и
поворот его положения вокруг начала мира дают разные результаты. Единицы высоты
ландшафта могут отличаться от единиц размещённых объектов. Эти преобразования
выполняются в одном месте и проверяются конкретными точками.
Оригинальный x86-код использует x87. Промежуточное значение может иметь большую
точность, чем сохранённый `float32`. Особенно внимательно проверяются переходы
между кадрами анимации, округление и границы треугольников. Эмулировать x87 во
всём движке не требуется: существенные расхождения разбираются в конкретной
формуле.
Случайные числа и порядок обхода тоже влияют на поведение. Перестановка вызовов
генератора меняет время молнии или траекторию частицы даже при прежнем seed.
Для повторяемой проверки сохраняют начальное состояние и одинаковую
последовательность шагов. Дополнительные потоки и альтернативные алгоритмы
имеют смысл после измерения узкого места.
## Проверка изображения
Успешное создание Vulkan pipeline доказывает только корректность обращения
к API. Положение моделей, масштаб карты, текстуры, прозрачность и свет
проверяются в самом окне. Validation layer помогает находить ошибки владения
GPU-ресурсами, синхронизации и пересоздания swapchain.
Кадр для сравнения читается после завершения работы GPU. При изменении размера
окна старые framebuffer и изображения освобождаются лишь после окончания их
использования. При сворачивании окно может иметь нулевой размер; тогда новые
кадры не отправляются. Обычное закрытие завершает программу успешно.
Оптимизация начинается с измерения: время загрузки, число повторных декодирований,
объём текстур и время кадра. Повторное использование уже загруженного ресурса
обычно полезнее дополнительного слоя управления кэшем.
+19 -663
View File
@@ -1,33 +1,9 @@
# VIII. Справочник и доказательная база
# VIII. Устройство оригинальной программы
Восьмой том фиксирует, на чём держится книга: ABI, exports/imports, файловая
поверхность, статистика корпусов, открытые вопросы, критерии доказанности и
словарь терминов. Это самостоятельная справочная глава: она не заменяет
профильные статьи о форматах, но задаёт общий контракт, по которому проверяются
реализация, parser-ы, compatibility layer и будущие динамические эксперименты.
## Как читать доказательства
Доказательством считается наблюдение, которое можно повторить на конкретном
файле, сборке или трассе. Вывод может объединять несколько наблюдений, но он
должен сохранять происхождение данных: демоверсия, полная Часть 1 и полная
Часть 2 не смешиваются в один безымянный corpus.
Для каждого утверждения полезно различать четыре уровня:
- `layout-confirmed`: известны offset, size, count, bounds и правила безопасного
чтения;
- `corpus-verified`: branch или вариант реально встречается в доступных игровых
данных;
- `code-confirmed`: branch виден в бинарном коде, но отсутствует в доступном
corpus;
- `behavior-confirmed`: поведение подтверждено исполнением оригинальной
программы, трассой API/vtable или controlled differential test.
Если поле не имеет доказанного предметного смысла, документация хранит его как
opaque field. Это не мешает lossless read/write, но запрещает строить writer,
который очищает, переименовывает или пересчитывает такое поле на основании
правдоподобной догадки.
Здесь собраны детали, полезные при чтении оригинальных DLL: экспортируемые
функции, соглашения вызова, адреса и конфигурационные файлы. Адрес относится
к конкретной сборке; сравнить её можно по
[хэшам модулей](../reference/original-binaries.md).
## ABI и границы модулей
@@ -215,12 +191,10 @@ RVA используются только для сопоставления и
implementation не должна встраивать их как постоянные игровые идентификаторы.
Таблица внутренних RVA хранится по SHA-256 конкретного модуля.
Операционные evidence-артефакты, которые должны оставаться синхронизированными
с кодом и acceptance, вынесены в отдельные страницы:
- [Hashes и import/export summary оригинального движка](../evidence/original_engine_hashes.md)
- [Stage 4 capture schema](../evidence/stage4_capture_schema.md)
- [Renderer truth table](../rendering/renderer_truth_table.md)
Сводка hashes и import/export оригинального движка вынесена в отдельную
[страницу](../reference/original-binaries.md). Текущее состояние
реализации и границы live Vulkan path описаны в [справочнике render frame](../reference/render-frame.md)
и в исходном коде адаптера.
Подтверждённые hashes неизменённых DLL:
@@ -229,11 +203,10 @@ World3D.dll 17e4a3089b2583a8cf2356c9db0390b1aba138356a09130d79b4e7e4791da61e
Ngi32.dll bab9840d94f4e4e74ffc26677724fa896cf4823845504d09a9e025f80016edf5
```
Повторный headless IDA/Hex-Rays review GOG `World3D.dll` с этим hash уточнил
RVA export-ов: `stdCalculateGame=0x139A0`, `stdRenderGame=0x13BD0`,
Для GOG `World3D.dll` с этим hash RVA export-ов такие: `stdCalculateGame=0x139A0`,
`stdRenderGame=0x13BD0`,
`sendEndOfRender=0x13D90`, `stdSetCurrentCamera=0x13E60` и
`stdGetCurrentCamera=0x13E80`. Предыдущая таблица была сдвинута и не должна
использоваться для hooks или differential capture.
`stdGetCurrentCamera=0x13E80`.
`stdRenderGame(camera)` сначала вызывает экспорт Terrain
`stdSetCurrentCamera2(camera)`, затем сохраняет текущий camera pointer в
@@ -254,7 +227,7 @@ Terrain object. Следовательно, selector `18`, slot `+12` и global
должны оставаться именованными evidence boundary до dynamic capture; считать
`stdGetCurrentCamera2` getter-ом переданной camera было бы ошибкой.
Повторный headless-IDA review той же GOG базы уточняет рабочий static contract
Статический анализ той же GOG базы уточняет рабочий контракт
`CBufferingCamera`. Метод Terrain RVA `0x4D740` копирует ровно 64 байта
(16 dword) в component offset `+0x10`. Frame-preparation метод RVA `0x4D9C0`
получает viewport rectangle через virtual slot `+0x3C`, выводит width, height,
@@ -546,628 +519,11 @@ provenance: parser хранит не только effective value, но и пр
identifier и path normalization должны оставаться разными слоями: локализация
текста не меняет ASCII-casefold policy имён entries.
## Результаты проверки корпусов
### Demo baseline
## Дальнейшее чтение
Демоверсия содержит `iron_3d.exe`, те же 15 DLL и сокращённый набор
миссий/ресурсов. Все 15 DLL совпали с первоначально исследованными файлами по
SHA-256. Поэтому executable, бинарный код DLL и demo-assets относятся к одной
совместимой технологической сборке.
```text
modules: 16, из них DLL: 15
DLL exports: 313
DLL imports: 1126
DLL identity: 15/15
```
`iron_3d.exe`: 36 864 байта, PE32/x86, image base `0x400000`, entry RVA
`0x141E`, timestamp 28 июня 2001 года, SHA-256
`b0a8b0db1c3a8698c4d4604d89c655496bd91ac1f8859a455e8a45838aebfbd6`.
### Миссии и сквозные ссылки
Шесть TMA разобраны до точного EOF: суммарно 20 paths, 15 clans, 201 placed
objects и 1 extra record. 48 объектов ссылаются на unit DAT, 153 -- на прямые
prototype keys. Unit-файлы раскрыли 348 компонентов.
Сквозной результат:
```text
501 prototype requests 501 resolved
501 MSH requests 501 resolved
501 WEAR requests 501 resolved
3879 material slots 3879 resolved
5067 texture requests 5067 resolved
18 lightmap requests 18 resolved
failures 0
```
Это самое сильное интеграционное подтверждение текущего корпуса: имена,
архивы, ASCII casefold и fallback согласуются между реальными форматами.
### Реестр и unit DAT
`objects.rlb` содержит 590 prototype entries:
```text
554 имеют прямую MSH-ссылку
549 прямых MSH разрешаются в demo-каталоге
34 раскрываются через родительский prototype и локальный BASE
7 не дают доступной геометрии
41 ссылка общего реестра указывает на отсутствующий demo-content
```
Негеометрические или неразрешённые глобальные entries:
```text
sun_01
sun_02
ws_al_01
ws_al_02
ws_fl_01
ws_hm_01
ws_hm_02
```
Они не входят в фактически требуемую цепочку проверенных миссий.
Проверено 425 unit DAT, 5 219 records, errors 0. Все records имеют kind 1 и
archive `objects.rlb`; в 5 205 name fields есть ненулевые хвостовые байты после
string terminator. Такой tail является данными, а не мусором, если цель --
lossless roundtrip.
### Модели
Проверено 435 MSH без errors/warnings; 157 анимированных. Диапазоны: 1-38
nodes, 1-112 slots, 12-9 686 vertices, 1-439 batches.
```text
414 моделей: types [1,2,3,4,5,15,13,6,7,8,19,9,10,17]
21 модель: [1,2,3,4,5,18,15,13,6,7,8,19,9,10,17,20]
```
Type 17 непуст у 29 моделей; type 20 встречается у 21. Редкий variant type 1
найден в `system.rlb::MTCHECK.MSH`.
Повторная проверка terrain исправила layout face: vertex indices находятся с
`+0x08`, neighbor indices с `+0x0E`. Эта локальная проверка имеет приоритет над
ранними черновыми описаниями.
### Материалы и текстуры
Проверено 457 WEAR, 905 MAT0 и 518 Texm без ошибок. У всех MAT0 `attr2 = 6`.
531 материал содержит одну phase; максимальное число phases -- 29. У 860
материалов один animation block, у 43 -- два, у 2 -- восемь.
Распределение Texm по форматам:
```text
indexed 15
565 155
4444 59
888 52
8888 237
```
Форматы 556 и 88 присутствуют в loader-е, но не встречаются в demo-assets.
65 текстур содержат `Page`; размеры лежат от `8x8` до `256x256`. Все 385
уникальных texture references из MAT0 разрешаются.
### Эффекты
Проверено 923 FXID без ошибок. Наиболее часты команды 3, 7, 1 и 2. Команда 6 в
данных демоверсии не встречается. Наблюдаются режимы времени 0, 1, 2, 4, 5,
14, 15, 16 и 17.
### Карты
Шесть `Land.msh` и шесть `Land.map` проходят проверку без ошибок. Всего 3 811
ареалов; grid всегда `128x128`, максимальное число candidates в ячейке -- 10,
`poly_count` во всех записях равен нулю.
```text
AutoMAP 3051 vertices, 3174 faces, 343 areas
PROL 11125 vertices, 9234 faces, 731 area
Tut_1 8827 vertices, 8290 faces, 378 areas
Tut_2 9456 vertices, 8996 faces, 900 areas
Tut_3 9833 vertices, 8560 faces, 722 areas
Tut_4 9022 vertices, 8612 faces, 737 areas
```
Максимальное отклонение длины areal normal от единицы около `1.05e-7`.
### Вспомогательные форматы
```text
CTPT 284 resources, 3599 points, errors 0
NDPR 494 resources, 1915 records, errors 0
BASE 30 resources, errors 0
EXPL 144 resources, versions 1/2/3, errors 0
reference arrays 585 resources, 2956 records, errors 0
SUND 2 resources, 12 keys, errors 0
CTLD 531 payloads, errors 0
TRF 5 files, errors 0
preload 38 entries
ANI 8 resources
SKE 6 resources
```
CTPT names подтверждают attachment semantics: `TurretCenter`, `TurretDirect`,
`CameraCenter`, `TargetDirect`, `Root`, `Sfx`, `Width`, `Height`, `Dir` и
другие.
### Как читать статистику
Нулевое число parser errors подтверждает layout и диапазонные инварианты на
имеющихся variants, но не автоматически раскрывает предметный смысл каждого
opaque field. Отсутствие opcode или poly branch в corpus означает, что эту
ветку нельзя считать corpus-verified.
Особенно важно различать весь архив и достижимый runtime path. В `objects.rlb`
есть ссылки на вырезанный demo-content, однако шесть миссий не требуют их.
Поэтому quality gate имеет два отчёта: global archive health и mission
reachability.
### Полные каталоги Частей 1 и 2
Статистика демоверсии остаётся неизменной. Полные Части 1 и 2 образуют два
самостоятельных профиля с отдельными manifests, hashes и golden data.
Часть 1:
```text
files 1 017, bytes 197 056 957
NRes 120 / 6 804 entries
TMA 29 / 864 objects / 28 extras
unit DAT 425 / 5 219 records
objects.rlb 590 prototypes
MSH 435, MAT0 905, Texm 518, FXID 923
Land maps 33 / 34 662 areals
reachable prototypes 4 701
materials 36 954, textures 48 806, lightmaps 139
reachability failures 0
```
Часть 2:
```text
files 1 302, bytes 358 004 931
NRes 134 / 8 171 entries
TMA 31 / 885 objects / 41 extras
unit DAT 676 / 8 145 records
objects.rlb 683 prototypes
MSH 511, MAT0 1 127, Texm 631, FXID 1 065
Land maps 32 / 18 984 areals
reachable prototypes 5 845
materials 50 888, textures 68 603, lightmaps 214
reachability failures 0
```
Bootstrap Частей 1 и 2 идентичен. Девять DLL идентичны, шесть пересобраны при
сохранённом ABI. Активные NRes entries сравниваются так: 3 733 идентичны, 2 503
имеют изменённый payload, 1 934 добавлены в Части 2, 567 удалены. Это
показывает стабильность форматов при существенной переработке content,
особенно MSH, CTLD и FXID.
## Границы знания
### Закрытые или практически закрытые области
- Startup bootstrap и восемь exports `iron3d.dll`.
- Карта 15 DLL, exports/imports и основные interface boundaries.
- NRes layout, поиск и writer rules.
- RsLi header, table transform, lookup, mapping и используемые decode paths.
- TMA всех 60 проверенных миссий, unit DAT и `objects.rlb` resolution.
- MSH core/animation range contracts.
- WEAR, MAT0, Texm и FXID framing.
- `Land.msh`/`Land.map` и areal grid.
- World3D calculation/render order и deferred deletion.
- Сквозная mission-to-texture цепочка.
Полная проверка доступных каталогов усилила NRes active ranges, recursive
prototype inheritance через `objects.rlb`, bounded non-NUL unit descriptions,
полный TMA epilogue, extra records и Clan mode 0, MSH/MAT0/Texm/FXID variant
matrix Частей 1 и 2, 65 `Land.msh`/`Land.map`, полный reachable graph 60
миссий, stability matrix пятнадцати DLL, empty SWAV и stale save-slot metadata.
### Render-state и pixel parity
Доказан порядок frame boundaries, world traversal, material resolve и крупных
проходов. Не доказаны символами точные названия renderer vtable slots
`+0x28/+0x30/+0x34`, полный набор state transitions CShade и окончательный
взаимный порядок некоторых transparent/FX/shadow subpasses.
Pixel parity требует эталонных кадров оригинала с фиксированными camera,
timing, seed, разрешением и capability profile. Вместе с изображением
необходимо сохранять command/state trace; иначе pixel difference не позволяет
отличить ошибку формата от ошибки backend-а.
Минимальный capture должен фиксировать resolution, bit depth, selected driver,
device capabilities, camera matrices, mission, game time, seed, input log,
scene boundaries, transforms, render states, texture-stage states, texture
binds, viewport, clear, draw calls и `Blt/Flip`. Сначала сравниваются command
lists; pixel diff имеет смысл только после совпадения geometry/state sequence.
### FXID field-level semantics
Размеры команд, resource references, lifecycle, flags families и используемые
time modes известны. Не закрыто значение каждого поля body opcodes 1-10,
отсутствующий во всех проверенных каталогах opcode 6 и точные формулы редких
time modes.
Закрывающий эксперимент: создать инструмент, который изменяет по одному полю
копии эффекта, воспроизводить его в контролируемой сцене и логировать runtime
command object, emitted primitives и sound events. Одновременно reads в
`Effect.dll` сопоставляются с offsets body.
### Script VM
Сценарные packages, symbol names, event sections, variable declarations и
version check доступны. Полная instruction grammar `.scr`, semantics всех
opcodes и serialization состояния VM ещё не восстановлены.
План реконструкции:
1. Найти loader `.scr`, version check, границы bytecode, таблицы
strings/symbols/events.
2. Найти dispatcher loop по повторяющемуся чтению opcode и indirect branch или
jump table.
3. Для каждого handler определить instruction size, operands, чтения/записи VM
state, stack effect, branch target и world side effects.
4. Hook-нуть dispatcher и писать запись `package,event,ip,opcode,raw
operands,state before,state after,next ip`.
5. Построить disassembler и CFG; branch target обязан попадать на
подтверждённую границу инструкции.
6. Закрывать opcode после статического handler contract, одного динамического
trace и одного regression script.
После opcode table отдельно восстанавливаются serialization IP, call/event
frames, variables, timers и RNG.
### Physical/control formats
CTLD и связанные resources структурно читаются, count patterns и variants
известны. Не названы все секции, shape types, coefficients и точный contact
solver. То же относится к редким MSH types 17/20 и части CTPT/NDPR flags.
Закрывающий эксперимент: трассировать `LoadControlSystem`,
`LoadPhysicalModel` и создание collision objects на нескольких прототипах;
записать offsets, созданные shape instances и реакции на контролируемое
движение. Изменение одного resource field должно связываться с одним
наблюдаемым параметром.
### Сеть
DirectPlay lifecycle и имена игровых сообщений известны. Точные framing,
payload schema, reliability flags и алгоритм `netZipData` пока не подтверждены
записью сетевого обмена. Поэтому совместимость с оригинальным сетевым клиентом
ещё не доказана.
Для закрытия нужны два оригинальных клиента в изолированной среде и логирование
`netZipData`, `netUnZipData`, DirectPlay Send/Receive и World3D message
enqueue/dequeue. Native interoperability подтверждается только успешным
обменом original client <-> compatibility implementation в обе стороны.
### Редкие или отсутствующие corpus-ветки
- `Land.map poly_count > 0`: layout читается из loader-а, но ни одна из 65
проверенных карт не содержит живой записи.
- RsLi adaptive methods `0x080`/`0x0A0`: decoder path известен, однако
демоверсия и обе полные части их не используют.
- Texm formats 556 и 88: loader поддерживает их, но ни один проверенный Texm не
использует эти значения.
- FX opcode 6: размер известен, однако живой command отсутствует во всём
доступном corpus.
- Некоторые material flags и MSH auxiliary streams встречаются слишком редко
для полного authoring contract.
Такие ветки реализуются строго по бинарному коду и synthetic tests, а статус
corpus-verified получают только после появления реального файла.
### Сохранения и campaign state
`saveslots.cfg` и `missions/dispatcher.ini` найдены, но полный бинарный
savegame payload, serialization World3D/AI/script/RNG и правила миграции версии
не восстановлены. Без этого нельзя честно заявлять полную campaign
compatibility.
Минимальный набор сохранений для каждой части:
```text
S0 сразу после старта миссии
S1 тот же state без simulation step
S2 изменена только позиция одного объекта
S3 изменено только здоровье/свойство
S4 активен один Behavior order/path
S5 активен один FX и timer
S6 изменена одна script variable
S7 изменён research/economy state
S8 перед/после mission completion
S9 pause и non-default game time
```
Без самих binary save payload возможно описать обязательный state и найти код
сериализации, но невозможно доказать disk layout и roundtrip.
### Shell, HUD, шрифты и локализация
Граница shell подтверждена экспортами `createShell`/`getIShell`, `IGUIServer`,
верхнеуровневым UI-pass и файлами `ui/*.cfg`, `DATA/TextRes.cfg`,
`gamefont.rlb` и `sprites.lib`. RsLi framing двух библиотек закрыт, но widget
tree, layout rules, font glyph metrics, sprite command semantics,
focus/navigation и полный HUD state machine пока не восстановлены до
field-level спецификации.
До закрытия новая реализация может построить функционально эквивалентный UI
поверх известных ресурсов, но не заявлять native layout/behavior parity.
### Исследования, экономика и игровые свойства
Экспорты `LoadResearch`, `CalcFullResearchCost`, TRF/preload resources и TMA
properties доказывают отдельный слой исследований, стоимости, добычи и
производственных параметров. Сквозные имена (`MaximumOre`, `CurrentOre`,
`FreeResearchTime`, `FreeConstructionTime` и другие) доступны, однако формулы
стоимости, dependency graph технологий, inventory/economy transitions и точная
типизация всех 16-byte property values не закрыты.
Закрывающий эксперимент: сопоставить `LoadResearch`/`CalcFullResearchCost` с
ресурсами и UI, снять изменения state на контролируемых покупках/исследованиях
и построить typed schema свойств по consumers, не по одному имени.
### Условия динамического этапа
Полное закрытие оставшихся вопросов технически возможно, но не только по
статическим архивам. Нужна среда, способная запускать оригинальный 32-битный
код, и набор эталонных наблюдений:
1. Изолированная 32-битная Windows VM или отдельная машина с исходными
DirectDraw/Direct3D/DirectSound/DirectPlay interfaces.
2. Два неизменённых игровых каталога и manifest SHA-256 для executable, DLL,
конфигураций и ключевых архивов.
3. Отладчик с hardware/software breakpoints, просмотром x87/SSE state и
сохранением memory dumps.
4. API/vtable hooking для Win32 file I/O, DirectDraw/Direct3D, DirectSound и
DirectPlay; hooks должны писать binary trace, не изменяя порядок вызовов.
5. Управляемые clocks, input log и RNG seed либо trace всех вызовов источника
случайности.
6. Автоматический launcher, который восстанавливает snapshot VM, запускает один
test case, собирает логи и завершает процесс без ручного вмешательства.
Для каждого capture сохраняются profile сборки, hash модулей,
mission/resource key, конфигурация, device profile, начальное состояние,
input/time script и версии инструментов.
### Критерий закрытия открытого вопроса
Для каждого открытого вопроса должны существовать:
- build fingerprint и адреса наблюдаемых функций;
- raw trace и автоматический parser trace-а;
- минимальный воспроизводимый input/resource/save/message;
- формальный контракт или явно ограниченная гипотеза;
- differential test для Частей 1 и 2, если модуль изменён;
- обновление тематической статьи;
- regression case, запускаемый без ручного анализа.
До выполнения этих условий статический контракт пригоден для реализации, но
утверждение о полном поведенческом или native-паритете не публикуется.
## Глоссарий
### Бинарные файлы и reverse engineering
**PE (Portable Executable)** -- формат исполняемых файлов Windows: EXE и DLL.
Он содержит заголовки, секции, таблицы импортов и экспортов, relocations и
адрес точки входа.
**Image base** -- предпочтительный адрес начала загруженного PE-образа.
**VA** -- виртуальный адрес в процессе. **RVA** -- адрес относительно image
base. Адрес функции в памяти обычно равен `image_base + RVA`.
**Import** -- внешняя функция или переменная, которую модуль получает из другой
DLL. **Export** -- символ, предоставляемый другим модулям. Имя, ordinal и
calling convention вместе образуют часть бинарного контракта.
**ABI** -- соглашение о двоичном взаимодействии: размещение аргументов, возврат
значений, очистка stack, layout структур, порядок virtual methods и правила
владения.
**Calling convention** -- часть ABI, определяющая передачу аргументов и очистку
stack. Для исследованного 32-битного кода важны `__cdecl`, `__stdcall` и
`__thiscall`.
**Vtable** -- массив указателей на virtual methods C++-объекта. Запись
`vtable +0x34` означает вызов указателя по байтовому смещению `0x34` от начала
таблицы.
**Static analysis** исследует файл без его исполнения: disassembly, strings,
imports, call graph и data flow. **Dynamic analysis** наблюдает работающую
программу: breakpoints, traces, API hooks, memory state и packet/frame captures.
**Evidence** -- наблюдение, которое можно повторить. **Inference** -- вывод,
объединяющий несколько наблюдений. **Hypothesis** -- рабочее предположение, ещё
не подтверждённое достаточным экспериментом.
### Форматы данных и ресурсы
**Archive** -- контейнер, объединяющий множество ресурсов. **Entry** -- запись
его каталога. **Payload** -- полезные bytes конкретной записи.
**Magic** -- короткая сигнатура формата, например `NRes` или `Texm`.
**Version** -- номер варианта layout. Проверка одной magic без проверки version
и размеров недостаточна.
**Offset** -- положение данных относительно начала файла или структуры.
**Size** -- число занимаемых bytes. **Stride** -- размер одного элемента
массива. **Alignment** -- требование начинать данные на address или offset,
кратном заданному числу.
**Little-endian** -- порядок, в котором младший byte многобайтного числа
расположен первым. Все основные числовые поля исследованных форматов Iron3D
используют этот порядок.
**Fixed-size string** -- поле заранее известной длины. Полезная строка
заканчивается первым NUL, но оставшиеся bytes поля могут содержать служебный
хвост и должны сохраняться.
**Opaque field** -- поле с доказанными offset и размером, но не установленным
предметным смыслом. Его безопасно читать и копировать, но нельзя очищать или
переосмысливать без эксперимента.
**Invariant** -- условие, которое обязано выполняться: диапазон находится
внутри payload, индекс указывает на существующий элемент, число записей
соответствует размеру секции.
**Strict reader** отклоняет любое нарушение контракта. **Compatibility reader**
дополнительно воспроизводит только известные особенности оригинала, например
именованный fallback. Compatibility mode не означает игнорирование произвольной
порчи.
**Roundtrip** -- последовательность decode -> encode. **Byte-identical
roundtrip** создаёт файл, полностью совпадающий с исходным. **Lossless editor**
может изменить известное поле, сохранив все остальные bytes и порядок записей.
**Fallback** -- явно предписанный запасной путь, например материал `DEFAULT`,
затем entry 0. **Heuristic** -- догадка по похожим данным; она не должна
незаметно заменять доказанный fallback.
### Игровой runtime
**Engine** -- программная среда, которая загружает данные, ведёт время,
исполняет мир и формирует изображение/звук. **Game** -- конкретные правила,
миссии и содержимое, работающие поверх engine services.
**World** -- долгоживущее состояние миссии: objects, terrain, время, кланы и
managers. **Scene** -- представление части мира для конкретной обработки, чаще
всего текущей камеры.
**Game object** -- сущность с идентичностью, transform, properties и lifecycle.
**Component/controller** -- специализированная часть поведения: animation,
physics, AI или rendering representation.
**Simulation** отвечает за изменение мира. **Tick** -- один расчётный шаг
simulation. **Frame** -- одно подготовленное изображение. Число ticks и frames
за единицу времени не обязано совпадать.
**Game loop** -- повторяющийся порядок ввода, расчёта, рендера и обслуживания.
**Scheduler phase** -- явно ограниченный участок loop, где разрешены
определённые операции.
**Event/message** -- типизированное сообщение между objects или subsystems.
**Queue traversal** -- стабильный обход зарегистрированных объектов.
**Deferred deletion** -- перенос фактического удаления до безопасной границы
после traversal.
**Determinism** -- одинаковый результат при одинаковом initial state, input,
времени и порядке событий. **Replay** -- повторное исполнение записанной
последовательности входов/сообщений для проверки determinism.
**Authority** -- subsystem или network peer, которому разрешено окончательно
менять состояние объекта. **Mirror object** -- локальное представление объекта,
authority которого находится у другого player.
### Геометрия, анимация и рендеринг
**Mesh** -- набор vertex/index streams и draw-групп, описывающий форму.
**Node** -- элемент hierarchy модели со своим local transform. **Slot** в MSH
-- выбранная геометрическая группа для комбинации node, LOD и group; он также
хранит bounds и диапазоны batches.
**Batch** -- непрерывный индексный диапазон с одним material slot и общим
render state. **Transform** переводит данные между local, world, view и clip
spaces. Порядок умножения matrices является частью контракта.
**Quaternion** -- четырёхкомпонентное представление вращения. **Keyframe** --
pose в определённое время. **Sampling** выбирает pose для времени, а
**blending** смешивает animation states.
**Bounds** -- упрощённый объём для быстрых тестов. **AABB** -- пара
minimum/maximum по осям. **Bounding sphere** -- center и radius.
**Renderer** -- subsystem, преобразующая подготовленную сцену в изображение.
**Backend** -- реализация renderer поверх конкретного API или устройства.
**Draw call** -- команда нарисовать диапазон primitives с текущими resources и
states. **Material** -- правила отображения поверхности: texture, коэффициенты,
прозрачность и режимы pipeline. **Material phase** -- одно временное состояние
анимированного материала.
**Texture** -- двумерный массив texels. **UV coordinates** -- координаты
выборки. **Mip chain** -- последовательность уменьшенных уровней texture.
**Lightmap** -- texture с заранее рассчитанным вкладом освещения.
**Fixed-function pipeline** -- старый графический pipeline, где приложение
выбирает predefined transform, lighting, texture-stage и blend states вместо
пользовательских shaders.
**Depth buffer** хранит глубину уже принятой поверхности. **Alpha test**
полностью принимает или отвергает fragment. **Blending** смешивает новый цвет с
framebuffer.
**Back buffer** -- скрытый framebuffer. **Present/flip** делает завершённый
кадр видимым. **Pixel parity** -- совпадение конечного изображения при
фиксированных условиях.
### Навигация, физика, звук и сеть
**Areal** -- логическая область карты с границей, class/flags и связями с
соседями. **Areal graph** -- граф, вершинами которого служат области, а рёбрами
-- допустимые переходы. **Cell grid** -- пространственный индекс для candidate
areas или objects.
**Pathfinding** -- поиск маршрута по графу. **A\*** использует стоимость уже
пройденного пути и оценку расстояния до цели. Навигационная проходимость,
отсутствие collision и видимость -- разные свойства.
**Collision proxy** -- упрощённое представление объекта для столкновений.
**Broad phase** быстро находит потенциальные пары; **narrow phase** выполняет
точную проверку и вычисляет contact.
**Sample** -- декодированные звуковые данные. **Source** -- экземпляр
воспроизведения с position, gain, loop state и временем. **Listener** -- позиция
и ориентация слушателя для 3D spatialization.
**Transport** -- механизм доставки bytes между peers. **Protocol** -- framing,
message types, порядок и правила подтверждения. **Serialization** --
преобразование typed state в byte sequence.
**Reliable delivery** гарантирует доставку/порядок в пределах выбранной модели;
**unreliable delivery** допускает потери ради задержки. **Wire compatibility**
-- способность обмениваться данными с оригинальным клиентом, а не только
воспроизводить ту же игровую семантику в новом протоколе.
## Связанные локальные справки
- [NRes](../reference/nres.md)
- [RsLi](../reference/rsli.md)
- [TMA](../reference/tma.md)
- [MSH](../reference/msh.md)
- [Texm](../reference/texm.md)
- [Materials](../reference/materials.md)
- [Render frame](../reference/render-frame.md)
- [Границы знания](../appendices/knowledge-boundaries.md)
- [Глоссарий](../appendices/glossary.md)
## Дополнительное чтение
Эти материалы помогают понять PE, ABI, сжатие, graphics pipeline, game loop и
навигацию. Они не являются доказательством поведения Iron3D: детали движка
принимаются только после проверки его бинарного кода и игровых ресурсов.
- [Microsoft PE/COFF specification](https://learn.microsoft.com/en-us/windows/win32/debug/pe-format)
- [Microsoft x86 calling conventions](https://learn.microsoft.com/en-us/cpp/build/x86-calling-conventions)
- [Intel Software Developer Manuals](https://www.intel.com/content/www/us/en/developer/articles/technical/intel-sdm.html)
- [Ghidra documentation](https://ghidra-sre.org/)
- [RFC 1951: DEFLATE](https://www.rfc-editor.org/rfc/rfc1951)
- [zlib manual](https://zlib.net/manual.html)
- [Kaitai Struct user guide](https://doc.kaitai.io/user_guide.html)
- [Microsoft Direct3D documentation](https://learn.microsoft.com/en-us/windows/win32/direct3d)
- [Vulkan specification](https://registry.khronos.org/vulkan/specs/1.4-extensions/html/vkspec.html)
- [Real-Time Rendering resources](https://www.realtimerendering.com/)
- [LearnOpenGL](https://learnopengl.com/)
- [Scratchapixel](https://www.scratchapixel.com/)
- [Game Programming Patterns](https://gameprogrammingpatterns.com/)
- [Fix Your Timestep](https://gafferongames.com/post/fix_your_timestep/)
- [Red Blob Games: A*](https://www.redblobgames.com/pathfinding/a-star/introduction.html)
[Глоссарий](../appendices/glossary.md),
[открытые вопросы](../appendices/knowledge-boundaries.md),
[сценарная VM](../appendices/script-vm.md),
[сохранения и кампания](../appendices/saves-campaign.md),
[интерфейс игры](../appendices/ui-shell.md).