# 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 и связи с объектом мира. ## Движок как программа длительного действия Обычная прикладная программа получает запрос, вычисляет результат и заканчивает работу. Игра живёт в цикле: прочитать ввод, обновить состояние мира, сформировать звук и изображение, показать кадр и повторить. Движок -- набор подсистем и соглашений, которые делают этот цикл устойчивым. **Simulation** отвечает на вопрос "что произошло в мире": куда переместился объект, кого он видит, сколько у него здоровья, сработал ли эффект, изменился ли маршрут или приказ. **Rendering** отвечает на другой вопрос: "как текущее состояние показать". В корректной архитектуре рендер не решает игровые правила, а читает подготовленное состояние. **Tick** -- один шаг расчёта. **Frame** -- одно изображение. Они могут выполняться с разной частотой: игра способна рассчитать несколько шагов между двумя показами или временно не рисовать, не останавливая логику. Поэтому время, накопление input, порядок callbacks и момент удаления объектов считаются частью контракта. ## Мир, сцена и объект **Мир** -- долгоживущее состояние миссии: ландшафт, объекты, время, погода, принадлежность к кланам и глобальные сервисы. **Сцена** -- представление той части мира, которую можно обработать для текущей камеры. **Игровой объект** -- сущность с идентификатором, положением, набором свойств и поведением. В Iron3D объектами управляет World3D. Объекты регистрируются в общей очереди, получают события, участвуют в расчёте и могут быть удалены отложенно, чтобы не разрушить обход коллекции посреди шага. Это важнее, чем конкретный контейнер в новой реализации: совместимость определяется моментом наблюдаемого добавления, обновления и удаления. Мир не равен renderer scene graph. Один объект может иметь runtime state, controller, сетевой mirror, визуальную модель, collision bounds и script state. Часть этих данных нужна для gameplay, часть -- для вывода, часть -- для сохранения и воспроизведения. ## Ресурс, модель и материал **Ресурс** -- именованный блок данных, который можно найти и загрузить. Архивы `NRes` и `RsLi` содержат таблицы таких блоков. Имя, индекс, размер, offset, compression method и fallback-правило являются частью контракта загрузки. **Модель** описывает форму объекта. Она состоит из вершин, индексов, узлов, групп треугольников, слотов материалов и auxiliary streams. **Vertex** хранит положение и обычно дополнительные атрибуты: нормаль для освещения и UV-координату для выборки texture. **Triangle** -- три вершины, образующие примитив. **Index buffer** хранит номера вершин и позволяет переиспользовать их между треугольниками. **Batch** -- непрерывный диапазон индексов, который рисуется одним материалом и одним набором состояний. **Материал** описывает способ отображения поверхности: texture references, цвет, прозрачность, режимы смешивания и анимацию параметров. **Texture** -- изображение в памяти графической системы. **Mip-уровни** -- уменьшенные копии изображения для дальних объектов. **Lightmap** -- дополнительная texture с заранее рассчитанным освещением. Runtime должен связывать эти уровни по цепочке: миссия выбирает объект, объект ссылается на prototype, prototype приводит к модели, модель -- к WEAR, материалам, textures и lightmaps. Ошибка на любом участке этой цепочки может не проявиться в parser-е, но проявится в игровом кадре. ## Пространственные понятия **Transform** переводит точку из локальных координат модели в координаты мира, камеры и экрана. **Иерархия узлов** позволяет одному элементу наследовать движение другого. **LOD** выбирает менее подробную геометрию вдали. **Culling** отбрасывает то, что не видно. **Bounds** -- упрощённая оболочка объекта, обычно сфера или AABB, используемая для быстрых тестов. **Collision** отвечает на геометрические пересечения. **Navigation** ищет допустимый маршрут. В Iron3D эти задачи разделены: Control обслуживает физическую модель и столкновения, а ArealMap хранит пространственные области и связи между ними. Важно не смешивать визуальные и игровые упрощения. Render bounds могут быть достаточны для отсечения, но не обязаны совпадать с collision shape. Навигация может использовать areal graph, который не является ни mesh-ем модели, ни геометрией ландшафта в renderer-е. ## Графический конвейер Процессор выбирает видимые объекты, готовит матрицы, материалы и списки примитивов. Графический backend передаёт вершины, индексы, textures и state драйверу. Видеокарта преобразует вершины в координаты экрана, разбивает треугольники на фрагменты, проверяет глубину, смешивает цвет и записывает результат в буфер кадра. После завершения буфер становится видимым пользователю. Для совместимости важны не только данные draw call. Контракт включает frame boundaries, viewport, camera state, порядок world traversal, material resolve, shadow/transparent/FX subpasses, завершение renderer-а, восстановление state и callbacks после рендера. Если часть имён vtable slots ещё не доказана, новая реализация должна фиксировать крупный порядок операций и оставлять детализацию проверяемой. ## Практический словарь реализации **Handle** -- компактная ссылка на управляемый объект. **Cache** -- сохранённый результат загрузки или декодирования. **Reference count** -- число владельцев ресурса. **Fallback** -- предписанный запасной вариант при отсутствии данных. **Invariant** -- условие, которое всегда должно быть истинным для корректного файла или runtime-состояния. **Determinism** -- повторяемость результата при одинаковых входных данных и порядке событий. **Strict mode** -- режим parser-а, который принимает только корректный файл: верные magic, версии, размеры, ranges, индексы и точный EOF. **Lossless mode** -- режим чтения/записи, который сохраняет неизвестные поля, padding, gaps и raw payload без нормализации. **Quirk** -- именованное отклонение, разрешённое только после проверки на реальных данных или исполняемом коде. Эти слова используются как технические термины. Если глава называет значение fallback-ом, invariant-ом или quirk-ом, это должно иметь проверяемое последствие в reader-е, writer-е или runtime. ## Как читать C/C++-схемы структур Структуры в главах описывают байтовый layout, а не переносимый C++ object model. Если поля на диске идут без padding, reader должен читать их по offsets либо использовать явно проверенный packed layout. Прямое отображение native struct допустимо только при доказанном размере, выравнивании и endian-правиле. `sizeof` обязательно проверяется `static_assert` или эквивалентным compile-time test. Это особенно важно для records, где 32-битное поле начинается после нечётного числа 16-битных или 8-битных полей: стандартное выравнивание современного compiler-а может вставить скрытые bytes и изменить offsets. Для variable-length форматов предпочтителен bounded cursor: 1. Прочитать header и проверить минимальный размер. 2. Проверить, что offsets и sizes лежат внутри текущего блока. 3. Прочитать таблицы до объявленного count, не до "пока получается". 4. Проверить ссылки между таблицами. 5. Дойти до точного EOF или сохранить явно разрешённый trailing payload. Writer пересчитывает только производные значения: размеры, offsets, число записей, сортировочные таблицы и 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. Что должна сделать реализация, если правило нарушено? Если на один из вопросов нет ответа, утверждение остаётся согласованным выводом или открытым вопросом, а не закрытым контрактом.