From dd87821bad0e29392291b36b919bb257055bbdb9 Mon Sep 17 00:00:00 2001 From: Nomi Date: Tue, 26 Sep 2023 07:12:12 +0200 Subject: [PATCH] Add nim:u service --- include/kernel/handles.hpp | 6 +- include/services/nim.hpp | 19 ++++++- src/core/services/nim.cpp | 79 +++++++++++++++++++++++++-- src/core/services/service_manager.cpp | 10 ++-- 4 files changed, 100 insertions(+), 14 deletions(-) diff --git a/include/kernel/handles.hpp b/include/kernel/handles.hpp index e3ccf165..2dd80c31 100644 --- a/include/kernel/handles.hpp +++ b/include/kernel/handles.hpp @@ -35,7 +35,8 @@ namespace KernelHandles { MCU_HWC, // Used for various MCU hardware-related things like battery control MIC, // MIC service (Controls the microphone) NFC, // NFC (Duh), used for Amiibo - NIM, // Updates, DLC, etc + NIM_AOC, // DLC, etc + NIM_U, // Updates NDM, // ????? NS_S, // Nintendo Shell service NWM_UDS, // Local multiplayer @@ -100,7 +101,8 @@ namespace KernelHandles { case NEWS_U: return "NEWS_U"; case NWM_UDS: return "nwm::UDS"; case NFC: return "NFC"; - case NIM: return "NIM"; + case NIM_AOC: return "NIM:AOC"; + case NIM_U: return "NIM:U"; case PTM_U: return "PTM:U"; case PTM_SYSM: return "PTM:SYSM"; case PTM_PLAY: return "PTM:PLAY"; diff --git a/include/services/nim.hpp b/include/services/nim.hpp index dfe13694..55e5655b 100644 --- a/include/services/nim.hpp +++ b/include/services/nim.hpp @@ -5,16 +5,29 @@ #include "memory.hpp" #include "result/result.hpp" +class Kernel; + class NIMService { - Handle handle = KernelHandles::NIM; Memory& mem; + Kernel& kernel; MAKE_LOG_FUNCTION(log, nimLogger) + std::optional backgroundSystemUpdateEvent; + // Service commands + void getAutoTitleDownloadTaskInfos(u32 messagePointer); + void getBackgroundEventForMenu(u32 messagePointer); + void getTaskInfos(u32 messagePointer); void initialize(u32 messagePointer); + void isPendingAutoTitleDownloadTasks(u32 messagePointer); public: - NIMService(Memory& mem) : mem(mem) {} + enum class Type { + AOC, // nim:aoc + U, // nim:u + }; + + NIMService(Memory& mem, Kernel& kernel) : mem(mem), kernel(kernel) {} void reset(); - void handleSyncRequest(u32 messagePointer); + void handleSyncRequest(u32 messagePointer, Type type); }; \ No newline at end of file diff --git a/src/core/services/nim.cpp b/src/core/services/nim.cpp index e4e14c1c..ed305881 100644 --- a/src/core/services/nim.cpp +++ b/src/core/services/nim.cpp @@ -1,19 +1,43 @@ #include "services/nim.hpp" #include "ipc.hpp" +#include "kernel.hpp" namespace NIMCommands { enum : u32 { - Initialize = 0x00210000 + GetBackgroundEventForMenu = 0x00050000, + GetTaskInfos = 0x000F0042, + IsPendingAutoTitleDownloadTasks = 0x00150000, + GetAutoTitleDownloadTaskInfos = 0x00170042, + Initialize = 0x00210000, }; } -void NIMService::reset() {} +void NIMService::reset() { + backgroundSystemUpdateEvent = std::nullopt; +} -void NIMService::handleSyncRequest(u32 messagePointer) { +void NIMService::handleSyncRequest(u32 messagePointer, Type type) { const u32 command = mem.read32(messagePointer); switch (command) { - case NIMCommands::Initialize: initialize(messagePointer); break; - default: Helpers::panic("NIM service requested. Command: %08X\n", command); + default: + if (type == Type::AOC) { + switch (command) { + case NIMCommands::Initialize: initialize(messagePointer); break; + + default: Helpers::panic("NIM AOC service requested. Command: %08X\n", command); + } + } else if (type == Type::U) { + switch (command) { + case NIMCommands::GetAutoTitleDownloadTaskInfos: getAutoTitleDownloadTaskInfos(messagePointer); break; + case NIMCommands::GetBackgroundEventForMenu: getBackgroundEventForMenu(messagePointer); break; + case NIMCommands::GetTaskInfos: getTaskInfos(messagePointer); break; + case NIMCommands::IsPendingAutoTitleDownloadTasks: isPendingAutoTitleDownloadTasks(messagePointer); break; + + default: Helpers::panic("NIM U service requested. Command: %08X\n", command); + } + } else { + Helpers::panic("NIM service requested. Command: %08X\n", command); + } } } @@ -21,4 +45,49 @@ void NIMService::initialize(u32 messagePointer) { log("NIM::Initialize\n"); mem.write32(messagePointer, IPC::responseHeader(0x21, 1, 0)); mem.write32(messagePointer + 4, Result::Success); +} + +void NIMService::getTaskInfos(u32 messagePointer) { + const u32 numTaskInfos = mem.read32(messagePointer + 4); + const u32 taskInfos = mem.read32(messagePointer + 12); + log("NIM::GetTaskInfos (num task infos = %X, task infos pointer = %X) (stubbed)\n", numTaskInfos, taskInfos); + + mem.write32(messagePointer, IPC::responseHeader(0xF, 2, 2)); + mem.write32(messagePointer + 4, Result::Success); + mem.write32(messagePointer + 8, 0); // Read task infos? + mem.write32(messagePointer + 12, IPC::pointerHeader(0, 0, IPC::BufferType::Receive)); + mem.write32(messagePointer + 16, taskInfos); +} + +void NIMService::getAutoTitleDownloadTaskInfos(u32 messagePointer) { + const u32 numTaskInfos = mem.read32(messagePointer + 4); + const u32 taskInfos = mem.read32(messagePointer + 12); + log("NIM::GetAutoTitleDownloadTaskInfos (num task infos = %X, task infos pointer = %X) (stubbed)\n", numTaskInfos, taskInfos); + + mem.write32(messagePointer, IPC::responseHeader(0x17, 2, 2)); + mem.write32(messagePointer + 4, Result::Success); + mem.write32(messagePointer + 8, 0); // Read task infos? + mem.write32(messagePointer + 12, IPC::pointerHeader(0, 0, IPC::BufferType::Receive)); + mem.write32(messagePointer + 16, taskInfos); +} + +void NIMService::isPendingAutoTitleDownloadTasks(u32 messagePointer) { + log("NIM::IsPendingAutoTitleDownloadTasks\n"); + + mem.write32(messagePointer, IPC::responseHeader(0x15, 2, 0)); + mem.write32(messagePointer + 4, Result::Success); + mem.write8(messagePointer + 8, 0); // Has pending tasks +} + +void NIMService::getBackgroundEventForMenu(u32 messagePointer) { + log("NIM::GetBackgroundEventForMenu\n"); + + if (!backgroundSystemUpdateEvent.has_value()) { + backgroundSystemUpdateEvent = kernel.makeEvent(ResetType::OneShot); + } + + mem.write32(messagePointer, IPC::responseHeader(0x5, 1, 2)); + mem.write32(messagePointer + 4, Result::Success); + mem.write32(messagePointer + 8, 0x04000000); + mem.write32(messagePointer + 12, backgroundSystemUpdateEvent.value()); } \ No newline at end of file diff --git a/src/core/services/service_manager.cpp b/src/core/services/service_manager.cpp index 8f8a9cf4..d176a689 100644 --- a/src/core/services/service_manager.cpp +++ b/src/core/services/service_manager.cpp @@ -8,8 +8,8 @@ ServiceManager::ServiceManager(std::span regs, Memory& mem, GPU& gpu, u32& currentPID, Kernel& kernel, const EmulatorConfig& config) : regs(regs), mem(mem), kernel(kernel), ac(mem), am(mem), boss(mem), act(mem), apt(mem, kernel), cam(mem, kernel), cecd(mem, kernel), cfg(mem), csnd(mem, kernel), dlp_srvr(mem), dsp(mem, kernel), hid(mem, kernel), http(mem), ir_user(mem, kernel), frd(mem), fs(mem, kernel, config), - gsp_gpu(mem, gpu, kernel, currentPID), gsp_lcd(mem), ldr(mem, kernel), mcu_hwc(mem, config), mic(mem, kernel), nfc(mem, kernel), nim(mem), ndm(mem), - news_u(mem), nwm_uds(mem, kernel), ns(mem), ptm(mem, config), soc(mem), ssl(mem), y2r(mem, kernel) {} + gsp_gpu(mem, gpu, kernel, currentPID), gsp_lcd(mem), ldr(mem, kernel), mcu_hwc(mem, config), mic(mem, kernel), nfc(mem, kernel), nim(mem, kernel), ndm(mem), + news_s(mem), news_u(mem), nwm_uds(mem, kernel), ns(mem), ptm(mem, config), soc(mem), ssl(mem), y2r(mem, kernel) {} static constexpr int MAX_NOTIFICATION_COUNT = 16; @@ -126,7 +126,8 @@ static std::map serviceMap = { { "nfc:u", KernelHandles::NFC }, { "ns:s", KernelHandles::NS_S }, { "nwm::UDS", KernelHandles::NWM_UDS }, - { "nim:aoc", KernelHandles::NIM }, + { "nim:aoc", KernelHandles::NIM_AOC }, + { "nim:u", KernelHandles::NIM_U }, { "ptm:u", KernelHandles::PTM_U }, // TODO: ptm:u and ptm:sysm have very different command sets { "ptm:sysm", KernelHandles::PTM_SYSM }, { "ptm:play", KernelHandles::PTM_PLAY }, @@ -225,7 +226,8 @@ void ServiceManager::sendCommandToService(u32 messagePointer, Handle handle) { case KernelHandles::MCU_HWC: mcu_hwc.handleSyncRequest(messagePointer); break; case KernelHandles::MIC: mic.handleSyncRequest(messagePointer); break; case KernelHandles::NFC: nfc.handleSyncRequest(messagePointer); break; - case KernelHandles::NIM: nim.handleSyncRequest(messagePointer); break; + case KernelHandles::NIM_AOC: nim.handleSyncRequest(messagePointer, NIMService::Type::AOC); break; + case KernelHandles::NIM_U: nim.handleSyncRequest(messagePointer, NIMService::Type::U); break; case KernelHandles::NDM: ndm.handleSyncRequest(messagePointer); break; case KernelHandles::NEWS_U: news_u.handleSyncRequest(messagePointer); break; case KernelHandles::NS_S: ns.handleSyncRequest(messagePointer, NSService::Type::S); break;