diff --git a/VERSION b/VERSION index d4c4950a..0c00f610 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -1.3.9 +1.3.10 diff --git a/loader/src/hooks/SaveFileFix.cpp b/loader/src/hooks/SaveFileFix.cpp index 2ed63e25..45b220b8 100644 --- a/loader/src/hooks/SaveFileFix.cpp +++ b/loader/src/hooks/SaveFileFix.cpp @@ -5,6 +5,17 @@ using namespace geode::prelude; #include <Geode/cocos/support/base64.h> +#include "../loader/LoaderImpl.hpp" + +void panic(std::string reason) { + LoaderImpl::get()->platformMessageBox("Critical", fmt::format( + "Your save file failed to load (reason: {})\n" + "As to not lose all of your data, the game will now abort.\n" + "Please backup your save files and try opening the game again, it might work.\n" + "Please contact the Geode Team about this", reason + )); + std::abort(); +} // This function is well known for crashing on certain save files, // causing the game to crash at startup, known as the infamous save file bug. @@ -14,23 +25,26 @@ using namespace geode::prelude; // // To fix this, we just rewrite the function. gd::string decompressString2(unsigned char* data, bool decrypt, int size, int decryptionKey) { - if (data == nullptr || size == 0 || *data == 0) { + log::debug("decompressString2 data={} size={}", reinterpret_cast<const void*>(data), size); + if (data == nullptr || size == 0) { return {}; } + std::vector<unsigned char> copiedData(data, data + size); if (decrypt) { for (int i = 0; i < size; i++) { - data[i] ^= decryptionKey; + copiedData[i] ^= decryptionKey; } } // TODO: maybe not use cocos's base64 and inflateMemory.. unsigned char* out = nullptr; - auto const decodedSize = cocos2d::base64Decode(data, size, &out); + auto const decodedSize = cocos2d::base64Decode(copiedData.data(), size, &out); std::unique_ptr<unsigned char> b64decoded { out }; if (decodedSize <= 0) { + panic(fmt::format("base64 (size={}) (data={} size={})", decodedSize, reinterpret_cast<const void*>(data), size)); return {}; } @@ -40,6 +54,7 @@ gd::string decompressString2(unsigned char* data, bool decrypt, int size, int de std::unique_ptr<unsigned char> inflated { out }; if (inflatedSize <= 0) { + panic(fmt::format("inflate (size={}) (data={} size={})", inflatedSize, reinterpret_cast<const void*>(data), size)); return {}; }