16
0
mirror of https://github.com/MaSzyna-EU07/maszyna.git synced 2026-07-18 08:59:18 +02:00
Files
maszyna/docs/eu7v2-format.md
maj00r beacc00932 Add headless parallel eu7v2 scenario bake with streaming and PLCE placements
Enable --eu7v2-bake from the main binary: parallel module pool, bounded-RAM
spool flush, streaming terrain triangles, flat include/model parsing, and
eu7v2 emit/load with optional verify. Large placement .scm files emit lean
PLCE records and bake referenced .inc modules separately for reuse.

- CLI: --eu7v2-bake, --eu7v2-verify, --eu7v2-mem-limit-gb, --eu7v2-threads,
  --eu7v2-max-parse; wire max_threads through to the bake parser
- eu7v2 v2 records: PLCE placements, runtime emitter/loader, batch verify
- Parallel bake pool with session cache; drop heavy-serial parse gate in spool
  mode; parse concurrency matches thread count
- Streaming terrain: batched parallel parse+bake, scan/bake pipeline, shape
  spool with persistent buffered I/O and flush-before-read
- Parallel flat-file streaming for models/includes; pack/model spool for
  low-memory incremental flush
- Optional 50 GB private-bytes guard during headless bake

Braniewo_szeroki: 160 modules, verify PASS, ~34s bake (nmt100 ~17s vs ~190s
serial baseline).

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-06-17 21:15:42 +02:00

