Skip to content

Support older WLD3 "v200" container header - #3

Open
BaesTheorem wants to merge 1 commit into
diamondman:masterfrom
BaesTheorem:v200-header-support
Open

Support older WLD3 "v200" container header#3
BaesTheorem wants to merge 1 commit into
diamondman:masterfrom
BaesTheorem:v200-header-support

Conversation

@BaesTheorem

Copy link
Copy Markdown

Support older WLD3 "v200" container header

What

WTDecoder.decode() in pywttools/wtextract.py only accepts the v300 header line:

WLD3.wav WildTangent 3D 300 Compressed and Patented

Older WildTangent assets use a v200 header:

WLD3 WildTangent 3D 200 Compressed and Patented

Two differences: a leading space after the WLD3 magic instead of .wav (there is no explicit type tag), and version 200 instead of 300. On a v200 file the current code fails at the magic-line check and exits with File does not have correct Magic Line.

Why it's safe

The payload encryption, CAB packaging, and MSZIP steps are identical between v200 and v300. Only the one header line differs. This PR replaces the single-version header check with one that accepts both versions, defaulting base_type to "wav" for the v200 sound containers (their payloads are wav/media, and the header carries no type tag to parse). v300 parsing is left byte-for-byte unchanged.

The code change is minimal:

rest = headline[1:]  # drop leading '.' (v300 ".wav ...") or ' ' (v200 " WildTangent...")
if rest.startswith("WildTangent"):
    # v200 container: no explicit type tag in header; sound.wwv payloads are wav/media
    self.base_type = "wav"
    magic_msg = rest
else:
    self.base_type, magic_msg = rest.split(' ', 1)
if magic_msg not in ("WildTangent 3D 300 Compressed and Patented\r\n",
                     "WildTangent 3D 200 Compressed and Patented\r\n"):
    raise WTFormatException("File does not have correct Magic Line. Exiting.", -2)

Evidence

Validated on 6 real v200 sound.wwv files.

Before (upstream) on a v200 file:

$ python pywttools/wtextract.py sound.wwv out.wav
File does not have correct Magic Line. Exiting.
(exit 254)

After (patched), all 6 decode to valid RIFF/WAVE:

EXPLOSION2    -> RIFF ... WAVE   (22728 B)
HUM           -> RIFF ... WAVE   (17700 B)
LAUNCH_CANNON -> RIFF ... WAVE   (14668 B)
OCEAN         -> RIFF ... WAVE   (94660 B)
SPLASH        -> RIFF ... WAVE   (33256 B)
WHISTLE       -> RIFF ... WAVE   (18022 B)

The existing v300 sample (sample_files/test.wwv) still decodes to a 381004 B RIFF/WAVE with the patch applied, so there is no regression.

Fixtures & test

Added the two smallest v200 samples as fixtures under sample_files/ (where the repo already keeps samples):

  • sample_files/test_v200_whistle.wwv (~8.5 KB)
  • sample_files/test_v200_hum.wwv (~9 KB)

and pywttools/test_wtextract_v200.py, a stdlib-unittest smoke test (no third-party runner) that decodes both fixtures via the CLI and asserts a RIFF/WAVE payload. Run it with:

python3 pywttools/test_wtextract_v200.py

The remaining four validated files (EXPLOSION2, LAUNCH_CANNON, OCEAN, SPLASH) were left out to avoid bloating the PR.

Provenance

The fixtures are extracted from WildTangent "Cannonballs" (2002), a game distributed as free abandonware. They contain only game sound effects (a whistle and a hum), no personal or copyrighted-music data.

🤖 Generated with Claude Code

WTDecoder.decode() only accepted the v300 header line
(`WLD3.wav WildTangent 3D 300 Compressed and Patented`). Older
WildTangent assets ship a v200 header
(`WLD3 WildTangent 3D 200 Compressed and Patented`) which differs in
two ways: a leading space instead of `.wav` (no explicit type tag),
and version "200" instead of "300".

The payload encryption, CAB, and MSZIP steps are identical between the
two versions; only the header line differs. This change replaces the
single-version header check with one that accepts both, defaulting the
base type to "wav" for the v200 sound containers (their payloads are
wav/media), and leaving v300 parsing untouched.

Adds two small v200 sample_files fixtures and a subprocess smoke test
that decodes them and asserts a valid RIFF/WAVE payload.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant