#include "prx/libSceSaveData/include/Api.hpp" #include "SceTypes.hpp" #include "prx/libc/include/general/VabiMacros.hpp" #include #include #include #include #include #include #include #include #include #include static void Check(bool value, int line) { if (!value) { std::fprintf(stderr, "Save-data replacement check failed at line %d\n", line); std::abort(); } } #define Require(value) Check((value), __LINE__) int main() { const auto originalDirectory = std::filesystem::current_path(); const auto root = std::filesystem::temp_directory_path() / ("anyps5-savedata-replacement-" + std::to_string(std::chrono::steady_clock::now().time_since_epoch().count())); Require(std::filesystem::create_directory(root)); std::filesystem::current_path(root); constexpr std::int32_t userId = 7531; const auto savePath = std::filesystem::path("_sd_mem") / ("u" + std::to_string(userId)) / "slot0.bin"; std::filesystem::create_directories(savePath.parent_path()); const std::vector oldData{'o', 'l', 'd'}; { std::ofstream file(savePath, std::ios::binary); Require(file.is_open()); file.write(oldData.data(), static_cast(oldData.size())); Require(static_cast(file)); } Require(sceSaveDataInitialize3(nullptr) == 0); SaveDataMemorySetup2 setup{}; setup.user_id = userId; setup.memory_size = oldData.size() + 3; SaveDataMemorySetupResult result{}; const int status = sceSaveDataSetupSaveDataMemory2(&setup, &result); Require(result.existed_memory_size == oldData.size()); Require(status == 0); std::vector savedData; { std::ifstream savedFile(savePath, std::ios::binary); savedData.assign(std::istreambuf_iterator(savedFile), std::istreambuf_iterator()); } Require(savedData.size() == setup.memory_size); Require(std::equal(oldData.begin(), oldData.end(), savedData.begin())); Require(std::all_of(savedData.begin() + static_cast(oldData.size()), savedData.end(), [](char byte) { return byte == 0; })); Require(sceSaveDataTerminate() == 0); std::filesystem::current_path(originalDirectory); std::filesystem::remove_all(root); }