From 135c8cb508fda0ec454833c39616d12d58b3ce5d Mon Sep 17 00:00:00 2001 From: wheremyfoodat <44909372+wheremyfoodat@users.noreply.github.com> Date: Sat, 11 Nov 2023 20:11:40 +0200 Subject: [PATCH 1/6] [Applets] Proper glance/receiveParameter sorta --- include/applets/applet_manager.hpp | 7 +++++ include/services/apt.hpp | 25 ++++++++++++++++ src/core/applets/applet_manager.cpp | 29 ++++++++++++++++++ src/core/services/apt.cpp | 46 +++++++++-------------------- 4 files changed, 75 insertions(+), 32 deletions(-) diff --git a/include/applets/applet_manager.hpp b/include/applets/applet_manager.hpp index 95b540090..e75e1268e 100644 --- a/include/applets/applet_manager.hpp +++ b/include/applets/applet_manager.hpp @@ -1,3 +1,6 @@ +#pragma once +#include + #include "applets/mii_selector.hpp" #include "applets/software_keyboard.hpp" #include "helpers.hpp" @@ -8,10 +11,14 @@ namespace Applets { class AppletManager { MiiSelectorApplet miiSelector; SoftwareKeyboardApplet swkbd; + std::optional nextParameter = std::nullopt; public: AppletManager(Memory& mem); void reset(); AppletBase* getApplet(u32 id); + + Applets::Parameter glanceParameter(); + Applets::Parameter receiveParameter(); }; } // namespace Applets \ No newline at end of file diff --git a/include/services/apt.hpp b/include/services/apt.hpp index a7df056fe..48a59c2d1 100644 --- a/include/services/apt.hpp +++ b/include/services/apt.hpp @@ -15,6 +15,31 @@ enum class ConsoleModel : u32 { Old3DS, New3DS }; +// https://www.3dbrew.org/wiki/NS_and_APT_Services#Command +namespace APT::Transitions { + enum : u32 { + None = 0, + Wakeup = 1, + Request = 2, + Response = 3, + Exit = 4, + Message = 5, + HomeButtonSingle = 6, + HomeButtonDouble = 7, + DSPSleep = 8, + DSPWakeup = 9, + WakeupByExit = 10, + WakuepByPause = 11, + WakeupByCancel = 12, + WakeupByCancelAll = 13, + WakeupByPowerButton = 14, + WakeupToJumpHome = 15, + RequestForApplet = 16, + WakeupToLaunchApp = 17, + ProcessDed = 0x41 + }; +} + class APTService { Handle handle = KernelHandles::APT; Memory& mem; diff --git a/src/core/applets/applet_manager.cpp b/src/core/applets/applet_manager.cpp index c94eee280..192a76c02 100644 --- a/src/core/applets/applet_manager.cpp +++ b/src/core/applets/applet_manager.cpp @@ -1,4 +1,7 @@ #include "applets/applet_manager.hpp" + +#include "services/apt.hpp" + using namespace Applets; AppletManager::AppletManager(Memory& mem) : miiSelector(mem), swkbd(mem) {} @@ -18,4 +21,30 @@ AppletBase* AppletManager::getApplet(u32 id) { default: return nullptr; } +} + +Applets::Parameter AppletManager::glanceParameter() { + if (nextParameter) { + // Copy parameter + Applets::Parameter param = nextParameter.value(); + // APT module clears next parameter even for GlanceParameter for these 2 signals + if (param.signal == APTSignal::DspWakeup || param.signal == APTSignal::DspSleep) { + nextParameter = std::nullopt; + } + + return param; + } + + // Default return value. This is legacy code from before applets were implemented. TODO: Update it + else { + return Applets::Parameter{.senderID = 0, .destID = Applets::AppletIDs::Application, .signal = APTSignal::Wakeup, .data = {}}; + } +} + +Applets::Parameter AppletManager::receiveParameter() { + Applets::Parameter param = glanceParameter(); + // ReceiveParameter always clears nextParameter whereas glanceParameter does not + nextParameter = std::nullopt; + + return param; } \ No newline at end of file diff --git a/src/core/services/apt.cpp b/src/core/services/apt.cpp index d969f2a44..64ff5cef6 100644 --- a/src/core/services/apt.cpp +++ b/src/core/services/apt.cpp @@ -32,31 +32,6 @@ namespace APTCommands { }; } -// https://www.3dbrew.org/wiki/NS_and_APT_Services#Command -namespace APTTransitions { - enum : u32 { - None = 0, - Wakeup = 1, - Request = 2, - Response = 3, - Exit = 4, - Message = 5, - HomeButtonSingle = 6, - HomeButtonDouble = 7, - DSPSleep = 8, - DSPWakeup = 9, - WakeupByExit = 10, - WakuepByPause = 11, - WakeupByCancel = 12, - WakeupByCancelAll = 13, - WakeupByPowerButton = 14, - WakeupToJumpHome = 15, - RequestForApplet = 16, - WakeupToLaunchApp = 17, - ProcessDed = 0x41 - }; -} - void APTService::reset() { // Set the default CPU time limit to 30%. Seems safe, as this is what Metroid 2 uses by default cpuTimeLimit = 30; @@ -273,13 +248,16 @@ void APTService::receiveParameter(u32 messagePointer) { log("APT::ReceiveParameter(app ID = %X, size = %04X) (STUBBED)\n", app, size); if (size > 0x1000) Helpers::panic("APT::ReceiveParameter with size > 0x1000"); + auto parameter = appletManager.receiveParameter(); - // TODO: Properly implement this. We currently stub somewhat like 3dmoo mem.write32(messagePointer, IPC::responseHeader(0xD, 4, 4)); mem.write32(messagePointer + 4, Result::Success); - mem.write32(messagePointer + 8, 0); // Sender App ID - mem.write32(messagePointer + 12, APTTransitions::Wakeup); // Command - mem.write32(messagePointer + 16, 0); + // Sender App ID + mem.write32(messagePointer + 8, parameter.senderID); + // Command + mem.write32(messagePointer + 12, static_cast(parameter.signal)); + // Size of parameter data + mem.write32(messagePointer + 16, parameter.data.size()); mem.write32(messagePointer + 20, 0x10); mem.write32(messagePointer + 24, 0); mem.write32(messagePointer + 28, 0); @@ -291,13 +269,17 @@ void APTService::glanceParameter(u32 messagePointer) { log("APT::GlanceParameter(app ID = %X, size = %04X) (STUBBED)\n", app, size); if (size > 0x1000) Helpers::panic("APT::GlanceParameter with size > 0x1000"); + auto parameter = appletManager.glanceParameter(); // TODO: Properly implement this. We currently stub it similar mem.write32(messagePointer, IPC::responseHeader(0xE, 4, 4)); mem.write32(messagePointer + 4, Result::Success); - mem.write32(messagePointer + 8, 0); // Sender App ID - mem.write32(messagePointer + 12, APTTransitions::Wakeup); // Command - mem.write32(messagePointer + 16, 0); + // Sender App ID + mem.write32(messagePointer + 8, parameter.senderID); + // Command + mem.write32(messagePointer + 12, static_cast(parameter.signal)); + // Size of parameter data + mem.write32(messagePointer + 16, parameter.data.size()); mem.write32(messagePointer + 20, 0); mem.write32(messagePointer + 24, 0); mem.write32(messagePointer + 28, 0); From 60b565273e881d8bf579c00cecbed8ef907cf43c Mon Sep 17 00:00:00 2001 From: wheremyfoodat <44909372+wheremyfoodat@users.noreply.github.com> Date: Sat, 11 Nov 2023 20:35:10 +0200 Subject: [PATCH 2/6] [Applets] Properly expose nextParameter --- include/applets/applet.hpp | 4 +++- include/applets/mii_selector.hpp | 2 +- include/applets/software_keyboard.hpp | 2 +- src/core/applets/applet_manager.cpp | 2 +- src/core/applets/software_keyboard.cpp | 9 +++++++++ 5 files changed, 15 insertions(+), 4 deletions(-) diff --git a/include/applets/applet.hpp b/include/applets/applet.hpp index 0c3ab519b..f1a91afd8 100644 --- a/include/applets/applet.hpp +++ b/include/applets/applet.hpp @@ -72,7 +72,9 @@ namespace Applets { }; class AppletBase { + protected: Memory& mem; + std::optional& nextParameter; public: virtual const char* name() = 0; @@ -83,6 +85,6 @@ namespace Applets { virtual Result::HorizonResult receiveParameter() = 0; virtual void reset() = 0; - AppletBase(Memory& mem) : mem(mem) {} + AppletBase(Memory& mem, std::optional& nextParam) : mem(mem), nextParameter(nextParam) {} }; } // namespace Applets \ No newline at end of file diff --git a/include/applets/mii_selector.hpp b/include/applets/mii_selector.hpp index e40547fbd..7a8826155 100644 --- a/include/applets/mii_selector.hpp +++ b/include/applets/mii_selector.hpp @@ -8,6 +8,6 @@ namespace Applets { virtual Result::HorizonResult receiveParameter() override; virtual void reset() override; - MiiSelectorApplet(Memory& memory) : AppletBase(memory) {} + MiiSelectorApplet(Memory& memory, std::optional& nextParam) : AppletBase(memory, nextParam) {} }; } // namespace Applets \ No newline at end of file diff --git a/include/applets/software_keyboard.hpp b/include/applets/software_keyboard.hpp index 1fb721a1a..89b879539 100644 --- a/include/applets/software_keyboard.hpp +++ b/include/applets/software_keyboard.hpp @@ -8,6 +8,6 @@ namespace Applets { virtual Result::HorizonResult receiveParameter() override; virtual void reset() override; - SoftwareKeyboardApplet(Memory& memory) : AppletBase(memory) {} + SoftwareKeyboardApplet(Memory& memory, std::optional& nextParam) : AppletBase(memory, nextParam) {} }; } // namespace Applets \ No newline at end of file diff --git a/src/core/applets/applet_manager.cpp b/src/core/applets/applet_manager.cpp index 192a76c02..196b1f600 100644 --- a/src/core/applets/applet_manager.cpp +++ b/src/core/applets/applet_manager.cpp @@ -4,7 +4,7 @@ using namespace Applets; -AppletManager::AppletManager(Memory& mem) : miiSelector(mem), swkbd(mem) {} +AppletManager::AppletManager(Memory& mem) : miiSelector(mem, nextParameter), swkbd(mem, nextParameter) {} void AppletManager::reset() { miiSelector.reset(); diff --git a/src/core/applets/software_keyboard.cpp b/src/core/applets/software_keyboard.cpp index 2ff227927..3c2031337 100644 --- a/src/core/applets/software_keyboard.cpp +++ b/src/core/applets/software_keyboard.cpp @@ -7,5 +7,14 @@ Result::HorizonResult SoftwareKeyboardApplet::start() { return Result::Success; Result::HorizonResult SoftwareKeyboardApplet::receiveParameter() { Helpers::warn("Software keyboard: Unimplemented ReceiveParameter"); + + Applets::Parameter param = Applets::Parameter{ + .senderID = AppletIDs::SoftwareKeyboard, + .destID = AppletIDs::Application, + .signal = APTSignal::Response, + .data = {}, + }; + + nextParameter = param; return Result::Success; } \ No newline at end of file From 5df44e0c4f91d5d6ee3a2c6fe5f85c52e3ca1675 Mon Sep 17 00:00:00 2001 From: wheremyfoodat <44909372+wheremyfoodat@users.noreply.github.com> Date: Sat, 11 Nov 2023 20:51:53 +0200 Subject: [PATCH 3/6] [GSP] Add GSP::GPU::ReleaseRight --- include/services/gsp_gpu.hpp | 1 + src/core/services/gsp_gpu.cpp | 12 ++++++++++++ 2 files changed, 13 insertions(+) diff --git a/include/services/gsp_gpu.hpp b/include/services/gsp_gpu.hpp index 92ca36e20..68e245803 100644 --- a/include/services/gsp_gpu.hpp +++ b/include/services/gsp_gpu.hpp @@ -65,6 +65,7 @@ class GPUService { void flushDataCache(u32 messagePointer); void importDisplayCaptureInfo(u32 messagePointer); void registerInterruptRelayQueue(u32 messagePointer); + void releaseRight(u32 messagePointer); void saveVramSysArea(u32 messagePointer); void setAxiConfigQoSMode(u32 messagePointer); void setBufferSwap(u32 messagePointer); diff --git a/src/core/services/gsp_gpu.cpp b/src/core/services/gsp_gpu.cpp index 0e27c0ec0..861dfb0a3 100644 --- a/src/core/services/gsp_gpu.cpp +++ b/src/core/services/gsp_gpu.cpp @@ -15,6 +15,7 @@ namespace ServiceCommands { FlushDataCache = 0x00080082, SetLCDForceBlack = 0x000B0040, TriggerCmdReqQueue = 0x000C0000, + ReleaseRight = 0x00170000, ImportDisplayCaptureInfo = 0x00180000, SaveVramSysArea = 0x00190000, SetInternalPriorities = 0x001E0080, @@ -49,6 +50,7 @@ void GPUService::handleSyncRequest(u32 messagePointer) { case ServiceCommands::FlushDataCache: flushDataCache(messagePointer); break; case ServiceCommands::ImportDisplayCaptureInfo: importDisplayCaptureInfo(messagePointer); break; case ServiceCommands::RegisterInterruptRelayQueue: registerInterruptRelayQueue(messagePointer); break; + case ServiceCommands::ReleaseRight: releaseRight(messagePointer); break; case ServiceCommands::SaveVramSysArea: saveVramSysArea(messagePointer); break; case ServiceCommands::SetAxiConfigQoSMode: setAxiConfigQoSMode(messagePointer); break; case ServiceCommands::SetBufferSwap: setBufferSwap(messagePointer); break; @@ -80,6 +82,16 @@ void GPUService::acquireRight(u32 messagePointer) { mem.write32(messagePointer + 4, Result::Success); } +void GPUService::releaseRight(u32 messagePointer) { + log("GSP::GPU::ReleaseRight\n"); + if (privilegedProcess == currentPID) { + privilegedProcess = 0xFFFFFFFF; + } + + mem.write32(messagePointer, IPC::responseHeader(0x17, 1, 0)); + mem.write32(messagePointer + 4, Result::Success); +} + // TODO: What is the flags field meant to be? // What is the "GSP module thread index" meant to be? // How does the shared memory handle thing work? From bd1d7b7a810422c81257ac5b573f7f3b115f8049 Mon Sep 17 00:00:00 2001 From: wheremyfoodat <44909372+wheremyfoodat@users.noreply.github.com> Date: Sun, 12 Nov 2023 21:07:44 +0200 Subject: [PATCH 4/6] [APT] Properly forward parameters in SendParameter --- include/applets/applet.hpp | 4 ++-- include/applets/mii_selector.hpp | 2 +- include/applets/software_keyboard.hpp | 2 +- src/core/applets/applet_manager.cpp | 9 +++++++-- src/core/applets/mii_selector.cpp | 2 +- src/core/applets/software_keyboard.cpp | 6 +++--- src/core/services/apt.cpp | 16 +++++++++++++++- 7 files changed, 30 insertions(+), 11 deletions(-) diff --git a/include/applets/applet.hpp b/include/applets/applet.hpp index f1a91afd8..79fba1cbc 100644 --- a/include/applets/applet.hpp +++ b/include/applets/applet.hpp @@ -67,7 +67,7 @@ namespace Applets { struct Parameter { u32 senderID; u32 destID; - APTSignal signal; + u32 signal; std::vector data; }; @@ -82,7 +82,7 @@ namespace Applets { // Called by APT::StartLibraryApplet and similar virtual Result::HorizonResult start() = 0; // Transfer parameters from application -> applet - virtual Result::HorizonResult receiveParameter() = 0; + virtual Result::HorizonResult receiveParameter(const Parameter& parameter) = 0; virtual void reset() = 0; AppletBase(Memory& mem, std::optional& nextParam) : mem(mem), nextParameter(nextParam) {} diff --git a/include/applets/mii_selector.hpp b/include/applets/mii_selector.hpp index 7a8826155..c90d4b598 100644 --- a/include/applets/mii_selector.hpp +++ b/include/applets/mii_selector.hpp @@ -5,7 +5,7 @@ namespace Applets { public: virtual const char* name() override { return "Mii Selector"; } virtual Result::HorizonResult start() override; - virtual Result::HorizonResult receiveParameter() override; + virtual Result::HorizonResult receiveParameter(const Applets::Parameter& parameter) override; virtual void reset() override; MiiSelectorApplet(Memory& memory, std::optional& nextParam) : AppletBase(memory, nextParam) {} diff --git a/include/applets/software_keyboard.hpp b/include/applets/software_keyboard.hpp index 89b879539..f41790122 100644 --- a/include/applets/software_keyboard.hpp +++ b/include/applets/software_keyboard.hpp @@ -5,7 +5,7 @@ namespace Applets { public: virtual const char* name() override { return "Software Keyboard"; } virtual Result::HorizonResult start() override; - virtual Result::HorizonResult receiveParameter() override; + virtual Result::HorizonResult receiveParameter(const Applets::Parameter& parameter) override; virtual void reset() override; SoftwareKeyboardApplet(Memory& memory, std::optional& nextParam) : AppletBase(memory, nextParam) {} diff --git a/src/core/applets/applet_manager.cpp b/src/core/applets/applet_manager.cpp index 196b1f600..4c2410279 100644 --- a/src/core/applets/applet_manager.cpp +++ b/src/core/applets/applet_manager.cpp @@ -28,7 +28,7 @@ Applets::Parameter AppletManager::glanceParameter() { // Copy parameter Applets::Parameter param = nextParameter.value(); // APT module clears next parameter even for GlanceParameter for these 2 signals - if (param.signal == APTSignal::DspWakeup || param.signal == APTSignal::DspSleep) { + if (param.signal == static_cast(APTSignal::DspWakeup) || param.signal == static_cast(APTSignal::DspSleep)) { nextParameter = std::nullopt; } @@ -37,7 +37,12 @@ Applets::Parameter AppletManager::glanceParameter() { // Default return value. This is legacy code from before applets were implemented. TODO: Update it else { - return Applets::Parameter{.senderID = 0, .destID = Applets::AppletIDs::Application, .signal = APTSignal::Wakeup, .data = {}}; + return Applets::Parameter{ + .senderID = 0, + .destID = Applets::AppletIDs::Application, + .signal = static_cast(APTSignal::Wakeup), + .data = {}, + }; } } diff --git a/src/core/applets/mii_selector.cpp b/src/core/applets/mii_selector.cpp index 211e6f077..f392d8462 100644 --- a/src/core/applets/mii_selector.cpp +++ b/src/core/applets/mii_selector.cpp @@ -5,7 +5,7 @@ using namespace Applets; void MiiSelectorApplet::reset() {} Result::HorizonResult MiiSelectorApplet::start() { return Result::Success; } -Result::HorizonResult MiiSelectorApplet::receiveParameter() { +Result::HorizonResult MiiSelectorApplet::receiveParameter(const Applets::Parameter& parameter) { Helpers::warn("Mii Selector: Unimplemented ReceiveParameter"); return Result::Success; } \ No newline at end of file diff --git a/src/core/applets/software_keyboard.cpp b/src/core/applets/software_keyboard.cpp index 3c2031337..be5a9e21d 100644 --- a/src/core/applets/software_keyboard.cpp +++ b/src/core/applets/software_keyboard.cpp @@ -5,13 +5,13 @@ using namespace Applets; void SoftwareKeyboardApplet::reset() {} Result::HorizonResult SoftwareKeyboardApplet::start() { return Result::Success; } -Result::HorizonResult SoftwareKeyboardApplet::receiveParameter() { +Result::HorizonResult SoftwareKeyboardApplet::receiveParameter(const Applets::Parameter& parameter) { Helpers::warn("Software keyboard: Unimplemented ReceiveParameter"); Applets::Parameter param = Applets::Parameter{ - .senderID = AppletIDs::SoftwareKeyboard, + .senderID = parameter.destID, .destID = AppletIDs::Application, - .signal = APTSignal::Response, + .signal = static_cast(APTSignal::Response), .data = {}, }; diff --git a/src/core/services/apt.cpp b/src/core/services/apt.cpp index 64ff5cef6..f1c43b265 100644 --- a/src/core/services/apt.cpp +++ b/src/core/services/apt.cpp @@ -234,7 +234,21 @@ void APTService::sendParameter(u32 messagePointer) { if (destApplet == nullptr) { Helpers::warn("APT::SendParameter: Unimplemented dest applet ID"); } else { - auto result = destApplet->receiveParameter(); + // Construct parameter, send it to applet + Applets::Parameter param; + param.senderID = sourceAppID; + param.destID = destAppID; + param.signal = cmd; + + // Fetch parameter data buffer + param.data.reserve(paramSize); + u32 pointer = parameterPointer; + + for (u32 i = 0; i < paramSize; i++) { + param.data.push_back(mem.read8(pointer++)); + } + + auto result = destApplet->receiveParameter(param); } if (resumeEvent.has_value()) { From aa40eaf4cc9d1094fa5d9f83e8090a4de6a0d07a Mon Sep 17 00:00:00 2001 From: wheremyfoodat <44909372+wheremyfoodat@users.noreply.github.com> Date: Sun, 12 Nov 2023 21:16:38 +0200 Subject: [PATCH 5/6] [APT] Remove redundant cast --- src/core/services/apt.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/core/services/apt.cpp b/src/core/services/apt.cpp index f1c43b265..0fc2bb8ad 100644 --- a/src/core/services/apt.cpp +++ b/src/core/services/apt.cpp @@ -269,7 +269,7 @@ void APTService::receiveParameter(u32 messagePointer) { // Sender App ID mem.write32(messagePointer + 8, parameter.senderID); // Command - mem.write32(messagePointer + 12, static_cast(parameter.signal)); + mem.write32(messagePointer + 12, parameter.signal); // Size of parameter data mem.write32(messagePointer + 16, parameter.data.size()); mem.write32(messagePointer + 20, 0x10); From 62af35c42b8a13e00b356d1a30904f295e24b768 Mon Sep 17 00:00:00 2001 From: wheremyfoodat <44909372+wheremyfoodat@users.noreply.github.com> Date: Sun, 12 Nov 2023 21:24:12 +0200 Subject: [PATCH 6/6] [Applet Manager] Fix resetting --- src/core/applets/applet_manager.cpp | 2 ++ src/core/services/apt.cpp | 2 +- 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/src/core/applets/applet_manager.cpp b/src/core/applets/applet_manager.cpp index 4c2410279..c27917777 100644 --- a/src/core/applets/applet_manager.cpp +++ b/src/core/applets/applet_manager.cpp @@ -7,6 +7,8 @@ using namespace Applets; AppletManager::AppletManager(Memory& mem) : miiSelector(mem, nextParameter), swkbd(mem, nextParameter) {} void AppletManager::reset() { + nextParameter = std::nullopt; + miiSelector.reset(); swkbd.reset(); } diff --git a/src/core/services/apt.cpp b/src/core/services/apt.cpp index 0fc2bb8ad..754baa139 100644 --- a/src/core/services/apt.cpp +++ b/src/core/services/apt.cpp @@ -291,7 +291,7 @@ void APTService::glanceParameter(u32 messagePointer) { // Sender App ID mem.write32(messagePointer + 8, parameter.senderID); // Command - mem.write32(messagePointer + 12, static_cast(parameter.signal)); + mem.write32(messagePointer + 12, parameter.signal); // Size of parameter data mem.write32(messagePointer + 16, parameter.data.size()); mem.write32(messagePointer + 20, 0);