diff options
Diffstat (limited to 'docs/tomes/07-implementation.md')
| -rw-r--r-- | docs/tomes/07-implementation.md | 674 |
1 files changed, 674 insertions, 0 deletions
diff --git a/docs/tomes/07-implementation.md b/docs/tomes/07-implementation.md new file mode 100644 index 0000000..968d61b --- /dev/null +++ b/docs/tomes/07-implementation.md @@ -0,0 +1,674 @@ +# 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 legacy-state compatibility 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. Legacy 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, а не готовую игру. + +### Этап 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. + +### Этап 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 + +Записывается начальная миссия, 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. Утверждение без проверяемого критерия остаётся +исследовательской заметкой, а не контрактом. |
