AnyPS5/core/libs/prx/libSceSaveData.native/Export.cpp

315 lines
9.5 KiB
C++

#include <atomic>
#include <cstddef>
#include <cstdint>
#include <cstring>
#include <filesystem>
#include <stdexcept>
#include <string>
#include "SceTypes.hpp"
#include "prx/libc/include/General.hpp"
#include "SaveData.hpp"
static constexpr char SAVE_DIR[] = "_SaveData";
static std::atomic<std::int32_t> g_transaction_counter{1};
static bool g_initialized = false;
static std::string save_root() {
return std::string(SAVE_DIR);
}
static std::string slot_mount_point(int slot) {
return std::string("/savedata") + std::to_string(slot);
}
static bool dir_name_match(const char* str, const char* pattern) {
if (pattern == nullptr || pattern[0] == '\0') {
return true;
}
while (*str != '\0' && *pattern != '\0') {
if (*pattern == '%') {
for (const char* s = str;; s++) {
if (dir_name_match(s, pattern + 1)) {
return true;
}
if (*s == '\0') {
break;
}
}
return false;
}
if (*pattern == '_') {
str++;
pattern++;
continue;
}
if (*pattern != *str) {
return false;
}
str++;
pattern++;
}
return *str == '\0' && *pattern == '\0';
}
extern "C" {
int sceSaveDataBackup(const SaveDataBackup* backup) {
(void)backup;
NotImplemented_nid_no_patch(__func__);
return 0;
}
int sceSaveDataCommit(const SaveDataCommitParam* param) {
(void)param;
return SAVE_DATA_OK;
}
int sceSaveDataCreateTransactionResource(uint32_t size) {
(void)size;
return g_transaction_counter.fetch_add(1);
}
int sceSaveDataDelete(const SaveDataDelete* del) {
if (del == nullptr || del->dir_name == nullptr) {
throw std::runtime_error("sceSaveDataDelete: null argument");
}
const std::string path = save_root() + "/" + std::string(del->dir_name->data);
if (std::filesystem::is_directory(path)) {
std::filesystem::remove_all(path);
}
return SAVE_DATA_OK;
}
int sceSaveDataDeleteTransactionResource(int32_t resource) {
(void)resource;
return SAVE_DATA_OK;
}
int sceSaveDataDirNameSearch(const SaveDataDirNameSearchCond* cond, SaveDataDirNameSearchResult* result) {
if (cond == nullptr || result == nullptr) {
throw std::runtime_error("sceSaveDataDirNameSearch: null argument");
}
result->hit_num = 0;
result->set_num = 0;
const char* pattern = (cond->dir_name != nullptr) ? cond->dir_name->data : nullptr;
const std::string root = save_root();
if (!std::filesystem::is_directory(root)) {
return SAVE_DATA_OK;
}
std::uint32_t hit = 0;
std::uint32_t set = 0;
for (const auto& entry : std::filesystem::directory_iterator(root)) {
if (!entry.is_directory()) {
continue;
}
const std::string name = entry.path().filename().string();
if (!dir_name_match(name.c_str(), pattern)) {
continue;
}
hit++;
if (result->dir_names != nullptr && set < result->dir_names_num) {
std::snprintf(result->dir_names[set].data, sizeof(result->dir_names[set].data), "%s", name.c_str());
if (result->params != nullptr) {
std::memset(&result->params[set], 0, sizeof(SaveDataParam));
}
set++;
}
}
result->hit_num = hit;
result->set_num = set;
return SAVE_DATA_OK;
}
int sceSaveDataGetEventResult(const void* event_param, SaveDataEvent* event) {
(void)event_param;
(void)event;
NotImplemented_nid_no_patch(__func__);
return 0;
}
int sceSaveDataGetMountInfo(const SaveDataMountPoint* mount_point, SaveDataMountInfo* info) {
if (mount_point == nullptr || info == nullptr) {
throw std::runtime_error("sceSaveDataGetMountInfo: null argument");
}
if (find_slot_by_mount_point(mount_point->data) == -1) {
return SAVE_DATA_ERROR_NOT_MOUNTED;
}
std::memset(info, 0, sizeof(*info));
info->blocks = SAVE_DATA_BLOCKS_MAX;
info->free_blocks = SAVE_DATA_BLOCKS_MAX;
return SAVE_DATA_OK;
}
int sceSaveDataGetParam(const SaveDataMountPoint* mount_point, uint32_t param_type, void* param_buf, size_t param_buf_size, size_t* got_size) {
(void)param_type;
if (mount_point == nullptr || param_buf == nullptr) {
throw std::runtime_error("sceSaveDataGetParam: null argument");
}
if (find_slot_by_mount_point(mount_point->data) == -1) {
return SAVE_DATA_ERROR_NOT_MOUNTED;
}
std::memset(param_buf, 0, param_buf_size);
if (got_size != nullptr) {
*got_size = param_buf_size;
}
return SAVE_DATA_OK;
}
int sceSaveDataGetSaveDataMemory2(SaveDataMemoryGet2* get_param) {
(void)get_param;
NotImplemented_nid_no_patch(__func__);
return 0;
}
int sceSaveDataInitialize3(const void* init) {
(void)init;
NotImplemented_nid_no_patch(__func__);
if (g_initialized) {
return SAVE_DATA_ERROR_ALREADY_INITIALIZED;
}
g_initialized = true;
return SAVE_DATA_OK;
}
int sceSaveDataLoadIcon(const SaveDataMountPoint* mount_point, SaveDataIcon* icon) {
(void)icon;
if (mount_point == nullptr) {
throw std::runtime_error("sceSaveDataLoadIcon: null mount_point");
}
if (find_slot_by_mount_point(mount_point->data) == -1) {
return SAVE_DATA_ERROR_NOT_MOUNTED;
}
if (icon != nullptr) {
icon->data_size = 0;
}
return SAVE_DATA_OK;
}
int sceSaveDataMount3(const SaveDataMount3* mount, SaveDataMountResult* mount_result) {
if (mount == nullptr || mount_result == nullptr || mount->dir_name == nullptr) {
throw std::runtime_error("sceSaveDataMount3: null argument");
}
std::memset(mount_result, 0, sizeof(*mount_result));
const bool create = (mount->mount_mode & SAVE_DATA_MOUNT_MODE_CREATE) != 0;
const bool create2 = (mount->mount_mode & SAVE_DATA_MOUNT_MODE_CREATE2) != 0;
const bool rdonly = (mount->mount_mode & SAVE_DATA_MOUNT_MODE_RDONLY) != 0;
const bool rdwr = (mount->mount_mode & SAVE_DATA_MOUNT_MODE_RDWR) != 0;
const bool open = !create && !create2 && (rdonly || rdwr);
if (!create && !create2 && !open) {
throw std::runtime_error("sceSaveDataMount3: unknown mount_mode");
}
const std::string dir_name = mount->dir_name->data;
const std::string real_path = save_root() + "/" + dir_name;
const bool exists = std::filesystem::is_directory(real_path);
if (create && exists) {
return SAVE_DATA_ERROR_EXISTS;
}
if (open && !exists) {
return SAVE_DATA_ERROR_NOT_FOUND;
}
int slot = find_free_slot();
if (slot == -1) {
return SAVE_DATA_ERROR_MOUNT_FULL;
}
if (create || create2) {
std::filesystem::create_directories(real_path);
}
const std::string mp = slot_mount_point(slot);
g_slots[slot].used = true;
g_slots[slot].mount_point = mp;
g_slots[slot].real_path = real_path;
std::snprintf(mount_result->mount_point.data, sizeof(mount_result->mount_point.data), "%s", mp.c_str());
mount_result->required_blocks = 0;
mount_result->mount_status = (create || create2) ? 1u : 0u;
return SAVE_DATA_OK;
}
int sceSaveDataPrepare(const SaveDataMountPoint* mount_point, const SaveDataPrepareParam* param) {
(void)mount_point;
(void)param;
return SAVE_DATA_OK;
}
int sceSaveDataSaveIcon(const SaveDataMountPoint* mount_point, const SaveDataIcon* icon) {
(void)icon;
if (mount_point == nullptr) {
throw std::runtime_error("sceSaveDataSaveIcon: null mount_point");
}
if (find_slot_by_mount_point(mount_point->data) == -1) {
return SAVE_DATA_ERROR_NOT_MOUNTED;
}
return SAVE_DATA_OK;
}
int sceSaveDataSaveIconByPath(const SaveDataMountPoint* mount_point, const char* path) {
(void)mount_point;
(void)path;
return SAVE_DATA_OK;
}
int sceSaveDataSetParam(const SaveDataMountPoint* mount_point, uint32_t param_type, const void* param_buf, size_t param_buf_size) {
(void)param_type;
(void)param_buf;
(void)param_buf_size;
if (mount_point == nullptr) {
throw std::runtime_error("sceSaveDataSetParam: null mount_point");
}
if (find_slot_by_mount_point(mount_point->data) == -1) {
return SAVE_DATA_ERROR_NOT_MOUNTED;
}
return SAVE_DATA_OK;
}
int sceSaveDataSetSaveDataMemory2(const SaveDataMemorySet2* set_param) {
(void)set_param;
NotImplemented_nid_no_patch(__func__);
return 0;
}
int sceSaveDataSetupSaveDataMemory2(const SaveDataMemorySetup2* setup_param, SaveDataMemorySetupResult* result) {
(void)setup_param;
(void)result;
NotImplemented_nid_no_patch(__func__);
return 0;
}
int sceSaveDataSyncSaveDataMemory(const void* sync_param) {
(void)sync_param;
NotImplemented_nid_no_patch(__func__);
return 0;
}
int sceSaveDataTerminate(void) {
if (!g_initialized) {
return SAVE_DATA_ERROR_NOT_INITIALIZED;
}
if (any_slot_used()) {
return SAVE_DATA_ERROR_BUSY;
}
g_initialized = false;
return SAVE_DATA_OK;
}
int sceSaveDataTransferringMount(const SaveDataTransferringMount* mount, SaveDataMountResult* mount_result) {
(void)mount;
(void)mount_result;
NotImplemented_nid_no_patch(__func__);
return 0;
}
int sceSaveDataUmount2(uint32_t mode, const SaveDataMountPoint* mount_point) {
(void)mode;
if (mount_point == nullptr) {
throw std::runtime_error("sceSaveDataUmount2: null mount_point");
}
int slot = find_slot_by_mount_point(mount_point->data);
if (slot == -1) {
return SAVE_DATA_ERROR_NOT_MOUNTED;
}
g_slots[slot] = MountSlot{};
return SAVE_DATA_OK;
}
}