mirror of
https://github.com/wheremyfoodat/Panda3DS.git
synced 2025-04-07 22:55:40 +12:00
Merge pull request #339 from wheremyfoodat/y2r
Implement more HLE applet and GSP stuff
This commit is contained in:
commit
a98fcfc56f
11 changed files with 131 additions and 43 deletions
|
@ -67,12 +67,14 @@ namespace Applets {
|
||||||
struct Parameter {
|
struct Parameter {
|
||||||
u32 senderID;
|
u32 senderID;
|
||||||
u32 destID;
|
u32 destID;
|
||||||
APTSignal signal;
|
u32 signal;
|
||||||
std::vector<u8> data;
|
std::vector<u8> data;
|
||||||
};
|
};
|
||||||
|
|
||||||
class AppletBase {
|
class AppletBase {
|
||||||
|
protected:
|
||||||
Memory& mem;
|
Memory& mem;
|
||||||
|
std::optional<Parameter>& nextParameter;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
virtual const char* name() = 0;
|
virtual const char* name() = 0;
|
||||||
|
@ -80,9 +82,9 @@ namespace Applets {
|
||||||
// Called by APT::StartLibraryApplet and similar
|
// Called by APT::StartLibraryApplet and similar
|
||||||
virtual Result::HorizonResult start() = 0;
|
virtual Result::HorizonResult start() = 0;
|
||||||
// Transfer parameters from application -> applet
|
// Transfer parameters from application -> applet
|
||||||
virtual Result::HorizonResult receiveParameter() = 0;
|
virtual Result::HorizonResult receiveParameter(const Parameter& parameter) = 0;
|
||||||
virtual void reset() = 0;
|
virtual void reset() = 0;
|
||||||
|
|
||||||
AppletBase(Memory& mem) : mem(mem) {}
|
AppletBase(Memory& mem, std::optional<Parameter>& nextParam) : mem(mem), nextParameter(nextParam) {}
|
||||||
};
|
};
|
||||||
} // namespace Applets
|
} // namespace Applets
|
|
@ -1,3 +1,6 @@
|
||||||
|
#pragma once
|
||||||
|
#include <optional>
|
||||||
|
|
||||||
#include "applets/mii_selector.hpp"
|
#include "applets/mii_selector.hpp"
|
||||||
#include "applets/software_keyboard.hpp"
|
#include "applets/software_keyboard.hpp"
|
||||||
#include "helpers.hpp"
|
#include "helpers.hpp"
|
||||||
|
@ -8,10 +11,14 @@ namespace Applets {
|
||||||
class AppletManager {
|
class AppletManager {
|
||||||
MiiSelectorApplet miiSelector;
|
MiiSelectorApplet miiSelector;
|
||||||
SoftwareKeyboardApplet swkbd;
|
SoftwareKeyboardApplet swkbd;
|
||||||
|
std::optional<Applets::Parameter> nextParameter = std::nullopt;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
AppletManager(Memory& mem);
|
AppletManager(Memory& mem);
|
||||||
void reset();
|
void reset();
|
||||||
AppletBase* getApplet(u32 id);
|
AppletBase* getApplet(u32 id);
|
||||||
|
|
||||||
|
Applets::Parameter glanceParameter();
|
||||||
|
Applets::Parameter receiveParameter();
|
||||||
};
|
};
|
||||||
} // namespace Applets
|
} // namespace Applets
|
|
@ -5,9 +5,9 @@ namespace Applets {
|
||||||
public:
|
public:
|
||||||
virtual const char* name() override { return "Mii Selector"; }
|
virtual const char* name() override { return "Mii Selector"; }
|
||||||
virtual Result::HorizonResult start() override;
|
virtual Result::HorizonResult start() override;
|
||||||
virtual Result::HorizonResult receiveParameter() override;
|
virtual Result::HorizonResult receiveParameter(const Applets::Parameter& parameter) override;
|
||||||
virtual void reset() override;
|
virtual void reset() override;
|
||||||
|
|
||||||
MiiSelectorApplet(Memory& memory) : AppletBase(memory) {}
|
MiiSelectorApplet(Memory& memory, std::optional<Parameter>& nextParam) : AppletBase(memory, nextParam) {}
|
||||||
};
|
};
|
||||||
} // namespace Applets
|
} // namespace Applets
|
|
@ -5,9 +5,9 @@ namespace Applets {
|
||||||
public:
|
public:
|
||||||
virtual const char* name() override { return "Software Keyboard"; }
|
virtual const char* name() override { return "Software Keyboard"; }
|
||||||
virtual Result::HorizonResult start() override;
|
virtual Result::HorizonResult start() override;
|
||||||
virtual Result::HorizonResult receiveParameter() override;
|
virtual Result::HorizonResult receiveParameter(const Applets::Parameter& parameter) override;
|
||||||
virtual void reset() override;
|
virtual void reset() override;
|
||||||
|
|
||||||
SoftwareKeyboardApplet(Memory& memory) : AppletBase(memory) {}
|
SoftwareKeyboardApplet(Memory& memory, std::optional<Parameter>& nextParam) : AppletBase(memory, nextParam) {}
|
||||||
};
|
};
|
||||||
} // namespace Applets
|
} // namespace Applets
|
|
@ -15,6 +15,31 @@ enum class ConsoleModel : u32 {
|
||||||
Old3DS, New3DS
|
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 {
|
class APTService {
|
||||||
Handle handle = KernelHandles::APT;
|
Handle handle = KernelHandles::APT;
|
||||||
Memory& mem;
|
Memory& mem;
|
||||||
|
|
|
@ -65,6 +65,7 @@ class GPUService {
|
||||||
void flushDataCache(u32 messagePointer);
|
void flushDataCache(u32 messagePointer);
|
||||||
void importDisplayCaptureInfo(u32 messagePointer);
|
void importDisplayCaptureInfo(u32 messagePointer);
|
||||||
void registerInterruptRelayQueue(u32 messagePointer);
|
void registerInterruptRelayQueue(u32 messagePointer);
|
||||||
|
void releaseRight(u32 messagePointer);
|
||||||
void saveVramSysArea(u32 messagePointer);
|
void saveVramSysArea(u32 messagePointer);
|
||||||
void setAxiConfigQoSMode(u32 messagePointer);
|
void setAxiConfigQoSMode(u32 messagePointer);
|
||||||
void setBufferSwap(u32 messagePointer);
|
void setBufferSwap(u32 messagePointer);
|
||||||
|
|
|
@ -1,9 +1,14 @@
|
||||||
#include "applets/applet_manager.hpp"
|
#include "applets/applet_manager.hpp"
|
||||||
|
|
||||||
|
#include "services/apt.hpp"
|
||||||
|
|
||||||
using namespace Applets;
|
using namespace Applets;
|
||||||
|
|
||||||
AppletManager::AppletManager(Memory& mem) : miiSelector(mem), swkbd(mem) {}
|
AppletManager::AppletManager(Memory& mem) : miiSelector(mem, nextParameter), swkbd(mem, nextParameter) {}
|
||||||
|
|
||||||
void AppletManager::reset() {
|
void AppletManager::reset() {
|
||||||
|
nextParameter = std::nullopt;
|
||||||
|
|
||||||
miiSelector.reset();
|
miiSelector.reset();
|
||||||
swkbd.reset();
|
swkbd.reset();
|
||||||
}
|
}
|
||||||
|
@ -18,4 +23,35 @@ AppletBase* AppletManager::getApplet(u32 id) {
|
||||||
|
|
||||||
default: return nullptr;
|
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 == static_cast<u32>(APTSignal::DspWakeup) || param.signal == static_cast<u32>(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 = static_cast<u32>(APTSignal::Wakeup),
|
||||||
|
.data = {},
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Applets::Parameter AppletManager::receiveParameter() {
|
||||||
|
Applets::Parameter param = glanceParameter();
|
||||||
|
// ReceiveParameter always clears nextParameter whereas glanceParameter does not
|
||||||
|
nextParameter = std::nullopt;
|
||||||
|
|
||||||
|
return param;
|
||||||
}
|
}
|
|
@ -5,7 +5,7 @@ using namespace Applets;
|
||||||
void MiiSelectorApplet::reset() {}
|
void MiiSelectorApplet::reset() {}
|
||||||
Result::HorizonResult MiiSelectorApplet::start() { return Result::Success; }
|
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");
|
Helpers::warn("Mii Selector: Unimplemented ReceiveParameter");
|
||||||
return Result::Success;
|
return Result::Success;
|
||||||
}
|
}
|
|
@ -5,7 +5,16 @@ using namespace Applets;
|
||||||
void SoftwareKeyboardApplet::reset() {}
|
void SoftwareKeyboardApplet::reset() {}
|
||||||
Result::HorizonResult SoftwareKeyboardApplet::start() { return Result::Success; }
|
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");
|
Helpers::warn("Software keyboard: Unimplemented ReceiveParameter");
|
||||||
|
|
||||||
|
Applets::Parameter param = Applets::Parameter{
|
||||||
|
.senderID = parameter.destID,
|
||||||
|
.destID = AppletIDs::Application,
|
||||||
|
.signal = static_cast<u32>(APTSignal::Response),
|
||||||
|
.data = {},
|
||||||
|
};
|
||||||
|
|
||||||
|
nextParameter = param;
|
||||||
return Result::Success;
|
return Result::Success;
|
||||||
}
|
}
|
|
@ -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() {
|
void APTService::reset() {
|
||||||
// Set the default CPU time limit to 30%. Seems safe, as this is what Metroid 2 uses by default
|
// Set the default CPU time limit to 30%. Seems safe, as this is what Metroid 2 uses by default
|
||||||
cpuTimeLimit = 30;
|
cpuTimeLimit = 30;
|
||||||
|
@ -259,7 +234,21 @@ void APTService::sendParameter(u32 messagePointer) {
|
||||||
if (destApplet == nullptr) {
|
if (destApplet == nullptr) {
|
||||||
Helpers::warn("APT::SendParameter: Unimplemented dest applet ID");
|
Helpers::warn("APT::SendParameter: Unimplemented dest applet ID");
|
||||||
} else {
|
} 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()) {
|
if (resumeEvent.has_value()) {
|
||||||
|
@ -273,13 +262,16 @@ void APTService::receiveParameter(u32 messagePointer) {
|
||||||
log("APT::ReceiveParameter(app ID = %X, size = %04X) (STUBBED)\n", app, size);
|
log("APT::ReceiveParameter(app ID = %X, size = %04X) (STUBBED)\n", app, size);
|
||||||
|
|
||||||
if (size > 0x1000) Helpers::panic("APT::ReceiveParameter with size > 0x1000");
|
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, IPC::responseHeader(0xD, 4, 4));
|
||||||
mem.write32(messagePointer + 4, Result::Success);
|
mem.write32(messagePointer + 4, Result::Success);
|
||||||
mem.write32(messagePointer + 8, 0); // Sender App ID
|
// Sender App ID
|
||||||
mem.write32(messagePointer + 12, APTTransitions::Wakeup); // Command
|
mem.write32(messagePointer + 8, parameter.senderID);
|
||||||
mem.write32(messagePointer + 16, 0);
|
// Command
|
||||||
|
mem.write32(messagePointer + 12, parameter.signal);
|
||||||
|
// Size of parameter data
|
||||||
|
mem.write32(messagePointer + 16, parameter.data.size());
|
||||||
mem.write32(messagePointer + 20, 0x10);
|
mem.write32(messagePointer + 20, 0x10);
|
||||||
mem.write32(messagePointer + 24, 0);
|
mem.write32(messagePointer + 24, 0);
|
||||||
mem.write32(messagePointer + 28, 0);
|
mem.write32(messagePointer + 28, 0);
|
||||||
|
@ -291,13 +283,17 @@ void APTService::glanceParameter(u32 messagePointer) {
|
||||||
log("APT::GlanceParameter(app ID = %X, size = %04X) (STUBBED)\n", app, size);
|
log("APT::GlanceParameter(app ID = %X, size = %04X) (STUBBED)\n", app, size);
|
||||||
|
|
||||||
if (size > 0x1000) Helpers::panic("APT::GlanceParameter with size > 0x1000");
|
if (size > 0x1000) Helpers::panic("APT::GlanceParameter with size > 0x1000");
|
||||||
|
auto parameter = appletManager.glanceParameter();
|
||||||
|
|
||||||
// TODO: Properly implement this. We currently stub it similar
|
// TODO: Properly implement this. We currently stub it similar
|
||||||
mem.write32(messagePointer, IPC::responseHeader(0xE, 4, 4));
|
mem.write32(messagePointer, IPC::responseHeader(0xE, 4, 4));
|
||||||
mem.write32(messagePointer + 4, Result::Success);
|
mem.write32(messagePointer + 4, Result::Success);
|
||||||
mem.write32(messagePointer + 8, 0); // Sender App ID
|
// Sender App ID
|
||||||
mem.write32(messagePointer + 12, APTTransitions::Wakeup); // Command
|
mem.write32(messagePointer + 8, parameter.senderID);
|
||||||
mem.write32(messagePointer + 16, 0);
|
// Command
|
||||||
|
mem.write32(messagePointer + 12, parameter.signal);
|
||||||
|
// Size of parameter data
|
||||||
|
mem.write32(messagePointer + 16, parameter.data.size());
|
||||||
mem.write32(messagePointer + 20, 0);
|
mem.write32(messagePointer + 20, 0);
|
||||||
mem.write32(messagePointer + 24, 0);
|
mem.write32(messagePointer + 24, 0);
|
||||||
mem.write32(messagePointer + 28, 0);
|
mem.write32(messagePointer + 28, 0);
|
||||||
|
|
|
@ -15,6 +15,7 @@ namespace ServiceCommands {
|
||||||
FlushDataCache = 0x00080082,
|
FlushDataCache = 0x00080082,
|
||||||
SetLCDForceBlack = 0x000B0040,
|
SetLCDForceBlack = 0x000B0040,
|
||||||
TriggerCmdReqQueue = 0x000C0000,
|
TriggerCmdReqQueue = 0x000C0000,
|
||||||
|
ReleaseRight = 0x00170000,
|
||||||
ImportDisplayCaptureInfo = 0x00180000,
|
ImportDisplayCaptureInfo = 0x00180000,
|
||||||
SaveVramSysArea = 0x00190000,
|
SaveVramSysArea = 0x00190000,
|
||||||
SetInternalPriorities = 0x001E0080,
|
SetInternalPriorities = 0x001E0080,
|
||||||
|
@ -49,6 +50,7 @@ void GPUService::handleSyncRequest(u32 messagePointer) {
|
||||||
case ServiceCommands::FlushDataCache: flushDataCache(messagePointer); break;
|
case ServiceCommands::FlushDataCache: flushDataCache(messagePointer); break;
|
||||||
case ServiceCommands::ImportDisplayCaptureInfo: importDisplayCaptureInfo(messagePointer); break;
|
case ServiceCommands::ImportDisplayCaptureInfo: importDisplayCaptureInfo(messagePointer); break;
|
||||||
case ServiceCommands::RegisterInterruptRelayQueue: registerInterruptRelayQueue(messagePointer); break;
|
case ServiceCommands::RegisterInterruptRelayQueue: registerInterruptRelayQueue(messagePointer); break;
|
||||||
|
case ServiceCommands::ReleaseRight: releaseRight(messagePointer); break;
|
||||||
case ServiceCommands::SaveVramSysArea: saveVramSysArea(messagePointer); break;
|
case ServiceCommands::SaveVramSysArea: saveVramSysArea(messagePointer); break;
|
||||||
case ServiceCommands::SetAxiConfigQoSMode: setAxiConfigQoSMode(messagePointer); break;
|
case ServiceCommands::SetAxiConfigQoSMode: setAxiConfigQoSMode(messagePointer); break;
|
||||||
case ServiceCommands::SetBufferSwap: setBufferSwap(messagePointer); break;
|
case ServiceCommands::SetBufferSwap: setBufferSwap(messagePointer); break;
|
||||||
|
@ -80,6 +82,16 @@ void GPUService::acquireRight(u32 messagePointer) {
|
||||||
mem.write32(messagePointer + 4, Result::Success);
|
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?
|
// TODO: What is the flags field meant to be?
|
||||||
// What is the "GSP module thread index" meant to be?
|
// What is the "GSP module thread index" meant to be?
|
||||||
// How does the shared memory handle thing work?
|
// How does the shared memory handle thing work?
|
||||||
|
|
Loading…
Add table
Reference in a new issue