Decompress the gameplay extent: the level light bank now parses
gameplay is a WAD stream, exactly like core_data. The extractor was writing it compressed, so the light bank framing read the WAD header's stream length as a light count: level 0's offset at +0x04 was 0xa0d and the "count" there was 698810368. The file says so in its first six bytes: 57 41 44 79 0d 0a -- "WADy". Decompressed, level 0's gameplay extent is 1,872,256 bytes, the offset at +0x04 is 0xc2b20, and the count there is 5. Five directional light sets. All 80,274 vertices of level 0 now go through LightTfrags, and the renderer's fallback line no longer appears. The frame's colour distribution goes from 295 to 737 distinct sampled colours and takes on the level's warm cast. This corrects a recorded negative result that was simply wrong. docs/roadmap.md carried "gameplay does not decode with the WAD LZ77 decoder, all 27 levels fail identically, so the input is wrong rather than the decoder", with bit order and header length also ruled out. That was true of the data being parsed and wrong about the cause: the decoder was never the problem, it was being handed a file that had not been through it. Same lesson as the origin bug, from the other direction. A recorded failure without a positive control is easy to record and easy to leave; the control here is trivial and should have been run first -- decompress and look. The renderer keeps counting and reporting how many vertices it lit, because a silent fallback to stored colours looks plausible and is wrong. Lighting magnitudes remain unverified: that needs comparison against reference frames via the PCSX2 loop, which is still to come.
This commit is contained in:
@@ -104,12 +104,37 @@ pub fn unpack(iso_path: &Path, out_dir: &Path) -> Result<Vec<Extracted>, String>
|
||||
);
|
||||
continue;
|
||||
}
|
||||
write_file(
|
||||
out_dir,
|
||||
&format!("{stem}/{}.bin", part.name()),
|
||||
&raw[offset as usize..offset as usize + len],
|
||||
&mut written,
|
||||
);
|
||||
let slice = &raw[offset as usize..offset as usize + len];
|
||||
// `gameplay` is a WAD stream, like `core_data`. It was
|
||||
// being written compressed, which is why the light bank
|
||||
// inside it did not parse: a WAD header where a count
|
||||
// was expected.
|
||||
if matches!(part, gc_formats::level_wad::LevelPart::Gameplay)
|
||||
&& gc_formats::wad::is_wad(slice)
|
||||
{
|
||||
match gc_formats::wad::decompress(slice) {
|
||||
Ok(decoded) => {
|
||||
write_file(
|
||||
out_dir,
|
||||
&format!("{stem}/{}.bin", part.name()),
|
||||
&decoded,
|
||||
&mut written,
|
||||
);
|
||||
}
|
||||
Err(e) => eprintln!(
|
||||
" {stem}/{}: WAD did not decompress ({e}); the compressed \
|
||||
form was kept",
|
||||
part.name()
|
||||
),
|
||||
}
|
||||
} else {
|
||||
write_file(
|
||||
out_dir,
|
||||
&format!("{stem}/{}.bin", part.name()),
|
||||
slice,
|
||||
&mut written,
|
||||
);
|
||||
}
|
||||
parts += 1;
|
||||
}
|
||||
// The `data` extent is itself a container of byte ranges.
|
||||
|
||||
Reference in New Issue
Block a user