forked from eden-emu/eden
[fs, qlaunch] add CreateSaveDataFileSystemWithCreationInfo2 and make qlaunch work again (#2760)
Fixes qlaunch regression I introduced previously. Add a few known structs. Adds CreateSaveDataFileSystemWithCreationInfo2, which is called when games are started via qlaunch and corrupts save files. Reviewed-on: eden-emu/eden#2760 Reviewed-by: crueter <crueter@eden-emu.dev> Reviewed-by: MaranBr <maranbr@eden-emu.dev> Co-authored-by: unknown <sahyno1996@gmail.com> Co-committed-by: unknown <sahyno1996@gmail.com>
This commit is contained in:
parent
3e8fe622a7
commit
de46b8e817
13 changed files with 221 additions and 79 deletions
|
@ -1,3 +1,6 @@
|
||||||
|
// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project
|
||||||
|
// SPDX-License-Identifier: GPL-3.0-or-later
|
||||||
|
|
||||||
// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project
|
// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project
|
||||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||||
|
|
||||||
|
@ -68,6 +71,11 @@ enum class SaveDataMetaType : u8 {
|
||||||
ExtensionContext = 2,
|
ExtensionContext = 2,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
enum class SaveDataFormatType : u8 {
|
||||||
|
Normal = 0,
|
||||||
|
NoJournal = 1,
|
||||||
|
};
|
||||||
|
|
||||||
struct SaveDataMetaInfo {
|
struct SaveDataMetaInfo {
|
||||||
u32 size;
|
u32 size;
|
||||||
SaveDataMetaType type;
|
SaveDataMetaType type;
|
||||||
|
@ -185,4 +193,31 @@ struct HashSalt {
|
||||||
static_assert(std::is_trivially_copyable_v<HashSalt>, "Data type must be trivially copyable.");
|
static_assert(std::is_trivially_copyable_v<HashSalt>, "Data type must be trivially copyable.");
|
||||||
static_assert(sizeof(HashSalt) == HashSalt::Size);
|
static_assert(sizeof(HashSalt) == HashSalt::Size);
|
||||||
|
|
||||||
|
struct SaveDataCreationInfo2 {
|
||||||
|
|
||||||
|
static constexpr u32 SaveDataCreationInfo2Version = 0x00010000;
|
||||||
|
|
||||||
|
u32 version;
|
||||||
|
SaveDataAttribute attribute;
|
||||||
|
s64 size;
|
||||||
|
s64 journal_size;
|
||||||
|
s64 block_size;
|
||||||
|
u64 owner_id;
|
||||||
|
u32 flags;
|
||||||
|
SaveDataSpaceId space_id;
|
||||||
|
SaveDataFormatType format_type;
|
||||||
|
bool pseudo;
|
||||||
|
u8 reserved1;
|
||||||
|
bool is_hash_salt_enabled;
|
||||||
|
u8 reserved2;
|
||||||
|
HashSalt hash_salt;
|
||||||
|
SaveDataMetaType meta_type;
|
||||||
|
u8 reserved3;
|
||||||
|
s32 meta_size;
|
||||||
|
u8 reserved4;
|
||||||
|
};
|
||||||
|
static_assert(std::is_trivially_copyable_v<SaveDataCreationInfo2>,
|
||||||
|
"Data type must be trivially copyable.");
|
||||||
|
static_assert(sizeof(SaveDataCreationInfo2) == 0xA0, "SaveDataCreationInfo has invalid size.");
|
||||||
|
|
||||||
} // namespace FileSys
|
} // namespace FileSys
|
||||||
|
|
|
@ -1,3 +1,6 @@
|
||||||
|
// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project
|
||||||
|
// SPDX-License-Identifier: GPL-3.0-or-later
|
||||||
|
|
||||||
// SPDX-FileCopyrightText: Copyright 2018 yuzu Emulator Project
|
// SPDX-FileCopyrightText: Copyright 2018 yuzu Emulator Project
|
||||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||||
|
|
||||||
|
@ -76,6 +79,7 @@ FSP_SRV::FSP_SRV(Core::System& system_)
|
||||||
{34, D<&FSP_SRV::GetCacheStorageSize>, "GetCacheStorageSize"},
|
{34, D<&FSP_SRV::GetCacheStorageSize>, "GetCacheStorageSize"},
|
||||||
{35, nullptr, "CreateSaveDataFileSystemByHashSalt"},
|
{35, nullptr, "CreateSaveDataFileSystemByHashSalt"},
|
||||||
{36, nullptr, "OpenHostFileSystemWithOption"},
|
{36, nullptr, "OpenHostFileSystemWithOption"},
|
||||||
|
{37, D<&FSP_SRV::CreateSaveDataFileSystemWithCreationInfo2>, "CreateSaveDataFileSystemWithCreationInfo2"},
|
||||||
{51, D<&FSP_SRV::OpenSaveDataFileSystem>, "OpenSaveDataFileSystem"},
|
{51, D<&FSP_SRV::OpenSaveDataFileSystem>, "OpenSaveDataFileSystem"},
|
||||||
{52, D<&FSP_SRV::OpenSaveDataFileSystemBySystemSaveDataId>, "OpenSaveDataFileSystemBySystemSaveDataId"},
|
{52, D<&FSP_SRV::OpenSaveDataFileSystemBySystemSaveDataId>, "OpenSaveDataFileSystemBySystemSaveDataId"},
|
||||||
{53, D<&FSP_SRV::OpenReadOnlySaveDataFileSystem>, "OpenReadOnlySaveDataFileSystem"},
|
{53, D<&FSP_SRV::OpenReadOnlySaveDataFileSystem>, "OpenReadOnlySaveDataFileSystem"},
|
||||||
|
@ -244,6 +248,13 @@ Result FSP_SRV::CreateSaveDataFileSystemBySystemSaveDataId(
|
||||||
save_struct));
|
save_struct));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Result FSP_SRV::CreateSaveDataFileSystemWithCreationInfo2(
|
||||||
|
FileSys::SaveDataCreationInfo2 save_data_creation_info) {
|
||||||
|
FileSys::VirtualDir save_data_dir{};
|
||||||
|
R_RETURN(save_data_controller->CreateSaveData(&save_data_dir, save_data_creation_info.space_id,
|
||||||
|
save_data_creation_info.attribute));
|
||||||
|
}
|
||||||
|
|
||||||
Result FSP_SRV::IsExFatSupported(Out<bool> out_is_supported) {
|
Result FSP_SRV::IsExFatSupported(Out<bool> out_is_supported) {
|
||||||
LOG_WARNING(Service_FS, "(STUBBED) called");
|
LOG_WARNING(Service_FS, "(STUBBED) called");
|
||||||
|
|
||||||
|
|
|
@ -1,3 +1,6 @@
|
||||||
|
// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project
|
||||||
|
// SPDX-License-Identifier: GPL-3.0-or-later
|
||||||
|
|
||||||
// SPDX-FileCopyrightText: Copyright 2018 yuzu Emulator Project
|
// SPDX-FileCopyrightText: Copyright 2018 yuzu Emulator Project
|
||||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||||
|
|
||||||
|
@ -55,6 +58,8 @@ private:
|
||||||
FileSys::SaveDataAttribute save_struct, u128 uid);
|
FileSys::SaveDataAttribute save_struct, u128 uid);
|
||||||
Result CreateSaveDataFileSystemBySystemSaveDataId(
|
Result CreateSaveDataFileSystemBySystemSaveDataId(
|
||||||
FileSys::SaveDataAttribute save_struct, FileSys::SaveDataCreationInfo save_create_struct);
|
FileSys::SaveDataAttribute save_struct, FileSys::SaveDataCreationInfo save_create_struct);
|
||||||
|
Result CreateSaveDataFileSystemWithCreationInfo2(
|
||||||
|
FileSys::SaveDataCreationInfo2 save_data_creation_info);
|
||||||
Result IsExFatSupported(Out<bool> out_is_supported);
|
Result IsExFatSupported(Out<bool> out_is_supported);
|
||||||
Result OpenSaveDataFileSystem(OutInterface<IFileSystem> out_interface,
|
Result OpenSaveDataFileSystem(OutInterface<IFileSystem> out_interface,
|
||||||
FileSys::SaveDataSpaceId space_id,
|
FileSys::SaveDataSpaceId space_id,
|
||||||
|
|
|
@ -1,3 +1,6 @@
|
||||||
|
// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project
|
||||||
|
// SPDX-License-Identifier: GPL-3.0-or-later
|
||||||
|
|
||||||
// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project
|
// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project
|
||||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||||
|
|
||||||
|
|
|
@ -206,12 +206,12 @@ IApplicationManagerInterface::IApplicationManagerInterface(Core::System& system_
|
||||||
{1600, nullptr, "GetSystemSeedForPseudoDeviceId"},
|
{1600, nullptr, "GetSystemSeedForPseudoDeviceId"},
|
||||||
{1601, nullptr, "ResetSystemSeedForPseudoDeviceId"},
|
{1601, nullptr, "ResetSystemSeedForPseudoDeviceId"},
|
||||||
{1700, nullptr, "ListApplicationDownloadingContentMeta"},
|
{1700, nullptr, "ListApplicationDownloadingContentMeta"},
|
||||||
{1701, D<&IApplicationManagerInterface::GetApplicationView>, "GetApplicationView"},
|
{1701, D<&IApplicationManagerInterface::GetApplicationViewDeprecated>, "GetApplicationViewDeprecated"},
|
||||||
{1702, nullptr, "GetApplicationDownloadTaskStatus"},
|
{1702, nullptr, "GetApplicationDownloadTaskStatus"},
|
||||||
{1703, nullptr, "GetApplicationViewDownloadErrorContext"},
|
{1703, nullptr, "GetApplicationViewDownloadErrorContext"},
|
||||||
{1704, D<&IApplicationManagerInterface::GetApplicationViewWithPromotionInfo>, "GetApplicationViewWithPromotionInfo"},
|
{1704, D<&IApplicationManagerInterface::GetApplicationViewWithPromotionInfo>, "GetApplicationViewWithPromotionInfo"},
|
||||||
{1705, nullptr, "IsPatchAutoDeletableApplication"},
|
{1705, nullptr, "IsPatchAutoDeletableApplication"},
|
||||||
{1706, D<&IApplicationManagerInterface::Unknown1706>, "Unknown1706"},
|
{1706, D<&IApplicationManagerInterface::GetApplicationView>, "GetApplicationView"},
|
||||||
{1800, nullptr, "IsNotificationSetupCompleted"},
|
{1800, nullptr, "IsNotificationSetupCompleted"},
|
||||||
{1801, nullptr, "GetLastNotificationInfoCount"},
|
{1801, nullptr, "GetLastNotificationInfoCount"},
|
||||||
{1802, nullptr, "ListLastNotificationInfo"},
|
{1802, nullptr, "ListLastNotificationInfo"},
|
||||||
|
@ -329,7 +329,7 @@ Result IApplicationManagerInterface::GetApplicationControlData(
|
||||||
OutBuffer<BufferAttr_HipcMapAlias> out_buffer, Out<u32> out_actual_size,
|
OutBuffer<BufferAttr_HipcMapAlias> out_buffer, Out<u32> out_actual_size,
|
||||||
ApplicationControlSource application_control_source, u64 application_id) {
|
ApplicationControlSource application_control_source, u64 application_id) {
|
||||||
LOG_DEBUG(Service_NS, "called");
|
LOG_DEBUG(Service_NS, "called");
|
||||||
R_RETURN(IReadOnlyApplicationControlDataInterface(system).GetApplicationControlData(
|
R_RETURN(IReadOnlyApplicationControlDataInterface(system).GetApplicationControlDataOld(
|
||||||
out_buffer, out_actual_size, application_control_source, application_id));
|
out_buffer, out_actual_size, application_control_source, application_id));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -410,7 +410,7 @@ Result IApplicationManagerInterface::IsAnyApplicationEntityInstalled(
|
||||||
R_SUCCEED();
|
R_SUCCEED();
|
||||||
}
|
}
|
||||||
|
|
||||||
Result IApplicationManagerInterface::GetApplicationView(
|
Result IApplicationManagerInterface::GetApplicationViewDeprecated(
|
||||||
OutArray<ApplicationView, BufferAttr_HipcMapAlias> out_application_views,
|
OutArray<ApplicationView, BufferAttr_HipcMapAlias> out_application_views,
|
||||||
InArray<u64, BufferAttr_HipcMapAlias> application_ids) {
|
InArray<u64, BufferAttr_HipcMapAlias> application_ids) {
|
||||||
const auto size = (std::min)(out_application_views.size(), application_ids.size());
|
const auto size = (std::min)(out_application_views.size(), application_ids.size());
|
||||||
|
@ -419,7 +419,7 @@ Result IApplicationManagerInterface::GetApplicationView(
|
||||||
for (size_t i = 0; i < size; i++) {
|
for (size_t i = 0; i < size; i++) {
|
||||||
ApplicationView view{};
|
ApplicationView view{};
|
||||||
view.application_id = application_ids[i];
|
view.application_id = application_ids[i];
|
||||||
view.unk = 0x70000;
|
view.version = 0x70000;
|
||||||
view.flags = 0x401f17;
|
view.flags = 0x401f17;
|
||||||
|
|
||||||
out_application_views[i] = view;
|
out_application_views[i] = view;
|
||||||
|
@ -437,7 +437,7 @@ Result IApplicationManagerInterface::GetApplicationViewWithPromotionInfo(
|
||||||
for (size_t i = 0; i < size; i++) {
|
for (size_t i = 0; i < size; i++) {
|
||||||
ApplicationViewWithPromotionInfo view{};
|
ApplicationViewWithPromotionInfo view{};
|
||||||
view.view.application_id = application_ids[i];
|
view.view.application_id = application_ids[i];
|
||||||
view.view.unk = 0x70000;
|
view.view.version = 0x70000;
|
||||||
view.view.flags = 0x401f17;
|
view.view.flags = 0x401f17;
|
||||||
view.promotion = {};
|
view.promotion = {};
|
||||||
|
|
||||||
|
@ -447,6 +447,24 @@ Result IApplicationManagerInterface::GetApplicationViewWithPromotionInfo(
|
||||||
R_SUCCEED();
|
R_SUCCEED();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Result IApplicationManagerInterface::GetApplicationView(
|
||||||
|
OutArray<ApplicationView, BufferAttr_HipcMapAlias> out_application_views,
|
||||||
|
InArray<u64, BufferAttr_HipcMapAlias> application_ids) {
|
||||||
|
const auto size = (std::min)(out_application_views.size(), application_ids.size());
|
||||||
|
LOG_WARNING(Service_NS, "(STUBBED) called, size={}", application_ids.size());
|
||||||
|
|
||||||
|
for (size_t i = 0; i < size; i++) {
|
||||||
|
ApplicationView view{};
|
||||||
|
view.application_id = application_ids[i];
|
||||||
|
view.version = 0x70000;
|
||||||
|
view.flags = 0x401f17;
|
||||||
|
|
||||||
|
out_application_views[i] = view;
|
||||||
|
}
|
||||||
|
|
||||||
|
R_SUCCEED();
|
||||||
|
}
|
||||||
|
|
||||||
Result IApplicationManagerInterface::GetApplicationRightsOnClient(
|
Result IApplicationManagerInterface::GetApplicationRightsOnClient(
|
||||||
OutArray<ApplicationRightsOnClient, BufferAttr_HipcMapAlias> out_rights, Out<u32> out_count,
|
OutArray<ApplicationRightsOnClient, BufferAttr_HipcMapAlias> out_rights, Out<u32> out_count,
|
||||||
u32 flags, u64 application_id, Uid account_id) {
|
u32 flags, u64 application_id, Uid account_id) {
|
||||||
|
@ -535,31 +553,6 @@ Result IApplicationManagerInterface::RequestDownloadApplicationControlDataInBack
|
||||||
R_SUCCEED();
|
R_SUCCEED();
|
||||||
}
|
}
|
||||||
|
|
||||||
Result IApplicationManagerInterface::Unknown1706(
|
|
||||||
OutBuffer<BufferAttr_HipcAutoSelect> out_buffer_58,
|
|
||||||
InBuffer<BufferAttr_HipcMapAlias> in_buffer_8) {
|
|
||||||
LOG_WARNING(Service_NS, "(STUBBED) Unknown1706 called: out_size={} in_size={}",
|
|
||||||
out_buffer_58.size(), in_buffer_8.size());
|
|
||||||
|
|
||||||
if (out_buffer_58.size() < 0x58 || in_buffer_8.size() < 0x8) {
|
|
||||||
R_THROW(ResultUnknown);
|
|
||||||
}
|
|
||||||
|
|
||||||
u64 application_id = 0;
|
|
||||||
std::memcpy(&application_id, in_buffer_8.data(), sizeof(u64));
|
|
||||||
|
|
||||||
ApplicationView view{};
|
|
||||||
view.application_id = application_id;
|
|
||||||
view.unk = 0x70000;
|
|
||||||
view.flags = 0x401f17;
|
|
||||||
|
|
||||||
std::memset(out_buffer_58.data(), 0, out_buffer_58.size());
|
|
||||||
std::memcpy(out_buffer_58.data(), &view, sizeof(ApplicationView));
|
|
||||||
|
|
||||||
|
|
||||||
R_SUCCEED();
|
|
||||||
}
|
|
||||||
|
|
||||||
Result IApplicationManagerInterface::Unknown4022(
|
Result IApplicationManagerInterface::Unknown4022(
|
||||||
OutCopyHandle<Kernel::KReadableEvent> out_event) {
|
OutCopyHandle<Kernel::KReadableEvent> out_event) {
|
||||||
LOG_WARNING(Service_NS, "(STUBBED) called");
|
LOG_WARNING(Service_NS, "(STUBBED) called");
|
||||||
|
|
|
@ -33,12 +33,15 @@ public:
|
||||||
Result GetApplicationRecordUpdateSystemEvent(OutCopyHandle<Kernel::KReadableEvent> out_event);
|
Result GetApplicationRecordUpdateSystemEvent(OutCopyHandle<Kernel::KReadableEvent> out_event);
|
||||||
Result GetGameCardMountFailureEvent(OutCopyHandle<Kernel::KReadableEvent> out_event);
|
Result GetGameCardMountFailureEvent(OutCopyHandle<Kernel::KReadableEvent> out_event);
|
||||||
Result IsAnyApplicationEntityInstalled(Out<bool> out_is_any_application_entity_installed);
|
Result IsAnyApplicationEntityInstalled(Out<bool> out_is_any_application_entity_installed);
|
||||||
Result GetApplicationView(
|
Result GetApplicationViewDeprecated(
|
||||||
OutArray<ApplicationView, BufferAttr_HipcMapAlias> out_application_views,
|
OutArray<ApplicationView, BufferAttr_HipcMapAlias> out_application_views,
|
||||||
InArray<u64, BufferAttr_HipcMapAlias> application_ids);
|
InArray<u64, BufferAttr_HipcMapAlias> application_ids);
|
||||||
Result GetApplicationViewWithPromotionInfo(
|
Result GetApplicationViewWithPromotionInfo(
|
||||||
OutArray<ApplicationViewWithPromotionInfo, BufferAttr_HipcMapAlias> out_application_views,
|
OutArray<ApplicationViewWithPromotionInfo, BufferAttr_HipcMapAlias> out_application_views,
|
||||||
InArray<u64, BufferAttr_HipcMapAlias> application_ids);
|
InArray<u64, BufferAttr_HipcMapAlias> application_ids);
|
||||||
|
Result GetApplicationView(
|
||||||
|
OutArray<ApplicationView, BufferAttr_HipcMapAlias> out_application_views,
|
||||||
|
InArray<u64, BufferAttr_HipcMapAlias> application_ids);
|
||||||
Result GetApplicationRightsOnClient(
|
Result GetApplicationRightsOnClient(
|
||||||
OutArray<ApplicationRightsOnClient, BufferAttr_HipcMapAlias> out_rights, Out<u32> out_count,
|
OutArray<ApplicationRightsOnClient, BufferAttr_HipcMapAlias> out_rights, Out<u32> out_count,
|
||||||
u32 flags, u64 application_id, Uid account_id);
|
u32 flags, u64 application_id, Uid account_id);
|
||||||
|
@ -59,8 +62,6 @@ public:
|
||||||
|
|
||||||
Result RequestDownloadApplicationControlDataInBackground(u64 unk,
|
Result RequestDownloadApplicationControlDataInBackground(u64 unk,
|
||||||
u64 application_id);
|
u64 application_id);
|
||||||
Result Unknown1706(OutBuffer<BufferAttr_HipcAutoSelect> out_buffer_58,
|
|
||||||
InBuffer<BufferAttr_HipcMapAlias> in_buffer_8);
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
KernelHelpers::ServiceContext service_context;
|
KernelHelpers::ServiceContext service_context;
|
||||||
|
|
|
@ -42,20 +42,26 @@ struct ApplicationRecord {
|
||||||
};
|
};
|
||||||
static_assert(sizeof(ApplicationRecord) == 0x18, "ApplicationRecord has incorrect size.");
|
static_assert(sizeof(ApplicationRecord) == 0x18, "ApplicationRecord has incorrect size.");
|
||||||
|
|
||||||
|
/// ApplicationDownloadState
|
||||||
|
struct ApplicationDownloadState {
|
||||||
|
u64 downloaded_size;
|
||||||
|
u64 total_size;
|
||||||
|
u32 unk_x10;
|
||||||
|
u8 state;
|
||||||
|
u8 unk_x19;
|
||||||
|
std::array<u8, 0x2> unk_x1a;
|
||||||
|
u64 unk_x20;
|
||||||
|
};
|
||||||
|
static_assert(sizeof(ApplicationDownloadState) == 0x20,
|
||||||
|
"ApplicationDownloadState has incorrect size.");
|
||||||
|
|
||||||
/// ApplicationView
|
/// ApplicationView
|
||||||
struct ApplicationView {
|
struct ApplicationView {
|
||||||
u64 application_id; ///< ApplicationId.
|
u64 application_id; ///< ApplicationId.
|
||||||
u32 unk; ///< Unknown.
|
u32 version; ///< Application Version(?)
|
||||||
u32 flags; ///< Flags.
|
u32 flags; ///< Flags.
|
||||||
std::array<u8, 0x10> unk_x10; ///< Unknown.
|
ApplicationDownloadState download_state; ///< \ref ApplicationDownloadState
|
||||||
u32 unk_x20; ///< Unknown.
|
ApplicationDownloadState download_progress; ///< \ref ApplicationDownloadState
|
||||||
u16 unk_x24; ///< Unknown.
|
|
||||||
std::array<u8, 0x2> unk_x26; ///< Unknown.
|
|
||||||
std::array<u8, 0x8> unk_x28; ///< Unknown.
|
|
||||||
std::array<u8, 0x10> unk_x30; ///< Unknown.
|
|
||||||
u32 unk_x40; ///< Unknown.
|
|
||||||
u8 unk_x44; ///< Unknown.
|
|
||||||
std::array<u8, 0xb> unk_x45; ///< Unknown.
|
|
||||||
};
|
};
|
||||||
static_assert(sizeof(ApplicationView) == 0x50, "ApplicationView has incorrect size.");
|
static_assert(sizeof(ApplicationView) == 0x50, "ApplicationView has incorrect size.");
|
||||||
|
|
||||||
|
@ -82,13 +88,13 @@ struct PromotionInfo {
|
||||||
};
|
};
|
||||||
static_assert(sizeof(PromotionInfo) == 0x20, "PromotionInfo has incorrect size.");
|
static_assert(sizeof(PromotionInfo) == 0x20, "PromotionInfo has incorrect size.");
|
||||||
|
|
||||||
|
// TODO(Maufeat): NsApplicationViewWithPromotionInfo is on SDK20+ 0x78 bytes
|
||||||
/// NsApplicationViewWithPromotionInfo
|
/// NsApplicationViewWithPromotionInfo
|
||||||
struct ApplicationViewWithPromotionInfo {
|
struct ApplicationViewWithPromotionInfo {
|
||||||
ApplicationView view; ///< \ref NsApplicationView
|
ApplicationView view; ///< \ref NsApplicationView
|
||||||
PromotionInfo promotion; ///< \ref NsPromotionInfo
|
PromotionInfo promotion; ///< \ref NsPromotionInfo
|
||||||
std::array<u8, 0x8> padding{}; ///< Extra padding for newer HOS versions
|
|
||||||
};
|
};
|
||||||
static_assert(sizeof(ApplicationViewWithPromotionInfo) == 0x78,
|
static_assert(sizeof(ApplicationViewWithPromotionInfo) == 0x70,
|
||||||
"ApplicationViewWithPromotionInfo has incorrect size.");
|
"ApplicationViewWithPromotionInfo has incorrect size.");
|
||||||
|
|
||||||
struct ApplicationOccupiedSizeEntity {
|
struct ApplicationOccupiedSizeEntity {
|
||||||
|
|
|
@ -22,12 +22,12 @@ IReadOnlyApplicationControlDataInterface::IReadOnlyApplicationControlDataInterfa
|
||||||
: ServiceFramework{system_, "IReadOnlyApplicationControlDataInterface"} {
|
: ServiceFramework{system_, "IReadOnlyApplicationControlDataInterface"} {
|
||||||
// clang-format off
|
// clang-format off
|
||||||
static const FunctionInfo functions[] = {
|
static const FunctionInfo functions[] = {
|
||||||
{0, D<&IReadOnlyApplicationControlDataInterface::GetApplicationControlData>, "GetApplicationControlData"},
|
{0, D<&IReadOnlyApplicationControlDataInterface::GetApplicationControlDataOld>, "GetApplicationControlDataOld"},
|
||||||
{1, D<&IReadOnlyApplicationControlDataInterface::GetApplicationDesiredLanguage>, "GetApplicationDesiredLanguage"},
|
{1, D<&IReadOnlyApplicationControlDataInterface::GetApplicationDesiredLanguage>, "GetApplicationDesiredLanguage"},
|
||||||
{2, D<&IReadOnlyApplicationControlDataInterface::ConvertApplicationLanguageToLanguageCode>, "ConvertApplicationLanguageToLanguageCode"},
|
{2, D<&IReadOnlyApplicationControlDataInterface::ConvertApplicationLanguageToLanguageCode>, "ConvertApplicationLanguageToLanguageCode"},
|
||||||
{3, nullptr, "ConvertLanguageCodeToApplicationLanguage"},
|
{3, nullptr, "ConvertLanguageCodeToApplicationLanguage"},
|
||||||
{4, nullptr, "SelectApplicationDesiredLanguage"},
|
{4, nullptr, "SelectApplicationDesiredLanguage"},
|
||||||
{5, D<&IReadOnlyApplicationControlDataInterface::GetApplicationDisplayData>, "GetApplicationDisplayData"},
|
{5, D<&IReadOnlyApplicationControlDataInterface::GetApplicationControlDataWithIconSize>, "GetApplicationControlDataWithIconSize"},
|
||||||
};
|
};
|
||||||
// clang-format on
|
// clang-format on
|
||||||
|
|
||||||
|
@ -36,7 +36,7 @@ IReadOnlyApplicationControlDataInterface::IReadOnlyApplicationControlDataInterfa
|
||||||
|
|
||||||
IReadOnlyApplicationControlDataInterface::~IReadOnlyApplicationControlDataInterface() = default;
|
IReadOnlyApplicationControlDataInterface::~IReadOnlyApplicationControlDataInterface() = default;
|
||||||
|
|
||||||
Result IReadOnlyApplicationControlDataInterface::GetApplicationControlData(
|
Result IReadOnlyApplicationControlDataInterface::GetApplicationControlDataOld(
|
||||||
OutBuffer<BufferAttr_HipcMapAlias> out_buffer, Out<u32> out_actual_size,
|
OutBuffer<BufferAttr_HipcMapAlias> out_buffer, Out<u32> out_actual_size,
|
||||||
ApplicationControlSource application_control_source, u64 application_id) {
|
ApplicationControlSource application_control_source, u64 application_id) {
|
||||||
LOG_INFO(Service_NS, "called with control_source={}, application_id={:016X}",
|
LOG_INFO(Service_NS, "called with control_source={}, application_id={:016X}",
|
||||||
|
@ -124,32 +124,87 @@ Result IReadOnlyApplicationControlDataInterface::ConvertApplicationLanguageToLan
|
||||||
R_SUCCEED();
|
R_SUCCEED();
|
||||||
}
|
}
|
||||||
|
|
||||||
Result IReadOnlyApplicationControlDataInterface::GetApplicationDisplayData(
|
Result IReadOnlyApplicationControlDataInterface::GetApplicationControlData(
|
||||||
OutBuffer<BufferAttr_HipcMapAlias> out_buffer, Out<u64> out_size, u64 language_code,
|
OutBuffer<BufferAttr_HipcMapAlias> out_buffer, Out<u32> out_actual_size,
|
||||||
u64 application_id) {
|
ApplicationControlSource application_control_source, u64 application_id) {
|
||||||
LOG_INFO(Service_NS, "called with application_id={:016X}, language_code={:016X}",
|
LOG_INFO(Service_NS, "called with control_source={}, application_id={:016X}",
|
||||||
application_id, language_code);
|
application_control_source, application_id);
|
||||||
|
|
||||||
constexpr u64 payload_size = sizeof(ApplicationDisplayData);
|
|
||||||
|
|
||||||
if (out_buffer.size() < payload_size) {
|
|
||||||
LOG_ERROR(Service_NS, "output buffer is too small! (actual={}, expected_min={})",
|
|
||||||
out_buffer.size(), payload_size);
|
|
||||||
R_THROW(ResultUnknown);
|
|
||||||
}
|
|
||||||
|
|
||||||
const FileSys::PatchManager pm{application_id, system.GetFileSystemController(),
|
const FileSys::PatchManager pm{application_id, system.GetFileSystemController(),
|
||||||
system.GetContentProvider()};
|
system.GetContentProvider()};
|
||||||
const auto control = pm.GetControlMetadata();
|
const auto control = pm.GetControlMetadata();
|
||||||
|
const auto size = out_buffer.size();
|
||||||
|
|
||||||
ApplicationDisplayData display_data{};
|
const auto icon_size = control.second ? control.second->GetSize() : 0;
|
||||||
|
const auto total_size = sizeof(FileSys::RawNACP) + icon_size;
|
||||||
|
|
||||||
std::memset(display_data.application_name.data(), 0, display_data.application_name.size());
|
if (size < total_size) {
|
||||||
std::memset(display_data.developer_name.data(), 0, display_data.developer_name.size());
|
LOG_ERROR(Service_NS, "output buffer is too small! (actual={:016X}, expected_min=0x4000)",
|
||||||
|
size);
|
||||||
|
R_THROW(ResultUnknown);
|
||||||
|
}
|
||||||
|
|
||||||
std::memcpy(out_buffer.data(), &display_data, payload_size);
|
if (control.first != nullptr) {
|
||||||
*out_size = payload_size;
|
const auto bytes = control.first->GetRawBytes();
|
||||||
|
std::memcpy(out_buffer.data(), bytes.data(), bytes.size());
|
||||||
|
} else {
|
||||||
|
LOG_WARNING(Service_NS, "missing NACP data for application_id={:016X}, defaulting to zero",
|
||||||
|
application_id);
|
||||||
|
std::memset(out_buffer.data(), 0, sizeof(FileSys::RawNACP));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (control.second != nullptr) {
|
||||||
|
control.second->Read(out_buffer.data() + sizeof(FileSys::RawNACP), icon_size);
|
||||||
|
} else {
|
||||||
|
LOG_WARNING(Service_NS, "missing icon data for application_id={:016X}", application_id);
|
||||||
|
}
|
||||||
|
|
||||||
|
*out_actual_size = static_cast<u32>(total_size);
|
||||||
|
R_SUCCEED();
|
||||||
|
}
|
||||||
|
|
||||||
|
Result IReadOnlyApplicationControlDataInterface::GetApplicationControlDataWithIconSize(
|
||||||
|
OutBuffer<BufferAttr_HipcMapAlias> out_buffer,
|
||||||
|
Out<u64> out_total_size,
|
||||||
|
ApplicationControlSource application_control_source,
|
||||||
|
u64 application_id) {
|
||||||
|
LOG_INFO(Service_NS, "called with control_source={}, application_id={:016X}",
|
||||||
|
application_control_source, application_id);
|
||||||
|
|
||||||
|
constexpr size_t kExpectedBufferSize = 0x14000;
|
||||||
|
constexpr size_t kNACPSize = sizeof(FileSys::RawNACP);
|
||||||
|
constexpr size_t kMaxIconSize = kExpectedBufferSize - kNACPSize;
|
||||||
|
|
||||||
|
const FileSys::PatchManager pm{application_id, system.GetFileSystemController(),
|
||||||
|
system.GetContentProvider()};
|
||||||
|
const auto control = pm.GetControlMetadata();
|
||||||
|
const auto size = out_buffer.size();
|
||||||
|
|
||||||
|
if (size < kExpectedBufferSize) {
|
||||||
|
LOG_ERROR(Service_NS, "output buffer is too small! (actual={:016X}, required={:016X})", size, kExpectedBufferSize);
|
||||||
|
R_THROW(ResultUnknown);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Copy NACP
|
||||||
|
if (control.first != nullptr) {
|
||||||
|
const auto bytes = control.first->GetRawBytes();
|
||||||
|
std::memcpy(out_buffer.data(), bytes.data(), bytes.size());
|
||||||
|
} else {
|
||||||
|
std::memset(out_buffer.data(), 0, kNACPSize);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Copy icon, pad with zeros if needed
|
||||||
|
size_t icon_size = control.second ? control.second->GetSize() : 0;
|
||||||
|
if (icon_size > kMaxIconSize) {
|
||||||
|
icon_size = kMaxIconSize; // Truncate if too large
|
||||||
|
}
|
||||||
|
if (control.second != nullptr && icon_size > 0) {
|
||||||
|
control.second->Read(out_buffer.data() + kNACPSize, icon_size);
|
||||||
|
} else {
|
||||||
|
std::memset(out_buffer.data() + kNACPSize, 0, kMaxIconSize);
|
||||||
|
}
|
||||||
|
|
||||||
|
*out_total_size = kExpectedBufferSize;
|
||||||
R_SUCCEED();
|
R_SUCCEED();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -19,7 +19,7 @@ public:
|
||||||
explicit IReadOnlyApplicationControlDataInterface(Core::System& system_);
|
explicit IReadOnlyApplicationControlDataInterface(Core::System& system_);
|
||||||
~IReadOnlyApplicationControlDataInterface() override;
|
~IReadOnlyApplicationControlDataInterface() override;
|
||||||
|
|
||||||
Result GetApplicationControlData(OutBuffer<BufferAttr_HipcMapAlias> out_buffer,
|
Result GetApplicationControlDataOld(OutBuffer<BufferAttr_HipcMapAlias> out_buffer,
|
||||||
Out<u32> out_actual_size,
|
Out<u32> out_actual_size,
|
||||||
ApplicationControlSource application_control_source,
|
ApplicationControlSource application_control_source,
|
||||||
u64 application_id);
|
u64 application_id);
|
||||||
|
@ -27,10 +27,15 @@ public:
|
||||||
u32 supported_languages);
|
u32 supported_languages);
|
||||||
Result ConvertApplicationLanguageToLanguageCode(Out<u64> out_language_code,
|
Result ConvertApplicationLanguageToLanguageCode(Out<u64> out_language_code,
|
||||||
ApplicationLanguage application_language);
|
ApplicationLanguage application_language);
|
||||||
|
Result GetApplicationControlData(OutBuffer<BufferAttr_HipcMapAlias> out_buffer,
|
||||||
Result GetApplicationDisplayData(OutBuffer<BufferAttr_HipcMapAlias> out_buffer,
|
Out<u32> out_actual_size,
|
||||||
Out<u64> out_size, u64 language_code,
|
ApplicationControlSource application_control_source,
|
||||||
u64 application_id);
|
u64 application_id);
|
||||||
|
Result GetApplicationControlDataWithIconSize(
|
||||||
|
OutBuffer<BufferAttr_HipcMapAlias> out_buffer,
|
||||||
|
Out<u64> out_total_size,
|
||||||
|
ApplicationControlSource application_control_source,
|
||||||
|
u64 application_id);
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace Service::NS
|
} // namespace Service::NS
|
||||||
|
|
|
@ -1,3 +1,6 @@
|
||||||
|
// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project
|
||||||
|
// SPDX-License-Identifier: GPL-3.0-or-later
|
||||||
|
|
||||||
// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project
|
// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project
|
||||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||||
|
|
||||||
|
@ -19,7 +22,7 @@ IDaemonController::IDaemonController(Core::System& system_)
|
||||||
{6, nullptr, "SetGlobalDownloadEnabledForAccount"},
|
{6, nullptr, "SetGlobalDownloadEnabledForAccount"},
|
||||||
{10, nullptr, "GetForbiddenSaveDataIndication"},
|
{10, nullptr, "GetForbiddenSaveDataIndication"},
|
||||||
{11, nullptr, "GetStopperObject"},
|
{11, nullptr, "GetStopperObject"},
|
||||||
{12, nullptr, "GetState"},
|
{12, D<&IDaemonController::GetState>, "GetState"},
|
||||||
};
|
};
|
||||||
// clang-format on
|
// clang-format on
|
||||||
|
|
||||||
|
@ -37,4 +40,11 @@ Result IDaemonController::GetAutoTransferEnabledForAccountAndApplication(Out<boo
|
||||||
R_SUCCEED();
|
R_SUCCEED();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Result IDaemonController::GetState(Out<u8> state, Common::UUID user_id, u64 application_id) {
|
||||||
|
LOG_WARNING(Service_OLSC, "(STUBBED) called, user_id={} application_id={:016X}",
|
||||||
|
user_id.FormattedString(), application_id);
|
||||||
|
*state = 0;
|
||||||
|
R_SUCCEED();
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace Service::OLSC
|
} // namespace Service::OLSC
|
||||||
|
|
|
@ -1,3 +1,6 @@
|
||||||
|
// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project
|
||||||
|
// SPDX-License-Identifier: GPL-3.0-or-later
|
||||||
|
|
||||||
// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project
|
// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project
|
||||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||||
|
|
||||||
|
@ -15,6 +18,7 @@ public:
|
||||||
private:
|
private:
|
||||||
Result GetAutoTransferEnabledForAccountAndApplication(Out<bool> out_is_enabled,
|
Result GetAutoTransferEnabledForAccountAndApplication(Out<bool> out_is_enabled,
|
||||||
Common::UUID user_id, u64 application_id);
|
Common::UUID user_id, u64 application_id);
|
||||||
|
Result GetState(Out<u8> state, Common::UUID user_id, u64 application_id);
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace Service::OLSC
|
} // namespace Service::OLSC
|
||||||
|
|
|
@ -1,3 +1,6 @@
|
||||||
|
// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project
|
||||||
|
// SPDX-License-Identifier: GPL-3.0-or-later
|
||||||
|
|
||||||
// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project
|
// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project
|
||||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||||
|
|
||||||
|
@ -100,10 +103,13 @@ Result IOlscServiceForSystemService::OpenDaemonController(
|
||||||
R_SUCCEED();
|
R_SUCCEED();
|
||||||
}
|
}
|
||||||
|
|
||||||
Result IOlscServiceForSystemService::GetDataTransferPolicyInfo(Out<u16> out_policy_info,
|
Result IOlscServiceForSystemService::GetDataTransferPolicyInfo(
|
||||||
u64 application_id) {
|
Out<DataTransferPolicy> out_policy_info, u64 application_id) {
|
||||||
LOG_WARNING(Service_OLSC, "(STUBBED) called");
|
LOG_WARNING(Service_OLSC, "(STUBBED) called");
|
||||||
*out_policy_info = 0;
|
DataTransferPolicy policy{};
|
||||||
|
policy.upload_policy = 0;
|
||||||
|
policy.download_policy = 0;
|
||||||
|
*out_policy_info = policy;
|
||||||
R_SUCCEED();
|
R_SUCCEED();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,3 +1,6 @@
|
||||||
|
// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project
|
||||||
|
// SPDX-License-Identifier: GPL-3.0-or-later
|
||||||
|
|
||||||
// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project
|
// SPDX-FileCopyrightText: Copyright 2024 yuzu Emulator Project
|
||||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||||
|
|
||||||
|
@ -10,6 +13,11 @@ class IDaemonController;
|
||||||
class IRemoteStorageController;
|
class IRemoteStorageController;
|
||||||
class ITransferTaskListController;
|
class ITransferTaskListController;
|
||||||
|
|
||||||
|
struct DataTransferPolicy {
|
||||||
|
u8 upload_policy;
|
||||||
|
u8 download_policy;
|
||||||
|
};
|
||||||
|
|
||||||
class IOlscServiceForSystemService final : public ServiceFramework<IOlscServiceForSystemService> {
|
class IOlscServiceForSystemService final : public ServiceFramework<IOlscServiceForSystemService> {
|
||||||
public:
|
public:
|
||||||
explicit IOlscServiceForSystemService(Core::System& system_);
|
explicit IOlscServiceForSystemService(Core::System& system_);
|
||||||
|
@ -20,7 +28,7 @@ private:
|
||||||
Out<SharedPointer<ITransferTaskListController>> out_interface);
|
Out<SharedPointer<ITransferTaskListController>> out_interface);
|
||||||
Result OpenRemoteStorageController(Out<SharedPointer<IRemoteStorageController>> out_interface);
|
Result OpenRemoteStorageController(Out<SharedPointer<IRemoteStorageController>> out_interface);
|
||||||
Result OpenDaemonController(Out<SharedPointer<IDaemonController>> out_interface);
|
Result OpenDaemonController(Out<SharedPointer<IDaemonController>> out_interface);
|
||||||
Result GetDataTransferPolicyInfo(Out<u16> out_policy_info, u64 application_id);
|
Result GetDataTransferPolicyInfo(Out<DataTransferPolicy> out_policy_info, u64 application_id);
|
||||||
Result CloneService(Out<SharedPointer<IOlscServiceForSystemService>> out_interface);
|
Result CloneService(Out<SharedPointer<IOlscServiceForSystemService>> out_interface);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue