Skip to content

Commit

Permalink
Merge pull request #339 from wheremyfoodat/y2r
Browse files Browse the repository at this point in the history
Implement more HLE applet and GSP stuff
  • Loading branch information
wheremyfoodat authored Nov 12, 2023
2 parents 11f42f8 + 62af35c commit a98fcfc
Show file tree
Hide file tree
Showing 11 changed files with 131 additions and 43 deletions.
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

0 comments on commit a98fcfc

Please sign in to comment.