Co-authored-by: Noumi <139501014+noumidev@users.noreply.github.com>
This commit is contained in:
wheremyfoodat 2024-12-10 18:52:53 +02:00 committed by GitHub
parent 4ce0768ba1
commit dc80828397
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
20 changed files with 456 additions and 107 deletions

View file

@ -326,6 +326,7 @@ set(SERVICE_SOURCE_FILES src/core/services/service_manager.cpp src/core/services
src/core/services/ir_user.cpp src/core/services/http.cpp src/core/services/soc.cpp src/core/services/ir_user.cpp src/core/services/http.cpp src/core/services/soc.cpp
src/core/services/ssl.cpp src/core/services/news_u.cpp src/core/services/amiibo_device.cpp src/core/services/ssl.cpp src/core/services/news_u.cpp src/core/services/amiibo_device.cpp
src/core/services/csnd.cpp src/core/services/nwm_uds.cpp src/core/services/fonts.cpp src/core/services/csnd.cpp src/core/services/nwm_uds.cpp src/core/services/fonts.cpp
src/core/services/ns.cpp
) )
set(PICA_SOURCE_FILES src/core/PICA/gpu.cpp src/core/PICA/regs.cpp src/core/PICA/shader_unit.cpp set(PICA_SOURCE_FILES src/core/PICA/gpu.cpp src/core/PICA/regs.cpp src/core/PICA/shader_unit.cpp
src/core/PICA/shader_interpreter.cpp src/core/PICA/dynapica/shader_rec.cpp src/core/PICA/shader_interpreter.cpp src/core/PICA/dynapica/shader_rec.cpp
@ -389,7 +390,7 @@ set(HEADER_FILES include/emulator.hpp include/helpers.hpp include/termcolor.hpp
include/align.hpp include/audio/aac_decoder.hpp include/PICA/pica_simd.hpp include/services/fonts.hpp include/align.hpp include/audio/aac_decoder.hpp include/PICA/pica_simd.hpp include/services/fonts.hpp
include/audio/audio_interpolation.hpp include/audio/hle_mixer.hpp include/audio/dsp_simd.hpp include/audio/audio_interpolation.hpp include/audio/hle_mixer.hpp include/audio/dsp_simd.hpp
include/services/dsp_firmware_db.hpp include/frontend_settings.hpp include/fs/archive_twl_photo.hpp include/services/dsp_firmware_db.hpp include/frontend_settings.hpp include/fs/archive_twl_photo.hpp
include/fs/archive_twl_sound.hpp include/fs/archive_card_spi.hpp include/fs/archive_twl_sound.hpp include/fs/archive_card_spi.hpp include/services/ns.hpp
) )
cmrc_add_resource_library( cmrc_add_resource_library(

View file

@ -2,8 +2,19 @@
#include <cstdint> #include <cstdint>
namespace IPC { namespace IPC {
namespace BufferType {
enum : std::uint32_t {
Send = 1,
Receive = 2,
};
}
constexpr std::uint32_t responseHeader(std::uint32_t commandID, std::uint32_t normalResponses, std::uint32_t translateResponses) { constexpr std::uint32_t responseHeader(std::uint32_t commandID, std::uint32_t normalResponses, std::uint32_t translateResponses) {
// TODO: Maybe validate the response count stuff fits in 6 bits // TODO: Maybe validate the response count stuff fits in 6 bits
return (commandID << 16) | (normalResponses << 6) | translateResponses; return (commandID << 16) | (normalResponses << 6) | translateResponses;
} }
}
constexpr std::uint32_t pointerHeader(std::uint32_t index, std::uint32_t size, std::uint32_t type) {
return (size << 14) | (index << 10) | (type << 1);
}
} // namespace IPC

View file

@ -8,6 +8,7 @@ namespace ConfigMem {
KernelVersionMajor = 0x1FF80003, KernelVersionMajor = 0x1FF80003,
SyscoreVer = 0x1FF80010, SyscoreVer = 0x1FF80010,
EnvInfo = 0x1FF80014, EnvInfo = 0x1FF80014,
PrevFirm = 0x1FF80016,
AppMemAlloc = 0x1FF80040, AppMemAlloc = 0x1FF80040,
FirmUnknown = 0x1FF80060, FirmUnknown = 0x1FF80060,
FirmRevision = 0x1FF80061, FirmRevision = 0x1FF80061,
@ -30,6 +31,11 @@ namespace ConfigMem {
// Shows what type of hardware we're running on // Shows what type of hardware we're running on
namespace HardwareCodes { namespace HardwareCodes {
enum : u8 { Product = 1, Devboard = 2, Debugger = 3, Capture = 4 }; enum : u8 {
Product = 1,
Devboard = 2,
Debugger = 3,
Capture = 4,
};
} }
} // namespace ConfigMem } // namespace ConfigMem

View file

@ -20,6 +20,7 @@ namespace KernelHandles {
CFG_U, // CFG service (Console & region info) CFG_U, // CFG service (Console & region info)
CFG_I, CFG_I,
CFG_S, // Used by most system apps in lieu of cfg:u CFG_S, // Used by most system apps in lieu of cfg:u
CFG_NOR, // Used by system settings app
CSND, // Plays audio directly from PCM samples CSND, // Plays audio directly from PCM samples
DLP_SRVR, // Download Play: Server. Used for network play. DLP_SRVR, // Download Play: Server. Used for network play.
DSP, // DSP service (Used for audio decoding and output) DSP, // DSP service (Used for audio decoding and output)
@ -38,11 +39,14 @@ namespace KernelHandles {
NIM, // Updates, DLC, etc NIM, // Updates, DLC, etc
NDM, // ????? NDM, // ?????
NS_S, // Nintendo Shell service NS_S, // Nintendo Shell service
NWM_EXT, // ?????
NWM_UDS, // Local multiplayer NWM_UDS, // Local multiplayer
NEWS_U, // This service literally has 1 command (AddNotification) and I don't even understand what it does NEWS_S, // news:u on steroids
NEWS_U, // This service literally has 1 command (AddNotification)
PTM_U, // PTM service (Used for accessing various console info, such as battery, shell and pedometer state) PTM_U, // PTM service (Used for accessing various console info, such as battery, shell and pedometer state)
PTM_SYSM, // PTM system service PTM_SYSM, // PTM system service
PTM_PLAY, // PTM Play service, used for retrieving play history PTM_PLAY, // PTM Play service, used for retrieving play history
PTM_GETS, // PTM RTC service (GetSystemTime)
SOC, // Socket service SOC, // Socket service
SSL, // SSL service (Totally didn't expect that) SSL, // SSL service (Totally didn't expect that)
Y2R, // Also does camera stuff Y2R, // Also does camera stuff
@ -82,6 +86,8 @@ namespace KernelHandles {
case CECD: return "CECD"; case CECD: return "CECD";
case CFG_U: return "CFG:U"; case CFG_U: return "CFG:U";
case CFG_I: return "CFG:I"; case CFG_I: return "CFG:I";
case CFG_S: return "CFG:S";
case CFG_NOR: return "CFG:NOR";
case CSND: return "CSND"; case CSND: return "CSND";
case DSP: return "DSP"; case DSP: return "DSP";
case DLP_SRVR: return "DLP::SRVR"; case DLP_SRVR: return "DLP::SRVR";
@ -97,13 +103,16 @@ namespace KernelHandles {
case MCU_HWC: return "MCU::HWC"; case MCU_HWC: return "MCU::HWC";
case MIC: return "MIC"; case MIC: return "MIC";
case NDM: return "NDM"; case NDM: return "NDM";
case NEWS_S: return "NEWS_S";
case NEWS_U: return "NEWS_U"; case NEWS_U: return "NEWS_U";
case NWM_EXT: return "nwm::EXT";
case NWM_UDS: return "nwm::UDS"; case NWM_UDS: return "nwm::UDS";
case NFC: return "NFC"; case NFC: return "NFC";
case NIM: return "NIM"; case NIM: return "NIM";
case PTM_U: return "PTM:U"; case PTM_U: return "PTM:U";
case PTM_SYSM: return "PTM:SYSM"; case PTM_SYSM: return "PTM:SYSM";
case PTM_PLAY: return "PTM:PLAY"; case PTM_PLAY: return "PTM:PLAY";
case PTM_GETS: return "PTM:GETS";
case SOC: return "SOC"; case SOC: return "SOC";
case SSL: return "SSL"; case SSL: return "SSL";
case Y2R: return "Y2R"; case Y2R: return "Y2R";

View file

@ -65,6 +65,7 @@ namespace Log {
static Logger<false> nwmUdsLogger; static Logger<false> nwmUdsLogger;
static Logger<false> nimLogger; static Logger<false> nimLogger;
static Logger<false> ndmLogger; static Logger<false> ndmLogger;
static Logger<false> nsLogger;
static Logger<false> ptmLogger; static Logger<false> ptmLogger;
static Logger<false> socLogger; static Logger<false> socLogger;
static Logger<false> sslLogger; static Logger<false> sslLogger;

View file

@ -19,6 +19,7 @@ class ACService {
void closeAsync(u32 messagePointer); void closeAsync(u32 messagePointer);
void createDefaultConfig(u32 messagePointer); void createDefaultConfig(u32 messagePointer);
void getConnectingInfraPriority(u32 messagePointer); void getConnectingInfraPriority(u32 messagePointer);
void getNZoneBeaconNotFoundEvent(u32 messagePointer);
void getStatus(u32 messagePointer); void getStatus(u32 messagePointer);
void getLastErrorCode(u32 messagePointer); void getLastErrorCode(u32 messagePointer);
void getWifiStatus(u32 messagePointer); void getWifiStatus(u32 messagePointer);

View file

@ -14,10 +14,14 @@ class BOSSService {
// Service commands // Service commands
void cancelTask(u32 messagePointer); void cancelTask(u32 messagePointer);
void deleteNsData(u32 messagePointer);
void initializeSession(u32 messagePointer); void initializeSession(u32 messagePointer);
void getAppNewFlag(u32 messagePointer);
void getErrorCode(u32 messagePointer); void getErrorCode(u32 messagePointer);
void getNsDataHeaderInfo(u32 messagePointer);
void getNewArrivalFlag(u32 messagePointer); void getNewArrivalFlag(u32 messagePointer);
void getNsDataIdList(u32 messagePointer, u32 commandWord); void getNsDataIdList(u32 messagePointer, u32 commandWord);
void getNsDataLastUpdated(u32 messagePointer);
void getOptoutFlag(u32 messagePointer); void getOptoutFlag(u32 messagePointer);
void getStorageEntryInfo(u32 messagePointer); // Unknown what this is, name taken from Citra void getStorageEntryInfo(u32 messagePointer); // Unknown what this is, name taken from Citra
void getTaskIdList(u32 messagePointer); void getTaskIdList(u32 messagePointer);
@ -26,12 +30,15 @@ class BOSSService {
void getTaskState(u32 messagePointer); void getTaskState(u32 messagePointer);
void getTaskStatus(u32 messagePointer); void getTaskStatus(u32 messagePointer);
void getTaskStorageInfo(u32 messagePointer); void getTaskStorageInfo(u32 messagePointer);
void readNsData(u32 messagePointer);
void receiveProperty(u32 messagePointer); void receiveProperty(u32 messagePointer);
void registerNewArrivalEvent(u32 messagePointer); void registerNewArrivalEvent(u32 messagePointer);
void registerStorageEntry(u32 messagePointer); void registerStorageEntry(u32 messagePointer);
void registerTask(u32 messagePointer); void registerTask(u32 messagePointer);
void sendProperty(u32 messagePointer); void sendProperty(u32 messagePointer);
void setAppNewFlag(u32 messagePointer);
void setOptoutFlag(u32 messagePointer); void setOptoutFlag(u32 messagePointer);
void startBgImmediate(u32 messagePointer);
void startTask(u32 messagePointer); void startTask(u32 messagePointer);
void unregisterStorage(u32 messagePointer); void unregisterStorage(u32 messagePointer);
void unregisterTask(u32 messagePointer); void unregisterTask(u32 messagePointer);

View file

@ -18,7 +18,7 @@ class CFGService {
// Service functions // Service functions
void getConfigInfoBlk2(u32 messagePointer); void getConfigInfoBlk2(u32 messagePointer);
void getConfigInfoBlk8(u32 messagePointer); void getConfigInfoBlk8(u32 messagePointer, u32 commandWord);
void getCountryCodeID(u32 messagePointer); void getCountryCodeID(u32 messagePointer);
void getLocalFriendCodeSeed(u32 messagePointer); void getLocalFriendCodeSeed(u32 messagePointer);
void getRegionCanadaUSA(u32 messagePointer); void getRegionCanadaUSA(u32 messagePointer);
@ -26,7 +26,14 @@ class CFGService {
void genUniqueConsoleHash(u32 messagePointer); void genUniqueConsoleHash(u32 messagePointer);
void secureInfoGetByte101(u32 messagePointer); void secureInfoGetByte101(u32 messagePointer);
void secureInfoGetRegion(u32 messagePointer); void secureInfoGetRegion(u32 messagePointer);
void setConfigInfoBlk4(u32 messagePointer);
void updateConfigNANDSavegame(u32 messagePointer);
void translateCountryInfo(u32 messagePointer); void translateCountryInfo(u32 messagePointer);
void isFangateSupported(u32 messagePointer);
// cfg:nor functions
void norInitialize(u32 messagePointer);
void norReadData(u32 messagePointer);
void getConfigInfo(u32 output, u32 blockID, u32 size, u32 permissionMask); void getConfigInfo(u32 output, u32 blockID, u32 size, u32 permissionMask);

View file

@ -121,4 +121,4 @@ class GPUService {
std::memset(ptr, 0, 0x1000); std::memset(ptr, 0, 0x1000);
} }
} }
}; };

View file

@ -6,15 +6,13 @@
#include "result/result.hpp" #include "result/result.hpp"
class LCDService { class LCDService {
using Handle = HorizonHandle;
Handle handle = KernelHandles::LCD;
Memory& mem; Memory& mem;
MAKE_LOG_FUNCTION(log, gspLCDLogger) MAKE_LOG_FUNCTION(log, gspLCDLogger)
// Service commands // Service commands
void setLedForceOff(u32 messagePointer);
public: public:
LCDService(Memory& mem) : mem(mem) {} LCDService(Memory& mem) : mem(mem) {}
void reset(); void reset();
void handleSyncRequest(u32 messagePointer); void handleSyncRequest(u32 messagePointer);

25
include/services/ns.hpp Normal file
View file

@ -0,0 +1,25 @@
#pragma once
#include "helpers.hpp"
#include "kernel_types.hpp"
#include "logger.hpp"
#include "memory.hpp"
#include "result/result.hpp"
class NSService {
Memory& mem;
MAKE_LOG_FUNCTION(log, nsLogger)
// Service commands
void launchTitle(u32 messagePointer);
public:
enum class Type {
S, // ns:s
P, // ns:p
C, // ns:c
};
NSService(Memory& mem) : mem(mem) {}
void reset();
void handleSyncRequest(u32 messagePointer, Type type);
};

View file

@ -24,6 +24,7 @@ class PTMService {
public: public:
enum class Type { enum class Type {
GETS, // ptm:gets
U, // ptm:u U, // ptm:u
SYSM, // ptm:sysm SYSM, // ptm:sysm
PLAY, // ptm:play PLAY, // ptm:play

View file

@ -28,10 +28,11 @@
#include "services/mcu/mcu_hwc.hpp" #include "services/mcu/mcu_hwc.hpp"
#include "services/mic.hpp" #include "services/mic.hpp"
#include "services/ndm.hpp" #include "services/ndm.hpp"
#include "services/nwm_uds.hpp"
#include "services/news_u.hpp" #include "services/news_u.hpp"
#include "services/nfc.hpp" #include "services/nfc.hpp"
#include "services/nim.hpp" #include "services/nim.hpp"
#include "services/ns.hpp"
#include "services/nwm_uds.hpp"
#include "services/ptm.hpp" #include "services/ptm.hpp"
#include "services/soc.hpp" #include "services/soc.hpp"
#include "services/ssl.hpp" #include "services/ssl.hpp"
@ -52,11 +53,11 @@ class ServiceManager {
MAKE_LOG_FUNCTION(log, srvLogger) MAKE_LOG_FUNCTION(log, srvLogger)
ACService ac; ACService ac;
ACTService act; ACTService act;
AMService am; AMService am;
APTService apt; APTService apt;
BOSSService boss; BOSSService boss;
CAMService cam; CAMService cam;
CECDService cecd; CECDService cecd;
CFGService cfg; CFGService cfg;
@ -76,7 +77,8 @@ class ServiceManager {
NewsUService news_u; NewsUService news_u;
NFCService nfc; NFCService nfc;
NwmUdsService nwm_uds; NwmUdsService nwm_uds;
NIMService nim; NIMService nim;
NSService ns;
PTMService ptm; PTMService ptm;
SOCService soc; SOCService soc;
SSLService ssl; SSLService ssl;

View file

@ -1,4 +1,5 @@
#include "services/ac.hpp" #include "services/ac.hpp"
#include "ipc.hpp" #include "ipc.hpp"
namespace ACCommands { namespace ACCommands {
@ -10,6 +11,7 @@ namespace ACCommands {
GetStatus = 0x000C0000, GetStatus = 0x000C0000,
GetWifiStatus = 0x000D0000, GetWifiStatus = 0x000D0000,
GetConnectingInfraPriority = 0x000F0000, GetConnectingInfraPriority = 0x000F0000,
GetNZoneBeaconNotFoundEvent = 0x002F0004,
RegisterDisconnectEvent = 0x00300004, RegisterDisconnectEvent = 0x00300004,
IsConnected = 0x003E0042, IsConnected = 0x003E0042,
SetClientVersion = 0x00400042, SetClientVersion = 0x00400042,
@ -29,12 +31,17 @@ void ACService::handleSyncRequest(u32 messagePointer) {
case ACCommands::CreateDefaultConfig: createDefaultConfig(messagePointer); break; case ACCommands::CreateDefaultConfig: createDefaultConfig(messagePointer); break;
case ACCommands::GetConnectingInfraPriority: getConnectingInfraPriority(messagePointer); break; case ACCommands::GetConnectingInfraPriority: getConnectingInfraPriority(messagePointer); break;
case ACCommands::GetLastErrorCode: getLastErrorCode(messagePointer); break; case ACCommands::GetLastErrorCode: getLastErrorCode(messagePointer); break;
case ACCommands::GetNZoneBeaconNotFoundEvent: getNZoneBeaconNotFoundEvent(messagePointer); break;
case ACCommands::GetStatus: getStatus(messagePointer); break; case ACCommands::GetStatus: getStatus(messagePointer); break;
case ACCommands::GetWifiStatus: getWifiStatus(messagePointer); break; case ACCommands::GetWifiStatus: getWifiStatus(messagePointer); break;
case ACCommands::IsConnected: isConnected(messagePointer); break; case ACCommands::IsConnected: isConnected(messagePointer); break;
case ACCommands::RegisterDisconnectEvent: registerDisconnectEvent(messagePointer); break; case ACCommands::RegisterDisconnectEvent: registerDisconnectEvent(messagePointer); break;
case ACCommands::SetClientVersion: setClientVersion(messagePointer); break; case ACCommands::SetClientVersion: setClientVersion(messagePointer); break;
default: Helpers::panic("AC service requested. Command: %08X\n", command);
default:
mem.write32(messagePointer + 4, Result::Success);
Helpers::warn("AC service requested. Command: %08X\n", command);
break;
} }
} }
@ -72,7 +79,7 @@ void ACService::getLastErrorCode(u32 messagePointer) {
mem.write32(messagePointer, IPC::responseHeader(0x0A, 2, 0)); mem.write32(messagePointer, IPC::responseHeader(0x0A, 2, 0));
mem.write32(messagePointer + 4, Result::Success); mem.write32(messagePointer + 4, Result::Success);
mem.write32(messagePointer + 8, 0); // Hopefully this means no error? mem.write32(messagePointer + 8, 0); // Hopefully this means no error?
} }
void ACService::getConnectingInfraPriority(u32 messagePointer) { void ACService::getConnectingInfraPriority(u32 messagePointer) {
@ -136,4 +143,13 @@ void ACService::registerDisconnectEvent(u32 messagePointer) {
mem.write32(messagePointer, IPC::responseHeader(0x30, 1, 0)); mem.write32(messagePointer, IPC::responseHeader(0x30, 1, 0));
mem.write32(messagePointer + 4, Result::Success); mem.write32(messagePointer + 4, Result::Success);
}
void ACService::getNZoneBeaconNotFoundEvent(u32 messagePointer) {
const u32 processID = mem.read32(messagePointer + 8);
const Handle event = mem.read32(messagePointer + 16);
log("AC::GetNZoneBeaconNotFoundEvent (process ID = %X, event = %X) (stubbed)\n", processID, event);
mem.write32(messagePointer, IPC::responseHeader(0x2F, 1, 0));
mem.write32(messagePointer + 4, Result::Success);
} }

View file

@ -1,4 +1,5 @@
#include "services/boss.hpp" #include "services/boss.hpp"
#include "ipc.hpp" #include "ipc.hpp"
namespace BOSSCommands { namespace BOSSCommands {
@ -25,27 +26,36 @@ namespace BOSSCommands {
GetTaskState = 0x00200082, GetTaskState = 0x00200082,
GetTaskStatus = 0x002300C2, GetTaskStatus = 0x002300C2,
GetTaskInfo = 0x00250082, GetTaskInfo = 0x00250082,
DeleteNsData = 0x00260040,
GetNsDataHeaderInfo = 0x002700C2,
ReadNsData = 0x00280102,
GetNsDataLastUpdated = 0x002D0040,
GetErrorCode = 0x002E0040, GetErrorCode = 0x002E0040,
RegisterStorageEntry = 0x002F0140, RegisterStorageEntry = 0x002F0140,
GetStorageEntryInfo = 0x00300000, GetStorageEntryInfo = 0x00300000,
StartBgImmediate = 0x00330042,
InitializeSessionPrivileged = 0x04010082,
GetAppNewFlag = 0x04040080,
SetAppNewFlag = 0x040500C0, // Probably
}; };
} }
void BOSSService::reset() { void BOSSService::reset() { optoutFlag = 0; }
optoutFlag = 0;
}
void BOSSService::handleSyncRequest(u32 messagePointer) { void BOSSService::handleSyncRequest(u32 messagePointer) {
const u32 command = mem.read32(messagePointer); const u32 command = mem.read32(messagePointer);
switch (command) { switch (command) {
case BOSSCommands::CancelTask: cancelTask(messagePointer); break; case BOSSCommands::CancelTask: cancelTask(messagePointer); break;
case BOSSCommands::DeleteNsData: deleteNsData(messagePointer); break;
case BOSSCommands::GetAppNewFlag: getAppNewFlag(messagePointer); break;
case BOSSCommands::GetErrorCode: getErrorCode(messagePointer); break; case BOSSCommands::GetErrorCode: getErrorCode(messagePointer); break;
case BOSSCommands::GetNsDataHeaderInfo: getNsDataHeaderInfo(messagePointer); break;
case BOSSCommands::GetNewArrivalFlag: getNewArrivalFlag(messagePointer); break; case BOSSCommands::GetNewArrivalFlag: getNewArrivalFlag(messagePointer); break;
case BOSSCommands::GetNsDataIdList: case BOSSCommands::GetNsDataIdList:
case BOSSCommands::GetNsDataIdList1: case BOSSCommands::GetNsDataIdList1:
case BOSSCommands::GetNsDataIdList2: case BOSSCommands::GetNsDataIdList2:
case BOSSCommands::GetNsDataIdList3: case BOSSCommands::GetNsDataIdList3: getNsDataIdList(messagePointer, command); break;
getNsDataIdList(messagePointer, command); break; case BOSSCommands::GetNsDataLastUpdated: getNsDataLastUpdated(messagePointer); break;
case BOSSCommands::GetOptoutFlag: getOptoutFlag(messagePointer); break; case BOSSCommands::GetOptoutFlag: getOptoutFlag(messagePointer); break;
case BOSSCommands::GetStorageEntryInfo: getStorageEntryInfo(messagePointer); break; case BOSSCommands::GetStorageEntryInfo: getStorageEntryInfo(messagePointer); break;
case BOSSCommands::GetTaskIdList: getTaskIdList(messagePointer); break; case BOSSCommands::GetTaskIdList: getTaskIdList(messagePointer); break;
@ -54,17 +64,31 @@ void BOSSService::handleSyncRequest(u32 messagePointer) {
case BOSSCommands::GetTaskState: getTaskState(messagePointer); break; case BOSSCommands::GetTaskState: getTaskState(messagePointer); break;
case BOSSCommands::GetTaskStatus: getTaskStatus(messagePointer); break; case BOSSCommands::GetTaskStatus: getTaskStatus(messagePointer); break;
case BOSSCommands::GetTaskStorageInfo: getTaskStorageInfo(messagePointer); break; case BOSSCommands::GetTaskStorageInfo: getTaskStorageInfo(messagePointer); break;
case BOSSCommands::InitializeSession: initializeSession(messagePointer); break; case BOSSCommands::InitializeSession:
case BOSSCommands::InitializeSessionPrivileged: initializeSession(messagePointer); break;
case BOSSCommands::ReadNsData: readNsData(messagePointer); break;
case BOSSCommands::ReceiveProperty: receiveProperty(messagePointer); break; case BOSSCommands::ReceiveProperty: receiveProperty(messagePointer); break;
case BOSSCommands::RegisterNewArrivalEvent: registerNewArrivalEvent(messagePointer); break; case BOSSCommands::RegisterNewArrivalEvent: registerNewArrivalEvent(messagePointer); break;
case BOSSCommands::RegisterStorageEntry: registerStorageEntry(messagePointer); break; case BOSSCommands::RegisterStorageEntry: registerStorageEntry(messagePointer); break;
case BOSSCommands::RegisterTask: registerTask(messagePointer); break; case BOSSCommands::RegisterTask: registerTask(messagePointer); break;
case BOSSCommands::SendProperty: sendProperty(messagePointer); break; case BOSSCommands::SendProperty: sendProperty(messagePointer); break;
case BOSSCommands::SetAppNewFlag: setAppNewFlag(messagePointer); break;
case BOSSCommands::SetOptoutFlag: setOptoutFlag(messagePointer); break; case BOSSCommands::SetOptoutFlag: setOptoutFlag(messagePointer); break;
case BOSSCommands::StartBgImmediate: startBgImmediate(messagePointer); break;
case BOSSCommands::StartTask: startTask(messagePointer); break; case BOSSCommands::StartTask: startTask(messagePointer); break;
case BOSSCommands::UnregisterStorage: unregisterStorage(messagePointer); break; case BOSSCommands::UnregisterStorage: unregisterStorage(messagePointer); break;
case BOSSCommands::UnregisterTask: unregisterTask(messagePointer); break; case BOSSCommands::UnregisterTask: unregisterTask(messagePointer); break;
default: Helpers::panic("BOSS service requested. Command: %08X\n", command);
case 0x04500102: // Home Menu uses this command, what is this?
Helpers::warn("BOSS command 0x04500102");
mem.write32(messagePointer, IPC::responseHeader(0x450, 1, 0));
mem.write32(messagePointer + 4, Result::Success);
break;
default:
mem.write32(messagePointer + 4, Result::Success);
Helpers::warn("BOSS service requested. Command: %08X\n", command);
break;
} }
} }
@ -99,7 +123,7 @@ void BOSSService::getTaskState(u32 messagePointer) {
mem.write32(messagePointer + 4, Result::Success); mem.write32(messagePointer + 4, Result::Success);
mem.write8(messagePointer + 8, 0); // TaskStatus: Report the task finished successfully mem.write8(messagePointer + 8, 0); // TaskStatus: Report the task finished successfully
mem.write32(messagePointer + 12, 0); // Current state value for task PropertyID 0x4 mem.write32(messagePointer + 12, 0); // Current state value for task PropertyID 0x4
mem.write8(messagePointer + 16, 0); // TODO: Figure out what this should be mem.write8(messagePointer + 16, 0); // TODO: Figure out what this should be
} }
void BOSSService::getTaskStatus(u32 messagePointer) { void BOSSService::getTaskStatus(u32 messagePointer) {
@ -150,15 +174,15 @@ void BOSSService::getErrorCode(u32 messagePointer) {
log("BOSS::GetErrorCode (stubbed)\n"); log("BOSS::GetErrorCode (stubbed)\n");
mem.write32(messagePointer, IPC::responseHeader(0x2E, 2, 0)); mem.write32(messagePointer, IPC::responseHeader(0x2E, 2, 0));
mem.write32(messagePointer + 4, Result::Success); mem.write32(messagePointer + 4, Result::Success);
mem.write32(messagePointer + 8, Result::Success); // No error code mem.write32(messagePointer + 8, Result::Success); // No error code
} }
void BOSSService::getStorageEntryInfo(u32 messagePointer) { void BOSSService::getStorageEntryInfo(u32 messagePointer) {
log("BOSS::GetStorageEntryInfo (undocumented)\n"); log("BOSS::GetStorageEntryInfo (undocumented)\n");
mem.write32(messagePointer, IPC::responseHeader(0x30, 3, 0)); mem.write32(messagePointer, IPC::responseHeader(0x30, 3, 0));
mem.write32(messagePointer + 4, Result::Success); mem.write32(messagePointer + 4, Result::Success);
mem.write32(messagePointer + 8, 0); // u32, unknown meaning mem.write32(messagePointer + 8, 0); // u32, unknown meaning
mem.write16(messagePointer + 12, 0); // s16, unknown meaning mem.write16(messagePointer + 12, 0); // s16, unknown meaning
} }
void BOSSService::sendProperty(u32 messagePointer) { void BOSSService::sendProperty(u32 messagePointer) {
@ -173,7 +197,6 @@ void BOSSService::sendProperty(u32 messagePointer) {
// TODO: Should this do anything else? // TODO: Should this do anything else?
} }
void BOSSService::receiveProperty(u32 messagePointer) { void BOSSService::receiveProperty(u32 messagePointer) {
const u32 id = mem.read32(messagePointer + 4); const u32 id = mem.read32(messagePointer + 4);
const u32 size = mem.read32(messagePointer + 8); const u32 size = mem.read32(messagePointer + 8);
@ -182,13 +205,13 @@ void BOSSService::receiveProperty(u32 messagePointer) {
log("BOSS::ReceiveProperty (id = %d, size = %08X, ptr = %08X) (stubbed)\n", id, size, ptr); log("BOSS::ReceiveProperty (id = %d, size = %08X, ptr = %08X) (stubbed)\n", id, size, ptr);
mem.write32(messagePointer, IPC::responseHeader(0x16, 2, 2)); mem.write32(messagePointer, IPC::responseHeader(0x16, 2, 2));
mem.write32(messagePointer + 4, Result::Success); mem.write32(messagePointer + 4, Result::Success);
mem.write32(messagePointer + 8, 0); // Read size mem.write32(messagePointer + 8, 0); // Read size
} }
// This seems to accept a KEvent as a parameter and register it for something Spotpass related // This seems to accept a KEvent as a parameter and register it for something Spotpass related
// I need to update the 3DBrew page when it's known what it does properly // I need to update the 3DBrew page when it's known what it does properly
void BOSSService::registerNewArrivalEvent(u32 messagePointer) { void BOSSService::registerNewArrivalEvent(u32 messagePointer) {
const Handle eventHandle = mem.read32(messagePointer + 4); // Kernel event handle to register const Handle eventHandle = mem.read32(messagePointer + 4); // Kernel event handle to register
log("BOSS::RegisterNewArrivalEvent (handle = %X)\n", eventHandle); log("BOSS::RegisterNewArrivalEvent (handle = %X)\n", eventHandle);
mem.write32(messagePointer, IPC::responseHeader(0x8, 1, 0)); mem.write32(messagePointer, IPC::responseHeader(0x8, 1, 0));
@ -252,5 +275,92 @@ void BOSSService::getNewArrivalFlag(u32 messagePointer) {
log("BOSS::GetNewArrivalFlag (stubbed)\n"); log("BOSS::GetNewArrivalFlag (stubbed)\n");
mem.write32(messagePointer, IPC::responseHeader(0x7, 2, 0)); mem.write32(messagePointer, IPC::responseHeader(0x7, 2, 0));
mem.write32(messagePointer + 4, Result::Success); mem.write32(messagePointer + 4, Result::Success);
mem.write8(messagePointer + 8, 0); // Flag mem.write8(messagePointer + 8, 0); // Flag
}
void BOSSService::startBgImmediate(u32 messagePointer) {
const u32 size = mem.read32(messagePointer + 8);
const u32 taskIDs = mem.read32(messagePointer + 12);
log("BOSS::StartBgImmediate (size = %X, task ID pointer = %X) (stubbed)\n", size, taskIDs);
mem.write32(messagePointer, IPC::responseHeader(0x33, 1, 2));
mem.write32(messagePointer + 4, Result::Success);
mem.write32(messagePointer + 8, IPC::pointerHeader(0, size, IPC::BufferType::Send));
mem.write32(messagePointer + 12, taskIDs);
}
void BOSSService::getAppNewFlag(u32 messagePointer) {
const u64 appID = mem.read64(messagePointer + 4);
log("BOSS::GetAppNewFlag (app ID = %llX)\n", appID);
mem.write32(messagePointer, IPC::responseHeader(0x404, 2, 0));
mem.write32(messagePointer + 4, Result::Success);
mem.write8(messagePointer + 8, 0); // No new content
}
void BOSSService::getNsDataHeaderInfo(u32 messagePointer) {
const u32 nsDataID = mem.read32(messagePointer + 4);
const u8 type = mem.read8(messagePointer + 8);
const u32 size = mem.read32(messagePointer + 12);
const u32 nsDataHeaderInfo = mem.read32(messagePointer + 20);
log("BOSS::GetNsDataHeaderInfo (NS data ID = %X, type = %X, size = %X, NS data header info pointer = %X) (stubbed)\n", nsDataID, type, size,
nsDataHeaderInfo);
switch (type) {
case 3:
case 5: mem.write32(nsDataHeaderInfo, 0); break; // ??
default: Helpers::panic("Unimplemented NS data header info type %X", type);
}
mem.write32(messagePointer, IPC::responseHeader(0x27, 1, 2));
mem.write32(messagePointer + 4, Result::Success);
mem.write32(messagePointer + 8, IPC::pointerHeader(0, size, IPC::BufferType::Receive));
mem.write32(messagePointer + 12, nsDataHeaderInfo);
}
void BOSSService::getNsDataLastUpdated(u32 messagePointer) {
const u32 nsDataID = mem.read32(messagePointer + 4);
log("BOSS::GetNsDataLastUpdated (NS data ID = %X) (stubbed)\n", nsDataID);
mem.write32(messagePointer, IPC::responseHeader(0x2D, 3, 0));
mem.write32(messagePointer + 4, Result::Success);
mem.write64(messagePointer + 8, 0); // Milliseconds since last update?
}
void BOSSService::readNsData(u32 messagePointer) {
const u32 nsDataID = mem.read32(messagePointer + 4);
const s64 offset = mem.read64(messagePointer + 8);
const u32 size = mem.read32(messagePointer + 20);
const u32 data = mem.read32(messagePointer + 24);
log("BOSS::ReadNsData (NS data ID = %X, offset = %llX, size = %X, data pointer = %X) (stubbed)\n", nsDataID, offset, size, data);
for (u32 i = 0; i < size; i++) {
mem.write8(data + i, 0);
}
mem.write32(messagePointer, IPC::responseHeader(0x28, 3, 2));
mem.write32(messagePointer + 4, Result::Success);
mem.write32(messagePointer + 8, size); // Technically how many bytes have been read
mem.write32(messagePointer + 12, 0); // ??
mem.write32(messagePointer + 16, IPC::pointerHeader(0, size, IPC::BufferType::Receive));
mem.write32(messagePointer + 20, data);
}
void BOSSService::deleteNsData(u32 messagePointer) {
const u32 nsDataID = mem.read32(messagePointer + 4);
log("BOSS::DeleteNsData (NS data ID = %X) (stubbed)\n", nsDataID);
mem.write32(messagePointer, IPC::responseHeader(0x26, 1, 0));
mem.write32(messagePointer + 4, Result::Success);
}
// Judging by the inputs and command number, this could very well be a "SetAppNewFlag"
void BOSSService::setAppNewFlag(u32 messagePointer) {
const u64 appID = mem.read64(messagePointer + 4);
const u8 flag = mem.read32(messagePointer + 12);
log("BOSS::SetAppNewFlag (app ID = %llX, flag = %X)\n", appID, flag);
mem.write32(messagePointer, IPC::responseHeader(0x405, 1, 0));
mem.write32(messagePointer + 4, Result::Success);
} }

View file

@ -17,40 +17,80 @@ namespace CFGCommands {
GetRegionCanadaUSA = 0x00040000, GetRegionCanadaUSA = 0x00040000,
GetSystemModel = 0x00050000, GetSystemModel = 0x00050000,
TranslateCountryInfo = 0x00080080, TranslateCountryInfo = 0x00080080,
GetCountryCodeID = 0x000A0040,
GetCountryCodeID = 0x000A0040,
IsFangateSupported = 0x000B0000,
SetConfigInfoBlk4 = 0x04020082,
UpdateConfigNANDSavegame = 0x04030000,
GetLocalFriendCodeSeed = 0x04050000, GetLocalFriendCodeSeed = 0x04050000,
SecureInfoGetByte101 = 0x04070000, SecureInfoGetByte101 = 0x04070000,
}; };
} }
// cfg:i commands
namespace CFGICommands {
enum : u32 {
GetConfigInfoBlk8 = 0x08010082,
};
}
// cfg:nor commands
namespace NORCommands {
enum : u32 {
Initialize = 0x00010040,
ReadData = 0x00050082,
};
}
void CFGService::reset() {} void CFGService::reset() {}
void CFGService::handleSyncRequest(u32 messagePointer, CFGService::Type type) { void CFGService::handleSyncRequest(u32 messagePointer, CFGService::Type type) {
const u32 command = mem.read32(messagePointer); const u32 command = mem.read32(messagePointer);
switch (command) {
case CFGCommands::GetConfigInfoBlk2: [[likely]] getConfigInfoBlk2(messagePointer); break;
case CFGCommands::GetCountryCodeID: getCountryCodeID(messagePointer); break;
case CFGCommands::GetRegionCanadaUSA: getRegionCanadaUSA(messagePointer); break;
case CFGCommands::GetSystemModel: getSystemModel(messagePointer); break;
case CFGCommands::GenHashConsoleUnique: genUniqueConsoleHash(messagePointer); break;
case CFGCommands::SecureInfoGetRegion: secureInfoGetRegion(messagePointer); break;
case CFGCommands::TranslateCountryInfo: translateCountryInfo(messagePointer); break;
default: if (type != Type::NOR) {
if (type == Type::S) { switch (command) {
// cfg:s-only functions case CFGCommands::GetConfigInfoBlk2: [[likely]] getConfigInfoBlk2(messagePointer); break;
switch (command) { case CFGCommands::GetCountryCodeID: getCountryCodeID(messagePointer); break;
case CFGCommands::GetConfigInfoBlk8: getConfigInfoBlk8(messagePointer); break; case CFGCommands::GetRegionCanadaUSA: getRegionCanadaUSA(messagePointer); break;
case CFGCommands::GetLocalFriendCodeSeed: getLocalFriendCodeSeed(messagePointer); break; case CFGCommands::GetSystemModel: getSystemModel(messagePointer); break;
case CFGCommands::SecureInfoGetByte101: secureInfoGetByte101(messagePointer); break; case CFGCommands::GenHashConsoleUnique: genUniqueConsoleHash(messagePointer); break;
default: Helpers::panic("CFG:S service requested. Command: %08X\n", command); case CFGCommands::IsFangateSupported: isFangateSupported(messagePointer); break;
case CFGCommands::SecureInfoGetRegion: secureInfoGetRegion(messagePointer); break;
case CFGCommands::TranslateCountryInfo: translateCountryInfo(messagePointer); break;
default:
if (type == Type::S) {
// cfg:s (and cfg:i) functions only functions
switch (command) {
case CFGCommands::GetConfigInfoBlk8: getConfigInfoBlk8(messagePointer, command); break;
case CFGCommands::GetLocalFriendCodeSeed: getLocalFriendCodeSeed(messagePointer); break;
case CFGCommands::SecureInfoGetByte101: secureInfoGetByte101(messagePointer); break;
case CFGCommands::SetConfigInfoBlk4: setConfigInfoBlk4(messagePointer); break;
case CFGCommands::UpdateConfigNANDSavegame: updateConfigNANDSavegame(messagePointer); break;
default: Helpers::panic("CFG:S service requested. Command: %08X\n", command);
}
} else if (type == Type::I) {
switch (command) {
case CFGCommands::GetConfigInfoBlk8:
case CFGICommands::GetConfigInfoBlk8: getConfigInfoBlk8(messagePointer, command); break;
default: Helpers::panic("CFG:I service requested. Command: %08X\n", command);
}
} else {
Helpers::panic("CFG service requested. Command: %08X\n", command);
} }
} else {
Helpers::panic("CFG service requested. Command: %08X\n", command);
}
break; break;
}
} else {
// cfg:nor functions
switch (command) {
case NORCommands::Initialize: norInitialize(messagePointer); break;
case NORCommands::ReadData: norReadData(messagePointer); break;
default: Helpers::panic("CFG:NOR service requested. Command: %08X\n", command);
}
} }
} }
@ -84,14 +124,14 @@ void CFGService::getConfigInfoBlk2(u32 messagePointer) {
mem.write32(messagePointer + 4, Result::Success); mem.write32(messagePointer + 4, Result::Success);
} }
void CFGService::getConfigInfoBlk8(u32 messagePointer) { void CFGService::getConfigInfoBlk8(u32 messagePointer, u32 commandWord) {
u32 size = mem.read32(messagePointer + 4); u32 size = mem.read32(messagePointer + 4);
u32 blockID = mem.read32(messagePointer + 8); u32 blockID = mem.read32(messagePointer + 8);
u32 output = mem.read32(messagePointer + 16); // Pointer to write the output data to u32 output = mem.read32(messagePointer + 16); // Pointer to write the output data to
log("CFG::GetConfigInfoBlk8 (size = %X, block ID = %X, output pointer = %08X\n", size, blockID, output); log("CFG::GetConfigInfoBlk8 (size = %X, block ID = %X, output pointer = %08X\n", size, blockID, output);
getConfigInfo(output, blockID, size, 0x8); getConfigInfo(output, blockID, size, 0x8);
mem.write32(messagePointer, IPC::responseHeader(0x401, 1, 2)); mem.write32(messagePointer, IPC::responseHeader(commandWord >> 16, 1, 2));
mem.write32(messagePointer + 4, Result::Success); mem.write32(messagePointer + 4, Result::Success);
} }
@ -160,6 +200,37 @@ void CFGService::getConfigInfo(u32 output, u32 blockID, u32 size, u32 permission
mem.write32(output, 0); mem.write32(output, 0);
} else if (size == 8 && blockID == 0x00090000) { } else if (size == 8 && blockID == 0x00090000) {
mem.write64(output, 0); // Some sort of key used with nwm::UDS::InitializeWithVersion mem.write64(output, 0); // Some sort of key used with nwm::UDS::InitializeWithVersion
} else if (size == 4 && blockID == 0x110000) {
mem.write32(output, 1); // According to 3Dbrew, 0 means system setup is required
} else if (size == 2 && blockID == 0x50001) {
// Backlight controls. Values taken from Citra
mem.write8(output, 0);
mem.write8(output + 1, 2);
} else if (size == 8 && blockID == 0x50009) {
// N3DS Backlight controls?
mem.write64(output, 0);
} else if (size == 4 && blockID == 0x180000) {
// Infrared LED related?
mem.write32(output, 0);
} else if (size == 1 && blockID == 0xE0000) {
mem.write8(output, 0);
} else if ((size == 512 && blockID == 0xC0002) || (size == 148 && blockID == 0x100001)) {
// CTR parental controls block (0xC0002) and TWL parental controls block (0x100001)
for (u32 i = 0; i < size; i++) {
mem.write8(output + i, 0);
}
} else if (size == 2 && blockID == 0x100000) {
// EULA agreed
mem.write8(output, 1); // We have agreed to the EULA
mem.write8(output + 1, 1); // EULA version = 1
} else if (size == 1 && blockID == 0x100002) {
Helpers::warn("Unimplemented TWL country code access");
mem.write8(output, 0);
} else if (size == 24 && blockID == 0x180001) {
// QTM calibration data
for (u32 i = 0; i < size; i++) {
mem.write8(output + i, 0);
}
} else { } else {
Helpers::panic("Unhandled GetConfigInfoBlk2 configuration. Size = %d, block = %X", size, blockID); Helpers::panic("Unhandled GetConfigInfoBlk2 configuration. Size = %d, block = %X", size, blockID);
} }
@ -260,6 +331,25 @@ void CFGService::getLocalFriendCodeSeed(u32 messagePointer) {
mem.write64(messagePointer + 8, 0); mem.write64(messagePointer + 8, 0);
} }
void CFGService::setConfigInfoBlk4(u32 messagePointer) {
u32 blockID = mem.read32(messagePointer + 4);
u32 size = mem.read32(messagePointer + 8);
u32 input = mem.read32(messagePointer + 16);
log("CFG::SetConfigInfoBlk4 (block ID = %X, size = %X, input pointer = %08X)\n", blockID, size, input);
mem.write32(messagePointer, IPC::responseHeader(0x401, 1, 2));
mem.write32(messagePointer + 4, Result::Success);
mem.write32(messagePointer + 8, IPC::pointerHeader(0, size, IPC::BufferType::Receive));
mem.write32(messagePointer + 12, input);
}
void CFGService::updateConfigNANDSavegame(u32 messagePointer) {
log("CFG::UpdateConfigNANDSavegame\n");
mem.write32(messagePointer, IPC::responseHeader(0x403, 1, 0));
mem.write32(messagePointer + 4, Result::Success);
}
// https://www.3dbrew.org/wiki/Cfg:TranslateCountryInfo // https://www.3dbrew.org/wiki/Cfg:TranslateCountryInfo
void CFGService::translateCountryInfo(u32 messagePointer) { void CFGService::translateCountryInfo(u32 messagePointer) {
const u32 country = mem.read32(messagePointer + 4); const u32 country = mem.read32(messagePointer + 4);
@ -292,4 +382,28 @@ void CFGService::translateCountryInfo(u32 messagePointer) {
mem.write32(messagePointer, IPC::responseHeader(0x8, 2, 0)); mem.write32(messagePointer, IPC::responseHeader(0x8, 2, 0));
mem.write32(messagePointer + 4, Result::Success); mem.write32(messagePointer + 4, Result::Success);
mem.write32(messagePointer + 8, result); mem.write32(messagePointer + 8, result);
}
void CFGService::isFangateSupported(u32 messagePointer) {
log("CFG::IsFangateSupported\n");
// TODO: What even is fangate?
mem.write32(messagePointer, IPC::responseHeader(0xB, 2, 0));
mem.write32(messagePointer + 4, Result::Success);
mem.write32(messagePointer + 8, 1);
}
void CFGService::norInitialize(u32 messagePointer) {
log("CFG::NOR::Initialize\n");
mem.write32(messagePointer, IPC::responseHeader(0x1, 1, 0));
mem.write32(messagePointer + 4, Result::Success);
}
void CFGService::norReadData(u32 messagePointer) {
log("CFG::NOR::ReadData\n");
Helpers::warn("Unimplemented CFG::NOR::ReadData");
mem.write32(messagePointer, IPC::responseHeader(0x5, 1, 0));
mem.write32(messagePointer + 4, Result::Success);
} }

View file

@ -1,4 +1,5 @@
#include "services/gsp_gpu.hpp" #include "services/gsp_gpu.hpp"
#include "PICA/regs.hpp" #include "PICA/regs.hpp"
#include "ipc.hpp" #include "ipc.hpp"
#include "kernel.hpp" #include "kernel.hpp"
@ -39,7 +40,7 @@ namespace GXCommands {
} }
void GPUService::reset() { void GPUService::reset() {
privilegedProcess = 0xFFFFFFFF; // Set the privileged process to an invalid handle privilegedProcess = 0xFFFFFFFF; // Set the privileged process to an invalid handle
interruptEvent = std::nullopt; interruptEvent = std::nullopt;
gspThreadCount = 0; gspThreadCount = 0;
sharedMem = nullptr; sharedMem = nullptr;
@ -113,38 +114,38 @@ void GPUService::registerInterruptRelayQueue(u32 messagePointer) {
log("GSP::GPU::RegisterInterruptRelayQueue (flags = %X, event handle = %X)\n", flags, eventHandle); log("GSP::GPU::RegisterInterruptRelayQueue (flags = %X, event handle = %X)\n", flags, eventHandle);
const auto event = kernel.getObject(eventHandle, KernelObjectType::Event); const auto event = kernel.getObject(eventHandle, KernelObjectType::Event);
if (event == nullptr) { // Check if interrupt event is invalid if (event == nullptr) { // Check if interrupt event is invalid
Helpers::panic("Invalid event passed to GSP::GPU::RegisterInterruptRelayQueue"); Helpers::panic("Invalid event passed to GSP::GPU::RegisterInterruptRelayQueue");
} else { } else {
interruptEvent = eventHandle; interruptEvent = eventHandle;
} }
mem.write32(messagePointer, IPC::responseHeader(0x13, 2, 2)); mem.write32(messagePointer, IPC::responseHeader(0x13, 2, 2));
mem.write32(messagePointer + 4, Result::GSP::SuccessRegisterIRQ); // First init returns a unique result mem.write32(messagePointer + 4, Result::GSP::SuccessRegisterIRQ); // First init returns a unique result
mem.write32(messagePointer + 8, 0); // TODO: GSP module thread index mem.write32(messagePointer + 8, 0); // TODO: GSP module thread index
mem.write32(messagePointer + 12, 0); // Translation descriptor mem.write32(messagePointer + 12, 0); // Translation descriptor
mem.write32(messagePointer + 16, KernelHandles::GSPSharedMemHandle); mem.write32(messagePointer + 16, KernelHandles::GSPSharedMemHandle);
} }
void GPUService::requestInterrupt(GPUInterrupt type) { void GPUService::requestInterrupt(GPUInterrupt type) {
if (sharedMem == nullptr) [[unlikely]] { // Shared memory hasn't been set up yet if (sharedMem == nullptr) [[unlikely]] { // Shared memory hasn't been set up yet
return; return;
} }
// TODO: Add support for multiple GSP threads // TODO: Add support for multiple GSP threads
u8 index = sharedMem[0]; // The interrupt block is normally located at sharedMem + processGSPIndex*0x40 u8 index = sharedMem[0]; // The interrupt block is normally located at sharedMem + processGSPIndex*0x40
u8& interruptCount = sharedMem[1]; u8& interruptCount = sharedMem[1];
u8 flagIndex = (index + interruptCount) % 0x34; u8 flagIndex = (index + interruptCount) % 0x34;
interruptCount++; interruptCount++;
sharedMem[2] = 0; // Set error code to 0 sharedMem[2] = 0; // Set error code to 0
sharedMem[0xC + flagIndex] = static_cast<u8>(type); // Write interrupt type to queue sharedMem[0xC + flagIndex] = static_cast<u8>(type); // Write interrupt type to queue
// Update framebuffer info in shared memory // Update framebuffer info in shared memory
// Most new games check to make sure that the "flag" byte of the framebuffer info header is set to 0 // Most new games check to make sure that the "flag" byte of the framebuffer info header is set to 0
// Not emulating this causes Yoshi's Wooly World, Captain Toad, Metroid 2 et al to hang // Not emulating this causes Yoshi's Wooly World, Captain Toad, Metroid 2 et al to hang
if (type == GPUInterrupt::VBlank0 || type == GPUInterrupt::VBlank1) { if (type == GPUInterrupt::VBlank0 || type == GPUInterrupt::VBlank1) {
int screen = static_cast<u32>(type) - static_cast<u32>(GPUInterrupt::VBlank0); // 0 for top screen, 1 for bottom int screen = static_cast<u32>(type) - static_cast<u32>(GPUInterrupt::VBlank0); // 0 for top screen, 1 for bottom
FramebufferUpdate* update = getFramebufferInfo(screen); FramebufferUpdate* update = getFramebufferInfo(screen);
if (update->dirtyFlag & 1) { if (update->dirtyFlag & 1) {
@ -165,7 +166,6 @@ void GPUService::readHwRegs(u32 messagePointer) {
const u32 initialDataPointer = mem.read32(messagePointer + 0x104); const u32 initialDataPointer = mem.read32(messagePointer + 0x104);
u32 dataPointer = initialDataPointer; u32 dataPointer = initialDataPointer;
log("GSP::GPU::ReadHwRegs (GPU address = %08X, size = %X, data address = %08X)\n", ioAddr, size, dataPointer); log("GSP::GPU::ReadHwRegs (GPU address = %08X, size = %X, data address = %08X)\n", ioAddr, size, dataPointer);
// Check for alignment // Check for alignment
if ((size & 3) || (ioAddr & 3) || (dataPointer & 3)) { if ((size & 3) || (ioAddr & 3) || (dataPointer & 3)) {
@ -197,8 +197,8 @@ void GPUService::readHwRegs(u32 messagePointer) {
} }
void GPUService::writeHwRegs(u32 messagePointer) { void GPUService::writeHwRegs(u32 messagePointer) {
u32 ioAddr = mem.read32(messagePointer + 4); // GPU address based at 0x1EB00000, word aligned u32 ioAddr = mem.read32(messagePointer + 4); // GPU address based at 0x1EB00000, word aligned
const u32 size = mem.read32(messagePointer + 8); // Size in bytes const u32 size = mem.read32(messagePointer + 8); // Size in bytes
u32 dataPointer = mem.read32(messagePointer + 16); u32 dataPointer = mem.read32(messagePointer + 16);
log("GSP::GPU::writeHwRegs (GPU address = %08X, size = %X, data address = %08X)\n", ioAddr, size, dataPointer); log("GSP::GPU::writeHwRegs (GPU address = %08X, size = %X, data address = %08X)\n", ioAddr, size, dataPointer);
@ -230,14 +230,14 @@ void GPUService::writeHwRegs(u32 messagePointer) {
// Update sequential GPU registers using an array of data and mask values using this formula // Update sequential GPU registers using an array of data and mask values using this formula
// GPU register = (register & ~mask) | (data & mask). // GPU register = (register & ~mask) | (data & mask).
void GPUService::writeHwRegsWithMask(u32 messagePointer) { void GPUService::writeHwRegsWithMask(u32 messagePointer) {
u32 ioAddr = mem.read32(messagePointer + 4); // GPU address based at 0x1EB00000, word aligned u32 ioAddr = mem.read32(messagePointer + 4); // GPU address based at 0x1EB00000, word aligned
const u32 size = mem.read32(messagePointer + 8); // Size in bytes const u32 size = mem.read32(messagePointer + 8); // Size in bytes
u32 dataPointer = mem.read32(messagePointer + 16); // Data pointer u32 dataPointer = mem.read32(messagePointer + 16); // Data pointer
u32 maskPointer = mem.read32(messagePointer + 24); // Mask pointer u32 maskPointer = mem.read32(messagePointer + 24); // Mask pointer
log("GSP::GPU::writeHwRegsWithMask (GPU address = %08X, size = %X, data address = %08X, mask address = %08X)\n", log("GSP::GPU::writeHwRegsWithMask (GPU address = %08X, size = %X, data address = %08X, mask address = %08X)\n", ioAddr, size, dataPointer,
ioAddr, size, dataPointer, maskPointer); maskPointer);
// Check for alignment // Check for alignment
if ((size & 3) || (ioAddr & 3) || (dataPointer & 3) || (maskPointer & 3)) { if ((size & 3) || (ioAddr & 3) || (dataPointer & 3) || (maskPointer & 3)) {
@ -351,11 +351,11 @@ void GPUService::setInternalPriorities(u32 messagePointer) {
} }
void GPUService::processCommandBuffer() { void GPUService::processCommandBuffer() {
if (sharedMem == nullptr) [[unlikely]] { // Shared memory hasn't been set up yet if (sharedMem == nullptr) [[unlikely]] { // Shared memory hasn't been set up yet
return; return;
} }
constexpr int threadCount = 1; // TODO: More than 1 thread can have GSP commands at a time constexpr int threadCount = 1; // TODO: More than 1 thread can have GSP commands at a time
for (int t = 0; t < threadCount; t++) { for (int t = 0; t < threadCount; t++) {
u8* cmdBuffer = &sharedMem[0x800 + t * 0x200]; u8* cmdBuffer = &sharedMem[0x800 + t * 0x200];
u8& commandsLeft = cmdBuffer[1]; u8& commandsLeft = cmdBuffer[1];
@ -408,9 +408,9 @@ void GPUService::memoryFill(u32* cmd) {
u32 control = cmd[7]; u32 control = cmd[7];
// buf0 parameters // buf0 parameters
u32 start0 = cmd[1]; // Start address for the fill. If 0, don't fill anything u32 start0 = cmd[1]; // Start address for the fill. If 0, don't fill anything
u32 value0 = cmd[2]; // Value to fill the framebuffer with u32 value0 = cmd[2]; // Value to fill the framebuffer with
u32 end0 = cmd[3]; // End address for the fill u32 end0 = cmd[3]; // End address for the fill
u32 control0 = control & 0xffff; u32 control0 = control & 0xffff;
// buf1 parameters // buf1 parameters
@ -439,7 +439,7 @@ void GPUService::triggerDisplayTransfer(u32* cmd) {
log("GSP::GPU::TriggerDisplayTransfer (Stubbed)\n"); log("GSP::GPU::TriggerDisplayTransfer (Stubbed)\n");
gpu.displayTransfer(inputAddr, outputAddr, inputSize, outputSize, flags); gpu.displayTransfer(inputAddr, outputAddr, inputSize, outputSize, flags);
requestInterrupt(GPUInterrupt::PPF); // Send "Display transfer finished" interrupt requestInterrupt(GPUInterrupt::PPF); // Send "Display transfer finished" interrupt
} }
void GPUService::triggerDMARequest(u32* cmd) { void GPUService::triggerDMARequest(u32* cmd) {
@ -453,22 +453,14 @@ void GPUService::triggerDMARequest(u32* cmd) {
requestInterrupt(GPUInterrupt::DMA); requestInterrupt(GPUInterrupt::DMA);
} }
void GPUService::flushCacheRegions(u32* cmd) { void GPUService::flushCacheRegions(u32* cmd) { log("GSP::GPU::FlushCacheRegions (Stubbed)\n"); }
log("GSP::GPU::FlushCacheRegions (Stubbed)\n");
}
void GPUService::setBufferSwapImpl(u32 screenId, const FramebufferInfo& info) { void GPUService::setBufferSwapImpl(u32 screenId, const FramebufferInfo& info) {
using namespace PICA::ExternalRegs; using namespace PICA::ExternalRegs;
static constexpr std::array<u32, 8> fbAddresses = { static constexpr std::array<u32, 8> fbAddresses = {
Framebuffer0AFirstAddr, Framebuffer0AFirstAddr, Framebuffer0BFirstAddr, Framebuffer1AFirstAddr, Framebuffer1BFirstAddr,
Framebuffer0BFirstAddr, Framebuffer0ASecondAddr, Framebuffer0BSecondAddr, Framebuffer1ASecondAddr, Framebuffer1BSecondAddr,
Framebuffer1AFirstAddr,
Framebuffer1BFirstAddr,
Framebuffer0ASecondAddr,
Framebuffer0BSecondAddr,
Framebuffer1ASecondAddr,
Framebuffer1BSecondAddr,
}; };
auto& regs = gpu.getExtRegisters(); auto& regs = gpu.getExtRegisters();
@ -478,12 +470,7 @@ void GPUService::setBufferSwapImpl(u32 screenId, const FramebufferInfo& info) {
regs[fbAddresses[fbIndex + 1]] = VaddrToPaddr(info.rightFramebufferVaddr); regs[fbAddresses[fbIndex + 1]] = VaddrToPaddr(info.rightFramebufferVaddr);
static constexpr std::array<u32, 6> configAddresses = { static constexpr std::array<u32, 6> configAddresses = {
Framebuffer0Config, Framebuffer0Config, Framebuffer0Select, Framebuffer0Stride, Framebuffer1Config, Framebuffer1Select, Framebuffer1Stride,
Framebuffer0Select,
Framebuffer0Stride,
Framebuffer1Config,
Framebuffer1Select,
Framebuffer1Stride,
}; };
const u32 configIndex = screenId * 3; const u32 configIndex = screenId * 3;
@ -494,14 +481,14 @@ void GPUService::setBufferSwapImpl(u32 screenId, const FramebufferInfo& info) {
// Actually send command list (aka display list) to GPU // Actually send command list (aka display list) to GPU
void GPUService::processCommandList(u32* cmd) { void GPUService::processCommandList(u32* cmd) {
const u32 address = cmd[1] & ~7; // Buffer address const u32 address = cmd[1] & ~7; // Buffer address
const u32 size = cmd[2] & ~3; // Buffer size in bytes const u32 size = cmd[2] & ~3; // Buffer size in bytes
[[maybe_unused]] const bool updateGas = cmd[3] == 1; // Update gas additive blend results (0 = don't update, 1 = update) [[maybe_unused]] const bool updateGas = cmd[3] == 1; // Update gas additive blend results (0 = don't update, 1 = update)
[[maybe_unused]] const bool flushBuffer = cmd[7] == 1; // Flush buffer (0 = don't flush, 1 = flush) [[maybe_unused]] const bool flushBuffer = cmd[7] == 1; // Flush buffer (0 = don't flush, 1 = flush)
log("GPU::GSP::processCommandList. Address: %08X, size in bytes: %08X\n", address, size); log("GPU::GSP::processCommandList. Address: %08X, size in bytes: %08X\n", address, size);
gpu.startCommandList(address, size); gpu.startCommandList(address, size);
requestInterrupt(GPUInterrupt::P3D); // Send an IRQ when command list processing is over requestInterrupt(GPUInterrupt::P3D); // Send an IRQ when command list processing is over
} }
// TODO: Emulate the transfer engine & its registers // TODO: Emulate the transfer engine & its registers
@ -576,4 +563,4 @@ void GPUService::importDisplayCaptureInfo(u32 messagePointer) {
mem.write32(messagePointer + 28, bottomScreenCapture.rightFramebuffer); mem.write32(messagePointer + 28, bottomScreenCapture.rightFramebuffer);
mem.write32(messagePointer + 32, bottomScreenCapture.format); mem.write32(messagePointer + 32, bottomScreenCapture.format);
mem.write32(messagePointer + 36, bottomScreenCapture.stride); mem.write32(messagePointer + 36, bottomScreenCapture.stride);
} }

View file

@ -1,8 +1,10 @@
#include "services/gsp_lcd.hpp" #include "services/gsp_lcd.hpp"
#include "ipc.hpp" #include "ipc.hpp"
namespace LCDCommands { namespace LCDCommands {
enum : u32 { enum : u32 {
SetLedForceOff = 0x00130040,
}; };
} }
@ -11,6 +13,16 @@ void LCDService::reset() {}
void LCDService::handleSyncRequest(u32 messagePointer) { void LCDService::handleSyncRequest(u32 messagePointer) {
const u32 command = mem.read32(messagePointer); const u32 command = mem.read32(messagePointer);
switch (command) { switch (command) {
case LCDCommands::SetLedForceOff: setLedForceOff(messagePointer); break;
default: Helpers::panic("LCD service requested. Command: %08X\n", command); default: Helpers::panic("LCD service requested. Command: %08X\n", command);
} }
}
void LCDService::setLedForceOff(u32 messagePointer) {
const u8 state = mem.read8(messagePointer + 4);
log("LCD::SetLedForceOff (state = %X)\n", state);
mem.write32(messagePointer, IPC::responseHeader(0x13, 1, 0));
mem.write32(messagePointer + 4, Result::Success);
} }

32
src/core/services/ns.cpp Normal file
View file

@ -0,0 +1,32 @@
#include "services/ns.hpp"
#include "ipc.hpp"
namespace NSCommands {
enum : u32 {
LaunchTitle = 0x000200C0,
};
}
void NSService::reset() {}
void NSService::handleSyncRequest(u32 messagePointer, Type type) {
const u32 command = mem.read32(messagePointer);
// ns:s commands
switch (command) {
case NSCommands::LaunchTitle: launchTitle(messagePointer); break;
default: Helpers::panic("NS service requested. Command: %08X\n", command);
}
}
void NSService::launchTitle(u32 messagePointer) {
const u64 titleID = mem.read64(messagePointer + 4);
const u32 launchFlags = mem.read32(messagePointer + 12);
Helpers::warn("NS::LaunchTitle (title ID = %llX, launch flags = %X) (stubbed)", titleID, launchFlags);
mem.write32(messagePointer, IPC::responseHeader(0x2, 2, 0));
mem.write32(messagePointer + 4, Result::Success);
mem.write32(messagePointer + 8, 0); // Process ID
}

View file

@ -7,9 +7,9 @@
ServiceManager::ServiceManager(std::span<u32, 16> regs, Memory& mem, GPU& gpu, u32& currentPID, Kernel& kernel, const EmulatorConfig& config) ServiceManager::ServiceManager(std::span<u32, 16> 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), : 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, config), hid(mem, kernel), http(mem), ir_user(mem, kernel), frd(mem), fs(mem, kernel, config), csnd(mem, kernel), dlp_srvr(mem), dsp(mem, kernel, config), hid(mem, kernel), http(mem), ir_user(mem, kernel), frd(mem),
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), fs(mem, kernel, config), gsp_gpu(mem, gpu, kernel, currentPID), gsp_lcd(mem), ldr(mem, kernel), mcu_hwc(mem, config), mic(mem, kernel),
news_u(mem), nwm_uds(mem, kernel), ptm(mem, config), soc(mem), ssl(mem), y2r(mem, kernel) {} nfc(mem, kernel), nim(mem), ndm(mem), news_u(mem), ns(mem), nwm_uds(mem, kernel), ptm(mem, config), soc(mem), ssl(mem), y2r(mem, kernel) {}
static constexpr int MAX_NOTIFICATION_COUNT = 16; static constexpr int MAX_NOTIFICATION_COUNT = 16;
@ -40,6 +40,7 @@ void ServiceManager::reset() {
news_u.reset(); news_u.reset();
nfc.reset(); nfc.reset();
nim.reset(); nim.reset();
ns.reset();
ptm.reset(); ptm.reset();
soc.reset(); soc.reset();
ssl.reset(); ssl.reset();
@ -99,19 +100,23 @@ static std::map<std::string, HorizonHandle> serviceMap = {
{ "act:a", KernelHandles::ACT }, { "act:a", KernelHandles::ACT },
{ "act:u", KernelHandles::ACT }, { "act:u", KernelHandles::ACT },
{ "am:app", KernelHandles::AM }, { "am:app", KernelHandles::AM },
{ "am:sys", KernelHandles::AM },
{ "APT:S", KernelHandles::APT }, // TODO: APT:A, APT:S and APT:U are slightly different { "APT:S", KernelHandles::APT }, // TODO: APT:A, APT:S and APT:U are slightly different
{ "APT:A", KernelHandles::APT }, { "APT:A", KernelHandles::APT },
{ "APT:U", KernelHandles::APT }, { "APT:U", KernelHandles::APT },
{ "boss:U", KernelHandles::BOSS }, { "boss:U", KernelHandles::BOSS },
{ "boss:P", KernelHandles::BOSS },
{ "cam:u", KernelHandles::CAM }, { "cam:u", KernelHandles::CAM },
{ "cecd:u", KernelHandles::CECD }, { "cecd:u", KernelHandles::CECD },
{ "cfg:u", KernelHandles::CFG_U }, { "cfg:u", KernelHandles::CFG_U },
{ "cfg:i", KernelHandles::CFG_I }, { "cfg:i", KernelHandles::CFG_I },
{ "cfg:s", KernelHandles::CFG_S }, { "cfg:s", KernelHandles::CFG_S },
{ "cfg:nor", KernelHandles::CFG_NOR },
{ "csnd:SND", KernelHandles::CSND }, { "csnd:SND", KernelHandles::CSND },
{ "dlp:SRVR", KernelHandles::DLP_SRVR }, { "dlp:SRVR", KernelHandles::DLP_SRVR },
{ "dsp::DSP", KernelHandles::DSP }, { "dsp::DSP", KernelHandles::DSP },
{ "hid:USER", KernelHandles::HID }, { "hid:USER", KernelHandles::HID },
{ "hid:SPVR", KernelHandles::HID },
{ "http:C", KernelHandles::HTTP }, { "http:C", KernelHandles::HTTP },
{ "ir:USER", KernelHandles::IR_USER }, { "ir:USER", KernelHandles::IR_USER },
{ "frd:a", KernelHandles::FRD_A }, { "frd:a", KernelHandles::FRD_A },
@ -126,11 +131,13 @@ static std::map<std::string, HorizonHandle> serviceMap = {
{ "news:u", KernelHandles::NEWS_U }, { "news:u", KernelHandles::NEWS_U },
{ "nfc:u", KernelHandles::NFC }, { "nfc:u", KernelHandles::NFC },
{ "ns:s", KernelHandles::NS_S }, { "ns:s", KernelHandles::NS_S },
{ "nwm::EXT", KernelHandles::NWM_EXT },
{ "nwm::UDS", KernelHandles::NWM_UDS }, { "nwm::UDS", KernelHandles::NWM_UDS },
{ "nim:aoc", KernelHandles::NIM }, { "nim:aoc", KernelHandles::NIM },
{ "ptm:u", KernelHandles::PTM_U }, // TODO: ptm:u and ptm:sysm have very different command sets { "ptm:u", KernelHandles::PTM_U }, // TODO: ptm:u and ptm:sysm have very different command sets
{ "ptm:sysm", KernelHandles::PTM_SYSM }, { "ptm:sysm", KernelHandles::PTM_SYSM },
{ "ptm:play", KernelHandles::PTM_PLAY }, { "ptm:play", KernelHandles::PTM_PLAY },
{ "ptm:gets", KernelHandles::PTM_GETS },
{ "soc:U", KernelHandles::SOC }, { "soc:U", KernelHandles::SOC },
{ "ssl:C", KernelHandles::SSL }, { "ssl:C", KernelHandles::SSL },
{ "y2r:u", KernelHandles::Y2R }, { "y2r:u", KernelHandles::Y2R },
@ -213,6 +220,7 @@ void ServiceManager::sendCommandToService(u32 messagePointer, Handle handle) {
case KernelHandles::CFG_U: cfg.handleSyncRequest(messagePointer, CFGService::Type::U); break; case KernelHandles::CFG_U: cfg.handleSyncRequest(messagePointer, CFGService::Type::U); break;
case KernelHandles::CFG_I: cfg.handleSyncRequest(messagePointer, CFGService::Type::I); break; case KernelHandles::CFG_I: cfg.handleSyncRequest(messagePointer, CFGService::Type::I); break;
case KernelHandles::CFG_S: cfg.handleSyncRequest(messagePointer, CFGService::Type::S); break; case KernelHandles::CFG_S: cfg.handleSyncRequest(messagePointer, CFGService::Type::S); break;
case KernelHandles::CFG_NOR: cfg.handleSyncRequest(messagePointer, CFGService::Type::NOR); break;
case KernelHandles::CSND: csnd.handleSyncRequest(messagePointer); break; case KernelHandles::CSND: csnd.handleSyncRequest(messagePointer); break;
case KernelHandles::DLP_SRVR: dlp_srvr.handleSyncRequest(messagePointer); break; case KernelHandles::DLP_SRVR: dlp_srvr.handleSyncRequest(messagePointer); break;
case KernelHandles::HID: hid.handleSyncRequest(messagePointer); break; case KernelHandles::HID: hid.handleSyncRequest(messagePointer); break;
@ -228,11 +236,12 @@ void ServiceManager::sendCommandToService(u32 messagePointer, Handle handle) {
case KernelHandles::NIM: nim.handleSyncRequest(messagePointer); break; case KernelHandles::NIM: nim.handleSyncRequest(messagePointer); break;
case KernelHandles::NDM: ndm.handleSyncRequest(messagePointer); break; case KernelHandles::NDM: ndm.handleSyncRequest(messagePointer); break;
case KernelHandles::NEWS_U: news_u.handleSyncRequest(messagePointer); break; case KernelHandles::NEWS_U: news_u.handleSyncRequest(messagePointer); break;
case KernelHandles::NS_S: Helpers::panic("Unimplemented SendSyncRequest to ns:s"); break; case KernelHandles::NS_S: ns.handleSyncRequest(messagePointer, NSService::Type::S); break;
case KernelHandles::NWM_UDS: nwm_uds.handleSyncRequest(messagePointer); break; case KernelHandles::NWM_UDS: nwm_uds.handleSyncRequest(messagePointer); break;
case KernelHandles::PTM_PLAY: ptm.handleSyncRequest(messagePointer, PTMService::Type::PLAY); break; case KernelHandles::PTM_PLAY: ptm.handleSyncRequest(messagePointer, PTMService::Type::PLAY); break;
case KernelHandles::PTM_SYSM: ptm.handleSyncRequest(messagePointer, PTMService::Type::SYSM); break; case KernelHandles::PTM_SYSM: ptm.handleSyncRequest(messagePointer, PTMService::Type::SYSM); break;
case KernelHandles::PTM_U: ptm.handleSyncRequest(messagePointer, PTMService::Type::U); break; case KernelHandles::PTM_U: ptm.handleSyncRequest(messagePointer, PTMService::Type::U); break;
case KernelHandles::PTM_GETS: ptm.handleSyncRequest(messagePointer, PTMService::Type::GETS); break;
case KernelHandles::SOC: soc.handleSyncRequest(messagePointer); break; case KernelHandles::SOC: soc.handleSyncRequest(messagePointer); break;
case KernelHandles::SSL: ssl.handleSyncRequest(messagePointer); break; case KernelHandles::SSL: ssl.handleSyncRequest(messagePointer); break;
case KernelHandles::Y2R: y2r.handleSyncRequest(messagePointer); break; case KernelHandles::Y2R: y2r.handleSyncRequest(messagePointer); break;