#include "SceTypes.hpp" #include #include #include #include #include #include #include #include extern "C" { int APS5_VABI sceSaveDataInitialize3(const void*); int APS5_VABI sceSaveDataTerminate(); int APS5_VABI sceSaveDataSetSaveDataMemory2(const SaveDataMemorySet2*); } static void Require(bool value) { if (!value) std::abort(); } static std::vector Read(const std::filesystem::path& path) { std::ifstream file(path, std::ios::binary); Require(file.is_open()); return {std::istreambuf_iterator(file), std::istreambuf_iterator()}; } int main() { const auto previous = std::filesystem::current_path(); const auto root = std::filesystem::temp_directory_path() / ("anyps5-metadata-" + std::to_string(std::chrono::steady_clock::now().time_since_epoch().count())); Require(std::filesystem::create_directory(root)); std::filesystem::current_path(root); const auto path = std::filesystem::path("_sd_mem/u7531/slot0.param"); std::filesystem::create_directories(path.parent_path()); { std::ofstream file("_sd_mem/u7531/slot0.bin"); file << "save"; Require(static_cast(file)); } Require(sceSaveDataInitialize3(nullptr) == 0); Require(sceSaveDataInitialize3(nullptr) == 0); Require(sceSaveDataTerminate() == 0); SaveDataParam param{}; SaveDataMemorySet2 set{}; set.user_id = 7531; set.param = ¶m; Require(sceSaveDataSetSaveDataMemory2(&set) == 0); const auto original = Read(path); Require(original.size() == sizeof(param)); param.user_param = 42; const auto temporary = path.string() + ".tmp"; Require(std::filesystem::create_directory(temporary)); const int status = sceSaveDataSetSaveDataMemory2(&set); Require(Read(path) == original); Require(status == static_cast(0x809F000Bu)); Require(!std::filesystem::exists(temporary)); Require(sceSaveDataSetSaveDataMemory2(&set) == 0); const auto* bytes = reinterpret_cast(¶m); Require(Read(path) == std::vector(bytes, bytes + sizeof(param))); set.param = nullptr; Require(sceSaveDataSetSaveDataMemory2(&set) == 0); Require(sceSaveDataTerminate() == 0); std::filesystem::current_path(previous); std::filesystem::remove_all(root); }