mirror of
https://git.eden-emu.dev/eden-emu/eden
synced 2026-04-21 12:28:58 +02:00
[core/hle] Adds sorting game titles and prevents hard crashes in qlaunch (#3330)
Adds correct sorting in qlaunch (tested with FW 19 and FW20-21) Reviewed-on: https://git.eden-emu.dev/eden-emu/eden/pulls/3330 Reviewed-by: DraVee <dravee@eden-emu.dev> Reviewed-by: CamilleLaVey <camillelavey99@gmail.com> Reviewed-by: MaranBr <maranbr@eden-emu.dev> Co-authored-by: Maufeat <sahyno1996@gmail.com> Co-committed-by: Maufeat <sahyno1996@gmail.com>
This commit is contained in:
parent
1fbace438c
commit
30cbec7ad5
20 changed files with 313 additions and 39 deletions
|
|
@ -138,12 +138,13 @@ private:
|
|||
R_SUCCEED();
|
||||
}
|
||||
|
||||
Result GetNetworkServiceLicenseCacheEx() {
|
||||
Result GetNetworkServiceLicenseCacheEx(Out<u32> out_license, Out<s64> out_expiration) {
|
||||
LOG_DEBUG(Service_ACC, "(STUBBED) called.");
|
||||
|
||||
// TODO (jarrodnorwell)
|
||||
*out_license = 0;
|
||||
*out_expiration = 0;
|
||||
|
||||
R_RETURN(ResultUnknown);
|
||||
R_SUCCEED();
|
||||
}
|
||||
|
||||
Common::UUID account_id;
|
||||
|
|
|
|||
|
|
@ -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-License-Identifier: GPL-2.0-or-later
|
||||
|
||||
|
|
@ -22,7 +25,7 @@ public:
|
|||
{2, nullptr, "SetInitialLaunchSettingsCompletionTime"},
|
||||
{3, nullptr, "ClearInitialLaunchSettingsCompletionTime"},
|
||||
{4, nullptr, "UpdatePowerOnTime"},
|
||||
{5, nullptr, "UpdateAwakeTime"},
|
||||
{5, D<&ErrorReportContext::UpdateAwakeTime>, "UpdateAwakeTime"},
|
||||
{6, nullptr, "SubmitMultipleCategoryContext"},
|
||||
{7, nullptr, "UpdateApplicationLaunchTime"},
|
||||
{8, nullptr, "ClearApplicationLaunchTime"},
|
||||
|
|
@ -74,6 +77,14 @@ private:
|
|||
report_type, unknown, create_report_option_flag);
|
||||
R_SUCCEED();
|
||||
}
|
||||
|
||||
Result UpdateAwakeTime(InBuffer<BufferAttr_HipcMapAlias> data_a,
|
||||
InBuffer<BufferAttr_HipcMapAlias> data_b, u32 flag_a, u32 flag_b) {
|
||||
LOG_WARNING(Service_SET,
|
||||
"(STUBBED) called, data_a_size={}, data_b_size={}, flag_a={}, flag_b={}",
|
||||
data_a.size(), data_b.size(), flag_a, flag_b);
|
||||
R_SUCCEED();
|
||||
}
|
||||
};
|
||||
|
||||
class ErrorReportSession final : public ServiceFramework<ErrorReportSession> {
|
||||
|
|
|
|||
|
|
@ -53,6 +53,7 @@ public:
|
|||
{20102, nullptr, "GetFriendDetailedInfo"},
|
||||
{20103, nullptr, "SyncFriendList"},
|
||||
{20104, &IFriendService::RequestSyncFriendList, "RequestSyncFriendList"},
|
||||
{20105, &IFriendService::GetFriendListForViewer, "GetFriendListForViewer"},
|
||||
{20110, nullptr, "LoadFriendSetting"},
|
||||
{20200, &IFriendService::GetReceivedFriendRequestCount, "GetReceivedFriendRequestCount"},
|
||||
{20201, nullptr, "GetFriendRequestList"},
|
||||
|
|
@ -65,11 +66,13 @@ public:
|
|||
{20401, nullptr, "SyncBlockedUserList"},
|
||||
{20500, nullptr, "GetProfileExtraList"},
|
||||
{20501, nullptr, "GetRelationship"},
|
||||
{20600, &IFriendService::GetUserPresenceView, "GetUserPresenceView"},
|
||||
{20600, &IFriendService::GetUserPresenceView, "GetUserPresenceViewV1"},
|
||||
{20601, &IFriendService::GetUserPresenceView, "GetUserPresenceViewV2"},
|
||||
{20700, nullptr, "GetPlayHistoryList"},
|
||||
{20701, &IFriendService::GetPlayHistoryStatistics, "GetPlayHistoryStatistics"},
|
||||
{20800, &IFriendService::LoadUserSetting, "LoadUserSetting"},
|
||||
{20800, &IFriendService::LoadUserSetting, "LoadUserSettingV1"},
|
||||
{20801, nullptr, "SyncUserSetting"},
|
||||
{20802, &IFriendService::LoadUserSetting, "LoadUserSettingV2"},
|
||||
{20900, &IFriendService::RequestListSummaryOverlayNotification, "RequestListSummaryOverlayNotification"},
|
||||
{21000, nullptr, "GetExternalApplicationCatalog"},
|
||||
{22000, nullptr, "GetReceivedFriendInvitationList"},
|
||||
|
|
@ -270,6 +273,14 @@ private:
|
|||
rb.Push(ResultSuccess);
|
||||
}
|
||||
|
||||
void GetFriendListForViewer(HLERequestContext& ctx) {
|
||||
LOG_DEBUG(Service_Friend, "(STUBBED) called");
|
||||
|
||||
IPC::ResponseBuilder rb{ctx, 3};
|
||||
rb.Push(ResultSuccess);
|
||||
rb.Push<u32>(0);
|
||||
}
|
||||
|
||||
void GetReceivedFriendRequestCount(HLERequestContext& ctx) {
|
||||
IPC::RequestParser rp{ctx};
|
||||
[[maybe_unused]] const auto uuid = rp.PopRaw<Common::UUID>();
|
||||
|
|
|
|||
|
|
@ -136,7 +136,7 @@ IApplicationManagerInterface::IApplicationManagerInterface(Core::System& system_
|
|||
{404, nullptr, "InvalidateApplicationControlCache"},
|
||||
{405, nullptr, "ListApplicationControlCacheEntryInfo"},
|
||||
{406, nullptr, "GetApplicationControlProperty"},
|
||||
{407, nullptr, "ListApplicationTitle"},
|
||||
{407, &IApplicationManagerInterface::ListApplicationTitle, "ListApplicationTitle"},
|
||||
{408, nullptr, "ListApplicationIcon"},
|
||||
{411, nullptr, "Unknown411"}, //19.0.0+
|
||||
{412, nullptr, "Unknown412"}, //19.0.0+
|
||||
|
|
@ -832,4 +832,9 @@ Result IApplicationManagerInterface::Unknown4053() {
|
|||
R_SUCCEED();
|
||||
}
|
||||
|
||||
void IApplicationManagerInterface::ListApplicationTitle(HLERequestContext& ctx) {
|
||||
LOG_DEBUG(Service_NS, "called");
|
||||
IReadOnlyApplicationControlDataInterface(system).ListApplicationTitle(ctx);
|
||||
}
|
||||
|
||||
} // namespace Service::NS
|
||||
|
|
|
|||
|
|
@ -71,6 +71,8 @@ public:
|
|||
Result RequestDownloadApplicationControlDataInBackground(u64 control_source,
|
||||
u64 application_id);
|
||||
|
||||
void ListApplicationTitle(HLERequestContext& ctx);
|
||||
|
||||
private:
|
||||
KernelHelpers::ServiceContext service_context;
|
||||
Event record_update_system_event;
|
||||
|
|
|
|||
|
|
@ -21,6 +21,7 @@ IContentManagementInterface::IContentManagementInterface(Core::System& system_)
|
|||
{43, D<&IContentManagementInterface::CheckSdCardMountStatus>, "CheckSdCardMountStatus"},
|
||||
{47, D<&IContentManagementInterface::GetTotalSpaceSize>, "GetTotalSpaceSize"},
|
||||
{48, D<&IContentManagementInterface::GetFreeSpaceSize>, "GetFreeSpaceSize"},
|
||||
{71, D<&IContentManagementInterface::GetUnknown71>, "Unknown71"},
|
||||
{600, nullptr, "CountApplicationContentMeta"},
|
||||
{601, nullptr, "ListApplicationContentMetaStatus"},
|
||||
{605, nullptr, "ListApplicationContentMetaStatusWithRightsCheck"},
|
||||
|
|
@ -73,4 +74,12 @@ Result IContentManagementInterface::GetFreeSpaceSize(Out<s64> out_free_space_siz
|
|||
R_SUCCEED();
|
||||
}
|
||||
|
||||
Result IContentManagementInterface::GetUnknown71(Out<u64> out_value_a, Out<u64> out_value_b,
|
||||
u8 flag) {
|
||||
LOG_INFO(Service_NS, "(STUBBED) called, flag={:02X}", flag);
|
||||
*out_value_a = 0;
|
||||
*out_value_b = 0;
|
||||
R_SUCCEED();
|
||||
}
|
||||
|
||||
} // 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-License-Identifier: GPL-2.0-or-later
|
||||
|
||||
|
|
@ -20,6 +23,7 @@ public:
|
|||
Result CheckSdCardMountStatus();
|
||||
Result GetTotalSpaceSize(Out<s64> out_total_space_size, FileSys::StorageId storage_id);
|
||||
Result GetFreeSpaceSize(Out<s64> out_free_space_size, FileSys::StorageId storage_id);
|
||||
Result GetUnknown71(Out<u64> out_value_a, Out<u64> out_value_b, u8 flag);
|
||||
};
|
||||
|
||||
} // namespace Service::NS
|
||||
|
|
|
|||
|
|
@ -47,9 +47,9 @@ struct ApplicationDownloadState {
|
|||
u64 total_size;
|
||||
u32 unk_x10;
|
||||
u8 state;
|
||||
u8 unk_x19;
|
||||
std::array<u8, 0x2> unk_x1a;
|
||||
u64 unk_x20;
|
||||
u8 unk_x15;
|
||||
std::array<u8, 0x2> unk_x16;
|
||||
u64 unk_x18;
|
||||
};
|
||||
static_assert(sizeof(ApplicationDownloadState) == 0x20,
|
||||
"ApplicationDownloadState has incorrect size.");
|
||||
|
|
|
|||
|
|
@ -9,10 +9,13 @@
|
|||
#include "core/hle/service/cmif_serialization.h"
|
||||
#include "core/hle/service/ns/query_service.h"
|
||||
#include "core/hle/service/service.h"
|
||||
#include "core/launch_timestamp_cache.h"
|
||||
#include "frontend_common/play_time_manager.h"
|
||||
|
||||
namespace Service::NS {
|
||||
|
||||
IQueryService::IQueryService(Core::System& system_) : ServiceFramework{system_, "pdm:qry"} {
|
||||
IQueryService::IQueryService(Core::System& system_) : ServiceFramework{system_, "pdm:qry"},
|
||||
play_time_manager{std::make_unique<PlayTime::PlayTimeManager>()} {
|
||||
// clang-format off
|
||||
static const FunctionInfo functions[] = {
|
||||
{0, nullptr, "QueryAppletEvent"},
|
||||
|
|
@ -33,8 +36,8 @@ IQueryService::IQueryService(Core::System& system_) : ServiceFramework{system_,
|
|||
{15, nullptr, "GetRecentlyPlayedApplicationUpdateEvent"},
|
||||
{16, nullptr, "QueryApplicationPlayStatisticsByUserAccountIdForSystemV0"},
|
||||
{17, D<&IQueryService::QueryLastPlayTime>, "QueryLastPlayTime"},
|
||||
{18, nullptr, "QueryApplicationPlayStatisticsForSystem"},
|
||||
{19, nullptr, "QueryApplicationPlayStatisticsByUserAccountIdForSystem"},
|
||||
{18, D<&IQueryService::QueryApplicationPlayStatisticsForSystem>, "QueryApplicationPlayStatisticsForSystem"},
|
||||
{19, D<&IQueryService::QueryApplicationPlayStatisticsByUserAccountIdForSystem>, "QueryApplicationPlayStatisticsByUserAccountIdForSystem"},
|
||||
};
|
||||
// clang-format on
|
||||
|
||||
|
|
@ -65,4 +68,32 @@ Result IQueryService::QueryLastPlayTime(
|
|||
R_SUCCEED();
|
||||
}
|
||||
|
||||
Result IQueryService::QueryApplicationPlayStatisticsForSystem(
|
||||
Out<s32> out_entries, u8 flag,
|
||||
OutArray<ApplicationPlayStatistics, BufferAttr_HipcMapAlias> out_stats,
|
||||
InArray<u64, BufferAttr_HipcMapAlias> application_ids) {
|
||||
const size_t count = std::min(out_stats.size(), application_ids.size());
|
||||
s32 written = 0;
|
||||
for (size_t i = 0; i < count; ++i) {
|
||||
const u64 app_id = application_ids[i];
|
||||
ApplicationPlayStatistics stats{};
|
||||
stats.application_id = app_id;
|
||||
stats.play_time_ns = play_time_manager->GetPlayTime(app_id) * 1'000'000'000ULL;
|
||||
stats.launch_count = Core::LaunchTimestampCache::GetLaunchCount(app_id);
|
||||
out_stats[i] = stats;
|
||||
++written;
|
||||
}
|
||||
*out_entries = written;
|
||||
LOG_DEBUG(Service_NS, "called, entries={} flag={}", written, flag);
|
||||
R_SUCCEED();
|
||||
}
|
||||
|
||||
Result IQueryService::QueryApplicationPlayStatisticsByUserAccountIdForSystem(
|
||||
Out<s32> out_entries, u8 flag, Common::UUID user_id,
|
||||
OutArray<ApplicationPlayStatistics, BufferAttr_HipcMapAlias> out_stats,
|
||||
InArray<u64, BufferAttr_HipcMapAlias> application_ids) {
|
||||
// well we don't do per-user tracking :>
|
||||
return QueryApplicationPlayStatisticsForSystem(out_entries, flag, out_stats, application_ids);
|
||||
}
|
||||
|
||||
} // namespace Service::NS
|
||||
|
|
|
|||
|
|
@ -7,10 +7,17 @@
|
|||
#pragma once
|
||||
|
||||
#include "common/uuid.h"
|
||||
#include "core/hle/service/am/am_types.h"
|
||||
#include "core/hle/service/cmif_types.h"
|
||||
#include "core/hle/service/ns/ns_types.h"
|
||||
#include "core/hle/service/service.h"
|
||||
|
||||
#include <memory>
|
||||
|
||||
namespace PlayTime {
|
||||
class PlayTimeManager;
|
||||
}
|
||||
|
||||
namespace Service::NS {
|
||||
|
||||
struct PlayStatistics {
|
||||
|
|
@ -28,6 +35,13 @@ static_assert(sizeof(PlayStatistics) == 0x28, "PlayStatistics is an invalid size
|
|||
|
||||
struct LastPlayTime {};
|
||||
|
||||
struct ApplicationPlayStatistics {
|
||||
u64 application_id{};
|
||||
u64 play_time_ns{};
|
||||
u64 launch_count{};
|
||||
};
|
||||
static_assert(sizeof(ApplicationPlayStatistics) == 0x18, "ApplicationPlayStatistics is an invalid size");
|
||||
|
||||
class IQueryService final : public ServiceFramework<IQueryService> {
|
||||
public:
|
||||
explicit IQueryService(Core::System& system_);
|
||||
|
|
@ -39,6 +53,16 @@ private:
|
|||
Result QueryLastPlayTime(Out<s32> out_entries, u8 unknown,
|
||||
OutArray<LastPlayTime, BufferAttr_HipcMapAlias> out_last_play_times,
|
||||
InArray<s32, BufferAttr_HipcMapAlias> application_ids);
|
||||
Result QueryApplicationPlayStatisticsForSystem(
|
||||
Out<s32> out_entries, u8 flag,
|
||||
OutArray<ApplicationPlayStatistics, BufferAttr_HipcMapAlias> out_stats,
|
||||
InArray<u64, BufferAttr_HipcMapAlias> application_ids);
|
||||
Result QueryApplicationPlayStatisticsByUserAccountIdForSystem(
|
||||
Out<s32> out_entries, u8 flag, Common::UUID user_id,
|
||||
OutArray<ApplicationPlayStatistics, BufferAttr_HipcMapAlias> out_stats,
|
||||
InArray<u64, BufferAttr_HipcMapAlias> application_ids);
|
||||
|
||||
std::unique_ptr<PlayTime::PlayTimeManager> play_time_manager;
|
||||
};
|
||||
|
||||
} // namespace Service::NS
|
||||
|
|
|
|||
|
|
@ -6,20 +6,24 @@
|
|||
|
||||
#include <algorithm>
|
||||
#include <vector>
|
||||
#include <optional>
|
||||
#include <stb_image.h>
|
||||
#include <stb_image_resize.h>
|
||||
#include <stb_image_write.h>
|
||||
#include <string>
|
||||
|
||||
#include "common/settings.h"
|
||||
#include "core/file_sys/control_metadata.h"
|
||||
#include "core/file_sys/patch_manager.h"
|
||||
#include "core/file_sys/vfs/vfs.h"
|
||||
#include "core/hle/kernel/k_transfer_memory.h"
|
||||
#include "core/hle/service/cmif_serialization.h"
|
||||
#include "core/hle/service/ns/language.h"
|
||||
#include "core/hle/service/ns/ns_types.h"
|
||||
#include "core/hle/service/ns/ns_results.h"
|
||||
#include "core/hle/service/ns/read_only_application_control_data_interface.h"
|
||||
#include "core/hle/service/set/settings_server.h"
|
||||
#include "core/hle/service/kernel_helpers.h"
|
||||
|
||||
namespace Service::NS {
|
||||
|
||||
|
|
@ -66,6 +70,70 @@ void SanitizeJPEGImageSize(std::vector<u8>& image) {
|
|||
|
||||
} // namespace
|
||||
|
||||
|
||||
// IAsyncValue implementation for ListApplicationTitle
|
||||
// https://switchbrew.org/wiki/NS_services#ListApplicationTitle
|
||||
class IAsyncValueForListApplicationTitle final : public ServiceFramework<IAsyncValueForListApplicationTitle> {
|
||||
public:
|
||||
explicit IAsyncValueForListApplicationTitle(Core::System& system_, s32 offset, s32 size)
|
||||
: ServiceFramework{system_, "IAsyncValue"}, service_context{system_, "IAsyncValue"},
|
||||
data_offset{offset}, data_size{size} {
|
||||
static const FunctionInfo functions[] = {
|
||||
{0, &IAsyncValueForListApplicationTitle::GetSize, "GetSize"},
|
||||
{1, &IAsyncValueForListApplicationTitle::Get, "Get"},
|
||||
{2, &IAsyncValueForListApplicationTitle::Cancel, "Cancel"},
|
||||
{3, &IAsyncValueForListApplicationTitle::GetErrorContext, "GetErrorContext"},
|
||||
};
|
||||
RegisterHandlers(functions);
|
||||
|
||||
completion_event = service_context.CreateEvent("IAsyncValue:Completion");
|
||||
completion_event->GetReadableEvent().Signal();
|
||||
}
|
||||
|
||||
~IAsyncValueForListApplicationTitle() override {
|
||||
service_context.CloseEvent(completion_event);
|
||||
}
|
||||
|
||||
Kernel::KReadableEvent& ReadableEvent() const {
|
||||
return completion_event->GetReadableEvent();
|
||||
}
|
||||
|
||||
private:
|
||||
void GetSize(HLERequestContext& ctx) {
|
||||
LOG_DEBUG(Service_NS, "called");
|
||||
IPC::ResponseBuilder rb{ctx, 4};
|
||||
rb.Push(ResultSuccess);
|
||||
rb.Push<s64>(data_size);
|
||||
}
|
||||
|
||||
void Get(HLERequestContext& ctx) {
|
||||
LOG_DEBUG(Service_NS, "called");
|
||||
std::vector<u8> buffer(sizeof(s32));
|
||||
std::memcpy(buffer.data(), &data_offset, sizeof(s32));
|
||||
ctx.WriteBuffer(buffer);
|
||||
|
||||
IPC::ResponseBuilder rb{ctx, 2};
|
||||
rb.Push(ResultSuccess);
|
||||
}
|
||||
|
||||
void Cancel(HLERequestContext& ctx) {
|
||||
LOG_DEBUG(Service_NS, "called");
|
||||
IPC::ResponseBuilder rb{ctx, 2};
|
||||
rb.Push(ResultSuccess);
|
||||
}
|
||||
|
||||
void GetErrorContext(HLERequestContext& ctx) {
|
||||
LOG_DEBUG(Service_NS, "called");
|
||||
IPC::ResponseBuilder rb{ctx, 2};
|
||||
rb.Push(ResultSuccess);
|
||||
}
|
||||
|
||||
KernelHelpers::ServiceContext service_context;
|
||||
Kernel::KEvent* completion_event{};
|
||||
s32 data_offset;
|
||||
s32 data_size;
|
||||
};
|
||||
|
||||
IReadOnlyApplicationControlDataInterface::IReadOnlyApplicationControlDataInterface(
|
||||
Core::System& system_)
|
||||
: ServiceFramework{system_, "IReadOnlyApplicationControlDataInterface"} {
|
||||
|
|
@ -76,8 +144,9 @@ IReadOnlyApplicationControlDataInterface::IReadOnlyApplicationControlDataInterfa
|
|||
{2, D<&IReadOnlyApplicationControlDataInterface::ConvertApplicationLanguageToLanguageCode>, "ConvertApplicationLanguageToLanguageCode"},
|
||||
{3, nullptr, "ConvertLanguageCodeToApplicationLanguage"},
|
||||
{4, nullptr, "SelectApplicationDesiredLanguage"},
|
||||
{5, D<&IReadOnlyApplicationControlDataInterface::GetApplicationControlData2>, "GetApplicationControlDataWithoutIcon"},
|
||||
{19, D<&IReadOnlyApplicationControlDataInterface::GetApplicationControlData3>, "GetApplicationControlDataWithoutIcon3"},
|
||||
{5, D<&IReadOnlyApplicationControlDataInterface::GetApplicationControlData2>, "GetApplicationControlData"},
|
||||
{13, &IReadOnlyApplicationControlDataInterface::ListApplicationTitle, "ListApplicationTitle"},
|
||||
{19, D<&IReadOnlyApplicationControlDataInterface::GetApplicationControlData3>, "GetApplicationControlData"},
|
||||
};
|
||||
// clang-format on
|
||||
|
||||
|
|
@ -240,6 +309,60 @@ Result IReadOnlyApplicationControlDataInterface::GetApplicationControlData2(
|
|||
R_SUCCEED();
|
||||
}
|
||||
|
||||
|
||||
void IReadOnlyApplicationControlDataInterface::ListApplicationTitle(HLERequestContext& ctx) {
|
||||
/*
|
||||
IPC::RequestParser rp{ctx};
|
||||
auto control_source = rp.PopRaw<u8>();
|
||||
rp.Skip(7, false);
|
||||
auto transfer_memory_size = rp.Pop<u64>();
|
||||
*/
|
||||
|
||||
const auto app_ids_buffer = ctx.ReadBuffer();
|
||||
const size_t app_count = app_ids_buffer.size() / sizeof(u64);
|
||||
|
||||
std::vector<u64> application_ids(app_count);
|
||||
if (app_count > 0) {
|
||||
std::memcpy(application_ids.data(), app_ids_buffer.data(), app_count * sizeof(u64));
|
||||
}
|
||||
|
||||
auto t_mem_obj = ctx.GetObjectFromHandle<Kernel::KTransferMemory>(ctx.GetCopyHandle(0));
|
||||
auto* t_mem = t_mem_obj.GetPointerUnsafe();
|
||||
|
||||
constexpr size_t title_entry_size = sizeof(FileSys::LanguageEntry);
|
||||
const size_t total_data_size = app_count * title_entry_size;
|
||||
|
||||
constexpr s32 data_offset = 0;
|
||||
|
||||
if (t_mem != nullptr && app_count > 0) {
|
||||
auto& memory = system.ApplicationMemory();
|
||||
const auto t_mem_address = t_mem->GetSourceAddress();
|
||||
|
||||
for (size_t i = 0; i < app_count; ++i) {
|
||||
const u64 app_id = application_ids[i];
|
||||
const FileSys::PatchManager pm{app_id, system.GetFileSystemController(),
|
||||
system.GetContentProvider()};
|
||||
const auto control = pm.GetControlMetadata();
|
||||
|
||||
FileSys::LanguageEntry entry{};
|
||||
if (control.first != nullptr) {
|
||||
entry = control.first->GetLanguageEntry();
|
||||
}
|
||||
|
||||
const size_t offset = i * title_entry_size;
|
||||
memory.WriteBlock(t_mem_address + offset, &entry, title_entry_size);
|
||||
}
|
||||
}
|
||||
|
||||
auto async_value = std::make_shared<IAsyncValueForListApplicationTitle>(
|
||||
system, data_offset, static_cast<s32>(total_data_size));
|
||||
|
||||
IPC::ResponseBuilder rb{ctx, 2, 1, 1};
|
||||
rb.Push(ResultSuccess);
|
||||
rb.PushCopyObjects(async_value->ReadableEvent());
|
||||
rb.PushIpcInterface(std::move(async_value));
|
||||
}
|
||||
|
||||
Result IReadOnlyApplicationControlDataInterface::GetApplicationControlData3(
|
||||
OutBuffer<BufferAttr_HipcMapAlias> out_buffer, Out<u32> out_flags_a, Out<u32> out_flags_b,
|
||||
Out<u32> out_actual_size, ApplicationControlSource application_control_source, u8 flag1, u8 flag2, u64 application_id) {
|
||||
|
|
|
|||
|
|
@ -34,6 +34,7 @@ public:
|
|||
u8 flag1,
|
||||
u8 flag2,
|
||||
u64 application_id);
|
||||
void ListApplicationTitle(HLERequestContext& ctx);
|
||||
Result GetApplicationControlData3(
|
||||
OutBuffer<BufferAttr_HipcMapAlias> out_buffer,
|
||||
Out<u32> out_flags_a,
|
||||
|
|
|
|||
|
|
@ -92,13 +92,10 @@ Result IDaemonController::SetGlobalAutoDownloadSetting(bool is_enabled, Common::
|
|||
R_SUCCEED();
|
||||
}
|
||||
|
||||
Result IDaemonController::GetAutonomyTaskStatus(Out<u8> out_state, Common::UUID user_id,
|
||||
u64 application_id) {
|
||||
LOG_INFO(Service_OLSC, "called, user_id={} application_id={:016X}", user_id.FormattedString(),
|
||||
application_id);
|
||||
AppKey key{user_id, application_id};
|
||||
const auto it = autonomy_task_status_.find(key);
|
||||
*out_state = (it != autonomy_task_status_.end()) ? it->second : 0; // default idle
|
||||
Result IDaemonController::GetAutonomyTaskStatus(Out<u8> out_status, Common::UUID user_id) {
|
||||
LOG_INFO(Service_OLSC, "called, user_id={}", user_id.FormattedString());
|
||||
|
||||
*out_status = 0;
|
||||
R_SUCCEED();
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -32,7 +32,7 @@ private:
|
|||
Result GetGlobalAutoDownloadSetting(Out<bool> out_is_enabled, Common::UUID user_id);
|
||||
Result SetGlobalAutoDownloadSetting(bool is_enabled, Common::UUID user_id);
|
||||
|
||||
Result GetAutonomyTaskStatus(Out<u8> out_state, Common::UUID user_id, u64 application_id);
|
||||
Result GetAutonomyTaskStatus(Out<u8> out_status, Common::UUID user_id);
|
||||
|
||||
// Internal in-memory state to back the above APIs
|
||||
struct AppKey {
|
||||
|
|
|
|||
|
|
@ -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-License-Identifier: GPL-2.0-or-later
|
||||
|
||||
|
|
@ -34,7 +37,7 @@ NSD::NSD(Core::System& system_, const char* name) : ServiceFramework{system_, na
|
|||
{12, nullptr, "GetDeviceId"},
|
||||
{13, nullptr, "DeleteSettings"},
|
||||
{14, nullptr, "ImportSettings"},
|
||||
{15, nullptr, "SetChangeEnvironmentIdentifierDisabled"},
|
||||
{15, &NSD::SetChangeEnvironmentIdentifierDisabled, "SetChangeEnvironmentIdentifierDisabled"},
|
||||
{20, &NSD::Resolve, "Resolve"},
|
||||
{21, &NSD::ResolveEx, "ResolveEx"},
|
||||
{30, nullptr, "GetNasServiceSetting"},
|
||||
|
|
@ -77,6 +80,16 @@ static Result ResolveCommon(const std::string& fqdn_in, std::array<char, 0x100>&
|
|||
return ResultSuccess;
|
||||
}
|
||||
|
||||
void NSD::SetChangeEnvironmentIdentifierDisabled(HLERequestContext& ctx) {
|
||||
IPC::RequestParser rp{ctx};
|
||||
const bool disabled = rp.Pop<bool>();
|
||||
|
||||
LOG_WARNING(Service, "(STUBBED) called, disabled={}", disabled);
|
||||
|
||||
IPC::ResponseBuilder rb{ctx, 1};
|
||||
rb.Push(ResultSuccess);
|
||||
}
|
||||
|
||||
void NSD::Resolve(HLERequestContext& ctx) {
|
||||
const std::string fqdn_in = Common::StringFromBuffer(ctx.ReadBuffer(0));
|
||||
|
||||
|
|
|
|||
|
|
@ -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-License-Identifier: GPL-2.0-or-later
|
||||
|
||||
|
|
@ -17,6 +20,7 @@ public:
|
|||
~NSD() override;
|
||||
|
||||
private:
|
||||
void SetChangeEnvironmentIdentifierDisabled(HLERequestContext& ctx);
|
||||
void Resolve(HLERequestContext& ctx);
|
||||
void ResolveEx(HLERequestContext& ctx);
|
||||
void GetEnvironmentIdentifier(HLERequestContext& ctx);
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue