Files
tony-remake/tools/wip_bob_sprite_research/bob_render_grid2.py
T
ARIA 5efba4b165 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)
2026-07-22 07:33:01 +00:00

67 lines
1.9 KiB
Python

from PIL import Image
import math, sys
def rle_decode_scanline_clipped(data, width, max_rows=400):
"""Decode with PCX-style per-scanline clipping: exactly `width` px per row,
overshoot from a run is discarded, continues to next row."""
rows = []
row = []
i = 0
n = len(data)
while i < n and len(rows) < max_rows:
if len(row) >= width:
rows.append(row)
row = []
continue
b = data[i]
if (b & 0xC0) == 0xC0:
count = b & 0x3F
i += 1
if i >= n:
break
val = data[i]
i += 1
need = width - len(row)
take = min(count, need)
row.extend([val]*take)
else:
row.append(b)
i += 1
if row:
row.extend([0]*(width-len(row)))
rows.append(row)
return rows
base = "/home/aria/kellogg_remake/extracted_pre/"
fn = sys.argv[1] if len(sys.argv) > 1 else "O.BOB"
skip = int(sys.argv[2]) if len(sys.argv) > 2 else 0
data = open(base+fn, "rb").read()[skip:]
widths = list(range(8, 60, 2))
cell_h = 90
cell_w = 60
cols = 8
rows_n = math.ceil(len(widths)/cols)
sheet = Image.new("L", (cols*cell_w, rows_n*cell_h), 40)
for idx, w in enumerate(widths):
rows = rle_decode_scanline_clipped(data, w, max_rows=cell_h)
h = len(rows)
if h == 0:
continue
flat = bytearray()
for r in rows:
flat.extend(r)
img = Image.frombytes("L", (w, h), bytes(flat))
scale = min(cell_w/w, cell_h/h)
nw, nh = max(1,int(w*scale)), max(1,int(h*scale))
img_r = img.resize((nw, nh), Image.NEAREST)
cx = (idx % cols) * cell_w
cy = (idx // cols) * cell_h
sheet.paste(img_r, (cx, cy))
sheet = sheet.resize((sheet.width*3, sheet.height*3), Image.NEAREST)
outpath = f"/home/aria/kellogg_remake/tools/{fn}_grid_clip_skip{skip}.png"
sheet.save(outpath)
print("saved", outpath, "widths:", widths)