mirror of
				https://git.zaroz.cloud/nintendo-back-up/yuzu/yuzu-mainline.git
				synced 2025-03-21 01:53:15 +00:00 
			
		
		
		
	Merge pull request #1879 from DarkLordZach/am-save-data-size
am: Implement GetSaveDataSize and ExtendSaveData using files
This commit is contained in:
		
						commit
						c4515d305b
					
				@ -36,18 +36,20 @@ std::string LanguageEntry::GetDeveloperName() const {
 | 
			
		||||
                                                       developer_name.size());
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
NACP::NACP(VirtualFile file) : raw(std::make_unique<RawNACP>()) {
 | 
			
		||||
    file->ReadObject(raw.get());
 | 
			
		||||
NACP::NACP() = default;
 | 
			
		||||
 | 
			
		||||
NACP::NACP(VirtualFile file) {
 | 
			
		||||
    file->ReadObject(&raw);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
NACP::~NACP() = default;
 | 
			
		||||
 | 
			
		||||
const LanguageEntry& NACP::GetLanguageEntry(Language language) const {
 | 
			
		||||
    if (language != Language::Default) {
 | 
			
		||||
        return raw->language_entries.at(static_cast<u8>(language));
 | 
			
		||||
        return raw.language_entries.at(static_cast<u8>(language));
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    for (const auto& language_entry : raw->language_entries) {
 | 
			
		||||
    for (const auto& language_entry : raw.language_entries) {
 | 
			
		||||
        if (!language_entry.GetApplicationName().empty())
 | 
			
		||||
            return language_entry;
 | 
			
		||||
    }
 | 
			
		||||
@ -65,21 +67,29 @@ std::string NACP::GetDeveloperName(Language language) const {
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
u64 NACP::GetTitleId() const {
 | 
			
		||||
    return raw->title_id;
 | 
			
		||||
    return raw.title_id;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
u64 NACP::GetDLCBaseTitleId() const {
 | 
			
		||||
    return raw->dlc_base_title_id;
 | 
			
		||||
    return raw.dlc_base_title_id;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
std::string NACP::GetVersionString() const {
 | 
			
		||||
    return Common::StringFromFixedZeroTerminatedBuffer(raw->version_string.data(),
 | 
			
		||||
                                                       raw->version_string.size());
 | 
			
		||||
    return Common::StringFromFixedZeroTerminatedBuffer(raw.version_string.data(),
 | 
			
		||||
                                                       raw.version_string.size());
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
u64 NACP::GetDefaultNormalSaveSize() const {
 | 
			
		||||
    return raw.normal_save_data_size;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
u64 NACP::GetDefaultJournalSaveSize() const {
 | 
			
		||||
    return raw.journal_sava_data_size;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
std::vector<u8> NACP::GetRawBytes() const {
 | 
			
		||||
    std::vector<u8> out(sizeof(RawNACP));
 | 
			
		||||
    std::memcpy(out.data(), raw.get(), sizeof(RawNACP));
 | 
			
		||||
    std::memcpy(out.data(), &raw, sizeof(RawNACP));
 | 
			
		||||
    return out;
 | 
			
		||||
}
 | 
			
		||||
} // namespace FileSys
 | 
			
		||||
 | 
			
		||||
@ -28,17 +28,30 @@ static_assert(sizeof(LanguageEntry) == 0x300, "LanguageEntry has incorrect size.
 | 
			
		||||
// The raw file format of a NACP file.
 | 
			
		||||
struct RawNACP {
 | 
			
		||||
    std::array<LanguageEntry, 16> language_entries;
 | 
			
		||||
    INSERT_PADDING_BYTES(0x38);
 | 
			
		||||
    std::array<u8, 0x25> isbn;
 | 
			
		||||
    u8 startup_user_account;
 | 
			
		||||
    INSERT_PADDING_BYTES(2);
 | 
			
		||||
    u32_le application_attribute;
 | 
			
		||||
    u32_le supported_languages;
 | 
			
		||||
    u32_le parental_control;
 | 
			
		||||
    bool screenshot_enabled;
 | 
			
		||||
    u8 video_capture_mode;
 | 
			
		||||
    bool data_loss_confirmation;
 | 
			
		||||
    INSERT_PADDING_BYTES(1);
 | 
			
		||||
    u64_le title_id;
 | 
			
		||||
    INSERT_PADDING_BYTES(0x20);
 | 
			
		||||
    std::array<u8, 0x20> rating_age;
 | 
			
		||||
    std::array<char, 0x10> version_string;
 | 
			
		||||
    u64_le dlc_base_title_id;
 | 
			
		||||
    u64_le title_id_2;
 | 
			
		||||
    INSERT_PADDING_BYTES(0x28);
 | 
			
		||||
    u64_le normal_save_data_size;
 | 
			
		||||
    u64_le journal_sava_data_size;
 | 
			
		||||
    INSERT_PADDING_BYTES(0x18);
 | 
			
		||||
    u64_le product_code;
 | 
			
		||||
    u64_le title_id_3;
 | 
			
		||||
    std::array<u64_le, 0x7> title_id_array;
 | 
			
		||||
    INSERT_PADDING_BYTES(0x8);
 | 
			
		||||
    std::array<u64_le, 0x8> local_communication;
 | 
			
		||||
    u8 logo_type;
 | 
			
		||||
    u8 logo_handling;
 | 
			
		||||
    bool runtime_add_on_content_install;
 | 
			
		||||
    INSERT_PADDING_BYTES(5);
 | 
			
		||||
    u64_le title_id_update;
 | 
			
		||||
    std::array<u8, 0x40> bcat_passphrase;
 | 
			
		||||
    INSERT_PADDING_BYTES(0xEC0);
 | 
			
		||||
@ -72,6 +85,7 @@ extern const std::array<const char*, 15> LANGUAGE_NAMES;
 | 
			
		||||
// These store application name, dev name, title id, and other miscellaneous data.
 | 
			
		||||
class NACP {
 | 
			
		||||
public:
 | 
			
		||||
    explicit NACP();
 | 
			
		||||
    explicit NACP(VirtualFile file);
 | 
			
		||||
    ~NACP();
 | 
			
		||||
 | 
			
		||||
@ -81,10 +95,12 @@ public:
 | 
			
		||||
    u64 GetTitleId() const;
 | 
			
		||||
    u64 GetDLCBaseTitleId() const;
 | 
			
		||||
    std::string GetVersionString() const;
 | 
			
		||||
    u64 GetDefaultNormalSaveSize() const;
 | 
			
		||||
    u64 GetDefaultJournalSaveSize() const;
 | 
			
		||||
    std::vector<u8> GetRawBytes() const;
 | 
			
		||||
 | 
			
		||||
private:
 | 
			
		||||
    std::unique_ptr<RawNACP> raw;
 | 
			
		||||
    RawNACP raw{};
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
} // namespace FileSys
 | 
			
		||||
 | 
			
		||||
@ -13,6 +13,8 @@
 | 
			
		||||
 | 
			
		||||
namespace FileSys {
 | 
			
		||||
 | 
			
		||||
constexpr char SAVE_DATA_SIZE_FILENAME[] = ".yuzu_save_size";
 | 
			
		||||
 | 
			
		||||
std::string SaveDataDescriptor::DebugInfo() const {
 | 
			
		||||
    return fmt::format("[type={:02X}, title_id={:016X}, user_id={:016X}{:016X}, save_id={:016X}]",
 | 
			
		||||
                       static_cast<u8>(type), title_id, user_id[1], user_id[0], save_id);
 | 
			
		||||
@ -132,4 +134,32 @@ std::string SaveDataFactory::GetFullPath(SaveDataSpaceId space, SaveDataType typ
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
SaveDataSize SaveDataFactory::ReadSaveDataSize(SaveDataType type, u64 title_id,
 | 
			
		||||
                                               u128 user_id) const {
 | 
			
		||||
    const auto path = GetFullPath(SaveDataSpaceId::NandUser, type, title_id, user_id, 0);
 | 
			
		||||
    const auto dir = GetOrCreateDirectoryRelative(this->dir, path);
 | 
			
		||||
 | 
			
		||||
    const auto size_file = dir->GetFile(SAVE_DATA_SIZE_FILENAME);
 | 
			
		||||
    if (size_file == nullptr || size_file->GetSize() < sizeof(SaveDataSize))
 | 
			
		||||
        return {0, 0};
 | 
			
		||||
 | 
			
		||||
    SaveDataSize out;
 | 
			
		||||
    if (size_file->ReadObject(&out) != sizeof(SaveDataSize))
 | 
			
		||||
        return {0, 0};
 | 
			
		||||
    return out;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void SaveDataFactory::WriteSaveDataSize(SaveDataType type, u64 title_id, u128 user_id,
 | 
			
		||||
                                        SaveDataSize new_value) {
 | 
			
		||||
    const auto path = GetFullPath(SaveDataSpaceId::NandUser, type, title_id, user_id, 0);
 | 
			
		||||
    const auto dir = GetOrCreateDirectoryRelative(this->dir, path);
 | 
			
		||||
 | 
			
		||||
    const auto size_file = dir->CreateFile(SAVE_DATA_SIZE_FILENAME);
 | 
			
		||||
    if (size_file == nullptr)
 | 
			
		||||
        return;
 | 
			
		||||
 | 
			
		||||
    size_file->Resize(sizeof(SaveDataSize));
 | 
			
		||||
    size_file->WriteObject(new_value);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
} // namespace FileSys
 | 
			
		||||
 | 
			
		||||
@ -46,6 +46,11 @@ struct SaveDataDescriptor {
 | 
			
		||||
};
 | 
			
		||||
static_assert(sizeof(SaveDataDescriptor) == 0x40, "SaveDataDescriptor has incorrect size.");
 | 
			
		||||
 | 
			
		||||
struct SaveDataSize {
 | 
			
		||||
    u64 normal;
 | 
			
		||||
    u64 journal;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
/// File system interface to the SaveData archive
 | 
			
		||||
class SaveDataFactory {
 | 
			
		||||
public:
 | 
			
		||||
@ -60,6 +65,9 @@ public:
 | 
			
		||||
    static std::string GetFullPath(SaveDataSpaceId space, SaveDataType type, u64 title_id,
 | 
			
		||||
                                   u128 user_id, u64 save_id);
 | 
			
		||||
 | 
			
		||||
    SaveDataSize ReadSaveDataSize(SaveDataType type, u64 title_id, u128 user_id) const;
 | 
			
		||||
    void WriteSaveDataSize(SaveDataType type, u64 title_id, u128 user_id, SaveDataSize new_value);
 | 
			
		||||
 | 
			
		||||
private:
 | 
			
		||||
    VirtualDir dir;
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
@ -150,7 +150,7 @@ public:
 | 
			
		||||
    template <typename T>
 | 
			
		||||
    std::size_t WriteArray(const T* data, std::size_t number_elements, std::size_t offset = 0) {
 | 
			
		||||
        static_assert(std::is_trivially_copyable_v<T>, "Data type must be trivially copyable.");
 | 
			
		||||
        return Write(data, number_elements * sizeof(T), offset);
 | 
			
		||||
        return Write(reinterpret_cast<const u8*>(data), number_elements * sizeof(T), offset);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    // Writes size bytes starting at memory location data to offset in file.
 | 
			
		||||
@ -166,7 +166,7 @@ public:
 | 
			
		||||
    template <typename T>
 | 
			
		||||
    std::size_t WriteObject(const T& data, std::size_t offset = 0) {
 | 
			
		||||
        static_assert(std::is_trivially_copyable_v<T>, "Data type must be trivially copyable.");
 | 
			
		||||
        return Write(&data, sizeof(T), offset);
 | 
			
		||||
        return Write(reinterpret_cast<const u8*>(&data), sizeof(T), offset);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    // Renames the file to name. Returns whether or not the operation was successsful.
 | 
			
		||||
 | 
			
		||||
@ -8,6 +8,7 @@
 | 
			
		||||
#include <stack>
 | 
			
		||||
#include "audio_core/audio_renderer.h"
 | 
			
		||||
#include "core/core.h"
 | 
			
		||||
#include "core/file_sys/savedata_factory.h"
 | 
			
		||||
#include "core/hle/ipc_helpers.h"
 | 
			
		||||
#include "core/hle/kernel/kernel.h"
 | 
			
		||||
#include "core/hle/kernel/process.h"
 | 
			
		||||
@ -865,8 +866,8 @@ IApplicationFunctions::IApplicationFunctions() : ServiceFramework("IApplicationF
 | 
			
		||||
        {22, &IApplicationFunctions::SetTerminateResult, "SetTerminateResult"},
 | 
			
		||||
        {23, &IApplicationFunctions::GetDisplayVersion, "GetDisplayVersion"},
 | 
			
		||||
        {24, nullptr, "GetLaunchStorageInfoForDebug"},
 | 
			
		||||
        {25, nullptr, "ExtendSaveData"},
 | 
			
		||||
        {26, nullptr, "GetSaveDataSize"},
 | 
			
		||||
        {25, &IApplicationFunctions::ExtendSaveData, "ExtendSaveData"},
 | 
			
		||||
        {26, &IApplicationFunctions::GetSaveDataSize, "GetSaveDataSize"},
 | 
			
		||||
        {30, &IApplicationFunctions::BeginBlockingHomeButtonShortAndLongPressed, "BeginBlockingHomeButtonShortAndLongPressed"},
 | 
			
		||||
        {31, &IApplicationFunctions::EndBlockingHomeButtonShortAndLongPressed, "EndBlockingHomeButtonShortAndLongPressed"},
 | 
			
		||||
        {32, &IApplicationFunctions::BeginBlockingHomeButton, "BeginBlockingHomeButton"},
 | 
			
		||||
@ -1043,6 +1044,48 @@ void IApplicationFunctions::GetPseudoDeviceId(Kernel::HLERequestContext& ctx) {
 | 
			
		||||
    rb.Push<u64>(0);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void IApplicationFunctions::ExtendSaveData(Kernel::HLERequestContext& ctx) {
 | 
			
		||||
    IPC::RequestParser rp{ctx};
 | 
			
		||||
    const auto type{rp.PopRaw<FileSys::SaveDataType>()};
 | 
			
		||||
    rp.Skip(1, false);
 | 
			
		||||
    const auto user_id{rp.PopRaw<u128>()};
 | 
			
		||||
    const auto new_normal_size{rp.PopRaw<u64>()};
 | 
			
		||||
    const auto new_journal_size{rp.PopRaw<u64>()};
 | 
			
		||||
 | 
			
		||||
    LOG_DEBUG(Service_AM,
 | 
			
		||||
              "called with type={:02X}, user_id={:016X}{:016X}, new_normal={:016X}, "
 | 
			
		||||
              "new_journal={:016X}",
 | 
			
		||||
              static_cast<u8>(type), user_id[1], user_id[0], new_normal_size, new_journal_size);
 | 
			
		||||
 | 
			
		||||
    FileSystem::WriteSaveDataSize(type, Core::CurrentProcess()->GetTitleID(), user_id,
 | 
			
		||||
                                  {new_normal_size, new_journal_size});
 | 
			
		||||
 | 
			
		||||
    IPC::ResponseBuilder rb{ctx, 4};
 | 
			
		||||
    rb.Push(RESULT_SUCCESS);
 | 
			
		||||
 | 
			
		||||
    // The following value is used upon failure to help the system recover.
 | 
			
		||||
    // Since we always succeed, this should be 0.
 | 
			
		||||
    rb.Push<u64>(0);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void IApplicationFunctions::GetSaveDataSize(Kernel::HLERequestContext& ctx) {
 | 
			
		||||
    IPC::RequestParser rp{ctx};
 | 
			
		||||
    const auto type{rp.PopRaw<FileSys::SaveDataType>()};
 | 
			
		||||
    rp.Skip(1, false);
 | 
			
		||||
    const auto user_id{rp.PopRaw<u128>()};
 | 
			
		||||
 | 
			
		||||
    LOG_DEBUG(Service_AM, "called with type={:02X}, user_id={:016X}{:016X}", static_cast<u8>(type),
 | 
			
		||||
              user_id[1], user_id[0]);
 | 
			
		||||
 | 
			
		||||
    const auto size =
 | 
			
		||||
        FileSystem::ReadSaveDataSize(type, Core::CurrentProcess()->GetTitleID(), user_id);
 | 
			
		||||
 | 
			
		||||
    IPC::ResponseBuilder rb{ctx, 6};
 | 
			
		||||
    rb.Push(RESULT_SUCCESS);
 | 
			
		||||
    rb.Push(size.normal);
 | 
			
		||||
    rb.Push(size.journal);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void InstallInterfaces(SM::ServiceManager& service_manager,
 | 
			
		||||
                       std::shared_ptr<NVFlinger::NVFlinger> nvflinger) {
 | 
			
		||||
    auto message_queue = std::make_shared<AppletMessageQueue>();
 | 
			
		||||
 | 
			
		||||
@ -206,6 +206,8 @@ private:
 | 
			
		||||
    void SetGamePlayRecordingState(Kernel::HLERequestContext& ctx);
 | 
			
		||||
    void NotifyRunning(Kernel::HLERequestContext& ctx);
 | 
			
		||||
    void GetPseudoDeviceId(Kernel::HLERequestContext& ctx);
 | 
			
		||||
    void ExtendSaveData(Kernel::HLERequestContext& ctx);
 | 
			
		||||
    void GetSaveDataSize(Kernel::HLERequestContext& ctx);
 | 
			
		||||
    void BeginBlockingHomeButtonShortAndLongPressed(Kernel::HLERequestContext& ctx);
 | 
			
		||||
    void EndBlockingHomeButtonShortAndLongPressed(Kernel::HLERequestContext& ctx);
 | 
			
		||||
    void BeginBlockingHomeButton(Kernel::HLERequestContext& ctx);
 | 
			
		||||
 | 
			
		||||
@ -8,18 +8,23 @@
 | 
			
		||||
#include "common/file_util.h"
 | 
			
		||||
#include "core/core.h"
 | 
			
		||||
#include "core/file_sys/bis_factory.h"
 | 
			
		||||
#include "core/file_sys/control_metadata.h"
 | 
			
		||||
#include "core/file_sys/errors.h"
 | 
			
		||||
#include "core/file_sys/mode.h"
 | 
			
		||||
#include "core/file_sys/partition_filesystem.h"
 | 
			
		||||
#include "core/file_sys/patch_manager.h"
 | 
			
		||||
#include "core/file_sys/registered_cache.h"
 | 
			
		||||
#include "core/file_sys/romfs_factory.h"
 | 
			
		||||
#include "core/file_sys/savedata_factory.h"
 | 
			
		||||
#include "core/file_sys/sdmc_factory.h"
 | 
			
		||||
#include "core/file_sys/vfs.h"
 | 
			
		||||
#include "core/file_sys/vfs_offset.h"
 | 
			
		||||
#include "core/hle/kernel/process.h"
 | 
			
		||||
#include "core/hle/service/filesystem/filesystem.h"
 | 
			
		||||
#include "core/hle/service/filesystem/fsp_ldr.h"
 | 
			
		||||
#include "core/hle/service/filesystem/fsp_pr.h"
 | 
			
		||||
#include "core/hle/service/filesystem/fsp_srv.h"
 | 
			
		||||
#include "core/loader/loader.h"
 | 
			
		||||
 | 
			
		||||
namespace Service::FileSystem {
 | 
			
		||||
 | 
			
		||||
@ -28,6 +33,10 @@ namespace Service::FileSystem {
 | 
			
		||||
// TODO(DarkLordZach): Eventually make this configurable in settings.
 | 
			
		||||
constexpr u64 EMULATED_SD_REPORTED_SIZE = 32000000000;
 | 
			
		||||
 | 
			
		||||
// A default size for normal/journal save data size if application control metadata cannot be found.
 | 
			
		||||
// This should be large enough to satisfy even the most extreme requirements (~4.2GB)
 | 
			
		||||
constexpr u64 SUFFICIENT_SAVE_DATA_SIZE = 0xF0000000;
 | 
			
		||||
 | 
			
		||||
static FileSys::VirtualDir GetDirectoryRelativeWrapped(FileSys::VirtualDir base,
 | 
			
		||||
                                                       std::string_view dir_name_) {
 | 
			
		||||
    std::string dir_name(FileUtil::SanitizePath(dir_name_));
 | 
			
		||||
@ -341,6 +350,44 @@ ResultVal<FileSys::VirtualDir> OpenSDMC() {
 | 
			
		||||
    return sdmc_factory->Open();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
FileSys::SaveDataSize ReadSaveDataSize(FileSys::SaveDataType type, u64 title_id, u128 user_id) {
 | 
			
		||||
    if (save_data_factory == nullptr) {
 | 
			
		||||
        return {0, 0};
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    const auto value = save_data_factory->ReadSaveDataSize(type, title_id, user_id);
 | 
			
		||||
 | 
			
		||||
    if (value.normal == 0 && value.journal == 0) {
 | 
			
		||||
        FileSys::SaveDataSize new_size{SUFFICIENT_SAVE_DATA_SIZE, SUFFICIENT_SAVE_DATA_SIZE};
 | 
			
		||||
 | 
			
		||||
        FileSys::NACP nacp;
 | 
			
		||||
        const auto res = Core::System::GetInstance().GetAppLoader().ReadControlData(nacp);
 | 
			
		||||
 | 
			
		||||
        if (res != Loader::ResultStatus::Success) {
 | 
			
		||||
            FileSys::PatchManager pm{Core::CurrentProcess()->GetTitleID()};
 | 
			
		||||
            auto [nacp_unique, discard] = pm.GetControlMetadata();
 | 
			
		||||
 | 
			
		||||
            if (nacp_unique != nullptr) {
 | 
			
		||||
                new_size = {nacp_unique->GetDefaultNormalSaveSize(),
 | 
			
		||||
                            nacp_unique->GetDefaultJournalSaveSize()};
 | 
			
		||||
            }
 | 
			
		||||
        } else {
 | 
			
		||||
            new_size = {nacp.GetDefaultNormalSaveSize(), nacp.GetDefaultJournalSaveSize()};
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        WriteSaveDataSize(type, title_id, user_id, new_size);
 | 
			
		||||
        return new_size;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    return value;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void WriteSaveDataSize(FileSys::SaveDataType type, u64 title_id, u128 user_id,
 | 
			
		||||
                       FileSys::SaveDataSize new_value) {
 | 
			
		||||
    if (save_data_factory != nullptr)
 | 
			
		||||
        save_data_factory->WriteSaveDataSize(type, title_id, user_id, new_value);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
FileSys::RegisteredCacheUnion GetUnionContents() {
 | 
			
		||||
    return FileSys::RegisteredCacheUnion{
 | 
			
		||||
        {GetSystemNANDContents(), GetUserNANDContents(), GetSDMCContents()}};
 | 
			
		||||
 | 
			
		||||
@ -21,9 +21,11 @@ class SDMCFactory;
 | 
			
		||||
enum class ContentRecordType : u8;
 | 
			
		||||
enum class Mode : u32;
 | 
			
		||||
enum class SaveDataSpaceId : u8;
 | 
			
		||||
enum class SaveDataType : u8;
 | 
			
		||||
enum class StorageId : u8;
 | 
			
		||||
 | 
			
		||||
struct SaveDataDescriptor;
 | 
			
		||||
struct SaveDataSize;
 | 
			
		||||
} // namespace FileSys
 | 
			
		||||
 | 
			
		||||
namespace Service {
 | 
			
		||||
@ -48,6 +50,10 @@ ResultVal<FileSys::VirtualDir> OpenSaveData(FileSys::SaveDataSpaceId space,
 | 
			
		||||
ResultVal<FileSys::VirtualDir> OpenSaveDataSpace(FileSys::SaveDataSpaceId space);
 | 
			
		||||
ResultVal<FileSys::VirtualDir> OpenSDMC();
 | 
			
		||||
 | 
			
		||||
FileSys::SaveDataSize ReadSaveDataSize(FileSys::SaveDataType type, u64 title_id, u128 user_id);
 | 
			
		||||
void WriteSaveDataSize(FileSys::SaveDataType type, u64 title_id, u128 user_id,
 | 
			
		||||
                       FileSys::SaveDataSize new_value);
 | 
			
		||||
 | 
			
		||||
FileSys::RegisteredCacheUnion GetUnionContents();
 | 
			
		||||
 | 
			
		||||
FileSys::RegisteredCache* GetSystemNANDContents();
 | 
			
		||||
 | 
			
		||||
@ -15,6 +15,10 @@
 | 
			
		||||
#include "core/file_sys/control_metadata.h"
 | 
			
		||||
#include "core/file_sys/vfs.h"
 | 
			
		||||
 | 
			
		||||
namespace FileSys {
 | 
			
		||||
class NACP;
 | 
			
		||||
} // namespace FileSys
 | 
			
		||||
 | 
			
		||||
namespace Kernel {
 | 
			
		||||
struct AddressMapping;
 | 
			
		||||
class Process;
 | 
			
		||||
@ -245,11 +249,11 @@ public:
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Get the developer of the application
 | 
			
		||||
     * @param developer Reference to store the application developer into
 | 
			
		||||
     * Get the control data (CNMT) of the application
 | 
			
		||||
     * @param control Reference to store the application control data into
 | 
			
		||||
     * @return ResultStatus result of function
 | 
			
		||||
     */
 | 
			
		||||
    virtual ResultStatus ReadDeveloper(std::string& developer) {
 | 
			
		||||
    virtual ResultStatus ReadControlData(FileSys::NACP& control) {
 | 
			
		||||
        return ResultStatus::ErrorNotImplemented;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@ -152,10 +152,10 @@ ResultStatus AppLoader_NSP::ReadTitle(std::string& title) {
 | 
			
		||||
    return ResultStatus::Success;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
ResultStatus AppLoader_NSP::ReadDeveloper(std::string& developer) {
 | 
			
		||||
ResultStatus AppLoader_NSP::ReadControlData(FileSys::NACP& nacp) {
 | 
			
		||||
    if (nacp_file == nullptr)
 | 
			
		||||
        return ResultStatus::ErrorNoControl;
 | 
			
		||||
    developer = nacp_file->GetDeveloperName();
 | 
			
		||||
    nacp = *nacp_file;
 | 
			
		||||
    return ResultStatus::Success;
 | 
			
		||||
}
 | 
			
		||||
} // namespace Loader
 | 
			
		||||
 | 
			
		||||
@ -43,7 +43,7 @@ public:
 | 
			
		||||
    ResultStatus ReadProgramId(u64& out_program_id) override;
 | 
			
		||||
    ResultStatus ReadIcon(std::vector<u8>& buffer) override;
 | 
			
		||||
    ResultStatus ReadTitle(std::string& title) override;
 | 
			
		||||
    ResultStatus ReadDeveloper(std::string& developer) override;
 | 
			
		||||
    ResultStatus ReadControlData(FileSys::NACP& nacp) override;
 | 
			
		||||
 | 
			
		||||
private:
 | 
			
		||||
    std::unique_ptr<FileSys::NSP> nsp;
 | 
			
		||||
 | 
			
		||||
@ -121,10 +121,11 @@ ResultStatus AppLoader_XCI::ReadTitle(std::string& title) {
 | 
			
		||||
    return ResultStatus::Success;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
ResultStatus AppLoader_XCI::ReadDeveloper(std::string& developer) {
 | 
			
		||||
ResultStatus AppLoader_XCI::ReadControlData(FileSys::NACP& control) {
 | 
			
		||||
    if (nacp_file == nullptr)
 | 
			
		||||
        return ResultStatus::ErrorNoControl;
 | 
			
		||||
    developer = nacp_file->GetDeveloperName();
 | 
			
		||||
    control = *nacp_file;
 | 
			
		||||
    return ResultStatus::Success;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
} // namespace Loader
 | 
			
		||||
 | 
			
		||||
@ -43,7 +43,7 @@ public:
 | 
			
		||||
    ResultStatus ReadProgramId(u64& out_program_id) override;
 | 
			
		||||
    ResultStatus ReadIcon(std::vector<u8>& buffer) override;
 | 
			
		||||
    ResultStatus ReadTitle(std::string& title) override;
 | 
			
		||||
    ResultStatus ReadDeveloper(std::string& developer) override;
 | 
			
		||||
    ResultStatus ReadControlData(FileSys::NACP& control) override;
 | 
			
		||||
 | 
			
		||||
private:
 | 
			
		||||
    std::unique_ptr<FileSys::XCI> xci;
 | 
			
		||||
 | 
			
		||||
@ -108,9 +108,9 @@ void ConfigurePerGameGeneral::loadConfiguration() {
 | 
			
		||||
        if (loader->ReadTitle(title) == Loader::ResultStatus::Success)
 | 
			
		||||
            ui->display_name->setText(QString::fromStdString(title));
 | 
			
		||||
 | 
			
		||||
        std::string developer;
 | 
			
		||||
        if (loader->ReadDeveloper(developer) == Loader::ResultStatus::Success)
 | 
			
		||||
            ui->display_developer->setText(QString::fromStdString(developer));
 | 
			
		||||
        FileSys::NACP nacp;
 | 
			
		||||
        if (loader->ReadControlData(nacp) == Loader::ResultStatus::Success)
 | 
			
		||||
            ui->display_developer->setText(QString::fromStdString(nacp.GetDeveloperName()));
 | 
			
		||||
 | 
			
		||||
        ui->display_version->setText(QStringLiteral("1.0.0"));
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
		Loading…
	
		Reference in New Issue
	
	Block a user