From d9bdd9b30189fa1eb7ec121de1893862a930d497 Mon Sep 17 00:00:00 2001 From: Andrei Kortunov Date: Tue, 20 Jun 2023 10:34:42 +0400 Subject: [PATCH] Allow OpenMW 0.48 to parse save headers from 0.49 --- components/esm3/esmreader.cpp | 38 +++++++++++++++++++++++++++++++++++ components/esm3/esmreader.hpp | 3 +++ components/esm3/loadtes3.cpp | 4 ++-- components/esm3/savedgame.cpp | 4 ++++ 4 files changed, 47 insertions(+), 2 deletions(-) diff --git a/components/esm3/esmreader.cpp b/components/esm3/esmreader.cpp index 5921854190..e4d44e792b 100644 --- a/components/esm3/esmreader.cpp +++ b/components/esm3/esmreader.cpp @@ -62,6 +62,44 @@ void ESMReader::clearCtx() mCtx.subName.clear(); } +std::string ESMReader::getMaybeFixedStringSize(std::size_t size) +{ + if (mHeader.mFormat > 22) + { + std::uint32_t storedSize = 0; + getT(storedSize); + if (storedSize > mCtx.leftSub) + fail("String does not fit subrecord (" + std::to_string(storedSize) + " > " + + std::to_string(mCtx.leftSub) + ")"); + size = static_cast(storedSize); + } + + return std::string(getStringView(size)); +} + +std::string_view ESMReader::getStringView(std::size_t size) +{ + if (mBuffer.size() <= size) + // Add some extra padding to reduce the chance of having to resize + // again later. + mBuffer.resize(3 * size); + + // And make sure the string is zero terminated + mBuffer[size] = 0; + + // read ESM data + char* ptr = mBuffer.data(); + getExact(ptr, size); + + size = strnlen(ptr, size); + + // Convert to UTF8 and return + if (mEncoder != nullptr) + return mEncoder->getUtf8(std::string_view(ptr, size)); + + return std::string_view(ptr, size); +} + void ESMReader::resolveParentFileIndices(ReadersCache& readers) { mCtx.parentFileIndices.clear(); diff --git a/components/esm3/esmreader.hpp b/components/esm3/esmreader.hpp index 4255428729..ef36d7edc0 100644 --- a/components/esm3/esmreader.hpp +++ b/components/esm3/esmreader.hpp @@ -43,6 +43,9 @@ public: const std::string& getName() const { return mCtx.filename; }; bool isOpen() const { return mEsm != nullptr; } + std::string getMaybeFixedStringSize(std::size_t size); + std::string_view getStringView(std::size_t size); + /************************************************************************* * * Opening and closing diff --git a/components/esm3/loadtes3.cpp b/components/esm3/loadtes3.cpp index 0c3ccf232e..6cdcb4cb00 100644 --- a/components/esm3/loadtes3.cpp +++ b/components/esm3/loadtes3.cpp @@ -35,8 +35,8 @@ void Header::load (ESMReader &esm) esm.getSubHeader(); esm.getT(mData.version); esm.getT(mData.type); - mData.author.assign( esm.getString(32) ); - mData.desc.assign( esm.getString(256) ); + mData.author.assign(esm.getMaybeFixedStringSize(32)); + mData.desc.assign(esm.getMaybeFixedStringSize(256)); esm.getT(mData.records); } diff --git a/components/esm3/savedgame.cpp b/components/esm3/savedgame.cpp index 69da8d087f..586eb70ca7 100644 --- a/components/esm3/savedgame.cpp +++ b/components/esm3/savedgame.cpp @@ -14,6 +14,10 @@ void SavedGame::load (ESMReader &esm) esm.getHNOT (mPlayerLevel, "PLLE"); mPlayerClassId = esm.getHNOString("PLCL"); + // Erase RefId type + if (esm.getFormat() >= 22 && !mPlayerClassId.empty()) + mPlayerClassId = mPlayerClassId.substr(1); + mPlayerClassName = esm.getHNOString("PLCN"); mPlayerCell = esm.getHNString("PLCE");