Merge pull request #346 from shadps4-emu/savedata_1

SaveData Fixes
This commit is contained in:
georgemoralis 2024-07-31 17:34:44 +03:00 committed by GitHub
commit 0ac9f8ffa4
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
4 changed files with 156 additions and 38 deletions

View File

@ -214,6 +214,22 @@ int PS4_SYSV_ABI posix_clock_getres(u32 clock_id, OrbisKernelTimespec* res) {
return SCE_KERNEL_ERROR_EINVAL; return SCE_KERNEL_ERROR_EINVAL;
} }
int PS4_SYSV_ABI sceKernelConvertLocaltimeToUtc(time_t param_1, int64_t param_2, time_t* seconds,
OrbisKernelTimezone* timezone, int* dst_seconds) {
LOG_INFO(Kernel, "called");
if (timezone) {
sceKernelGettimezone(timezone);
param_1 -= (timezone->tz_minuteswest + timezone->tz_dsttime) * 60;
if (seconds)
*seconds = param_1;
if (dst_seconds)
*dst_seconds = timezone->tz_dsttime * 60;
} else {
return SCE_KERNEL_ERROR_EINVAL;
}
return SCE_OK;
}
void timeSymbolsRegister(Core::Loader::SymbolsResolver* sym) { void timeSymbolsRegister(Core::Loader::SymbolsResolver* sym) {
clock = std::make_unique<Common::NativeClock>(); clock = std::make_unique<Common::NativeClock>();
initial_ptc = clock->GetUptime(); initial_ptc = clock->GetUptime();
@ -239,6 +255,7 @@ void timeSymbolsRegister(Core::Loader::SymbolsResolver* sym) {
LIB_FUNCTION("lLMT9vJAck0", "libkernel", 1, "libkernel", 1, 1, posix_clock_gettime); LIB_FUNCTION("lLMT9vJAck0", "libkernel", 1, "libkernel", 1, 1, posix_clock_gettime);
LIB_FUNCTION("lLMT9vJAck0", "libScePosix", 1, "libkernel", 1, 1, posix_clock_gettime); LIB_FUNCTION("lLMT9vJAck0", "libScePosix", 1, "libkernel", 1, 1, posix_clock_gettime);
LIB_FUNCTION("smIj7eqzZE8", "libScePosix", 1, "libkernel", 1, 1, posix_clock_getres); LIB_FUNCTION("smIj7eqzZE8", "libScePosix", 1, "libkernel", 1, 1, posix_clock_getres);
LIB_FUNCTION("0NTHN1NKONI", "libkernel", 1, "libkernel", 1, 1, sceKernelConvertLocaltimeToUtc);
} }
} // namespace Libraries::Kernel } // namespace Libraries::Kernel

View File

