diff options
| author | Valentin Popov <valentin@popov.link> | 2026-06-22 00:58:51 +0300 |
|---|---|---|
| committer | Valentin Popov <valentin@popov.link> | 2026-06-22 00:58:51 +0300 |
| commit | 78fc5f1debf1395d5df0bab7cc0dde54351205cb (patch) | |
| tree | ef8f7c72a183723fcbea0b2d1fefd7c28ca7bc18 /docs/tomes/01-guide.md | |
| parent | 50c2cf4686b53ebd2b76318223096660e92305a4 (diff) | |
| download | fparkan-78fc5f1debf1395d5df0bab7cc0dde54351205cb.tar.xz fparkan-78fc5f1debf1395d5df0bab7cc0dde54351205cb.zip | |
docs: rewrite MkDocs documentation
Diffstat (limited to 'docs/tomes/01-guide.md')
| -rw-r--r-- | docs/tomes/01-guide.md | 371 |
1 files changed, 371 insertions, 0 deletions
diff --git a/docs/tomes/01-guide.md b/docs/tomes/01-guide.md new file mode 100644 index 0000000..cc4e4c0 --- /dev/null +++ b/docs/tomes/01-guide.md @@ -0,0 +1,371 @@ +# 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. Что должна сделать реализация, если правило нарушено? + +Если на один из вопросов нет ответа, утверждение остаётся согласованным выводом +или открытым вопросом, а не закрытым контрактом. |
