mirror of
https://github.com/yuzu-emu/yuzu-mainline
synced 2024-11-22 11:13:54 +00:00
fsp: Move ISaveDataInfoReader to a seperate file
This commit is contained in:
parent
c9ef2e26ca
commit
380475af32
4 changed files with 214 additions and 165 deletions
|
@ -585,6 +585,8 @@ add_library(core STATIC
|
||||||
hle/service/filesystem/fsp/fs_i_file.h
|
hle/service/filesystem/fsp/fs_i_file.h
|
||||||
hle/service/filesystem/fsp/fs_i_filesystem.cpp
|
hle/service/filesystem/fsp/fs_i_filesystem.cpp
|
||||||
hle/service/filesystem/fsp/fs_i_filesystem.h
|
hle/service/filesystem/fsp/fs_i_filesystem.h
|
||||||
|
hle/service/filesystem/fsp/fs_i_save_data_info_reader.cpp
|
||||||
|
hle/service/filesystem/fsp/fs_i_save_data_info_reader.h
|
||||||
hle/service/filesystem/fsp/fs_i_storage.cpp
|
hle/service/filesystem/fsp/fs_i_storage.cpp
|
||||||
hle/service/filesystem/fsp/fs_i_storage.h
|
hle/service/filesystem/fsp/fs_i_storage.h
|
||||||
hle/service/filesystem/fsp/fsp_ldr.cpp
|
hle/service/filesystem/fsp/fsp_ldr.cpp
|
||||||
|
|
|
@ -0,0 +1,162 @@
|
||||||
|
// SPDX-FileCopyrightText: Copyright 2018 yuzu Emulator Project
|
||||||
|
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||||
|
|
||||||
|
#include "common/hex_util.h"
|
||||||
|
#include "core/file_sys/savedata_factory.h"
|
||||||
|
#include "core/hle/service/filesystem/fsp/fs_i_save_data_info_reader.h"
|
||||||
|
#include "core/hle/service/filesystem/save_data_controller.h"
|
||||||
|
#include "core/hle/service/ipc_helpers.h"
|
||||||
|
|
||||||
|
namespace Service::FileSystem {
|
||||||
|
|
||||||
|
ISaveDataInfoReader::ISaveDataInfoReader(Core::System& system_,
|
||||||
|
std::shared_ptr<SaveDataController> save_data_controller_,
|
||||||
|
FileSys::SaveDataSpaceId space)
|
||||||
|
: ServiceFramework{system_, "ISaveDataInfoReader"},
|
||||||
|
save_data_controller{save_data_controller_} {
|
||||||
|
static const FunctionInfo functions[] = {
|
||||||
|
{0, &ISaveDataInfoReader::ReadSaveDataInfo, "ReadSaveDataInfo"},
|
||||||
|
};
|
||||||
|
RegisterHandlers(functions);
|
||||||
|
|
||||||
|
FindAllSaves(space);
|
||||||
|
}
|
||||||
|
|
||||||
|
ISaveDataInfoReader::~ISaveDataInfoReader() = default;
|
||||||
|
|
||||||
|
static u64 stoull_be(std::string_view str) {
|
||||||
|
if (str.size() != 16) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
const auto bytes = Common::HexStringToArray<0x8>(str);
|
||||||
|
u64 out{};
|
||||||
|
std::memcpy(&out, bytes.data(), sizeof(u64));
|
||||||
|
|
||||||
|
return Common::swap64(out);
|
||||||
|
}
|
||||||
|
|
||||||
|
void ISaveDataInfoReader::ReadSaveDataInfo(HLERequestContext& ctx) {
|
||||||
|
LOG_DEBUG(Service_FS, "called");
|
||||||
|
|
||||||
|
// Calculate how many entries we can fit in the output buffer
|
||||||
|
const u64 count_entries = ctx.GetWriteBufferNumElements<SaveDataInfo>();
|
||||||
|
|
||||||
|
// Cap at total number of entries.
|
||||||
|
const u64 actual_entries = std::min(count_entries, info.size() - next_entry_index);
|
||||||
|
|
||||||
|
// Determine data start and end
|
||||||
|
const auto* begin = reinterpret_cast<u8*>(info.data() + next_entry_index);
|
||||||
|
const auto* end = reinterpret_cast<u8*>(info.data() + next_entry_index + actual_entries);
|
||||||
|
const auto range_size = static_cast<std::size_t>(std::distance(begin, end));
|
||||||
|
|
||||||
|
next_entry_index += actual_entries;
|
||||||
|
|
||||||
|
// Write the data to memory
|
||||||
|
ctx.WriteBuffer(begin, range_size);
|
||||||
|
|
||||||
|
IPC::ResponseBuilder rb{ctx, 4};
|
||||||
|
rb.Push(ResultSuccess);
|
||||||
|
rb.Push<u64>(actual_entries);
|
||||||
|
}
|
||||||
|
|
||||||
|
void ISaveDataInfoReader::FindAllSaves(FileSys::SaveDataSpaceId space) {
|
||||||
|
FileSys::VirtualDir save_root{};
|
||||||
|
const auto result = save_data_controller->OpenSaveDataSpace(&save_root, space);
|
||||||
|
|
||||||
|
if (result != ResultSuccess || save_root == nullptr) {
|
||||||
|
LOG_ERROR(Service_FS, "The save root for the space_id={:02X} was invalid!", space);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (const auto& type : save_root->GetSubdirectories()) {
|
||||||
|
if (type->GetName() == "save") {
|
||||||
|
FindNormalSaves(space, type);
|
||||||
|
} else if (space == FileSys::SaveDataSpaceId::TemporaryStorage) {
|
||||||
|
FindTemporaryStorageSaves(space, type);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void ISaveDataInfoReader::FindNormalSaves(FileSys::SaveDataSpaceId space,
|
||||||
|
const FileSys::VirtualDir& type) {
|
||||||
|
for (const auto& save_id : type->GetSubdirectories()) {
|
||||||
|
for (const auto& user_id : save_id->GetSubdirectories()) {
|
||||||
|
// Skip non user id subdirectories
|
||||||
|
if (user_id->GetName().size() != 0x20) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
const auto save_id_numeric = stoull_be(save_id->GetName());
|
||||||
|
auto user_id_numeric = Common::HexStringToArray<0x10>(user_id->GetName());
|
||||||
|
std::reverse(user_id_numeric.begin(), user_id_numeric.end());
|
||||||
|
|
||||||
|
if (save_id_numeric != 0) {
|
||||||
|
// System Save Data
|
||||||
|
info.emplace_back(SaveDataInfo{
|
||||||
|
0,
|
||||||
|
space,
|
||||||
|
FileSys::SaveDataType::SystemSaveData,
|
||||||
|
{},
|
||||||
|
user_id_numeric,
|
||||||
|
save_id_numeric,
|
||||||
|
0,
|
||||||
|
user_id->GetSize(),
|
||||||
|
{},
|
||||||
|
{},
|
||||||
|
});
|
||||||
|
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (const auto& title_id : user_id->GetSubdirectories()) {
|
||||||
|
const auto device = std::all_of(user_id_numeric.begin(), user_id_numeric.end(),
|
||||||
|
[](u8 val) { return val == 0; });
|
||||||
|
info.emplace_back(SaveDataInfo{
|
||||||
|
0,
|
||||||
|
space,
|
||||||
|
device ? FileSys::SaveDataType::DeviceSaveData
|
||||||
|
: FileSys::SaveDataType::SaveData,
|
||||||
|
{},
|
||||||
|
user_id_numeric,
|
||||||
|
save_id_numeric,
|
||||||
|
stoull_be(title_id->GetName()),
|
||||||
|
title_id->GetSize(),
|
||||||
|
{},
|
||||||
|
{},
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void ISaveDataInfoReader::FindTemporaryStorageSaves(FileSys::SaveDataSpaceId space,
|
||||||
|
const FileSys::VirtualDir& type) {
|
||||||
|
for (const auto& user_id : type->GetSubdirectories()) {
|
||||||
|
// Skip non user id subdirectories
|
||||||
|
if (user_id->GetName().size() != 0x20) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
for (const auto& title_id : user_id->GetSubdirectories()) {
|
||||||
|
if (!title_id->GetFiles().empty() || !title_id->GetSubdirectories().empty()) {
|
||||||
|
auto user_id_numeric = Common::HexStringToArray<0x10>(user_id->GetName());
|
||||||
|
std::reverse(user_id_numeric.begin(), user_id_numeric.end());
|
||||||
|
|
||||||
|
info.emplace_back(SaveDataInfo{
|
||||||
|
0,
|
||||||
|
space,
|
||||||
|
FileSys::SaveDataType::TemporaryStorage,
|
||||||
|
{},
|
||||||
|
user_id_numeric,
|
||||||
|
stoull_be(type->GetName()),
|
||||||
|
stoull_be(title_id->GetName()),
|
||||||
|
title_id->GetSize(),
|
||||||
|
{},
|
||||||
|
{},
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace Service::FileSystem
|
|
@ -0,0 +1,48 @@
|
||||||
|
// SPDX-FileCopyrightText: Copyright 2018 yuzu Emulator Project
|
||||||
|
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <vector>
|
||||||
|
#include "common/common_types.h"
|
||||||
|
#include "core/hle/service/service.h"
|
||||||
|
|
||||||
|
namespace Service::FileSystem {
|
||||||
|
|
||||||
|
class SaveDataController;
|
||||||
|
|
||||||
|
class ISaveDataInfoReader final : public ServiceFramework<ISaveDataInfoReader> {
|
||||||
|
public:
|
||||||
|
explicit ISaveDataInfoReader(Core::System& system_,
|
||||||
|
std::shared_ptr<SaveDataController> save_data_controller_,
|
||||||
|
FileSys::SaveDataSpaceId space);
|
||||||
|
~ISaveDataInfoReader() override;
|
||||||
|
|
||||||
|
void ReadSaveDataInfo(HLERequestContext& ctx);
|
||||||
|
|
||||||
|
private:
|
||||||
|
void FindAllSaves(FileSys::SaveDataSpaceId space);
|
||||||
|
void FindNormalSaves(FileSys::SaveDataSpaceId space, const FileSys::VirtualDir& type);
|
||||||
|
void FindTemporaryStorageSaves(FileSys::SaveDataSpaceId space, const FileSys::VirtualDir& type);
|
||||||
|
|
||||||
|
struct SaveDataInfo {
|
||||||
|
u64_le save_id_unknown;
|
||||||
|
FileSys::SaveDataSpaceId space;
|
||||||
|
FileSys::SaveDataType type;
|
||||||
|
INSERT_PADDING_BYTES_NOINIT(0x6);
|
||||||
|
std::array<u8, 0x10> user_id;
|
||||||
|
u64_le save_id;
|
||||||
|
u64_le title_id;
|
||||||
|
u64_le save_image_size;
|
||||||
|
u16_le index;
|
||||||
|
FileSys::SaveDataRank rank;
|
||||||
|
INSERT_PADDING_BYTES_NOINIT(0x25);
|
||||||
|
};
|
||||||
|
static_assert(sizeof(SaveDataInfo) == 0x60, "SaveDataInfo has incorrect size.");
|
||||||
|
|
||||||
|
std::shared_ptr<SaveDataController> save_data_controller;
|
||||||
|
std::vector<SaveDataInfo> info;
|
||||||
|
u64 next_entry_index = 0;
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace Service::FileSystem
|
|
@ -29,6 +29,7 @@
|
||||||
#include "core/hle/result.h"
|
#include "core/hle/result.h"
|
||||||
#include "core/hle/service/filesystem/filesystem.h"
|
#include "core/hle/service/filesystem/filesystem.h"
|
||||||
#include "core/hle/service/filesystem/fsp/fs_i_filesystem.h"
|
#include "core/hle/service/filesystem/fsp/fs_i_filesystem.h"
|
||||||
|
#include "core/hle/service/filesystem/fsp/fs_i_save_data_info_reader.h"
|
||||||
#include "core/hle/service/filesystem/fsp/fs_i_storage.h"
|
#include "core/hle/service/filesystem/fsp/fs_i_storage.h"
|
||||||
#include "core/hle/service/filesystem/fsp/fsp_srv.h"
|
#include "core/hle/service/filesystem/fsp/fsp_srv.h"
|
||||||
#include "core/hle/service/filesystem/romfs_controller.h"
|
#include "core/hle/service/filesystem/romfs_controller.h"
|
||||||
|
@ -39,6 +40,7 @@
|
||||||
#include "core/reporter.h"
|
#include "core/reporter.h"
|
||||||
|
|
||||||
namespace Service::FileSystem {
|
namespace Service::FileSystem {
|
||||||
|
|
||||||
enum class FileSystemProxyType : u8 {
|
enum class FileSystemProxyType : u8 {
|
||||||
Code = 0,
|
Code = 0,
|
||||||
Rom = 1,
|
Rom = 1,
|
||||||
|
@ -51,171 +53,6 @@ enum class FileSystemProxyType : u8 {
|
||||||
RegisteredUpdate = 8,
|
RegisteredUpdate = 8,
|
||||||
};
|
};
|
||||||
|
|
||||||
class ISaveDataInfoReader final : public ServiceFramework<ISaveDataInfoReader> {
|
|
||||||
public:
|
|
||||||
explicit ISaveDataInfoReader(Core::System& system_,
|
|
||||||
std::shared_ptr<SaveDataController> save_data_controller_,
|
|
||||||
FileSys::SaveDataSpaceId space)
|
|
||||||
: ServiceFramework{system_, "ISaveDataInfoReader"}, save_data_controller{
|
|
||||||
save_data_controller_} {
|
|
||||||
static const FunctionInfo functions[] = {
|
|
||||||
{0, &ISaveDataInfoReader::ReadSaveDataInfo, "ReadSaveDataInfo"},
|
|
||||||
};
|
|
||||||
RegisterHandlers(functions);
|
|
||||||
|
|
||||||
FindAllSaves(space);
|
|
||||||
}
|
|
||||||
|
|
||||||
void ReadSaveDataInfo(HLERequestContext& ctx) {
|
|
||||||
LOG_DEBUG(Service_FS, "called");
|
|
||||||
|
|
||||||
// Calculate how many entries we can fit in the output buffer
|
|
||||||
const u64 count_entries = ctx.GetWriteBufferNumElements<SaveDataInfo>();
|
|
||||||
|
|
||||||
// Cap at total number of entries.
|
|
||||||
const u64 actual_entries = std::min(count_entries, info.size() - next_entry_index);
|
|
||||||
|
|
||||||
// Determine data start and end
|
|
||||||
const auto* begin = reinterpret_cast<u8*>(info.data() + next_entry_index);
|
|
||||||
const auto* end = reinterpret_cast<u8*>(info.data() + next_entry_index + actual_entries);
|
|
||||||
const auto range_size = static_cast<std::size_t>(std::distance(begin, end));
|
|
||||||
|
|
||||||
next_entry_index += actual_entries;
|
|
||||||
|
|
||||||
// Write the data to memory
|
|
||||||
ctx.WriteBuffer(begin, range_size);
|
|
||||||
|
|
||||||
IPC::ResponseBuilder rb{ctx, 4};
|
|
||||||
rb.Push(ResultSuccess);
|
|
||||||
rb.Push<u64>(actual_entries);
|
|
||||||
}
|
|
||||||
|
|
||||||
private:
|
|
||||||
static u64 stoull_be(std::string_view str) {
|
|
||||||
if (str.size() != 16)
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
const auto bytes = Common::HexStringToArray<0x8>(str);
|
|
||||||
u64 out{};
|
|
||||||
std::memcpy(&out, bytes.data(), sizeof(u64));
|
|
||||||
|
|
||||||
return Common::swap64(out);
|
|
||||||
}
|
|
||||||
|
|
||||||
void FindAllSaves(FileSys::SaveDataSpaceId space) {
|
|
||||||
FileSys::VirtualDir save_root{};
|
|
||||||
const auto result = save_data_controller->OpenSaveDataSpace(&save_root, space);
|
|
||||||
|
|
||||||
if (result != ResultSuccess || save_root == nullptr) {
|
|
||||||
LOG_ERROR(Service_FS, "The save root for the space_id={:02X} was invalid!", space);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
for (const auto& type : save_root->GetSubdirectories()) {
|
|
||||||
if (type->GetName() == "save") {
|
|
||||||
for (const auto& save_id : type->GetSubdirectories()) {
|
|
||||||
for (const auto& user_id : save_id->GetSubdirectories()) {
|
|
||||||
// Skip non user id subdirectories
|
|
||||||
if (user_id->GetName().size() != 0x20) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
const auto save_id_numeric = stoull_be(save_id->GetName());
|
|
||||||
auto user_id_numeric = Common::HexStringToArray<0x10>(user_id->GetName());
|
|
||||||
std::reverse(user_id_numeric.begin(), user_id_numeric.end());
|
|
||||||
|
|
||||||
if (save_id_numeric != 0) {
|
|
||||||
// System Save Data
|
|
||||||
info.emplace_back(SaveDataInfo{
|
|
||||||
0,
|
|
||||||
space,
|
|
||||||
FileSys::SaveDataType::SystemSaveData,
|
|
||||||
{},
|
|
||||||
user_id_numeric,
|
|
||||||
save_id_numeric,
|
|
||||||
0,
|
|
||||||
user_id->GetSize(),
|
|
||||||
{},
|
|
||||||
{},
|
|
||||||
});
|
|
||||||
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
for (const auto& title_id : user_id->GetSubdirectories()) {
|
|
||||||
const auto device =
|
|
||||||
std::all_of(user_id_numeric.begin(), user_id_numeric.end(),
|
|
||||||
[](u8 val) { return val == 0; });
|
|
||||||
info.emplace_back(SaveDataInfo{
|
|
||||||
0,
|
|
||||||
space,
|
|
||||||
device ? FileSys::SaveDataType::DeviceSaveData
|
|
||||||
: FileSys::SaveDataType::SaveData,
|
|
||||||
{},
|
|
||||||
user_id_numeric,
|
|
||||||
save_id_numeric,
|
|
||||||
stoull_be(title_id->GetName()),
|
|
||||||
title_id->GetSize(),
|
|
||||||
{},
|
|
||||||
{},
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else if (space == FileSys::SaveDataSpaceId::TemporaryStorage) {
|
|
||||||
// Temporary Storage
|
|
||||||
for (const auto& user_id : type->GetSubdirectories()) {
|
|
||||||
// Skip non user id subdirectories
|
|
||||||
if (user_id->GetName().size() != 0x20) {
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
for (const auto& title_id : user_id->GetSubdirectories()) {
|
|
||||||
if (!title_id->GetFiles().empty() ||
|
|
||||||
!title_id->GetSubdirectories().empty()) {
|
|
||||||
auto user_id_numeric =
|
|
||||||
Common::HexStringToArray<0x10>(user_id->GetName());
|
|
||||||
std::reverse(user_id_numeric.begin(), user_id_numeric.end());
|
|
||||||
|
|
||||||
info.emplace_back(SaveDataInfo{
|
|
||||||
0,
|
|
||||||
space,
|
|
||||||
FileSys::SaveDataType::TemporaryStorage,
|
|
||||||
{},
|
|
||||||
user_id_numeric,
|
|
||||||
stoull_be(type->GetName()),
|
|
||||||
stoull_be(title_id->GetName()),
|
|
||||||
title_id->GetSize(),
|
|
||||||
{},
|
|
||||||
{},
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
struct SaveDataInfo {
|
|
||||||
u64_le save_id_unknown;
|
|
||||||
FileSys::SaveDataSpaceId space;
|
|
||||||
FileSys::SaveDataType type;
|
|
||||||
INSERT_PADDING_BYTES(0x6);
|
|
||||||
std::array<u8, 0x10> user_id;
|
|
||||||
u64_le save_id;
|
|
||||||
u64_le title_id;
|
|
||||||
u64_le save_image_size;
|
|
||||||
u16_le index;
|
|
||||||
FileSys::SaveDataRank rank;
|
|
||||||
INSERT_PADDING_BYTES(0x25);
|
|
||||||
};
|
|
||||||
static_assert(sizeof(SaveDataInfo) == 0x60, "SaveDataInfo has incorrect size.");
|
|
||||||
|
|
||||||
ProcessId process_id = 0;
|
|
||||||
std::shared_ptr<SaveDataController> save_data_controller;
|
|
||||||
std::vector<SaveDataInfo> info;
|
|
||||||
u64 next_entry_index = 0;
|
|
||||||
};
|
|
||||||
|
|
||||||
FSP_SRV::FSP_SRV(Core::System& system_)
|
FSP_SRV::FSP_SRV(Core::System& system_)
|
||||||
: ServiceFramework{system_, "fsp-srv"}, fsc{system.GetFileSystemController()},
|
: ServiceFramework{system_, "fsp-srv"}, fsc{system.GetFileSystemController()},
|
||||||
content_provider{system.GetContentProvider()}, reporter{system.GetReporter()} {
|
content_provider{system.GetContentProvider()}, reporter{system.GetReporter()} {
|
||||||
|
|
Loading…
Reference in a new issue