diff --git a/src/core/hle/service/nim/nim_u.cpp b/src/core/hle/service/nim/nim_u.cpp index b44ef3539..7a677aa85 100644 --- a/src/core/hle/service/nim/nim_u.cpp +++ b/src/core/hle/service/nim/nim_u.cpp @@ -3,9 +3,9 @@ // Refer to the license.txt file included. #include "common/archives.h" +#include "common/string_util.h" #include "core/core.h" #include "core/hle/ipc_helpers.h" -#include "core/hle/kernel/event.h" #include "core/hle/service/nim/nim_u.h" SERVICE_CONSTRUCT_IMPL(Service::NIM::NIM_U) @@ -13,37 +13,736 @@ SERIALIZE_EXPORT_IMPL(Service::NIM::NIM_U) namespace Service::NIM { +enum class SystemUpdateState : u32 { + NotInitialized, + StartingSystemUpdate, + FetchingHashAndAccountStatus, + InstallingNewTickets, + InstallingTitles, + UpdateComplete, + SystemUpdatesDisabled, + Unknown7, + Unknown8, +}; + +struct SystemUpdateProgress { + SystemUpdateState state; + u32 last_operation_result; + u64 current_title_downloaded_bytes; + u64 current_title_total_bytes; + u64 titles_downloaded; + u64 titles_total; +}; + +static_assert(sizeof(SystemUpdateProgress) == 0x28, "SystemUpdateProgress structure size is wrong"); + +enum class TitleDownloadState : u32 { + NotInitialized, + StartingTitleDownload, + InstallingTmd, + CommittingTmd, + InstallingContents, + ContentsInstalled, + CommittingTitles, + Finished, + Unknown8, + Unknown9, + BackgroundDownloadFailed, +}; + +struct TitleDownloadProgress { + TitleDownloadState state; + u32 last_operation_result; + u64 downloaded_bytes; + u64 total_bytes; +}; + +static_assert(sizeof(TitleDownloadProgress) == 0x18, + "TitleDownloadProgress structure size is wrong"); + +struct TitleDownloadConfig { + u64 title_id; + u32 title_version; + u32 unknown_1; + u8 age_rating; + u8 media_type; + INSERT_PADDING_BYTES(2); + u32 unknown_2; +}; + +static_assert(sizeof(TitleDownloadConfig) == 0x18, "TitleDownloadConfig structure size is wrong"); + +#pragma pack(1) +struct BackgroundTitleDownloadConfig { + TitleDownloadConfig base_config; + u8 unknown_1; + u8 unknown_2; + INSERT_PADDING_BYTES(6); + u64 requester_title_id; + std::array title_name; + u16 title_name_terminator; + std::array developer_name; + u16 developer_name_terminator; +}; + +static_assert(sizeof(BackgroundTitleDownloadConfig) == 0x104, + "BackgroundTitleDownloadConfig structure size is wrong"); + +struct BackgroundTitleDownloadTaskInfo { + BackgroundTitleDownloadConfig config; + INSERT_PADDING_BYTES(4); + TitleDownloadProgress progress; +}; + +static_assert(sizeof(BackgroundTitleDownloadTaskInfo) == 0x120, + "BackgroundTitleDownloadTaskInfo structure size is wrong"); + +struct AutoTitleDownloadTaskInfo { + u64 task_id; + u64 title_id; + u32 title_version; + u8 unknown_4[0x14]; + u64 required_size; + u32 last_operation_result_code; + u32 last_operation_customer_support_code; + std::array title_name; + u16 title_name_terminator; + std::array developer_name; + u16 developer_name_terminator; + u8 unknown_5[0x24]; +}; + +static_assert(sizeof(AutoTitleDownloadTaskInfo) == 0x138, + "AutoTitleDownloadTaskInfo structure size is wrong"); + +struct AutoDbgDat { + u8 unknown_1[0x4]; + u32 num_auto_download_tasks; + u8 unknown_2[0x100]; +}; + +static_assert(sizeof(AutoDbgDat) == 0x108, "AutoDbgDat structure size is wrong"); + NIM_U::NIM_U(Core::System& system) : ServiceFramework("nim:u", 2) { const FunctionInfo functions[] = { - {0x00010000, nullptr, "StartSysUpdate"}, - {0x00020000, nullptr, "GetUpdateDownloadProgress"}, - {0x00040000, nullptr, "FinishTitlesInstall"}, - {0x00050000, &NIM_U::CheckForSysUpdateEvent, "CheckForSysUpdateEvent"}, - {0x00090000, &NIM_U::CheckSysUpdateAvailable, "CheckSysUpdateAvailable"}, - {0x000A0000, nullptr, "GetState"}, - {0x000B0000, nullptr, "GetSystemTitleHash"}, + {0x00010000, &NIM_U::StartNetworkUpdate, "StartNetworkUpdate"}, + {0x00020000, &NIM_U::GetProgress, "GetProgress"}, + {0x00030000, &NIM_U::Cancel, "Cancel"}, + {0x00040000, &NIM_U::CommitSystemTitles, "CommitSystemTitles"}, + {0x00050000, &NIM_U::GetBackgroundEventForMenu, "GetBackgroundEventForMenu"}, + {0x00060000, &NIM_U::GetBackgroundEventForNews, "GetBackgroundEventForNews"}, + {0x00070000, &NIM_U::FormatSaveData, "FormatSaveData"}, + {0x00080000, &NIM_U::GetCustomerSupportCode, "GetCustomerSupportCode"}, + {0x00090000, &NIM_U::IsCommittableAllSystemTitles, "IsCommittableAllSystemTitles"}, + {0x000A0000, &NIM_U::GetBackgroundProgress, "GetBackgroundProgress"}, + {0x000B0000, &NIM_U::GetSavedHash, "GetSavedHash"}, + {0x000C0082, &NIM_U::UnregisterTask, "UnregisterTask"}, + {0x000D0080, &NIM_U::IsRegistered, "IsRegistered"}, + {0x000E0080, &NIM_U::FindTaskInfo, "FindTaskInfo"}, + {0x000F0042, &NIM_U::GetTaskInfos, "GetTaskInfos"}, + {0x00100000, &NIM_U::DeleteUnmanagedContexts, "DeleteUnmanagedContexts"}, + {0x00110000, &NIM_U::UpdateAutoTitleDownloadTasksAsync, + "UpdateAutoTitleDownloadTasksAsync"}, + {0x00120000, &NIM_U::StartPendingAutoTitleDownloadTasksAsync, + "StartPendingAutoTitleDownloadTasksAsync"}, + {0x00130000, &NIM_U::GetAsyncResult, "GetAsyncResult"}, + {0x00140000, &NIM_U::CancelAsyncCall, "CancelAsyncCall"}, + {0x00150000, &NIM_U::IsPendingAutoTitleDownloadTasks, "IsPendingAutoTitleDownloadTasks"}, + {0x00160000, &NIM_U::GetNumAutoTitleDownloadTasks, "GetNumAutoTitleDownloadTasks"}, + {0x00170042, &NIM_U::GetAutoTitleDownloadTaskInfos, "GetAutoTitleDownloadTaskInfos"}, + {0x00180080, &NIM_U::CancelAutoTitleDownloadTask, "CancelAutoTitleDownloadTask"}, + {0x00190002, &NIM_U::SetAutoDbgDat, "SetAutoDbgDat"}, + {0x001A0002, &NIM_U::GetAutoDbgDat, "GetAutoDbgDat"}, + {0x001B0042, &NIM_U::SetDbgTasks, "SetDbgTasks"}, + {0x001C0042, &NIM_U::GetDbgTasks, "GetDbgTasks"}, + {0x001D0000, &NIM_U::DeleteDbgData, "DeleteDbgData"}, + {0x001E0042, &NIM_U::SetTslXml, "SetTslXml"}, + {0x001F0000, &NIM_U::GetTslXmlSize, "GetTslXmlSize"}, + {0x00200042, &NIM_U::GetTslXml, "GetTslXml"}, + {0x00210000, &NIM_U::DeleteTslXml, "DeleteTslXml"}, + {0x00220042, &NIM_U::SetDtlXml, "SetDtlXml"}, + {0x00230000, &NIM_U::GetDtlXmlSize, "GetDtlXmlSize"}, + {0x00240042, &NIM_U::GetDtlXml, "GetDtlXml"}, + {0x00250000, &NIM_U::UpdateAccountStatus, "UpdateAccountStatus"}, + {0x00260180, &NIM_U::StartTitleDownload, "StartTitleDownload"}, + {0x00270000, &NIM_U::StopTitleDownload, "StopTitleDownload"}, + {0x00280000, &NIM_U::GetTitleDownloadProgress, "GetTitleDownloadProgress"}, + {0x00290246, &NIM_U::RegisterTask, "RegisterTask"}, + {0x002A0000, &NIM_U::IsSystemUpdateAvailable, "IsSystemUpdateAvailable"}, + {0x002B0000, &NIM_U::Unknown2B, "Unknown2B"}, + {0x002C0000, &NIM_U::UpdateTickets, "UpdateTickets"}, + {0x002D00C0, &NIM_U::DownloadTitleSeedAsync, "DownloadTitleSeedAsync"}, + {0x002E0000, &NIM_U::DownloadMissingTitleSeedsAsync, "DownloadMissingTitleSeedsAsync"}, }; RegisterHandlers(functions); - nim_system_update_event = - system.Kernel().CreateEvent(Kernel::ResetType::OneShot, "NIM System Update Event"); + nim_system_update_event_for_menu = + system.Kernel().CreateEvent(Kernel::ResetType::OneShot, "NIM System Update Event (Menu)"); + nim_system_update_event_for_news = + system.Kernel().CreateEvent(Kernel::ResetType::OneShot, "NIM System Update Event (News)"); + nim_async_completion_event = + system.Kernel().CreateEvent(Kernel::ResetType::OneShot, "NIM Async Completion Event"); } NIM_U::~NIM_U() = default; -void NIM_U::CheckForSysUpdateEvent(Kernel::HLERequestContext& ctx) { - IPC::RequestParser rp(ctx, 0x5, 0, 0); // 0x50000 - IPC::RequestBuilder rb = rp.MakeBuilder(1, 2); +void NIM_U::StartNetworkUpdate(Kernel::HLERequestContext& ctx) { + IPC::RequestParser rp(ctx, 0x1, 0, 0); // 0x10000 + + IPC::RequestBuilder rb = rp.MakeBuilder(1, 0); rb.Push(RESULT_SUCCESS); - rb.PushCopyObjects(nim_system_update_event); - LOG_TRACE(Service_NIM, "called"); + + LOG_WARNING(Service_NIM, "(STUBBED) called"); } -void NIM_U::CheckSysUpdateAvailable(Kernel::HLERequestContext& ctx) { +void NIM_U::GetProgress(Kernel::HLERequestContext& ctx) { + IPC::RequestParser rp(ctx, 0x2, 0, 0); // 0x20000 + + SystemUpdateProgress progress{}; + std::memset(&progress, 0, sizeof(progress)); + + IPC::RequestBuilder rb = rp.MakeBuilder(13, 0); + rb.Push(RESULT_SUCCESS); + rb.PushRaw(progress); + rb.Push(0); + rb.Push(0); + + LOG_WARNING(Service_NIM, "(STUBBED) called"); +} + +void NIM_U::Cancel(Kernel::HLERequestContext& ctx) { + IPC::RequestParser rp(ctx, 0x3, 0, 0); // 0x30000 + + IPC::RequestBuilder rb = rp.MakeBuilder(1, 0); + rb.Push(RESULT_SUCCESS); + + LOG_WARNING(Service_NIM, "(STUBBED) called"); +} + +void NIM_U::CommitSystemTitles(Kernel::HLERequestContext& ctx) { + IPC::RequestParser rp(ctx, 0x4, 0, 0); // 0x40000 + + IPC::RequestBuilder rb = rp.MakeBuilder(1, 0); + rb.Push(RESULT_SUCCESS); + + LOG_WARNING(Service_NIM, "(STUBBED) called"); +} + +void NIM_U::GetBackgroundEventForMenu(Kernel::HLERequestContext& ctx) { + IPC::RequestParser rp(ctx, 0x5, 0, 0); // 0x50000 + + IPC::RequestBuilder rb = rp.MakeBuilder(1, 2); + rb.Push(RESULT_SUCCESS); + rb.PushCopyObjects(nim_system_update_event_for_menu); + + LOG_WARNING(Service_NIM, "(STUBBED) called"); +} + +void NIM_U::GetBackgroundEventForNews(Kernel::HLERequestContext& ctx) { + IPC::RequestParser rp(ctx, 0x6, 0, 0); // 0x60000 + + IPC::RequestBuilder rb = rp.MakeBuilder(1, 2); + rb.Push(RESULT_SUCCESS); + rb.PushCopyObjects(nim_system_update_event_for_news); + + LOG_WARNING(Service_NIM, "(STUBBED) called"); +} + +void NIM_U::FormatSaveData(Kernel::HLERequestContext& ctx) { + IPC::RequestParser rp(ctx, 0x7, 0, 0); // 0x70000 + + IPC::RequestBuilder rb = rp.MakeBuilder(1, 0); + rb.Push(RESULT_SUCCESS); + + LOG_WARNING(Service_NIM, "(STUBBED) called"); +} + +void NIM_U::GetCustomerSupportCode(Kernel::HLERequestContext& ctx) { + IPC::RequestParser rp(ctx, 0x8, 0, 0); // 0x80000 + + IPC::RequestBuilder rb = rp.MakeBuilder(2, 0); + rb.Push(RESULT_SUCCESS); + rb.Push(0); // Customer support code + + LOG_WARNING(Service_NIM, "(STUBBED) called"); +} + +void NIM_U::IsCommittableAllSystemTitles(Kernel::HLERequestContext& ctx) { IPC::RequestParser rp(ctx, 0x9, 0, 0); // 0x90000 IPC::RequestBuilder rb = rp.MakeBuilder(2, 0); rb.Push(RESULT_SUCCESS); - rb.Push(false); // No update available + rb.Push(false); + + LOG_WARNING(Service_NIM, "(STUBBED) called"); +} + +void NIM_U::GetBackgroundProgress(Kernel::HLERequestContext& ctx) { + IPC::RequestParser rp(ctx, 0xA, 0, 0); // 0xA0000 + + SystemUpdateProgress progress{}; + std::memset(&progress, 0, sizeof(progress)); + + IPC::RequestBuilder rb = rp.MakeBuilder(13, 0); + rb.Push(RESULT_SUCCESS); + rb.PushRaw(progress); + rb.Push(0); + rb.Push(0); + + LOG_WARNING(Service_NIM, "(STUBBED) called"); +} + +void NIM_U::GetSavedHash(Kernel::HLERequestContext& ctx) { + IPC::RequestParser rp(ctx, 0xB, 0, 0); // 0xB0000 + + std::array hash{}; + std::memset(&hash, 0, sizeof(hash)); + + IPC::RequestBuilder rb = rp.MakeBuilder(10, 0); + rb.Push(RESULT_SUCCESS); + rb.PushRaw(hash); + + LOG_WARNING(Service_NIM, "(STUBBED) called"); +} + +void NIM_U::UnregisterTask(Kernel::HLERequestContext& ctx) { + IPC::RequestParser rp(ctx, 0xC, 2, 2); // 0xC0082 + + const u64 title_id = rp.Pop(); + const u32 process_id = rp.PopPID(); + + IPC::RequestBuilder rb = rp.MakeBuilder(1, 0); + rb.Push(ResultCode(ErrorDescription::NotFound, ErrorModule::NIM, ErrorSummary::NotFound, + ErrorLevel::Status)); + + LOG_WARNING(Service_NIM, "(STUBBED) called title_id={:016X}, process_id={:08X}", title_id, + process_id); +} + +void NIM_U::IsRegistered(Kernel::HLERequestContext& ctx) { + IPC::RequestParser rp(ctx, 0xD, 2, 0); // 0xD0080 + + const u64 title_id = rp.Pop(); + + IPC::RequestBuilder rb = rp.MakeBuilder(2, 0); + rb.Push(RESULT_SUCCESS); + rb.Push(false); + + LOG_WARNING(Service_NIM, "(STUBBED) called title_id={:016X}", title_id); +} + +void NIM_U::FindTaskInfo(Kernel::HLERequestContext& ctx) { + IPC::RequestParser rp(ctx, 0xE, 2, 0); // 0xE0080 + + const u64 title_id = rp.Pop(); + + std::vector buffer(0x120, 0); + + IPC::RequestBuilder rb = rp.MakeBuilder(1, 2); + rb.Push(ResultCode(ErrorDescription::NotFound, ErrorModule::NIM, ErrorSummary::NotFound, + ErrorLevel::Status)); + rb.PushStaticBuffer(std::move(buffer), 0); + + LOG_WARNING(Service_NIM, "(STUBBED) called title_id={:016X}", title_id); +} + +void NIM_U::GetTaskInfos(Kernel::HLERequestContext& ctx) { + IPC::RequestParser rp(ctx, 0xF, 1, 2); // 0xF0042 + + const u64 max_task_infos = rp.Pop(); + auto& task_infos_buffer = rp.PopMappedBuffer(); + + IPC::RequestBuilder rb = rp.MakeBuilder(2, 2); + rb.Push(RESULT_SUCCESS); + rb.Push(0); + rb.PushMappedBuffer(task_infos_buffer); + + LOG_WARNING(Service_NIM, "(STUBBED) called max_task_infos={:08X}, task_infos_buffer=0x{:08X}", + max_task_infos, task_infos_buffer.GetId()); +} + +void NIM_U::DeleteUnmanagedContexts(Kernel::HLERequestContext& ctx) { + IPC::RequestParser rp(ctx, 0x10, 0, 0); // 0x100000 + + IPC::RequestBuilder rb = rp.MakeBuilder(1, 0); + rb.Push(RESULT_SUCCESS); + + LOG_WARNING(Service_NIM, "(STUBBED) called"); +} + +void NIM_U::UpdateAutoTitleDownloadTasksAsync(Kernel::HLERequestContext& ctx) { + IPC::RequestParser rp(ctx, 0x11, 0, 0); // 0x110000 + + // Since this is a stub, signal the completion event so the caller won't get stuck waiting. + nim_async_completion_event->Signal(); + + IPC::RequestBuilder rb = rp.MakeBuilder(1, 2); + rb.Push(RESULT_SUCCESS); + rb.PushCopyObjects(nim_async_completion_event); + + LOG_WARNING(Service_NIM, "(STUBBED) called"); +} + +void NIM_U::StartPendingAutoTitleDownloadTasksAsync(Kernel::HLERequestContext& ctx) { + IPC::RequestParser rp(ctx, 0x11, 0, 0); // 0x120000 + + // Since this is a stub, signal the completion event so the caller won't get stuck waiting. + nim_async_completion_event->Signal(); + + IPC::RequestBuilder rb = rp.MakeBuilder(1, 2); + rb.Push(RESULT_SUCCESS); + rb.PushCopyObjects(nim_async_completion_event); + + LOG_WARNING(Service_NIM, "(STUBBED) called"); +} + +void NIM_U::GetAsyncResult(Kernel::HLERequestContext& ctx) { + IPC::RequestParser rp(ctx, 0x13, 0, 0); // 0x130000 + + IPC::RequestBuilder rb = rp.MakeBuilder(3, 0); + rb.Push(RESULT_SUCCESS); + rb.Push(RESULT_SUCCESS); + rb.Push(0); + + LOG_WARNING(Service_NIM, "(STUBBED) called"); +} + +void NIM_U::CancelAsyncCall(Kernel::HLERequestContext& ctx) { + IPC::RequestParser rp(ctx, 0x14, 0, 0); // 0x140000 + + IPC::RequestBuilder rb = rp.MakeBuilder(1, 0); + rb.Push(RESULT_SUCCESS); + + LOG_WARNING(Service_NIM, "(STUBBED) called"); +} + +void NIM_U::IsPendingAutoTitleDownloadTasks(Kernel::HLERequestContext& ctx) { + IPC::RequestParser rp(ctx, 0x15, 0, 0); // 0x150000 + + IPC::RequestBuilder rb = rp.MakeBuilder(2, 0); + rb.Push(RESULT_SUCCESS); + rb.Push(false); + + LOG_WARNING(Service_NIM, "(STUBBED) called"); +} + +void NIM_U::GetNumAutoTitleDownloadTasks(Kernel::HLERequestContext& ctx) { + IPC::RequestParser rp(ctx, 0x16, 0, 0); // 0x160000 + + IPC::RequestBuilder rb = rp.MakeBuilder(2, 0); + rb.Push(RESULT_SUCCESS); + rb.Push(0); + + LOG_WARNING(Service_NIM, "(STUBBED) called"); +} + +void NIM_U::GetAutoTitleDownloadTaskInfos(Kernel::HLERequestContext& ctx) { + IPC::RequestParser rp(ctx, 0x17, 1, 2); // 0x170042 + + const u64 max_task_infos = rp.Pop(); + auto& task_infos_buffer = rp.PopMappedBuffer(); + + IPC::RequestBuilder rb = rp.MakeBuilder(2, 2); + rb.Push(RESULT_SUCCESS); + rb.Push(0); + rb.PushMappedBuffer(task_infos_buffer); + + LOG_WARNING(Service_NIM, "(STUBBED) called max_task_infos={:08X}, task_infos_buffer=0x{:08X}", + max_task_infos, task_infos_buffer.GetId()); +} + +void NIM_U::CancelAutoTitleDownloadTask(Kernel::HLERequestContext& ctx) { + IPC::RequestParser rp(ctx, 0x18, 2, 0); // 0x180080 + + const u64 task_id = rp.Pop(); + + IPC::RequestBuilder rb = rp.MakeBuilder(1, 0); + rb.Push(RESULT_SUCCESS); + + LOG_WARNING(Service_NIM, "(STUBBED) called task_id={:016X}", task_id); +} + +void NIM_U::SetAutoDbgDat(Kernel::HLERequestContext& ctx) { + IPC::RequestParser rp(ctx, 0x19, 0, 2); // 0x190002 + + auto& auto_dbg_dat_buffer = rp.PopMappedBuffer(); + + IPC::RequestBuilder rb = rp.MakeBuilder(1, 2); + rb.Push(RESULT_SUCCESS); + rb.PushMappedBuffer(auto_dbg_dat_buffer); + + LOG_WARNING(Service_NIM, "(STUBBED) called auto_dbg_dat_buffer=0x{:08X}", + auto_dbg_dat_buffer.GetId()); +} + +void NIM_U::GetAutoDbgDat(Kernel::HLERequestContext& ctx) { + IPC::RequestParser rp(ctx, 0x1A, 0, 2); // 0x1A0002 + + auto& auto_dbg_dat_buffer = rp.PopMappedBuffer(); + + IPC::RequestBuilder rb = rp.MakeBuilder(1, 2); + rb.Push(RESULT_SUCCESS); + rb.PushMappedBuffer(auto_dbg_dat_buffer); + + LOG_WARNING(Service_NIM, "(STUBBED) called auto_dbg_dat_buffer=0x{:08X}", + auto_dbg_dat_buffer.GetId()); +} + +void NIM_U::SetDbgTasks(Kernel::HLERequestContext& ctx) { + IPC::RequestParser rp(ctx, 0x1B, 1, 2); // 0x1B0042 + + const u64 max_task_infos = rp.Pop(); + auto& task_infos_buffer = rp.PopMappedBuffer(); + + IPC::RequestBuilder rb = rp.MakeBuilder(1, 2); + rb.Push(RESULT_SUCCESS); + rb.PushMappedBuffer(task_infos_buffer); + + LOG_WARNING(Service_NIM, "(STUBBED) called max_task_infos={:08X}, task_infos_buffer=0x{:08X}", + max_task_infos, task_infos_buffer.GetId()); +} + +void NIM_U::GetDbgTasks(Kernel::HLERequestContext& ctx) { + IPC::RequestParser rp(ctx, 0x1C, 1, 2); // 0x1C0042 + + const u64 max_task_infos = rp.Pop(); + auto& task_infos_buffer = rp.PopMappedBuffer(); + + IPC::RequestBuilder rb = rp.MakeBuilder(2, 2); + rb.Push(RESULT_SUCCESS); + rb.Push(0); + rb.PushMappedBuffer(task_infos_buffer); + + LOG_WARNING(Service_NIM, "(STUBBED) called max_task_infos={:08X}, task_infos_buffer=0x{:08X}", + max_task_infos, task_infos_buffer.GetId()); +} + +void NIM_U::DeleteDbgData(Kernel::HLERequestContext& ctx) { + IPC::RequestParser rp(ctx, 0x1D, 0, 0); // 0x1D0000 + + IPC::RequestBuilder rb = rp.MakeBuilder(1, 0); + rb.Push(RESULT_SUCCESS); + + LOG_WARNING(Service_NIM, "(STUBBED) called"); +} + +void NIM_U::SetTslXml(Kernel::HLERequestContext& ctx) { + IPC::RequestParser rp(ctx, 0x1E, 1, 2); // 0x1E0042 + + const u32 buffer_size = rp.Pop(); + auto& xml_buffer = rp.PopMappedBuffer(); + + IPC::RequestBuilder rb = rp.MakeBuilder(1, 2); + rb.Push(RESULT_SUCCESS); + rb.PushMappedBuffer(xml_buffer); + + LOG_WARNING(Service_NIM, "(STUBBED) called buffer_size={:08X}, xml_buffer=0x{:08X}", + buffer_size, xml_buffer.GetId()); +} + +void NIM_U::GetTslXmlSize(Kernel::HLERequestContext& ctx) { + IPC::RequestParser rp(ctx, 0x1F, 0, 0); // 0x1F0000 + + IPC::RequestBuilder rb = rp.MakeBuilder(3, 0); + rb.Push(RESULT_SUCCESS); + rb.Push(0); + + LOG_WARNING(Service_NIM, "(STUBBED) called"); +} + +void NIM_U::GetTslXml(Kernel::HLERequestContext& ctx) { + IPC::RequestParser rp(ctx, 0x20, 1, 2); // 0x200042 + + const u32 buffer_capacity = rp.Pop(); + auto& xml_buffer = rp.PopMappedBuffer(); + + IPC::RequestBuilder rb = rp.MakeBuilder(1, 2); + rb.Push(RESULT_SUCCESS); + rb.PushMappedBuffer(xml_buffer); + + LOG_WARNING(Service_NIM, "(STUBBED) called buffer_capacity={:08X}, xml_buffer=0x{:08X}", + buffer_capacity, xml_buffer.GetId()); +} + +void NIM_U::DeleteTslXml(Kernel::HLERequestContext& ctx) { + IPC::RequestParser rp(ctx, 0x21, 0, 0); // 0x210000 + + IPC::RequestBuilder rb = rp.MakeBuilder(1, 0); + rb.Push(RESULT_SUCCESS); + + LOG_WARNING(Service_NIM, "(STUBBED) called"); +} + +void NIM_U::SetDtlXml(Kernel::HLERequestContext& ctx) { + IPC::RequestParser rp(ctx, 0x22, 1, 2); // 0x220042 + + const u32 buffer_size = rp.Pop(); + auto& xml_buffer = rp.PopMappedBuffer(); + + IPC::RequestBuilder rb = rp.MakeBuilder(1, 2); + rb.Push(RESULT_SUCCESS); + rb.PushMappedBuffer(xml_buffer); + + LOG_WARNING(Service_NIM, "(STUBBED) called buffer_size={:08X}, xml_buffer=0x{:08X}", + buffer_size, xml_buffer.GetId()); +} + +void NIM_U::GetDtlXmlSize(Kernel::HLERequestContext& ctx) { + IPC::RequestParser rp(ctx, 0x23, 0, 0); // 0x230000 + + IPC::RequestBuilder rb = rp.MakeBuilder(3, 0); + rb.Push(RESULT_SUCCESS); + rb.Push(0); + + LOG_WARNING(Service_NIM, "(STUBBED) called"); +} + +void NIM_U::GetDtlXml(Kernel::HLERequestContext& ctx) { + IPC::RequestParser rp(ctx, 0x24, 1, 2); // 0x240042 + + const u32 buffer_capacity = rp.Pop(); + auto& xml_buffer = rp.PopMappedBuffer(); + + IPC::RequestBuilder rb = rp.MakeBuilder(1, 2); + rb.Push(RESULT_SUCCESS); + rb.PushMappedBuffer(xml_buffer); + + LOG_WARNING(Service_NIM, "(STUBBED) called buffer_capacity={:08X}, xml_buffer=0x{:08X}", + buffer_capacity, xml_buffer.GetId()); +} + +void NIM_U::UpdateAccountStatus(Kernel::HLERequestContext& ctx) { + IPC::RequestParser rp(ctx, 0x25, 0, 0); // 0x250000 + + IPC::RequestBuilder rb = rp.MakeBuilder(3, 0); + rb.Push(RESULT_SUCCESS); + rb.Push(RESULT_SUCCESS); + rb.Push(0); + + LOG_WARNING(Service_NIM, "(STUBBED) called"); +} + +void NIM_U::StartTitleDownload(Kernel::HLERequestContext& ctx) { + IPC::RequestParser rp(ctx, 0x26, 6, 0); // 0x260180 + + const auto& download_config = rp.PopRaw(); + + IPC::RequestBuilder rb = rp.MakeBuilder(1, 0); + rb.Push(RESULT_SUCCESS); + + LOG_WARNING(Service_NIM, "(STUBBED) called title_id={:016X}", download_config.title_id); +} + +void NIM_U::StopTitleDownload(Kernel::HLERequestContext& ctx) { + IPC::RequestParser rp(ctx, 0x27, 0, 0); // 0x270000 + + IPC::RequestBuilder rb = rp.MakeBuilder(1, 0); + rb.Push(RESULT_SUCCESS); + + LOG_WARNING(Service_NIM, "(STUBBED) called"); +} + +void NIM_U::GetTitleDownloadProgress(Kernel::HLERequestContext& ctx) { + IPC::RequestParser rp(ctx, 0x28, 0, 0); // 0x280000 + + TitleDownloadProgress progress{}; + std::memset(&progress, 0, sizeof(progress)); + + IPC::RequestBuilder rb = rp.MakeBuilder(9, 0); + rb.Push(RESULT_SUCCESS); + rb.PushRaw(progress); + rb.Push(0); + rb.Push(0); + + LOG_WARNING(Service_NIM, "(STUBBED) called"); +} + +void NIM_U::RegisterTask(Kernel::HLERequestContext& ctx) { + IPC::RequestParser rp(ctx, 0x29, 9, 6); // 0x290246 + + const auto& download_config = rp.PopRaw(); + const u32 unknown_1 = rp.Pop(); + const u32 unknown_2 = rp.Pop(); + const u32 unknown_3 = rp.Pop(); + const u32 pid = rp.PopPID(); + const auto& title_name = rp.PopStaticBuffer(); + const auto& developer_name = rp.PopStaticBuffer(); + + IPC::RequestBuilder rb = rp.MakeBuilder(1, 0); + rb.Push(RESULT_SUCCESS); + + const auto title_name_end = std::find(title_name.begin(), title_name.end(), u'\0'); + const auto title_name_utf8 = + Common::UTF16ToUTF8(std::u16string{title_name.begin(), title_name_end}); + + const auto developer_name_end = std::find(developer_name.begin(), developer_name.end(), u'\0'); + const auto developer_name_utf8 = + Common::UTF16ToUTF8(std::u16string{developer_name.begin(), developer_name_end}); + + LOG_WARNING(Service_NIM, + "(STUBBED) called title_id={:016X}, unknown_1={:08X}, unknown_2={:08X}, " + "unknown_3={:08X}, pid={:08X}, title_name='{}', developer_name='{}'", + download_config.title_id, unknown_1, unknown_2, unknown_3, pid, title_name_utf8, + developer_name_utf8); +} + +void NIM_U::IsSystemUpdateAvailable(Kernel::HLERequestContext& ctx) { + IPC::RequestParser rp(ctx, 0x2A, 0, 0); // 0x2A0000 + + IPC::RequestBuilder rb = rp.MakeBuilder(4, 0); + rb.Push(RESULT_SUCCESS); + rb.Push(RESULT_SUCCESS); + rb.Push(0); + rb.Push(false); + + LOG_WARNING(Service_NIM, "(STUBBED) called"); +} + +void NIM_U::Unknown2B(Kernel::HLERequestContext& ctx) { + IPC::RequestParser rp(ctx, 0x2B, 0, 0); // 0x2B0000 + + IPC::RequestBuilder rb = rp.MakeBuilder(1, 0); + rb.Push(RESULT_SUCCESS); + + LOG_WARNING(Service_NIM, "(STUBBED) called"); +} + +void NIM_U::UpdateTickets(Kernel::HLERequestContext& ctx) { + IPC::RequestParser rp(ctx, 0x2C, 0, 0); // 0x2C0000 + + IPC::RequestBuilder rb = rp.MakeBuilder(3, 0); + rb.Push(RESULT_SUCCESS); + rb.Push(RESULT_SUCCESS); + rb.Push(0); + + LOG_WARNING(Service_NIM, "(STUBBED) called"); +} + +void NIM_U::DownloadTitleSeedAsync(Kernel::HLERequestContext& ctx) { + IPC::RequestParser rp(ctx, 0x2D, 3, 0); // 0x2D00C0 + + const u64 title_id = rp.Pop(); + const u16 country_code = rp.Pop(); + + // Since this is a stub, signal the completion event so the caller won't get stuck waiting. + nim_async_completion_event->Signal(); + + IPC::RequestBuilder rb = rp.MakeBuilder(1, 2); + rb.Push(RESULT_SUCCESS); + rb.PushCopyObjects(nim_async_completion_event); + + LOG_WARNING(Service_NIM, "(STUBBED) called title_id={:016X}, country_code={:04X}", title_id, + country_code); +} + +void NIM_U::DownloadMissingTitleSeedsAsync(Kernel::HLERequestContext& ctx) { + IPC::RequestParser rp(ctx, 0x2E, 0, 0); // 0x2E0000 + + // Since this is a stub, signal the completion event so the caller won't get stuck waiting. + nim_async_completion_event->Signal(); + + IPC::RequestBuilder rb = rp.MakeBuilder(1, 2); + rb.Push(RESULT_SUCCESS); + rb.PushCopyObjects(nim_async_completion_event); LOG_WARNING(Service_NIM, "(STUBBED) called"); } diff --git a/src/core/hle/service/nim/nim_u.h b/src/core/hle/service/nim/nim_u.h index 98fec69b2..c3042e985 100644 --- a/src/core/hle/service/nim/nim_u.h +++ b/src/core/hle/service/nim/nim_u.h @@ -20,32 +20,522 @@ public: private: /** - * NIM::CheckForSysUpdateEvent service function + * NIM::StartNetworkUpdate service function * Inputs: * 1 : None * Outputs: * 1 : Result of function, 0 on success, otherwise error code - * 2 : Copy handle descriptor - * 3 : System Update event handle */ - void CheckForSysUpdateEvent(Kernel::HLERequestContext& ctx); + void StartNetworkUpdate(Kernel::HLERequestContext& ctx); /** - * NIM::CheckSysUpdateAvailable service function + * NIM::GetProgress service function * Inputs: * 1 : None * Outputs: * 1 : Result of function, 0 on success, otherwise error code - * 2 : u8 flag, 0 = no system update available, 1 = system update available. + * 2-11 : SystemUpdateProgress structure for the foreground system update + * 12: ? + * 13: ? */ - void CheckSysUpdateAvailable(Kernel::HLERequestContext& ctx); + void GetProgress(Kernel::HLERequestContext& ctx); - std::shared_ptr nim_system_update_event; + /** + * NIM::Cancel service function + * Inputs: + * 1 : None + * Outputs: + * 1 : Result of function, 0 on success, otherwise error code + */ + void Cancel(Kernel::HLERequestContext& ctx); + + /** + * NIM::CommitSystemTitles service function + * Inputs: + * 1 : None + * Outputs: + * 1 : Result of function, 0 on success, otherwise error code + */ + void CommitSystemTitles(Kernel::HLERequestContext& ctx); + + /** + * NIM::GetBackgroundEventForMenu service function + * Inputs: + * 1 : None + * Outputs: + * 1 : Result of function, 0 on success, otherwise error code + * 2 : Copy handle IPC header + * 3 : System update ready event handle for home menu + */ + void GetBackgroundEventForMenu(Kernel::HLERequestContext& ctx); + + /** + * NIM::GetBackgroundEventForNews service function + * Inputs: + * 1 : None + * Outputs: + * 1 : Result of function, 0 on success, otherwise error code + * 2 : Copy handle IPC header + * 3 : System update ready event handle for news module + */ + void GetBackgroundEventForNews(Kernel::HLERequestContext& ctx); + + /** + * NIM::FormatSaveData service function + * Inputs: + * 1 : None + * Outputs: + * 1 : Result of function, 0 on success, otherwise error code + */ + void FormatSaveData(Kernel::HLERequestContext& ctx); + + /** + * NIM::GetCustomerSupportCode service function + * Inputs: + * 1 : None + * Outputs: + * 1 : Result of function, 0 on success, otherwise error code + * 2 : Customer support code for the last system update error + */ + void GetCustomerSupportCode(Kernel::HLERequestContext& ctx); + + /** + * NIM::IsCommittableAllSystemTitles service function + * Inputs: + * 1 : None + * Outputs: + * 1 : Result of function, 0 on success, otherwise error code + * 2 : Boolean indicating whether system titles are ready to commit + */ + void IsCommittableAllSystemTitles(Kernel::HLERequestContext& ctx); + + /** + * NIM::GetBackgroundProgress service function + * Inputs: + * 1 : None + * Outputs: + * 1 : Result of function, 0 on success, otherwise error code + * 2-11 : SystemUpdateProgress structure for the background system update + * 12: ? + * 13: ? + */ + void GetBackgroundProgress(Kernel::HLERequestContext& ctx); + + /** + * NIM::GetSavedHash service function + * Inputs: + * 1 : None + * Outputs: + * 1 : Result of function, 0 on success, otherwise error code + * 2-10 : NUL-terminated saved system update hash + */ + void GetSavedHash(Kernel::HLERequestContext& ctx); + + /** + * NIM::UnregisterTask service function + * Inputs: + * 1-2 : Title ID + * 3 : Process ID IPC Header + * 4 : Process ID (Auto-filled by kernel) + * Outputs: + * 1 : Result of function, 0 on success, otherwise error code + */ + void UnregisterTask(Kernel::HLERequestContext& ctx); + + /** + * NIM::IsRegistered service function + * Inputs: + * 1-2 : Title ID + * Outputs: + * 1 : Result of function, 0 on success, otherwise error code + * 2 : Boolean indicating whether a download task is registered for the title ID + */ + void IsRegistered(Kernel::HLERequestContext& ctx); + + /** + * NIM::FindTaskInfo service function + * Inputs: + * 1-2 : Title ID + * Outputs: + * 1 : Result of function, 0 on success, otherwise error code + * 2 : Static Buffer IPC Header (ID = 0, Size = 0x120) + * 3 : BackgroundTitleDownloadTaskInfo structure pointer + */ + void FindTaskInfo(Kernel::HLERequestContext& ctx); + + /** + * NIM::GetTaskInfos service function + * Inputs: + * 1 : Maximum Number of BackgroundTitleDownloadTaskInfos + * 2 : Mapped Output Buffer IPC Header + * 3 : BackgroundTitleDownloadTaskInfos Output Buffer Pointer + * Outputs: + * 1 : Result of function, 0 on success, otherwise error code + * 2 : Number of BackgroundTitleDownloadTaskInfos Read + * 3 : Mapped Output Buffer IPC Header + * 4 : BackgroundTitleDownloadTaskInfos Output Buffer Pointer + */ + void GetTaskInfos(Kernel::HLERequestContext& ctx); + + /** + * NIM::DeleteUnmanagedContexts service function + * Inputs: + * 1 : None + * Outputs: + * 1 : Result of function, 0 on success, otherwise error code + */ + void DeleteUnmanagedContexts(Kernel::HLERequestContext& ctx); + + /** + * NIM::UpdateAutoTitleDownloadTasksAsync service function + * Inputs: + * 1 : None + * Outputs: + * 1 : Result of function, 0 on success, otherwise error code + * 2 : Copy Handle IPC Header + * 3 : Event handle signaled when the operation completes + */ + void UpdateAutoTitleDownloadTasksAsync(Kernel::HLERequestContext& ctx); + + /** + * NIM::StartPendingAutoTitleDownloadTasksAsync service function + * Inputs: + * 1 : None + * Outputs: + * 1 : Result of function, 0 on success, otherwise error code + * 2 : Copy Handle IPC Header + * 3 : Event handle signaled when the operation completes + */ + void StartPendingAutoTitleDownloadTasksAsync(Kernel::HLERequestContext& ctx); + + /** + * NIM::GetAsyncResult service function + * Inputs: + * 1 : None + * Outputs: + * 1 : Result of function, 0 on success, otherwise error code + * 2 : Async operation result code + * 3 : Async operation customer support code + */ + void GetAsyncResult(Kernel::HLERequestContext& ctx); + + /** + * NIM::CancelAsyncCall service function + * Inputs: + * 1 : None + * Outputs: + * 1 : Result of function, 0 on success, otherwise error code + */ + void CancelAsyncCall(Kernel::HLERequestContext& ctx); + + /** + * NIM::IsPendingAutoTitleDownloadTasks service function + * Inputs: + * 1 : None + * Outputs: + * 1 : Result of function, 0 on success, otherwise error code + * 2 : Boolean indicating whether there are auto title downloads ready to start + */ + void IsPendingAutoTitleDownloadTasks(Kernel::HLERequestContext& ctx); + + /** + * NIM::GetNumAutoTitleDownloadTasks service function + * Inputs: + * 1 : None + * Outputs: + * 1 : Result of function, 0 on success, otherwise error code + * 2 : Number of auto title download tasks + */ + void GetNumAutoTitleDownloadTasks(Kernel::HLERequestContext& ctx); + + /** + * NIM::GetAutoTitleDownloadTasks service function + * Inputs: + * 1 : Maximum number of AutoTitleDownloadTaskInfos + * 2 : Mapped Output Buffer IPC Header + * 3 : AutoTitleDownloadTaskInfos Output Buffer Pointer + * Outputs: + * 1 : Result of function, 0 on success, otherwise error code + * 2 : Number of AutoTitleDownloadTaskInfos Read + * 3 : Mapped Output Buffer IPC Header + * 4 : AutoTitleDownloadTaskInfos Output Buffer Pointer + */ + void GetAutoTitleDownloadTaskInfos(Kernel::HLERequestContext& ctx); + + /** + * NIM::CancelAutoTitleDownloadTask service function + * Inputs: + * 1-2 : Auto Title Download Task ID + * Outputs: + * 1 : Result of function, 0 on success, otherwise error code + */ + void CancelAutoTitleDownloadTask(Kernel::HLERequestContext& ctx); + + /** + * NIM::SetAutoDbgDat service function + * Inputs: + * 1 : Mapped Input Buffer IPC Header + * 2 : AutoDbgDat Input Buffer Pointer + * Outputs: + * 1 : Result of function, 0 on success, otherwise error code + * 2 : Mapped Input Buffer IPC Header + * 3 : AutoDbgDat Input Buffer Pointer + */ + void SetAutoDbgDat(Kernel::HLERequestContext& ctx); + + /** + * NIM::GetAutoDbgDat service function + * Inputs: + * 1 : Mapped Output Buffer IPC Header + * 2 : AutoDbgDat Output Buffer Pointer + * Outputs: + * 1 : Result of function, 0 on success, otherwise error code + * 2 : Mapped Output Buffer IPC Header + * 3 : AutoDbgDat Output Buffer Pointer + */ + void GetAutoDbgDat(Kernel::HLERequestContext& ctx); + + /** + * NIM::SetDbgTasks service function + * Inputs: + * 1 : Number of AutoTitleDownloadTaskInfos + * 2 : Mapped Input Buffer IPC Header + * 3 : AutoTitleDownloadTaskInfos Input Buffer Pointer + * Outputs: + * 1 : Result of function, 0 on success, otherwise error code + * 3 : Mapped Input Buffer IPC Header + * 4 : AutoTitleDownloadTaskInfos Input Buffer Pointer + */ + void SetDbgTasks(Kernel::HLERequestContext& ctx); + + /** + * NIM::GetDbgTasks service function + * Inputs: + * 1 : Maximum number of AutoTitleDownloadTaskInfos + * 2 : Mapped Output Buffer IPC Header + * 3 : AutoTitleDownloadTaskInfos Output Buffer Pointer + * Outputs: + * 1 : Result of function, 0 on success, otherwise error code + * 2 : Number of AutoTitleDownloadTaskInfos Read + * 3 : Mapped Output Buffer IPC Header + * 4 : AutoTitleDownloadTaskInfos Output Buffer Pointer + */ + void GetDbgTasks(Kernel::HLERequestContext& ctx); + + /** + * NIM::DeleteDbgData service function + * Inputs: + * 1 : None + * Outputs: + * 1 : Result of function, 0 on success, otherwise error code + */ + void DeleteDbgData(Kernel::HLERequestContext& ctx); + + /** + * NIM::SetTslXml service function + * Inputs: + * 1 : Buffer Size + * 2 : Mapped Input Buffer IPC Header + * 3 : XML Input Buffer Pointer + * Outputs: + * 1 : Result of function, 0 on success, otherwise error code + * 2 : Mapped Input Buffer IPC Header + * 3 : XML Input Buffer Pointer + */ + void SetTslXml(Kernel::HLERequestContext& ctx); + + /** + * NIM::GetTslXmlSize service function + * Inputs: + * 1 : None + * Outputs: + * 1 : Result of function, 0 on success, otherwise error code + * 2-3 : XML Size + */ + void GetTslXmlSize(Kernel::HLERequestContext& ctx); + + /** + * NIM::GetTslXml service function + * Inputs: + * 1 : Buffer Capacity + * 2 : Mapped Output Buffer IPC Header + * 3 : XML Output Buffer Pointer + * Outputs: + * 1 : Result of function, 0 on success, otherwise error code + * 2 : Mapped Output Buffer IPC Header + * 3 : XML Output Buffer Pointer + */ + void GetTslXml(Kernel::HLERequestContext& ctx); + + /** + * NIM::DeleteTslXml service function + * Inputs: + * 1 : None + * Outputs: + * 1 : Result of function, 0 on success, otherwise error code + */ + void DeleteTslXml(Kernel::HLERequestContext& ctx); + + /** + * NIM::SetDtlXml service function + * Inputs: + * 1 : Buffer Size + * 2 : Mapped Input Buffer IPC Header + * 3 : XML Input Buffer Pointer + * Outputs: + * 1 : Result of function, 0 on success, otherwise error code + * 2 : Mapped Input Buffer IPC Header + * 3 : XML Input Buffer Pointer + */ + void SetDtlXml(Kernel::HLERequestContext& ctx); + + /** + * NIM::GetDtlXmlSize service function + * Inputs: + * 1 : None + * Outputs: + * 1 : Result of function, 0 on success, otherwise error code + * 2-3 : XML Size + */ + void GetDtlXmlSize(Kernel::HLERequestContext& ctx); + + /** + * NIM::GetDtlXml service function + * Inputs: + * 1 : Buffer Capacity + * 2 : Mapped Output Buffer IPC Header + * 3 : XML Output Buffer Pointer + * Outputs: + * 1 : Result of function, 0 on success, otherwise error code + * 2 : Mapped Output Buffer IPC Header + * 3 : XML Output Buffer Pointer + */ + void GetDtlXml(Kernel::HLERequestContext& ctx); + + /** + * NIM::UpdateAccountStatus service function + * Inputs: + * 1 : None + * Outputs: + * 1 : Result of function, 0 on success, otherwise error code + * 2 : Result of the actual operation + * 3 : Customer support code of the actual operation + */ + void UpdateAccountStatus(Kernel::HLERequestContext& ctx); + + /** + * NIM::StartTitleDownload service function + * Inputs: + * 1-6 : TitleDownloadConfig structure + * Outputs: + * 1 : Result of function, 0 on success, otherwise error code + */ + void StartTitleDownload(Kernel::HLERequestContext& ctx); + + /** + * NIM::StopDownload service function + * Inputs: + * 1 : None + * Outputs: + * 1 : Result of function, 0 on success, otherwise error code + */ + void StopTitleDownload(Kernel::HLERequestContext& ctx); + + /** + * NIM::GetTitleDownloadProgress service function + * Inputs: + * 1 : None + * Outputs: + * 1 : Result of function, 0 on success, otherwise error code + * 2-7 : TitleDownloadProgress structure + * 8: ? + * 9: ? + */ + void GetTitleDownloadProgress(Kernel::HLERequestContext& ctx); + + /** + * NIM::RegisterTask service function + * Inputs: + * 1-6 : TitleDownloadConfig structure + * 7: ? + * 8: ? + * 9: ? + * 10: Process ID IPC Header + * 11: Process ID (Auto-filled by Kernel) + * 12: Static Buffer IPC Header (ID = 0, Size = 0x90) + * 13: Title Name UTF-16 String Pointer + * 14: Static Buffer IPC Header (ID = 1, Size = 0x48) + * 15: Developer Name UTF-16 String Pointer + * Outputs: + * 1 : Result of function, 0 on success, otherwise error code + */ + void RegisterTask(Kernel::HLERequestContext& ctx); + + /** + * NIM::IsSystemUpdateAvailable service function + * Inputs: + * 1 : None + * Outputs: + * 1 : Result of function, 0 on success, otherwise error code + * 2 : Result code from the actual operation + * 3 : Customer support code from the actual operation + * 4 : Boolean indicating whether a system update is available + */ + void IsSystemUpdateAvailable(Kernel::HLERequestContext& ctx); + + /** + * NIM::Unknown2B service function + * Inputs: + * 1 : None + * Outputs: + * 1 : Result of function, 0 on success, otherwise error code + */ + void Unknown2B(Kernel::HLERequestContext& ctx); + + /** + * NIM::UpdateTickets service function + * Inputs: + * 1 : None + * Outputs: + * 1 : Result of function, 0 on success, otherwise error code + * 2 : Result code from the actual operation + * 3 : Customer support code from the actual operation + */ + void UpdateTickets(Kernel::HLERequestContext& ctx); + + /** + * NIM::DownloadTitleSeedAsync service function + * Inputs: + * 1-2 : Title ID + * 3: u16 Country Code + * Outputs: + * 1 : Result of function, 0 on success, otherwise error code + * 2 : Copy Handle IPC Header + * 3 : Event handle signaled when the operation completes + */ + void DownloadTitleSeedAsync(Kernel::HLERequestContext& ctx); + + /** + * NIM::DownloadMissingTitleSeedsAsync service function + * Inputs: + * 1 : None + * Outputs: + * 1 : Result of function, 0 on success, otherwise error code + * 2 : Copy Handle IPC Header + * 3 : Event handle signaled when the operation completes + */ + void DownloadMissingTitleSeedsAsync(Kernel::HLERequestContext& ctx); + + std::shared_ptr nim_system_update_event_for_menu; + std::shared_ptr nim_system_update_event_for_news; + std::shared_ptr nim_async_completion_event; template void serialize(Archive& ar, const unsigned int) { ar& boost::serialization::base_object(*this); - ar& nim_system_update_event; + ar& nim_system_update_event_for_menu; + ar& nim_system_update_event_for_news; + ar& nim_async_completion_event; } friend class boost::serialization::access; };