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)
65 lines
2.2 KiB
Python
65 lines
2.2 KiB
Python
import sys
|
|
|
|
def try_decode_scanline(data, width, max_height=2000):
|
|
"""PCX-style per-scanline RLE decode: for each row, decode exactly `width`
|
|
pixels (excess from a run discarded), continue until input consumed.
|
|
Returns (rows_pixels_list, bytes_consumed, ok, error_msg)."""
|
|
i = 0
|
|
n = len(data)
|
|
rows = []
|
|
row = []
|
|
while i < n:
|
|
if len(row) >= width:
|
|
rows.append(row)
|
|
row = []
|
|
if len(rows) > max_height:
|
|
return rows, i, False, "too many rows"
|
|
continue
|
|
b = data[i]
|
|
if (b & 0xC0) == 0xC0:
|
|
count = b & 0x3F
|
|
i += 1
|
|
if i >= n:
|
|
return rows, i, False, "truncated run (missing value byte)"
|
|
val = data[i]
|
|
i += 1
|
|
need = width - len(row)
|
|
take = min(count, need)
|
|
row.extend([val]*take)
|
|
# NOTE: if count > need, the overshoot pixels for the *next* row
|
|
# are DISCARDED per classic PCX semantics (not carried over)
|
|
else:
|
|
row.append(b)
|
|
i += 1
|
|
if row:
|
|
# leftover partial row at EOF
|
|
rows.append(row)
|
|
return rows, i, False, f"EOF with partial row of {len(row)} px"
|
|
return rows, i, True, "clean"
|
|
|
|
def scan_widths(data, wmin=4, wmax=250):
|
|
results = []
|
|
for w in range(wmin, wmax+1):
|
|
rows, consumed, ok, msg = try_decode_scanline(data, w)
|
|
# figure out leftover partial-row size from msg if present
|
|
leftover = None
|
|
if "partial row of" in msg:
|
|
leftover = int(msg.split("partial row of")[1].split("px")[0].strip())
|
|
elif msg == "clean":
|
|
leftover = 0
|
|
results.append((w, len(rows), leftover, ok, msg))
|
|
return results
|
|
|
|
base = "/home/aria/kellogg_remake/extracted_pre/"
|
|
files = ["A.BOB","B.BOB","E.BOB","N.BOB","O.BOB","D.BOB","J.BOB"]
|
|
for fn in files:
|
|
data = open(base+fn,"rb").read()
|
|
print(f"=== {fn} (size={len(data)}) ===")
|
|
results = scan_widths(data)
|
|
clean = [r for r in results if r[2]==0]
|
|
if clean:
|
|
for r in clean:
|
|
print(" CLEAN (leftover=0):", r)
|
|
else:
|
|
print(" no width in range gives leftover==0")
|