Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Implement more HLE applet and GSP stuff #339

Merged
merged 6 commits into from
Nov 12, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 5 additions & 3 deletions include/applets/applet.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -67,22 +67,24 @@ namespace Applets {
struct Parameter {
u32 senderID;
u32 destID;
APTSignal signal;
u32 signal;
std::vector<u8> data;
};

class AppletBase {
protected:
Memory& mem;
std::optional<Parameter>& nextParameter;

public:
virtual const char* name() = 0;

// 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) : mem(mem) {}
AppletBase(Memory& mem, std::optional<Parameter>& nextParam) : mem(mem), nextParameter(nextParam) {}
};
} // namespace Applets
7 changes: 7 additions & 0 deletions include/applets/applet_manager.hpp
Original file line number Diff line number Diff line change
@@ -1,3 +1,6 @@
#pragma once
#include <optional>

#include "applets/mii_selector.hpp"
#include "applets/software_keyboard.hpp"
#include "helpers.hpp"
Expand All @@ -8,10 +11,14 @@ namespace Applets {
class AppletManager {
MiiSelectorApplet miiSelector;
SoftwareKeyboardApplet swkbd;
std::optional<Applets::Parameter> nextParameter = std::nullopt;

public:
AppletManager(Memory& mem);
void reset();
AppletBase* getApplet(u32 id);

Applets::Parameter glanceParameter();
Applets::Parameter receiveParameter();
};
} // namespace Applets
4 changes: 2 additions & 2 deletions include/applets/mii_selector.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,9 @@ 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) : AppletBase(memory) {}
MiiSelectorApplet(Memory& memory, std::optional<Parameter>& nextParam) : AppletBase(memory, nextParam) {}
};
} // namespace Applets
4 changes: 2 additions & 2 deletions include/applets/software_keyboard.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,9 @@ 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) : AppletBase(memory) {}
SoftwareKeyboardApplet(Memory& memory, std::optional<Parameter>& nextParam) : AppletBase(memory, nextParam) {}
};
} // namespace Applets
25 changes: 25 additions & 0 deletions include/services/apt.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down
1 change: 1 addition & 0 deletions include/services/gsp_gpu.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down
38 changes: 37 additions & 1 deletion src/core/applets/applet_manager.cpp
Original file line number Diff line number Diff line change
@@ -1,9 +1,14 @@
#include "applets/applet_manager.hpp"

#include "services/apt.hpp"

using namespace Applets;

AppletManager::AppletManager(Memory& mem) : miiSelector(mem), swkbd(mem) {}
AppletManager::AppletManager(Memory& mem) : miiSelector(mem, nextParameter), swkbd(mem, nextParameter) {}

void AppletManager::reset() {
nextParameter = std::nullopt;

miiSelector.reset();
swkbd.reset();
}
Expand All @@ -18,4 +23,35 @@ 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 == 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;
}
2 changes: 1 addition & 1 deletion src/core/applets/mii_selector.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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;
}
11 changes: 10 additions & 1 deletion src/core/applets/software_keyboard.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,16 @@ 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 = parameter.destID,
.destID = AppletIDs::Application,
.signal = static_cast<u32>(APTSignal::Response),
.data = {},
};

nextParameter = param;
return Result::Success;
}
62 changes: 29 additions & 33 deletions src/core/services/apt.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -259,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()) {
Expand All @@ -273,13 +262,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, 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);
Expand All @@ -291,13 +283,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, 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);
Expand Down
12 changes: 12 additions & 0 deletions src/core/services/gsp_gpu.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ namespace ServiceCommands {
FlushDataCache = 0x00080082,
SetLCDForceBlack = 0x000B0040,
TriggerCmdReqQueue = 0x000C0000,
ReleaseRight = 0x00170000,
ImportDisplayCaptureInfo = 0x00180000,
SaveVramSysArea = 0x00190000,
SetInternalPriorities = 0x001E0080,
Expand Down Expand Up @@ -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;
Expand Down Expand Up @@ -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?
Expand Down
Loading