diff options
author | FearlessTobi <thm.frey@gmail.com> | 2024-02-18 23:02:37 +0100 |
---|---|---|
committer | FearlessTobi <thm.frey@gmail.com> | 2024-02-19 19:06:31 +0100 |
commit | 380475af32507cf8fd1a42d470667bce8f0b69c7 (patch) | |
tree | 2176dc3a293baadfa0c6e95bd66d70c6ecff9df4 /src/core/hle/service/filesystem/fsp/fs_i_save_data_info_reader.cpp | |
parent | Merge pull request #13080 from FearlessTobi/scope-exit (diff) | |
download | yuzu-380475af32507cf8fd1a42d470667bce8f0b69c7.tar yuzu-380475af32507cf8fd1a42d470667bce8f0b69c7.tar.gz yuzu-380475af32507cf8fd1a42d470667bce8f0b69c7.tar.bz2 yuzu-380475af32507cf8fd1a42d470667bce8f0b69c7.tar.lz yuzu-380475af32507cf8fd1a42d470667bce8f0b69c7.tar.xz yuzu-380475af32507cf8fd1a42d470667bce8f0b69c7.tar.zst yuzu-380475af32507cf8fd1a42d470667bce8f0b69c7.zip |
Diffstat (limited to 'src/core/hle/service/filesystem/fsp/fs_i_save_data_info_reader.cpp')
-rw-r--r-- | src/core/hle/service/filesystem/fsp/fs_i_save_data_info_reader.cpp | 162 |
1 files changed, 162 insertions, 0 deletions
diff --git a/src/core/hle/service/filesystem/fsp/fs_i_save_data_info_reader.cpp b/src/core/hle/service/filesystem/fsp/fs_i_save_data_info_reader.cpp new file mode 100644 index 000000000..872377d03 --- /dev/null +++ b/src/core/hle/service/filesystem/fsp/fs_i_save_data_info_reader.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 |