@ -15,7 +15,7 @@
#include "error_codes.h" #include "error_codes.h"
namespace Libraries::SaveData { namespace Libraries::SaveData {
bool is_rw_mode = false;
static constexpr std::string_view g_mount_point = "/savedata0"; // temp mount point (todo) static constexpr std::string_view g_mount_point = "/savedata0"; // temp mount point (todo)
std::string game_serial; std::string game_serial;
@ -180,25 +180,27 @@ int PS4_SYSV_ABI sceSaveDataDirNameSearch(const OrbisSaveDataDirNameSearchCond*
OrbisSaveDataDirNameSearchResult* result) { OrbisSaveDataDirNameSearchResult* result) {
if (cond == nullptr) if (cond == nullptr)
return ORBIS_SAVE_DATA_ERROR_PARAMETER; return ORBIS_SAVE_DATA_ERROR_PARAMETER;
LOG_ERROR(Lib_SaveData, "TODO sceSaveDataDirNameSearch: Add params"); LOG_INFO(Lib_SaveData, "called");
const auto& mount_dir = Common::FS::GetUserPath(Common::FS::PathType::SaveDataDir) / const auto& mount_dir = Common::FS::GetUserPath(Common::FS::PathType::SaveDataDir) /
std::to_string(cond->userId) / game_serial; std::to_string(cond->userId) / game_serial;
if (!mount_dir.empty() && std::filesystem::exists(mount_dir)) { if (!mount_dir.empty() && std::filesystem::exists(mount_dir)) {
if (cond->dirName == nullptr) { // look for all dirs if no dir is provided. if (cond->dirName == nullptr || std::string_view(cond->dirName->data)
.empty()) { // look for all dirs if no dir is provided.
for (int i = 0; const auto& entry : std::filesystem::directory_iterator(mount_dir)) { for (int i = 0; const auto& entry : std::filesystem::directory_iterator(mount_dir)) {
if (std::filesystem::is_directory(entry.path()) && if (std::filesystem::is_directory(entry.path()) &&
entry.path().filename().string() != "sdmemory") { entry.path().filename().string() != "sdmemory") {
// sceSaveDataDirNameSearch does not search for dataMemory1/2 dirs. // sceSaveDataDirNameSearch does not search for dataMemory1/2 dirs.
i++;
result->dirNamesNum = 0; // why is it 1024? is it max?
// copy dir name to be used by sceSaveDataMount in read mode. // copy dir name to be used by sceSaveDataMount in read mode.
strncpy(result->dirNames[i].data, entry.path().filename().string().c_str(), 32); strncpy(result->dirNames[i].data, entry.path().filename().string().c_str(), 32);
result->hitNum = i + 1; i++;
result->dirNamesNum = i + 1; result->hitNum = i;
result->setNum = i + 1; result->dirNamesNum = i;
result->setNum = i;
} }
} }
} else { // Need a game to test. } else { // Need a game to test.
LOG_ERROR(Lib_SaveData, "Check Me. sceSaveDataDirNameSearch: dirName = {}",
cond->dirName->data);
strncpy(result->dirNames[0].data, cond->dirName->data, 32); strncpy(result->dirNames[0].data, cond->dirName->data, 32);
result->hitNum = 1; result->hitNum = 1;
result->dirNamesNum = 1; result->dirNamesNum = 1;
@ -305,8 +307,51 @@ int PS4_SYSV_ABI sceSaveDataGetMountInfo(const OrbisSaveDataMountPoint* mountPoi
return ORBIS_OK; return ORBIS_OK;
} }
int PS4_SYSV_ABI sceSaveDataGetParam() { int PS4_SYSV_ABI sceSaveDataGetParam(const OrbisSaveDataMountPoint* mountPoint,
LOG_ERROR(Lib_SaveData, "(STUBBED) called"); const OrbisSaveDataParamType paramType, void* paramBuf,
const size_t paramBufSize, size_t* gotSize) {
if (mountPoint == nullptr)
return ORBIS_SAVE_DATA_ERROR_PARAMETER;
auto* mnt = Common::Singleton<Core::FileSys::MntPoints>::Instance();
const auto mount_dir = mnt->GetHostPath(mountPoint->data);
Common::FS::IOFile file(mount_dir / "param.txt", Common::FS::FileAccessMode::Read);
OrbisSaveDataParam params;
file.Read(params);
LOG_INFO(Lib_SaveData, "called");
switch (paramType) {
case ORBIS_SAVE_DATA_PARAM_TYPE_ALL: {
memcpy(paramBuf, &params, sizeof(OrbisSaveDataParam));
*gotSize = sizeof(OrbisSaveDataParam);
} break;
case ORBIS_SAVE_DATA_PARAM_TYPE_TITLE: {
std::memcpy(paramBuf, &params.title, ORBIS_SAVE_DATA_TITLE_MAXSIZE);
*gotSize = ORBIS_SAVE_DATA_TITLE_MAXSIZE;
} break;
case ORBIS_SAVE_DATA_PARAM_TYPE_SUB_TITLE: {
std::memcpy(paramBuf, &params.subTitle, ORBIS_SAVE_DATA_SUBTITLE_MAXSIZE);
*gotSize = ORBIS_SAVE_DATA_SUBTITLE_MAXSIZE;
} break;
case ORBIS_SAVE_DATA_PARAM_TYPE_DETAIL: {
std::memcpy(paramBuf, &params.detail, ORBIS_SAVE_DATA_DETAIL_MAXSIZE);
*gotSize = ORBIS_SAVE_DATA_DETAIL_MAXSIZE;
} break;
case ORBIS_SAVE_DATA_PARAM_TYPE_USER_PARAM: {
std::memcpy(paramBuf, &params.userParam, sizeof(u32));
*gotSize = sizeof(u32);
} break;
case ORBIS_SAVE_DATA_PARAM_TYPE_MTIME: {
std::memcpy(paramBuf, &params.mtime, sizeof(time_t));
*gotSize = sizeof(time_t);
} break;
default: {
UNREACHABLE_MSG("Unknown Param = {}", paramType);
} break;
}
return ORBIS_OK; return ORBIS_OK;
} }
@ -445,6 +490,7 @@ s32 saveDataMount(u32 user_id, char* dir_name, u32 mount_mode,
case ORBIS_SAVE_DATA_MOUNT_MODE_RDWR: case ORBIS_SAVE_DATA_MOUNT_MODE_RDWR:
case ORBIS_SAVE_DATA_MOUNT_MODE_RDWR | ORBIS_SAVE_DATA_MOUNT_MODE_DESTRUCT_OFF: case ORBIS_SAVE_DATA_MOUNT_MODE_RDWR | ORBIS_SAVE_DATA_MOUNT_MODE_DESTRUCT_OFF:
case ORBIS_SAVE_DATA_MOUNT_MODE_RDONLY | ORBIS_SAVE_DATA_MOUNT_MODE_DESTRUCT_OFF: { case ORBIS_SAVE_DATA_MOUNT_MODE_RDONLY | ORBIS_SAVE_DATA_MOUNT_MODE_DESTRUCT_OFF: {
is_rw_mode = (mount_mode == ORBIS_SAVE_DATA_MOUNT_MODE_RDWR) ? true : false;
if (!std::filesystem::exists(mount_dir)) { if (!std::filesystem::exists(mount_dir)) {
return ORBIS_SAVE_DATA_ERROR_NOT_FOUND; return ORBIS_SAVE_DATA_ERROR_NOT_FOUND;
} }
@ -462,10 +508,6 @@ s32 saveDataMount(u32 user_id, char* dir_name, u32 mount_mode,
case ORBIS_SAVE_DATA_MOUNT_MODE_CREATE | ORBIS_SAVE_DATA_MOUNT_MODE_DESTRUCT_OFF | case ORBIS_SAVE_DATA_MOUNT_MODE_CREATE | ORBIS_SAVE_DATA_MOUNT_MODE_DESTRUCT_OFF |
ORBIS_SAVE_DATA_MOUNT_MODE_COPY_ICON: { ORBIS_SAVE_DATA_MOUNT_MODE_COPY_ICON: {
if (std::filesystem::exists(mount_dir)) { if (std::filesystem::exists(mount_dir)) {
g_mount_point.copy(mount_result->mount_point.data, 16);
mnt->Mount(mount_dir, mount_result->mount_point.data);
mount_result->required_blocks = 0;
mount_result->mount_status = 0;
return ORBIS_SAVE_DATA_ERROR_EXISTS; return ORBIS_SAVE_DATA_ERROR_EXISTS;
} }
if (std::filesystem::create_directories(mount_dir)) { if (std::filesystem::create_directories(mount_dir)) {
@ -485,7 +527,7 @@ s32 saveDataMount(u32 user_id, char* dir_name, u32 mount_mode,
mount_result->mount_status = 1; mount_result->mount_status = 1;
} break; } break;
default: default:
UNREACHABLE(); UNREACHABLE_MSG("Unknown mount mode = {}", mount_mode);
} }
mount_result->required_blocks = 0; mount_result->required_blocks = 0;
@ -585,15 +627,46 @@ int PS4_SYSV_ABI sceSaveDataSetEventInfo() {
int PS4_SYSV_ABI sceSaveDataSetParam(const OrbisSaveDataMountPoint* mountPoint, int PS4_SYSV_ABI sceSaveDataSetParam(const OrbisSaveDataMountPoint* mountPoint,
OrbisSaveDataParamType paramType, const void* paramBuf, OrbisSaveDataParamType paramType, const void* paramBuf,
size_t paramBufSize) { size_t paramBufSize) {
auto* mnt = Common::Singleton<Core::FileSys::MntPoints>::Instance(); if (paramBuf == nullptr)
const auto mount_dir = mnt->GetHostPath(mountPoint->data); return ORBIS_SAVE_DATA_ERROR_PARAMETER;
LOG_INFO(Lib_SaveData, "called = {}, mountPoint->data = {}", mount_dir.string(),
mountPoint->data);
if (paramBuf != nullptr) { auto* mnt = Common::Singleton<Core::FileSys::MntPoints>::Instance();
Common::FS::IOFile file(mount_dir / "param.txt", Common::FS::FileAccessMode::Write); const auto mount_dir = mnt->GetHostPath(mountPoint->data) / "param.txt";
file.WriteRaw<u8>(paramBuf, paramBufSize); OrbisSaveDataParam params;
if (std::filesystem::exists(mount_dir)) {
Common::FS::IOFile file(mount_dir, Common::FS::FileAccessMode::Read);
file.ReadRaw<u8>(&params, sizeof(OrbisSaveDataParam));
} }
LOG_INFO(Lib_SaveData, "called");
switch (paramType) {
case ORBIS_SAVE_DATA_PARAM_TYPE_ALL: {
memcpy(&params, paramBuf, sizeof(OrbisSaveDataParam));
} break;
case ORBIS_SAVE_DATA_PARAM_TYPE_TITLE: {
strncpy(params.title, static_cast<const char*>(paramBuf), paramBufSize);
} break;
case ORBIS_SAVE_DATA_PARAM_TYPE_SUB_TITLE: {
strncpy(params.subTitle, static_cast<const char*>(paramBuf), paramBufSize);
} break;
case ORBIS_SAVE_DATA_PARAM_TYPE_DETAIL: {
strncpy(params.detail, static_cast<const char*>(paramBuf), paramBufSize);
} break;
case ORBIS_SAVE_DATA_PARAM_TYPE_USER_PARAM: {
params.userParam = *(static_cast<const u32*>(paramBuf));
} break;
case ORBIS_SAVE_DATA_PARAM_TYPE_MTIME: {
params.mtime = *(static_cast<const time_t*>(paramBuf));
} break;
default: {
UNREACHABLE_MSG("Unknown Param = {}", paramType);
}
}
Common::FS::IOFile file(mount_dir, Common::FS::FileAccessMode::Write);
file.WriteRaw<u8>(&params, sizeof(OrbisSaveDataParam));
return ORBIS_OK; return ORBIS_OK;
} }
@ -610,7 +683,7 @@ int PS4_SYSV_ABI sceSaveDataSetSaveDataMemory(const u32 userId, const void* buf,
Common::FS::IOFile file(mount_dir, Common::FS::FileAccessMode::Write); Common::FS::IOFile file(mount_dir, Common::FS::FileAccessMode::Write);
file.Seek(offset); file.Seek(offset);
file.WriteRaw<u8>((void*)buf, bufSize); file.WriteRaw<u8>(buf, bufSize);
return ORBIS_OK; return ORBIS_OK;
} }
@ -624,7 +697,7 @@ int PS4_SYSV_ABI sceSaveDataSetSaveDataMemory2(const OrbisSaveDataMemorySet2* se
if (!file.IsOpen()) if (!file.IsOpen())
return -1; return -1;
file.Seek(setParam->data->offset); file.Seek(setParam->data->offset);
file.WriteRaw<u8>((void*)setParam->data->buf, setParam->data->bufSize); file.WriteRaw<u8>(setParam->data->buf, setParam->data->bufSize);
} }
if (setParam->param != nullptr) { if (setParam->param != nullptr) {
@ -634,7 +707,7 @@ int PS4_SYSV_ABI sceSaveDataSetSaveDataMemory2(const OrbisSaveDataMemorySet2* se
if (setParam->icon != nullptr) { if (setParam->icon != nullptr) {
Common::FS::IOFile file(mount_dir / "save_icon.png", Common::FS::FileAccessMode::Write); Common::FS::IOFile file(mount_dir / "save_icon.png", Common::FS::FileAccessMode::Write);
file.WriteRaw<u8>((void*)setParam->icon->buf, setParam->icon->bufSize); file.WriteRaw<u8>(setParam->icon->buf, setParam->icon->bufSize);
} }
return ORBIS_OK; return ORBIS_OK;
@ -719,16 +792,17 @@ int PS4_SYSV_ABI sceSaveDataTransferringMount() {
} }
s32 PS4_SYSV_ABI sceSaveDataUmount(const OrbisSaveDataMountPoint* mountPoint) { s32 PS4_SYSV_ABI sceSaveDataUmount(const OrbisSaveDataMountPoint* mountPoint) {
LOG_INFO(Lib_SaveData, "mountPoint = {}", std::string(mountPoint->data));
if (std::string(mountPoint->data).empty()) { if (std::string(mountPoint->data).empty()) {
return ORBIS_SAVE_DATA_ERROR_NOT_MOUNTED; return ORBIS_SAVE_DATA_ERROR_NOT_MOUNTED;
} }
const auto& mount_dir = Common::FS::GetUserPath(Common::FS::PathType::SaveDataDir) / const auto& mount_dir = Common::FS::GetUserPath(Common::FS::PathType::SaveDataDir) /
std::to_string(1) / game_serial / mountPoint->data; std::to_string(1) / game_serial / mountPoint->data;
auto* mnt = Common::Singleton<Core::FileSys::MntPoints>::Instance(); auto* mnt = Common::Singleton<Core::FileSys::MntPoints>::Instance();
const auto& guest_path = mnt->GetHostPath(mountPoint->data);
if (guest_path.empty())
return ORBIS_SAVE_DATA_ERROR_NOT_MOUNTED;
mnt->Unmount(mount_dir, mountPoint->data); mnt->Unmount(mount_dir, mountPoint->data);
LOG_INFO(Lib_SaveData, "mountPoint = {}", std::string(mountPoint->data));
return ORBIS_OK; return ORBIS_OK;
} }
@ -738,23 +812,33 @@ int PS4_SYSV_ABI sceSaveDataUmountSys() {
} }
int PS4_SYSV_ABI sceSaveDataUmountWithBackup(const OrbisSaveDataMountPoint* mountPoint) { int PS4_SYSV_ABI sceSaveDataUmountWithBackup(const OrbisSaveDataMountPoint* mountPoint) {
LOG_ERROR(Lib_SaveData, "called = {}", std::string(mountPoint->data)); LOG_INFO(Lib_SaveData, "called mount = {}, is_rw_mode = {}", std::string(mountPoint->data),
is_rw_mode);
auto* mnt = Common::Singleton<Core::FileSys::MntPoints>::Instance(); auto* mnt = Common::Singleton<Core::FileSys::MntPoints>::Instance();
const auto mount_dir = mnt->GetHostPath(mountPoint->data); const auto mount_dir = mnt->GetHostPath(mountPoint->data);
if (!std::filesystem::exists(mount_dir)) { if (!std::filesystem::exists(mount_dir)) {
return ORBIS_SAVE_DATA_ERROR_NOT_FOUND; return ORBIS_SAVE_DATA_ERROR_NOT_FOUND;
} }
// leave disabled for now. and just unmount.
std::filesystem::create_directories(mount_dir.parent_path() / "backup"); /* if (is_rw_mode) { // backup is done only when mount mode is ReadWrite.
auto backup_path = mount_dir;
std::string save_data_dir = (mount_dir.string() + "_backup");
backup_path.replace_filename(save_data_dir);
for (const auto& entry : std::filesystem::recursive_directory_iterator(mount_dir)) { std::filesystem::create_directories(backup_path);
const auto& path = entry.path();
const auto target_path = mount_dir.parent_path() / "backup"; for (const auto& entry : std::filesystem::recursive_directory_iterator(mount_dir)) {
if (std::filesystem::is_regular_file(path)) { const auto& path = entry.path();
std::filesystem::copy(path, target_path, if (std::filesystem::is_regular_file(path)) {
std::filesystem::copy_options::overwrite_existing); std::filesystem::copy(path, save_data_dir,
std::filesystem::copy_options::overwrite_existing);
}
} }
} }*/
const auto& guest_path = mnt->GetHostPath(mountPoint->data);
if (guest_path.empty())
return ORBIS_SAVE_DATA_ERROR_NOT_MOUNTED;
mnt->Unmount(mount_dir, mountPoint->data); mnt->Unmount(mount_dir, mountPoint->data);
return ORBIS_OK; return ORBIS_OK;

View File

@ -242,6 +242,13 @@ struct OrbisSaveDataMemorySync {
u8 reserved[28]; u8 reserved[28];
}; };
constexpr int ORBIS_SAVE_DATA_PARAM_TYPE_ALL = 0;
constexpr int ORBIS_SAVE_DATA_PARAM_TYPE_TITLE = 1;
constexpr int ORBIS_SAVE_DATA_PARAM_TYPE_SUB_TITLE = 2;
constexpr int ORBIS_SAVE_DATA_PARAM_TYPE_DETAIL = 3;
constexpr int ORBIS_SAVE_DATA_PARAM_TYPE_USER_PARAM = 4;
constexpr int ORBIS_SAVE_DATA_PARAM_TYPE_MTIME = 5;
int PS4_SYSV_ABI sceSaveDataAbort(); int PS4_SYSV_ABI sceSaveDataAbort();
int PS4_SYSV_ABI sceSaveDataBackup(); int PS4_SYSV_ABI sceSaveDataBackup();
int PS4_SYSV_ABI sceSaveDataBindPsnAccount(); int PS4_SYSV_ABI sceSaveDataBindPsnAccount();
@ -291,7 +298,9 @@ int PS4_SYSV_ABI sceSaveDataGetFormat();
int PS4_SYSV_ABI sceSaveDataGetMountedSaveDataCount(); int PS4_SYSV_ABI sceSaveDataGetMountedSaveDataCount();
int PS4_SYSV_ABI sceSaveDataGetMountInfo(const OrbisSaveDataMountPoint* mountPoint, int PS4_SYSV_ABI sceSaveDataGetMountInfo(const OrbisSaveDataMountPoint* mountPoint,
OrbisSaveDataMountInfo* info); OrbisSaveDataMountInfo* info);
int PS4_SYSV_ABI sceSaveDataGetParam(); int PS4_SYSV_ABI sceSaveDataGetParam(const OrbisSaveDataMountPoint* mountPoint,
const OrbisSaveDataParamType paramType, void* paramBuf,
const size_t paramBufSize, size_t* gotSize);
int PS4_SYSV_ABI sceSaveDataGetProgress(); int PS4_SYSV_ABI sceSaveDataGetProgress();
int PS4_SYSV_ABI sceSaveDataGetSaveDataCount(); int PS4_SYSV_ABI sceSaveDataGetSaveDataCount();
int PS4_SYSV_ABI sceSaveDataGetSaveDataMemory(const u32 userId, void* buf, const size_t bufSize, int PS4_SYSV_ABI sceSaveDataGetSaveDataMemory(const u32 userId, void* buf, const size_t bufSize,

View File

@ -317,6 +317,7 @@ std::span<const vk::Format> GetAllFormats() {
vk::Format::eR8Sint, vk::Format::eR8Sint,
vk::Format::eR8Uint, vk::Format::eR8Uint,
vk::Format::eR8Unorm, vk::Format::eR8Unorm,
vk::Format::eR8Srgb,
vk::Format::eR16G16B16A16Sfloat, vk::Format::eR16G16B16A16Sfloat,
vk::Format::eR16G16B16A16Sint, vk::Format::eR16G16B16A16Sint,
vk::Format::eR16G16B16A16Snorm, vk::Format::eR16G16B16A16Snorm,
@ -542,6 +543,13 @@ vk::Format SurfaceFormat(AmdGpu::DataFormat data_format, AmdGpu::NumberFormat nu
if (data_format == AmdGpu::DataFormat::FormatBc6 && num_format == AmdGpu::NumberFormat::Unorm) { if (data_format == AmdGpu::DataFormat::FormatBc6 && num_format == AmdGpu::NumberFormat::Unorm) {
return vk::Format::eBc6HUfloatBlock; return vk::Format::eBc6HUfloatBlock;
} }
if (data_format == AmdGpu::DataFormat::Format8_8_8_8 &&
num_format == AmdGpu::NumberFormat::Sint) {
return vk::Format::eR8G8B8A8Sint;
}
if (data_format == AmdGpu::DataFormat::Format8 && num_format == AmdGpu::NumberFormat::Srgb) {
return vk::Format::eR8Srgb;
}
UNREACHABLE_MSG("Unknown data_format={} and num_format={}", u32(data_format), u32(num_format)); UNREACHABLE_MSG("Unknown data_format={} and num_format={}", u32(data_format), u32(num_format));
} }