Asset Extraction Pipeline

The offline tooling that walks the player’s CLAW.REZ, decodes each proprietary format to an open one, and emits a directory tree the engine can load at runtime.

Why it matters

OpenClaw ships no game data — the user supplies their legally owned CLAW.REZ, and the pipeline converts it on first run (see legal-boundaries-code-vs-original-game-assets). Decoding PID and XMI live, every frame, would burn CPU and complicate the resource manager; converting once to PNG/OGG up front means the runtime loader is a plain file read. The pipeline is the bridge between the 1997 monolith and a modern, debuggable asset tree.

How it works

A pipeline is a fan-out over the REZ directory: classify each leaf by its FOURCC type, route to a decoder, write an open equivalent.

Source (in REZ)Decoder stepOutputNote
PID + PCX paletteunpack RLE + apply palettePNG (RGBA)palette is a separate entry
PCX bitmapRLE decodePNGbackgrounds, UI
WWD levelparse, keep as-isWWD / XMLlogic stays binary-faithful
XMI musicXMI SMF synthOGG/WAVneeds a soundfont
WAV soundpassthroughWAValready usable
  • Path mirroring. Preserve the REZ virtual path under an output root (ASSETS/LEVEL1/TILES/ACTION.png) so the resource manager maps logical names to files with a string swap, not a database.
  • Palette coupling. A PID is paletted; its colours live in a sibling PCX/PAL entry. Resolve the palette before decoding the sprite or every pixel is wrong.
  • Idempotent + cached. Hash the input REZ; skip extraction if the output tree already matches. A re-run after a code change should not re-decode 70 MB.
  • Manifest. Emit a small index (path, type, dims, frame count) so the engine validates assets without re-opening every file.

Example

for entry in walk(rez):
  match entry.type:
    "PID ": pal = load(sibling_palette(entry)); png = decode_pid(entry, pal)
    "PCX ": png = decode_pcx(entry)
    "XMI ": ogg = xmi_to_ogg(entry, soundfont)
    "WAV ": copy(entry)
  write(mirror_path(entry, OUT), result); manifest.add(entry, dims)

A full CLAW.REZ (~70 MB, tens of thousands of entries) extracts in a handful of seconds and expands to a browsable tree — sprites you can open in an image viewer, music you can scrub.

Pitfalls

  • Decoding sprites without the palette — produces correctly shaped but garbage-coloured PNGs; the palette entry must load first.
  • Re-extracting every launch — skip via an input hash; users notice a multi-second stall on every start.
  • Committing extracted assets — the output tree is derived from copyrighted data; keep it out of git and generate it locally only.
  • Lossy audio for SFX — re-encoding short hits to low-bitrate OGG adds artifacts; passthrough WAV or use high quality.

See also