Files
llamamod/notes/debugviz.md
T

222 lines
18 KiB
Markdown
Raw 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.
# Debug-Ansicht: Kollision & unsichtbare Objekte im Spiel (`tools/debugviz.py`)
Stand: 2026-11-06. Zeigt in **allen 34 Level-WADs** die Kollisionsgeometrie (auch unsichtbare
Wände/Böden, Todesebenen) und unsichtbare Logik-Objekte (Kameras, Trigger, Ausgänge,
Checkpoints, Kraft-/Box-Zonen, Umgebungszonen …) direkt im Spiel – als farbiges Drahtgitter,
unsichtbare Flächen zusätzlich halbtransparent gefüllt. Spielmechanik bleibt unverändert.
## Benutzung
```
lama-mod debug an # Debug-WADs zuschalten (baut das Overlay neu, aktiviert damit auch andere Mods)
lama-mod debug aus # wieder Original-Level (testlevel-Mod bleibt, wie sie war)
lama-mod debug # Status
```
Wirkt beim nächsten Laden eines Levels (am besten Spiel neu starten). Nicht umschalten,
während ein Level lädt. Mod-Ordner: `~/.wine-lama/mods/debug/wads/*.wad` (gleiche Namen wie
auf der CD, z. B. `t1l1m001.wad`); die Datei `~/.wine-lama/mods/debug/.aus` = abgeschaltet.
Reihenfolge im Overlay: alphabetisch, spätere gewinnen → `testlevel` (T1L9*) bleibt immer,
Debug-WADs ersetzen nur die Original-Level. `lama-mod an|aus|status` funktionieren wie
vorher (`an` überspringt Mod-Ordner mit `.aus`). Sicherung des alten Skripts:
`deb-build/lama-mod.bak-vor-debug`.
Neu bauen (z. B. nach Änderungen an Farben):
```
python3 tools/debugviz.py --all ~/.wine-lama/mods/debug/wads --report /tmp/dv.json
python3 tools/debugviz.py IN.wad OUT.wad [--no-fill] [--no-markers] [--no-coll] [--opaque]
[--width 0.007] [--offset 0.012]
```
Laufzeit ≈ 10–40 s je Level.
## Farblegende
Alle Farben sind RGB (0–255). **Linien** = Drahtgitter (deckend), **Füllung** = halbtransparent
(Alpha 96/255, Blendmodus 1 der Engine).
### Kollisionsflächen (Rahmen um jedes Kollisionspolygon der Welt-Kacheln)
Kantenfarbe nach Lage, solange das Material 0 (normal) ist:
| Farbe | RGB | Bedeutung |
|---|---|---|
| **Grün** (Linien) | 40,255,40 | begehbarer Boden (Normale steil nach oben, ny ≥ 0,7) |
| **Gelbgrün** (Linien) | 200,255,0 | Schräge (0,2 ≤ ny < 0,7) |
| **Blau** (Linien) | 0,150,255 | Wand (−0,2 < ny < 0,2) |
| **Orange** (Linien) | 255,130,0 | Decke / Überhang (ny ≤ −0,2) |
| **Rot, halbtransparent gefüllt** | 255,0,0 | **unsichtbare Kollision**: keine Render-Fläche innerhalb ±0,5 Einheiten entlang der Normale (= unsichtbare Wand/Boden/Decke). Die Kantenfarbe zeigt weiterhin Lage bzw. Material. |
Kollision mit Sondermaterial (Byte 1 des Kollisionspolygons ≠ 0): Kanten in Materialfarbe,
bei unsichtbaren Polygonen auch die Füllung in Materialfarbe (statt Rot):
| Material | Farbe | RGB | Bedeutung |
|---|---|---|---|
| 30 (0x1e) | **Magenta**, nur Linien (keine Füllung) | 255,0,255 | **kein Boden / Fall- und Todesebene**: Spieler fällt hindurch (FUN_004036d0 setzt Boden = keiner). Meist Modell 0 bei y ≈ −2,75 in jeder Rasterzelle unter den Inseln → magentafarbenes Gitter = Absturz-/Todeszone. |
| 16 | **Violett**, immer gefüllt | 190,60,255 | Ausgangs-Boden: LevelDoor löst nur aus, wenn der Spieler auf Material 16 in der Türzelle steht |
| 17 (0x11) | **Gelb** | 255,255,0 | selektive Kollision: wirkt nur für Objekte mit Laufzeit-Flag 0x8000000 (Strat+0xe8) |
| 18 (0x12) | **Hellorange/Pfirsich** | 255,200,120 | selektive Kollision: wirkt NICHT für Objekte mit Flag 0x8000000 |
| 1 | Türkis | 0,200,200 | Sondermaterial, Bedeutung unbekannt (Strat-Skripte werten es aus) |
| 2 | Weiß | 255,255,255 | dto. |
| 3 | Rosa | 255,120,170 | dto. (häufig in Welt 5 Berg) |
| 5 | Mint | 120,255,200 | dto. (Fluss, Achterbahn) |
| 6 | Lavendel | 160,120,255 | dto. |
| 7 | Hellorange | 255,170,80 | dto. |
| 8 | Dunkelgrün | 0,130,60 | dto. |
| 9 | Hellblau | 150,200,255 | dto. |
| 10 | Oliv | 150,150,0 | dto. |
| 11 | Braun | 150,90,40 | dto. |
| 13 | Lachs | 255,130,110 | dto. |
| 15 | Hellgelb | 255,255,150 | dto. |
| 20 | Petrol | 0,120,140 | dto. |
| 26 | Dunkelviolett | 110,40,160 | dto. |
| 27 | Silber | 190,190,190 | dto. (Verfolgungsjagd t1l2m003) |
| 28 | Pink | 255,0,140 | dto. |
| 33 | Dunkelrot | 150,0,0 | dto. |
| 255 | Fast schwarz | 20,20,20 | dto. |
| sonstige | Hellgrau | 230,230,230 | (kommt in den Originalen nicht vor) |
### Objekt-Marker (unsichtbare Strats, MAP-Strat-Einträge)
Markerwürfel (10 cm) auf einem dünnen Pfahl 0,35 über dem Objekt-Ursprung; kurzer waagrechter
Strich = Blickrichtung (Kameras, Checkpoints).
| Farbe | RGB | Kategorie | Typen |
|---|---|---|---|
| **Weiß**, Pfeil flach am Boden | 255,255,255 | Spielerstart (Richtung) | Llama, KuscoAndPachaTogetherOnATree (Fluss), RollerCoaster, LlamaChase |
| **Violett** + Drahtwürfel 1×1×1 um die Rasterzelle | 190,60,255 | Ausgang (Auslösezelle) | LevelDoor, VillageEndDoor, EndGameDoor, TeleportDoor |
| **Grüntürkis** | 0,255,140 | Checkpoint | CheckPointPost, CheckPointBox |
| **Cyan** | 0,255,255 | Kamera | Camera* (CameraSide, CameraLift, CameraForceInsideBox …), CutSceneCamera*, RiverWaterfallCamera |
| **Gelb** | 255,255,0 | Trigger | CutSceneTrigger*, *Trigger*, Say* (Sprüche), ChangeToBunny/Turtle, RiverStartSign |
| **Orange** | 255,90,0 | Kraft-/Sonderzonen | Force*, FallOffNoHurt, ObjectDontDropInBox, RiverCurrentBox, RiverRebound, WaterReboundPoints*, SuckingWPs, ObjectSuckPoints, RiverTrackChange, TrackSwitch, RiverWhirlpool, BackgroundRotationChanger |
| **Gold** | 255,200,0 | Geheimnis-Zone | Secret |
| **Grau** | 170,170,170 | sonstige unsichtbare Steuer-Objekte | CheatTeleport, Wompy*, Spawner, Helper, Coin-Linien/-Kreise, Rain, DrippingWater, WaterfallMist, MusicBox, FlockOfBirds, Bats, Scorpions*, AppearingPlatforms* … |
| **Dunkelgrau**, kleiner Punkt (6 cm) | 90,90,90 | alle übrigen Objekte (Ursprung) | Münzen, Gegner, Türen … – damit wirklich nichts fehlt |
| **Rosa** Drahtwürfel je Rasterzelle | 255,100,180 | Umgebungs-/Musik-/Nebelzone | MAP-Block 4 (90-Byte-Einträge, Zelle x/y/z) |
**Zonen-Boxen:** hat ein Marker-Objekt genau 2 Wegpunkte und liegt das Objekt im Rechteck
dazwischen, ist das ein Box-Bereich (Secret, CameraSide/Lift, ObjectDontDropInBox,
FallOffNoHurt, RiverCurrentBox …): Drahtquader in der Kategoriefarbe von min(y) bis max(y)+1,2
(die Höhe ist geschätzt – der Code prüft vermutlich nur x/z), bei Flächen ≤ 64 Einheiten² mit
halbtransparentem Boden (Alpha 70).
**Wegpunkt-Ketten** anderer Marker-Objekte: kleine Würfel (5 cm) in abgedunkelter
Kategoriefarbe (60 %), bei Kraftzonen mit Verbindungslinien (z. B. WaterReboundPoints-Pfade,
CutSceneTrigger-Kamerafahrt nur als Punkte).
## Wie es gebaut ist (Entscheidungen)
* **Kollisions-Overlay an die TRAK-Modelle angehängt** (nicht als eigene Kacheln): pro
Kollisionspolygon ein Rahmen aus 2·n Vertices (äußere Ecken + um die Linienbreite nach innen
versetzte Ecken, aus den Kantenebenen berechnet), 2·n Dreiecke; Füllung nutzt die inneren
Ecken mit. Alles 0,012 entlang der Flächennormale versetzt (kein Z-Fighting). Dadurch stimmen
Kachel-Transformation, Zonen-/Sichtbarkeit und Kachel-Wechsel (Alt-Modelle, WFPC 0x10000)
automatisch. Kollision wird aus dem Spielraum zurückgerechnet (geomlib.coll_decode/
coll_polygon, z gespiegelt).
* Face-Flags der Overlay-Dreiecke: 0x800 | 0x400 (doppelseitig) | 0x4000 (Vertexfarben
ignorieren) | 0x8 bei jedem Texturwechsel und spätestens alle 250 Faces (Render-Batch).
* **Farben** = angehängte Flachfarb-Texturen (TEXT-Tabelle, Seite −1): deckend Flags 0x105,
halbtransparent **0x1105** (Bits 12–14 = 1 → Tabelle 0x573eb8: Blendmodus 1 =
SRCALPHA/INVSRCALPHA, Alpha aus dem 4. Byte (v1) des Eintrags; im Spiel geprüft).
Halbtransparente Dreiecke laufen über den Sortierpuffer (FUN_0041ed90, 512 KB/Frame ≈ 5000
Dreiecke; ist er voll, fallen sie einfach weg – kein Absturz). Deshalb gibt es Füllungen nur
für unsichtbare Kollision, Material 16 und kleine Zonenböden.
* **Vertexfarben-Block** in MAP: je Kachel (und je Farbsatz/Frame, auch für Alt-Modelle) um
nV(Overlay) Einträge 0x00808080 verlängert (Byte 3 = 0, ändert die Frame-Anzahl nicht).
* **Unsichtbar-Erkennung**: Render-Dreiecke aller Kacheln in Weltkoordinaten, nach Zellen
gebuckelt; für Mittelpunkt + 4 Punkte (70 % Richtung Ecken) jedes Kollisionspolygons wird ein
Strahl entlang der Normale (±0,5) gegen Dreiecke mit ähnlicher Ausrichtung (|cos| > 0,4)
getestet; < 60 % Treffer = unsichtbar. Je Modell Mehrheitsentscheid über bis zu 6 Instanzen.
Strat-Modelle (STPC: Türen, Plattformen, Figuren) zählen NICHT als Render-Fläche – Kollision
hinter beweglichen Objekten kann daher rot erscheinen.
(Erste Version mit 0,06/0,15 Abstand markierte ganze Hauswände und Felswände rot, weil die
Kollisionshülle 0,2–0,4 vor der sichtbaren Wand liegt – zu viel Rauschen.)
* **Marker** als neue Kacheln ohne Kollision, je Rasterzelle ein Modell (Linien in ≤ 1-Stücke
zerteilt und in die Zelle ihres Mittelpunkts gelegt) → bekommen automatisch die Zone der
Zelle. Neue Kacheln werden hinten angehängt (Indizes der Original-Kacheln bleiben).
* **Spielmechanik unverändert**: keine Kollisionspolygone hinzugefügt/geändert, Strats,
Wegpunkte, Parameterpool, Zonen und Rest von MAP byte-gleich (wird nach dem Schreiben
geprüft: Strats/Knoten/Rest/Original-Kacheln identisch).
* Größe: WADs wachsen um 0,1–4 MB (max. 8,9 MB, t1l6m003). Level-Speicher (Arena 16 MB,
FUN_0041ef00) hält TRAK+STPC+MAP – reicht für alle (Ladetest).
## Grenzen / bekannt
* Kollision der **Objekt-Modelle** (STPC: bewegliche Plattformen, Türen, Kisten …) wird nicht
gezeigt – die bewegen sich; nur ihr Ursprung als dunkelgrauer Punkt.
* Zonen-Höhen der Box-Bereiche sind geschätzt; ob die Engine y prüft, ist offen.
* Bedeutung der meisten Sondermaterialien unbekannt (nur Farbe + Anzahl, s. Tabelle unten);
Material 30 = kein Boden, 16 = Ausgang, 17/18 = selektiv sicher aus dem Code.
* Umgebungszonen (MAP-Block 4): Zelle sicher, Bedeutung (Nebel/Musik/Kamera) nur mittel sicher;
Vorgabe-Eintrag (Position 1,1,1) wird nicht gezeichnet.
* Liegt die Kamera dicht an einem Marker/einer Linie, zerschneidet der Near-Plane-Clip der
Engine die Dreiecke manchmal zu großen Fetzen (nur kurz sichtbar).
* Leistung: unter Wine/llvmpipe (Xvfb) ohne spürbaren Einbruch; auf echter GPU unkritisch
(≤ 2000 zusätzliche Vertices je Kachelmodell, Ø ~1–2× so viele Dreiecke wie das Original).
* Testlevel T1L9 (Testwelt) hat keine Debug-Version (testlevel-Mod hat Vorrang).
## Statistik je Level (Stand Build 2026-11-06)
| Level | Welt | WAD alt→neu (KB) | Koll.-Polygone | davon unsichtbar | Sondermaterialien (Anzahl Polygone) | Marker |
|---|---|---|---|---|---|---|
| t1l1m001 | Dorf | 6158→8235 | 3474 | 215 | 2:138, 6:4, 8:35, 9:13, 16:8, 17:5, 18:84, 28:19, 30:1 | ausgang 1, checkpoint 6, geheimnis 2, kamera 6, kraft 6, objekt 95, sonst 4, start 1, trigger 1, umgebung 12 |
| t1l1m002 | Dorf | 5471→7573 | 3909 | 130 | 6:4, 8:14, 16:9, 18:65, 28:23, 30:1 | ausgang 1, checkpoint 5, geheimnis 1, kamera 8, kraft 5, objekt 89, sonst 9, start 1, trigger 1, umgebung 15 |
| t1l1m003 | Dorf | 5891→8348 | 3893 | 79 | 2:15, 6:4, 8:8, 16:5, 17:3, 18:458, 20:6, 28:23, 30:1 | ausgang 1, kamera 3, kraft 6, objekt 45, sonst 3, start 1, trigger 2, umgebung 4 |
| t1l1m004 | Dorf | 5866→7006 | 2169 | 60 | 2:15, 8:8, 16:16, 17:3, 18:90, 30:1 | ausgang 2, geheimnis 1, kamera 2, kraft 1, objekt 31, sonst 2, start 1, trigger 1, umgebung 5 |
| t1l2m001 | Dschungelnacht | 5094→7491 | 3933 | 460 | 1:26, 2:111, 6:156, 9:34, 16:22, 17:24, 18:284, 20:80, 28:28, 30:138, 33:1 | ausgang 1, checkpoint 2, geheimnis 1, kamera 3, kraft 6, objekt 39, sonst 8, start 1, trigger 1, umgebung 8 |
| t1l2m002 | Dschungelnacht | 5329→7561 | 3715 | 389 | 1:216, 2:57, 6:154, 9:24, 16:34, 17:23, 18:319, 28:28, 30:50 | ausgang 1, checkpoint 4, geheimnis 1, kamera 3, kraft 7, objekt 105, sonst 2, start 1, trigger 1, umgebung 18 |
| t1l2m003 | Dschungelnacht (Verfolgung) | 2837→5142 | 4844 | 630 | 5:3, 9:6, 10:6, 11:37, 16:26, 27:206, 30:46 | kamera 2, kraft 1, objekt 33, sonst 4, start 1, trigger 1 |
| t1l3m001 | Fluss | 4099→8220 | 8371 | 1000 | 5:26, 16:8, 18:23 | ausgang 2, geheimnis 1, kamera 13, kraft 4, objekt 140, sonst 13, start 1, trigger 5 |
| t1l3m002 | Fluss | 3799→8249 | 8824 | 1097 | 5:40, 16:5, 18:23, 30:1 | ausgang 2, geheimnis 1, kamera 19, kraft 44, objekt 115, sonst 39, start 1, trigger 6 |
| t1l3m003 | Fluss | 4497→8537 | 8387 | 868 | 5:56, 16:5 | ausgang 4, geheimnis 1, kamera 15, kraft 7, objekt 52, sonst 15, start 1, trigger 3 |
| t1l3m004 | Fluss | 2674→3754 | 2201 | 228 | 5:18, 16:5 | ausgang 2, kamera 5, kraft 4, objekt 31, sonst 7, start 1, trigger 2 |
| t1l4m001 | Dschungeltag | 5469→7380 | 3214 | 230 | 1:148, 6:105, 10:33, 16:18, 17:33, 18:158, 20:25, 28:24, 30:10 | ausgang 1, checkpoint 9, geheimnis 1, kamera 5, kraft 12, objekt 120, sonst 3, start 1, trigger 1, umgebung 10 |
| t1l4m002 | Dschungeltag | 5807→8045 | 3820 | 157 | 1:186, 6:123, 10:80, 16:33, 17:55, 18:309, 20:6, 28:98, 30:22 | ausgang 1, checkpoint 7, geheimnis 2, kamera 1, kraft 14, objekt 135, sonst 3, start 1, trigger 1, umgebung 14 |
| t1l4m003 | Dschungeltag | 6320→8886 | 4805 | 135 | 1:174, 2:52, 6:10, 10:33, 16:36, 17:110, 18:890, 20:186, 28:27, 30:33, 255:8 | ausgang 1, checkpoint 3, geheimnis 2, kamera 6, kraft 4, objekt 99, sonst 3, start 1, trigger 1, umgebung 16 |
| t1l5m001 | Berg | 6090→8613 | 4419 | 188 | 3:356, 8:96, 16:24, 17:35, 18:539, 20:66, 28:6, 30:87 | ausgang 1, checkpoint 3, geheimnis 2, kamera 5, kraft 2, objekt 83, sonst 7, start 1, trigger 1, umgebung 15 |
| t1l5m002 | Berg | 5949→8558 | 5242 | 220 | 2:20, 3:396, 8:23, 9:15, 16:19, 17:33, 18:342, 20:57, 30:120 | ausgang 1, checkpoint 3, geheimnis 4, kamera 10, kraft 3, objekt 67, sonst 6, start 1, trigger 1, umgebung 7 |
| t1l5m003 | Berg | 4989→6796 | 3399 | 98 | 3:232, 8:223, 16:17, 18:20, 20:6, 30:78 | ausgang 1, checkpoint 5, geheimnis 1, kamera 4, kraft 1, objekt 71, sonst 6, start 1, trigger 1, umgebung 2 |
| t1l6m001 | Stadt | 6210→8227 | 2857 | 169 | 6:29, 16:18, 17:140, 18:110, 30:38 | ausgang 1, checkpoint 4, geheimnis 1, kamera 5, kraft 3, objekt 83, sonst 3, start 1, trigger 5, umgebung 20 |
| t1l6m002 | Stadt | 5155→7060 | 1771 | 106 | 6:56, 16:9, 17:20, 18:39, 30:17 | ausgang 1, checkpoint 10, geheimnis 1, kamera 7, kraft 9, objekt 127, sonst 16, start 1, trigger 5, umgebung 46 |
| t1l6m003 | Stadt | 6693→8924 | 2462 | 148 | 1:39, 16:13, 17:80, 18:154, 28:3, 30:10 | ausgang 1, checkpoint 11, geheimnis 6, kamera 11, kraft 6, objekt 107, sonst 15, start 1, trigger 3, umgebung 59 |
| t1l7m001 | Katakomben (Achterbahn) | 3054→6705 | 4043 | 20 | 5:54, 11:18, 13:18, 16:9, 30:18 | kamera 1, objekt 2, sonst 36, start 1, trigger 1, umgebung 14 |
| t1l7m002 | Katakomben | 5280→7722 | 1795 | 111 | 2:1, 11:3, 16:44, 30:93 | ausgang 3, checkpoint 12, geheimnis 5, kamera 6, kraft 4, objekt 186, sonst 12, start 1, trigger 1, umgebung 23 |
| t1l7m003 | Katakomben (Achterbahn) | 2496→5140 | 1999 | 11 | 5:54, 11:90, 13:36, 15:18, 16:9, 30:9 | kamera 1, objekt 11, sonst 41, start 1, trigger 1 |
| t1l7m004 | Katakomben | 5299→6978 | 1892 | 61 | 2:7, 16:32, 30:70 | ausgang 1, checkpoint 3, geheimnis 3, kamera 4, kraft 7, objekt 93, sonst 10, start 1, trigger 2, umgebung 15 |
| t1l7m005 | Katakomben (Achterbahn) | 2390→4782 | 1885 | 9 | 5:54, 11:36, 13:36, 16:9, 30:9 | kamera 1, objekt 1, sonst 51, start 1, trigger 1, umgebung 9 |
| t1l8m001 | Labor | 6632→8824 | 3396 | 185 | 1:40, 8:9, 16:16, 17:8, 18:181, 30:56 | ausgang 1, checkpoint 2, geheimnis 2, kamera 8, kraft 2, objekt 99, sonst 3, start 1, trigger 2, umgebung 19 |
| t1l8m002 | Labor | 5427→7112 | 2204 | 76 | 16:1, 17:44, 18:496, 30:42 | ausgang 1, geheimnis 1, kamera 5, kraft 2, objekt 74, sonst 2, start 1, trigger 3, umgebung 1 |
| t1l8m003 | Labor | 4656→5546 | 1398 | 34 | 16:9, 17:10, 18:196, 30:21 | ausgang 1, checkpoint 2, geheimnis 1, kamera 2, kraft 2, objekt 36, sonst 2, start 1, trigger 3, umgebung 6 |
| t1l8m004 | Labor | 5817→8407 | 2993 | 124 | 9:10, 16:66, 17:1, 30:57 | ausgang 1, checkpoint 7, geheimnis 3, kamera 12, kraft 6, objekt 164, sonst 3, start 1, trigger 7, umgebung 46 |
| t1l8m005 | Labor | 5375→8660 | 4041 | 179 | 7:10, 16:78, 17:1, 30:82 | checkpoint 7, geheimnis 1, kamera 14, kraft 5, objekt 113, sonst 15, start 1, trigger 2, umgebung 47 |
| t1l8m006 | Labor | 5423→5948 | 738 | 44 | 2:13, 8:24, 16:3, 17:5, 18:27, 26:4 | ausgang 1, objekt 15, start 1, trigger 17 |
| t6l6m001 | Sonder (Optionen/Karte) | 1331→1482 | 333 | 0 | | kamera 1, objekt 3 |
| t6l6m002 | Sonder (Optionen/Karte) | 3605→3640 | 64 | 0 | | kamera 1, objekt 2 |
(Kollisionspolygone je TRAK-Modell gezählt, nicht je Kachel-Instanz.)
## Tests (2026-11-06)
**Offline (alle 33 Debug-WADs, `$JOB/tmp/dv/offcheck.py`):** TRAK parst und baut byte-gleich
zurück; ≤ 8000 Vertices je Modell (max. 2012, t1l4m003); Render-Batches ≤ 256 Faces; alle
Texturindizes < Tabellengröße; Vertexfarben-Block je Kachel = nV(Modell) (alle Frames);
MAP mit `mapchunk` vollständig geparst (Rest 0 Byte) und byte-gleich neu gebaut; Strats,
Wegpunkte, Parameterpool, Umgebungszonen, Zonentabelle/-raster, Alt-Block und Original-Kacheln
unverändert; Original-Modelle (Vertices, Faces, **Kollision**) byte-genau unverändert; neue
Marker-Modelle ohne Kollision; alle anderen Chunks (STPC, Sound, LGPC …) identisch;
Kacheln im Raster. TRAK+STPC+MAP+LGPC ≤ 7,6 MB (Level-Arena 16 MB).
**Im Spiel geladen** (lamatest, über Slot Welt 9 als T1L9M001.wad, ~40–90 s gespielt/gedreht,
kein Absturz, kein Hänger, keine Fehler im Wine-Log): t1l1m001 (mehrfach, Sichtprüfung),
t1l1m003, t1l1m004, t1l2m001, t1l2m002, t1l3m001–004 (Fluss läuft auch im Slot 9 normal:
Boot fährt), t1l4m001–003, t1l5m001–003, t1l6m001–003 = 19 Level.
Getestet wurde der Build direkt vor dem endgültigen: identische Geometrie, nur die Farbwerte
der Sondermaterialien wurden danach auf feste Farben je Material umgestellt (+8–16 Byte
Texturtabelle). Die Vorschaubilder stammen ebenfalls aus diesem Build – Sondermaterial-Farben
darin (z. B. Türkis-Füllung im Berg-Bild) entsprechen noch nicht ganz der Legende oben.
**Nur offline geprüft:** t1l1m002 und t1l2m003 (Ladeversuch scheiterte vorher an der
Menü-Erkennung von lamatest, nicht am Level), t1l7m001–005 (Katakomben/Achterbahn),
t1l8m001–006 (Labor), t6l6m001/002. Ein Test über den echten Spielstand-Slot wurde nicht gemacht.
lamatest-Änderung nebenbei: Spielstand-Auswahl mit mehr Versuchen und 0,3 s langen
Tastendrücken (unter CPU-Last gingen kurze Drücke verloren).
Bilder: `notes/img/debug/00_montage.jpg` (6 Welten), `01_…06_*.jpg` (1280×720).