PCC-Decoder-Bugfix: RLE-Runs duerfen Zeilengrenzen ueberschreiten (Row-Reset war falsch)
Stefan hat zurecht bemaengelt dass KARTE.PCC/KELLOGGS.PCC verzerrt/verrutscht
aussehen (Smacks-Frosch an falscher Position, Notch-Fehlstelle im Logo-Rahmen).
Root Cause: Der Decoder hat RLE-Runs am Ende jeder Bildzeile hart abgeschnitten
und den Rest verworfen (klassisches PCX-Verhalten angenommen). Dieses Format
haelt sich aber NICHT an die PCX-Konvention 'ein Run ueberschreitet nie eine
Zeile' -- Runs laufen frei ueber Zeilengrenzen. Verifiziert per Pixel-fuer-Pixel-
Vergleich gegen echten DOSBox-Screenshot (world map): mit durchgehender
Dekodierung (kein Row-Reset) ist das Ergebnis jetzt pixel-identisch zur Referenz.
- tools/pcc_to_png.py: Row-Reset entfernt, decodiert jetzt width*height Pixel
am Stueck aus dem RLE-Strom
- png_out/: alle 77 PNGs mit dem Fix neu generiert
- tools/wip_bob_sprite_research/: Backup der laufenden (noch ungeloesten)
BOB-Sprite-Format-Exploration von aria-wohnung, damit nichts bei einem
VM-Neustart verloren geht
- NOTES.md: Root-Cause-Analyse dokumentiert, alte Fehldiagnose ('byte-identisch
zwischen Row-Reset und kontinuierlich') korrigiert, Rauser-Intro-Frage
beantwortet (3 Frames vorhanden, Text-Logo, keine Video-Datei)
This commit is contained in:
@@ -465,3 +465,85 @@ Original-Asset-Material, nur unverpackt). Mit eingecheckt: `NOTES.md`,
|
||||
`tools/` (unser Code: `split_pre.py`, `pcc_to_png.py`), `dosbox/`
|
||||
(Test-Konfiguration), `png_out/` (unsere konvertierten PNG-Ergebnisse,
|
||||
408 KB, reine Arbeitsergebnisse kein Originalmaterial).
|
||||
|
||||
## KELLOGGS.PCC/KARTE.PCC-Notch-Artefakt — GELOEST (2026-07-22, ~09:30 Ortszeit)
|
||||
|
||||
**Die Notiz oben ("Ausgeschlossen als Ursache ... Zeilenweises Verwerfen von
|
||||
RLE-Overshoot ... liefern byte-identische Ergebnisse") war FALSCH.** Das war
|
||||
ein Messfehler einer frueheren Session: der "kontinuierliche" Testdecoder
|
||||
hat versehentlich weiterhin die width/height aus Offset 12-15 gelesen (dem
|
||||
VERWORFENEN Bugfix-1-Feld) statt aus Xmax/Ymax — dadurch kam bei den beiden
|
||||
320x200-Vollbildern zufaellig das gleiche (korrekte) Ergebnis raus wie beim
|
||||
zeilenbasierten Decoder, und der Test schien zu bestaetigen, dass beide
|
||||
Methoden aequivalent sind. Sind sie nicht.
|
||||
|
||||
**Neu verifiziert mit einem sauberen Vergleichstest** (`Buffer.compare` in
|
||||
Node.js, unabhaengige Re-Implementierung): zeilenbasiertes Decoding
|
||||
(Row-Reset, discard Overflow am Zeilenende) und durchgehendes Decoding
|
||||
(RLE-Runs duerfen ueber Zeilengrenzen hinweglaufen) liefern **NICHT**
|
||||
identische Ergebnisse — 216 von 64000 Pixeln unterscheiden sich bei
|
||||
KARTE.PCC, 293 von 64000 bei KELLOGGS.PCC. Klingt nach wenig (<0.5%), reicht
|
||||
aber, um ganze Bildbereiche sichtbar zu verschieben, weil ab dem ersten
|
||||
"verlorenen" Ueberlauf-Pixel alle nachfolgenden Zeilen einen Pixel weiter
|
||||
"nachruecken".
|
||||
|
||||
**Beweis per Ground-Truth-Vergleich:** DOSBox-Screenshot
|
||||
`aria_kellogg_worldmap.png` (1024x768 mit schwarzen Balken) exakt auf den
|
||||
reinen Spielbereich zugeschnitten (`convert -fuzz 5% -trim` → 640x400,
|
||||
= 2x 320x200) und auf 320x200 runterskaliert
|
||||
(`/shared/uploads/aria_karte_reference_320.png`). Nebeneinander-Vergleich
|
||||
mit dem durchgehend (ohne Row-Reset) decodierten `KARTE.PCC`
|
||||
(`/shared/uploads/aria_karte_compare2.png`): **pixel-identisch** — Berge,
|
||||
Schloss, Drache, Tiger, Affe/Coco, Frosch, Teich, Haus, Voegel-Ecke, alles
|
||||
exakt an der richtigen Stelle. Das Row-Reset-Verhalten war der einzige
|
||||
Bug; es gibt kein horizontales Rollen, keine Palette-Fehlzuordnung, keine
|
||||
RLE-Ambiguitaet bei Werten >=0xC0.
|
||||
|
||||
**Fix:** `tools/pcc_to_png.py` decodiert jetzt global `width*height` Pixel
|
||||
aus dem RLE-Strom OHNE pro Zeile abzuschneiden (kein Row-Reset mehr). Alle
|
||||
77 PNGs in `png_out/` wurden mit diesem finalen Decoder neu erzeugt
|
||||
(diesmal wirklich verifiziert, nicht nur "sieht plausibel aus"). Kleine
|
||||
Sprites/Logos waren von diesem Bug kaum betroffen (selten ein Run, der eine
|
||||
Zeilengrenze ueberschreitet) — deshalb fiel es dort nie auf, nur bei den
|
||||
zwei grossen 320x200-Vollbildern.
|
||||
|
||||
**Rauser-Intro bestaetigt (Frage von Stefan):** `RAUSER1/2/3.PCC` sind schon
|
||||
laenger extrahiert und liegen jetzt mit dem finalen Decoder sauber decodiert
|
||||
in `png_out/`. Es ist ein Text-Logo "RAUSER" + "ADVERTAINMENT" (Studio-Card),
|
||||
als 3 Bild-Frames — vermutlich fuer einen Scroll-/Fade-Effekt, den die
|
||||
Original-Engine (RTM.EXE) zur Laufzeit zusammensetzt, KEIN Video/keine
|
||||
Animation-Datei. Fuers Remake heisst das: die 3 Frames sind da, die
|
||||
Overlay-/Scroll-Logik muss im Python-Port nachgebaut werden (vermutlich
|
||||
simpel: Frame croppen + ueber Zeit einblenden, sobald wir wissen wie die
|
||||
Original-Sequenz zeitlich ablaeuft — dafuer ggf. DOSBox-Referenzvideo/
|
||||
Screenshots in der Sequenz aufnehmen, spaeterer Schritt).
|
||||
|
||||
## BOB-Sprite-Format — Exploration laeuft, noch nicht geloest (Stand 09:30)
|
||||
|
||||
Auf `aria-wohnung` (`/home/aria/kellogg_remake/tools/`) lief parallel schon
|
||||
einiges an Exploration fuer das naechste Format (BOB-Sprites): Brute-Force-
|
||||
Breitensuche (`bob_width_search.py`), Header-Diff zwischen aehnlich grossen
|
||||
Dateien (`bob_header_diff.py`, `bob_header_search.py`), Histogramm-Analyse
|
||||
(`bob_histogram.py`), Sichtgitter-Rendering mit mehreren Breiten-Kandidaten
|
||||
(`bob_render_grid.py`/`bob_render_grid2.py`), sowie erste Versuche die
|
||||
`PCKELL.DAT`-Offset-Tabelle zu parsen (`dat_analyze.py`/`dat_analyze2.py`,
|
||||
`dat_table2.py`, `dat_u16.py`). **Kein Ergebnis/Durchbruch bisher** — alles
|
||||
noch offene Exploration, keiner der Scripts hat schon eine verifizierte
|
||||
Loesung. Zur Sicherheit (Stefans Wunsch: nichts soll bei einem VM-Neustart
|
||||
verloren gehen) sind alle diese Scripts jetzt zusaetzlich hier im
|
||||
Projekt gesichert unter `tools/wip_bob_sprite_research/` (noch nicht
|
||||
aufgeraeumt/nicht final, bewusst als "work in progress" separiert von den
|
||||
fertigen Tools `split_pre.py`/`pcc_to_png.py`).
|
||||
|
||||
## Naechste Schritte (Prioritaet, Stand 09:30)
|
||||
1. **BOB/SRB-Sprite-Format weiter reversen** — siehe `tools/wip_bob_sprite_research/`
|
||||
fuer den aktuellen (unfertigen) Exploration-Stand. Naechster konkreter
|
||||
Schritt: `PCKELL.DAT`-Offset-Tabelle sauber mit den 32 `SRB.LST`-Namen
|
||||
abgleichen, danach `A.BOB` (kleinstes Beispiel) testdecodieren.
|
||||
2. Rauser-Intro-Sequenz (3 Frames) zu einer zusammengesetzten Vorschau
|
||||
rendern/dokumentieren, sobald Zeit ist — niedrige Prioritaet, Assets sind
|
||||
schon da.
|
||||
3. MAP/ARE-Levelformat reversen.
|
||||
4. Python/pygame-Projektstruktur aufsetzen (PCC-Loader ist fertig, muss nur
|
||||
noch von PPM/ImageMagick-Zwischenschritt auf direktes Pillow-basiertes
|
||||
PNG/Surface-Schreiben umgestellt werden fuer den finalen Port).
|
||||
|
||||
Reference in New Issue
Block a user