diff --git a/dCommon/ZoneFile.cpp b/dCommon/ZoneFile.cpp index a1c95f1c9..3efdf63a8 100644 --- a/dCommon/ZoneFile.cpp +++ b/dCommon/ZoneFile.cpp @@ -3,6 +3,8 @@ #include #include #include +#include +#include #include "BinaryIO.h" #include "Game.h" @@ -10,6 +12,10 @@ void ZoneFile::ReadHeader(std::istream& file) { BinaryIO::BinaryRead(file, fileFormatVersion); + // Before PrePreAlpha a scene is only its ID, with no file to load it from (LuzReader::ReadScenes) + if (fileFormatVersion < FileFormatVersion::PrePreAlpha) { + throw std::runtime_error("Zone file version " + std::to_string(static_cast(fileFormatVersion)) + " is older than " + std::to_string(static_cast(FileFormatVersion::PrePreAlpha)) + ": its scenes have no files"); + } if (fileFormatVersion >= FileFormatVersion::Alpha) BinaryIO::BinaryRead(file, mapRevision); @@ -68,10 +74,8 @@ void ZoneFile::ReadScene(std::istream& file) { BinaryIO::ReadString(file, scene.filename, BinaryIO::ReadType::String); - if (fileFormatVersion >= FileFormatVersion::LatePreAlpha || fileFormatVersion < FileFormatVersion::PrePreAlpha) { - BinaryIO::BinaryRead(file, scene.id); - } if (fileFormatVersion >= FileFormatVersion::LatePreAlpha) { + BinaryIO::BinaryRead(file, scene.id); BinaryIO::BinaryRead(file, scene.sceneType); BinaryIO::ReadString(file, scene.name, BinaryIO::ReadType::String); diff --git a/tests/dCommonTests/ZoneFileTests.cpp b/tests/dCommonTests/ZoneFileTests.cpp index 1b60a06ee..739efd7fb 100644 --- a/tests/dCommonTests/ZoneFileTests.cpp +++ b/tests/dCommonTests/ZoneFileTests.cpp @@ -138,6 +138,16 @@ TEST(ZoneFileTests, LateAlphaSceneCountIsAU32) { EXPECT_EQ(zone.zoneRawPath, "zone.raw"); } +// Before version 30 a scene is only an ID, with no file to load +TEST(ZoneFileTests, VersionsBeforePrePreAlphaThrow) { + ZoneBytes w; + w.Put(20).Put(53).Put(1).Put(53).Put(0).Text(".raw"); + std::istringstream stream(w.data); + ZoneFile zone; + EXPECT_THROW(zone.Read(stream), std::runtime_error); + EXPECT_TRUE(zone.scenes.empty()); +} + TEST(ZoneFileTests, ShortFilesThrowOrFail) { const auto zone = SampleZone(); for (const size_t length : { size_t{ 3 }, size_t{ 40 }, zone.size() / 2, zone.size() - 1 }) {