382 lines
14 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# Format pliku EU7v2 (`.eu7v2`)
> Dokumentacja oparta na kodzie źródłowym z:
> - `scene/eu7/v2/` — format, emitter, loader, testy roundtrip
> - `scene/eu7/eu7_bake_parser.cpp` — headless bake scenariusza
> - `eu07-parser/include/eu07/scene/bake/` — pool bake, streaming terenu
>
> Stan: **czerwiec 2026**, wersja kontenera **v1** (`kVersion = 1`).
---
## Spis treści
1. [Przegląd ogólny](#1-przegląd-ogólny)
2. [Nagłówek pliku](#2-nagłówek-pliku)
3. [Struktura chunku](#3-struktura-chunku)
4. [Rodzaje pliku (`file_kind`)](#4-rodzaje-pliku-file_kind)
5. [Katalog chunków](#5-katalog-chunków)
6. [Typy podstawowe](#6-typy-podstawowe)
7. [STRS — tablica łańcuchów](#7-strs--tablica-łańcuchów)
8. [META — metadane modułu](#8-meta--metadane-modułu)
9. [INCL — include rekurencyjne](#9-incl--include-rekurencyjne)
10. [PLCE — placementy modułów wielokrotnego użytku](#10-plce--placementy-modułów-wielokrotnego-użytku)
11. [PROT + INST — prototypy i instancje modeli](#11-prot--inst--prototypy-i-instancje-modeli)
12. [SHPE — kształty (triangles)](#12-shpe--kształty-triangles)
13. [MESH — teren (tile)](#13-mesh--teren-tile)
14. [LINE — linie](#14-line--linie)
15. [Rekordy symulacji](#15-rekordy-symulacji)
16. [Bake headless i drzewo modułów](#16-bake-headless-i-drzewo-modułów)
17. [Ścieżki plików](#17-ścieżki-plików)
---
## 1. Przegląd ogólny
Plik `.eu7v2` to binarny format skompilowanego modułu scenerii:
- **Moduły wielokrotnego użytku** — osobny plik `.eu7v2` per `.inc` / `.scm`, placementy jako lean **PLCE**
- **Prototypy + instancje** — chunk **PROT** (deduplikacja meshów) + **INST** (transformacja w world-space)
- **Chunki pomijalne** — nieznany FourCC można pominąć po polu `size`
- **Little-endian** — deterministyczny zapis niezależny od endianness hosta
- **Centralna tablica STRS** — wszystkie stringi przez `string_id` (`uint32`)
Magic pliku: **`EU7C`** (FourCC `'E','U','7','C'`).
---
## 2. Nagłówek pliku
```
Offset Rozmiar Typ Opis
------ ------- -------- -------------------------
0 4 uint32 Magic = 'EU7C'
4 2 uint16 Version (= 1)
6 2 uint16 file_kind (patrz sekcja 4)
8 4 uint32 Reserved (= 0)
12 4 uint32 Reserved (= 0)
16 ... chunks Strumień chunkowy (do EOF)
```
Nagłówek ma **16 bajtów**. Brak pola „rozmiar całego pliku”.
---
## 3. Struktura chunku
```
Offset Rozmiar Typ Opis
------ ------- ------- -----------------------------------------
0 4 uint32 Chunk ID — FourCC little-endian
4 8 uint64 Payload size (tylko payload, BEZ nagłówka chunku)
12 ... bytes Payload
```
Pole `size` to rozmiar **samego payloadu** (`uint64`), bez nagłówka chunku.
Chunki są sekwencyjne do EOF. Nieznany chunk: `seek(payload_size)`.
FourCC — bajty w pliku w kolejności ASCII (np. `STRS``53 54 52 53`).
---
## 4. Rodzaje pliku (`file_kind`)
| Wartość | Nazwa | Typowy źródłowy plik | Opis |
|---------|------------|-----------------------------|-------------------------------------------|
| `1` | `sim` | `.scn`, `.scm`, `.sbt`, `.ctr` | Moduł scenariusza / root |
| `2` | `module` | `.inc` | Moduł wielokrotnego użytku (trawa, drzewo…) |
| `3` | `tile` | (planowane) | Kafel 1 km — teren + instancje |
| `4` | `manifest` | (planowane) | Indeks kafli / modułów mapy |
Emitter runtime (`eu7v2_emit_runtime.cpp`) ustawia:
- `.inc``file_kind::module`
- pozostałe rozszerzenia modułów → `file_kind::sim`
Loader akceptuje `sim` i `module` (`eu7v2_load.cpp`).
---
## 5. Katalog chunków
| FourCC | Stała C++ | Typ pliku | Opis |
|---------|---------------|-------------|---------------------------------------------------|
| `STRS` | `chunk::strs` | wszystkie | Tablica stringów (zawsze pierwszy logicznie) |
| `META` | `chunk::meta` | sim/module | Metadane modułu (first-init, placement params) |
| `INCL` | `chunk::incl` | sim/module | Include rekurencyjne (submoduły `.eu7v2`) |
| `PLCE` | `chunk::plce` | sim/module | Lean placementy → osobne moduły `.eu7v2` |
| `PROT` | `chunk::prot` | sim/module/tile | Prototypy modeli (mesh bez transformacji) |
| `INST` | `chunk::inst` | sim/module/tile | Instancje modeli (proto + transform) |
| `MESH` | `chunk::mesh` | tile/sim | Teren — mesh z origin f64 + wierzchołki f32 |
| `SHPE` | `chunk::shpe` | sim/module | Kształty triangles/strip/fan (nie-teren) |
| `LINE` | `chunk::line` | sim/module | Geometria linii |
| `TRAK` | `chunk::trak` | sim | Tory |
| `TRAC` | `chunk::trac` | sim | Przewody trakcyjne |
| `PWRS` | `chunk::pwrs` | sim | Źródła zasilania |
| `MEMC` | `chunk::memc` | sim | Komórki pamięci |
| `LAUN` | `chunk::laun` | sim | Wyzwalacze zdarzeń |
| `EVNT` | `chunk::evnt` | sim | Zdarzenia |
| `SOND` | `chunk::sond` | sim | Dźwięki |
| `DYNM` | `chunk::dynm` | sim | Pojazdy dynamiczne |
| `TRST` | `chunk::trst` | sim/module | Zestawy wagonowe |
| `TRGR` | `chunk::trgr` | sim | Precomputed track graph (planowane) |
| `SIDX` | `chunk::sidx` | manifest | Indeks sekcji przestrzennej (planowane) |
Chunki o zerowej liczności (pusta tablica) **nie są zapisywane** przez emitter.
---
## 6. Typy podstawowe
| Typ w pliku | Rozmiar | Opis |
|-------------|---------|---------------------------------------------------|
| `uint8` | 1 B | Bajt bez znaku |
| `uint16` | 2 B | LE |
| `uint32` | 4 B | LE |
| `uint64` | 8 B | LE |
| `int32` | 4 B | LE, ze znakiem |
| `float32` | 4 B | IEEE 754 |
| `float64` | 8 B | IEEE 754 — pozycje world-space, originy mesh |
| `string_id` | 4 B | Indeks STRS; `0xFFFFFFFF` = brak (`kNoString`) |
Współrzędne instancji modeli i placementów: **float64** (x/y/z).
Wierzchołki mesh/shape: **float32** względem origin (f64).
---
## 7. STRS — tablica łańcuchów
```
uint32 count
Powtórzone count razy:
uint32 length
char[] data (length bajtów, bez null-terminatora)
```
Indeks `0xFFFFFFFF` (`kNoString`) oznacza brak stringu.
---
## 8. META — metadane modułu
Layout wersjonowany (pole `layout_version`):
```
uint32 layout_version (= 1)
uint32 first_init_count
uint8 has_terrain_chunk (informacyjne)
uint8 has_pack_chunk (informacyjne)
uint8 placement_origin_x (numer parametru include, 0 = brak)
uint8 placement_origin_y
uint8 placement_origin_z
uint8 placement_rotation_y
```
---
## 9. INCL — include rekurencyjne
Submoduły wczytywane rekurencyjnie (np. zagnieżdżone `.scm`, tory, CTR):
```
uint32 count
Powtórzone count razy:
uint32 source_line
string_id source_path (.scm/.inc tekstowy)
string_id binary_path (.eu7v2)
uint32 param_count
string_id[] parameters
TransformRecord site_transform:
uint32 origin_stack_count
dvec3[] origin_stack
uint32 scale_stack_count
dvec3[] scale_stack
dvec3 rotation (stopnie, XYZ)
uint32 group_depth
```
---
## 10. PLCE — placementy modułów wielokrotnego użytku
Pliki placement (flora, dekoracje) emitują lean rekordy wskazujące na **osobny** moduł `.eu7v2`:
```
uint32 count
Powtórzone count razy:
string_id module_path (np. scenery/grass_l61/20.eu7v2)
string_id texture_override (kNoString jeśli brak)
float64 x, y, z (world-space)
float32 rotation_y (stopnie)
uint8 cell_id (0xFF = brak)
```
**Bake:** unikalne `.inc` z placement file są bake'owane jako osobne moduły `file_kind::module`.
**Runtime:** loader syntetyzuje include z PLCE (ładuje wskazany moduł z transformacją).
Typowy rozmiar: **~37 B / placement**.
Przykład: `204_trawky_ter.scm` (110k linii include) → `.eu7v2` ~4 MB (PLCE) + osobne `grass_l61/20.eu7v2` per unikalny `.inc`.
---
## 11. PROT + INST — prototypy i instancje modeli
### PROT — prototyp
```
uint32 count
Powtórzone count razy:
string_id model_file
string_id texture_file
uint8 flags (bit 0=transition, 1=is_terrain, 2=instanceable)
float32 range_min
float32 range_max
uint32 light_state_count
float32[] light_states
uint32 light_color_count
uint32[] light_colors
```
### INST — instancja
```
uint32 count
Powtórzone count razy:
uint8 flags (bit 0=has_scale, 1=texture_override, 2=has_node)
uint32 proto (indeks PROT)
float64 x, y, z
float32 ax, ay, az (kąty Eulera, stopnie)
uint8 cell_id
[flags & 1]: float32 sx, sy, sz
[flags & 2]: string_id texture_override
[flags & 4]: node_record
```
Root scenariusza: modele z PACK bake są deduplikowane do PROT+INST (flattened world-space).
---
## 12. SHPE — kształty (triangles)
```
uint32 count
Powtórzone count razy:
node_record node
uint8 translucent
string_id material
lighting_block (12 × float32: diffuse/ambient/specular RGBA)
float64 ox, oy, oz (origin world-space)
uint32 vertex_count
Powtórzone vertex_count razy:
float32 px, py, pz (względem origin)
float32 nx, ny, nz
float32 u, v
```
Typ węzła (`node.type`) niesie subtype: `triangles`, `triangle_strip`, `triangle_fan`.
Duże pliki terenu (same `node … triangles`) mogą być streamowane przy bake; shapes trafiają do **shape spool** na dysku, potem do chunku SHPE przy emit.
---
## 13. MESH — teren (tile)
Format terenu dla kafli 1 km (origin f64 + relative f32):
```
uint32 count
Powtórzone count razy:
string_id material
uint8 translucent
float64 ox, oy, oz
uint32 vertex_count
Powtórzone vertex_count razy:
float32 px, py, pz, nx, ny, nz, u, v
```
---
## 14. LINE — linie
```
uint32 count
Powtórzone count razy:
node_record
lighting_block
float32 line_width
float64 ox, oy, oz
uint32 vertex_count
dvec3[] vertices (float64 × 3)
```
---
## 15. Rekordy symulacji
Chunki symulacji: `TRAK`, `TRAC`, `PWRS`, `MEMC`, `LAUN`, `EVNT`, `SOND`, `DYNM`, `TRST`.
Wspólny nagłówek węzła: **`node_record`**. Stringi przez STRS. Pozycje torów/krzywych Béziera: **float64**.
Szczegóły pól: `scene/eu7/v2/eu7v2_records.h` (funkcje `write_*` / `read_*`).
---
## 16. Bake headless i drzewo modułów
CLI (binarny `eu07`, bez GUI):
```
eu07.exe --eu7v2-bake <sciezka.scn|.inc> [opcje]
```
| Opcja | Opis |
|--------------------------|---------------------------------------------------|
| `--eu7v2-verify` | Roundtrip: przeładuj `.eu7v2`, porównaj liczności rekordów |
| `--eu7v2-mem-limit-gb N` | Limit pamięci procesu (domyślnie 50 GB); włącza tryb spool |
| `--eu7v2-threads N` | Wątki pool bake (0 = auto = liczba rdzeni) |
| `--eu7v2-max-parse N` | Równoległe parse (0 = auto) |
| `--eu7v2-heavy-parse-mb N` | Próg serial parse dużych plików (0 = wyłączony w trybie spool) |
**Przepływ bake scenariusza:**
1. Root `.scn` → enqueue drzewa modułów (dedup po ścieżce kanonicznej)
2. Pool workerów bake'uje moduły równolegle
3. Każdy `.scm`/`.inc` → osobny `.eu7v2` obok źródła tekstowego
4. Placement `.scm`**PLCE** + enqueue unikalnych `.inc` jako `module`
5. Root emit na końcu (PACK → PROT+INST, includes z podmodułów)
6. Opcjonalnie verify batch wszystkich modułów
Implementacja: `scene/eu7/eu7_bake_parser.cpp`, `eu07-parser/.../bake_tree.hpp`.
---
## 17. Ścieżki plików
```cpp
binary_path_from_text("scenery/foo/bar.scm") scenery/foo/bar.eu7v2
binary_path_from_text("scenery/grass_l61/20.inc") scenery/grass_l61/20.eu7v2
binary_path_from_text("scenery/foo/base.ctr") scenery/foo/base.ctr.eu7v2
```
Rozszerzenia `.scm`, `.scn`, `.sbt`, `.inc``<stem>.eu7v2`.
Inne (np. `.ctr`) → `<nazwa_pliku>.eu7v2` (bez utraty suffixu).
---
## Pliki implementacji
| Temat | Plik |
|--------------------|---------------------------------------------------|
| Format core | `scene/eu7/v2/eu7v2_format.h` |
| Scene payloads | `scene/eu7/v2/eu7v2_scene.h` |
| Sim records | `scene/eu7/v2/eu7v2_records.h` |
| Emit RuntimeModule | `scene/eu7/v2/eu7v2_emit_runtime.cpp` |
| Load runtime | `scene/eu7/v2/eu7v2_load.cpp` |
| Test roundtrip | `scene/eu7/v2/eu7v2_test.cpp` |
| Headless bake | `scene/eu7/eu7_bake_parser.cpp` |
| Bake pool | `eu07-parser/include/eu07/scene/bake/bake_tree.hpp` |
---
*Dokumentacja na podstawie kodu; stan na 17 czerwca 2026.*