fix(zone): zone files of version 37 have a u32 scene count

The scene count is a u8 before version 37 (LateAlpha) and a u32 from 37
on (LuzFile::ReadLUZFile, 1.10.64: revision < 37 reads a byte). The
reader took the u8 for 37 too, so version 37 files misread from their
scenes on and failed.

No live zone is version 37; four older LUP zones
now read in full.
Every other zone file on disk reads the same as before.

Check in game: nothing to check on live worlds (none is version 37).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
Aaron Kimbrell
2026-09-29 04:24:21 -05:00
parent 97a1453bf7
commit 04852fce7e
2 changed files with 21 additions and 1 deletions

View File

@@ -20,8 +20,9 @@ void ZoneFile::ReadHeader(std::istream& file) {
BinaryIO::BinaryRead(file, spawnpointRotation);
}
// A u8 before LateAlpha, a u32 from it on (LuzFile::ReadLUZFile)
uint32_t sceneCount = 0;
if (fileFormatVersion <= FileFormatVersion::LateAlpha) {
if (fileFormatVersion < FileFormatVersion::LateAlpha) {
uint8_t count;
BinaryIO::BinaryRead(file, count);
sceneCount = count;

View File

@@ -119,6 +119,25 @@ TEST(ZoneFileTests, ReadsZoneBoundaries) {
EXPECT_EQ(zone.zoneDesc, "Description");
}
// From LateAlpha (37) on the scene count is a u32 (some LUP zones are 37)
TEST(ZoneFileTests, LateAlphaSceneCountIsAU32) {
ZoneBytes w;
w.Put<uint32_t>(37).Put<uint32_t>(1).Put<uint32_t>(20022); // version, revision, world; no spawn point before 38
w.Put<uint32_t>(1);
w.Text("scene.lvl").Put<uint32_t>(5).Put<uint32_t>(0).Text("Global Scene").Put<uint8_t>(0).Put<uint8_t>(0).Put<uint8_t>(0);
w.Put<uint8_t>(0).Text("zone.raw").Text("Name").Text("Description");
w.Put<uint32_t>(0).Put<uint32_t>(8).Put<uint32_t>(1).Put<uint32_t>(0); // no transitions, no paths
std::istringstream stream(w.data);
ZoneFile zone;
zone.Read(stream);
EXPECT_FALSE(stream.fail());
ASSERT_EQ(zone.scenes.size(), 1u);
EXPECT_EQ(zone.scenes[0].filename, "scene.lvl");
EXPECT_EQ(zone.scenes[0].id, 5u);
EXPECT_EQ(zone.zoneRawPath, "zone.raw");
}
TEST(ZoneFileTests, ShortFilesThrowOrFail) {
const auto zone = SampleZone();
for (const size_t length : { size_t{ 3 }, size_t{ 40 }, zone.size() / 2, zone.size() - 1 }) {