mirror of
https://github.com/wheremyfoodat/Panda3DS.git
synced 2025-04-06 06:05:40 +12:00
Backup Noumi's Home Menu changes from her deleted repo
Co-Authored-By: Noumi <139501014+noumidev@users.noreply.github.com>
This commit is contained in:
parent
6be642a118
commit
38ef0dbe4c
32 changed files with 661 additions and 34 deletions
|
@ -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/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/ns.cpp src/core/services/news_s.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
|
||||
|
@ -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/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/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 include/services/news_s.hpp
|
||||
)
|
||||
|
||||
cmrc_add_resource_library(
|
||||
|
|
|
@ -2,8 +2,19 @@
|
|||
#include <cstdint>
|
||||
|
||||
namespace IPC {
|
||||
namespace BufferType {
|
||||
enum : std::uint32_t {
|
||||
Send = 1,
|
||||
Receive,
|
||||
};
|
||||
}
|
||||
|
||||
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
|
||||
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
|
|
@ -8,6 +8,7 @@ namespace ConfigMem {
|
|||
KernelVersionMajor = 0x1FF80003,
|
||||
SyscoreVer = 0x1FF80010,
|
||||
EnvInfo = 0x1FF80014,
|
||||
PrevFirm = 0x1FF80016,
|
||||
AppMemAlloc = 0x1FF80040,
|
||||
FirmUnknown = 0x1FF80060,
|
||||
FirmRevision = 0x1FF80061,
|
||||
|
@ -30,6 +31,12 @@ namespace ConfigMem {
|
|||
|
||||
// Shows what type of hardware we're running on
|
||||
namespace HardwareCodes {
|
||||
enum : u8 { Product = 1, Devboard = 2, Debugger = 3, Capture = 4 };
|
||||
enum : u8 {
|
||||
Product = 1,
|
||||
Devboard = 2,
|
||||
Debugger = 3,
|
||||
Capture = 4,
|
||||
};
|
||||
}
|
||||
} // namespace ConfigMem
|
||||
|
|
@ -35,14 +35,17 @@ namespace KernelHandles {
|
|||
MCU_HWC, // Used for various MCU hardware-related things like battery control
|
||||
MIC, // MIC service (Controls the microphone)
|
||||
NFC, // NFC (Duh), used for Amiibo
|
||||
NIM, // Updates, DLC, etc
|
||||
NIM_AOC, // DLC, etc
|
||||
NIM_U, // Updates
|
||||
NDM, // ?????
|
||||
NS_S, // Nintendo Shell service
|
||||
NWM_UDS, // Local multiplayer
|
||||
NEWS_S, // news:u on steroids
|
||||
NEWS_U, // This service literally has 1 command (AddNotification) and I don't even understand what it does
|
||||
PTM_U, // PTM service (Used for accessing various console info, such as battery, shell and pedometer state)
|
||||
PTM_SYSM, // PTM system service
|
||||
PTM_PLAY, // PTM Play service, used for retrieving play history
|
||||
PTM_GETS, // PTM RTC service (GetSystemTime)
|
||||
SOC, // Socket service
|
||||
SSL, // SSL service (Totally didn't expect that)
|
||||
Y2R, // Also does camera stuff
|
||||
|
@ -97,10 +100,12 @@ namespace KernelHandles {
|
|||
case MCU_HWC: return "MCU::HWC";
|
||||
case MIC: return "MIC";
|
||||
case NDM: return "NDM";
|
||||
case NEWS_S: return "NEWS_S";
|
||||
case NEWS_U: return "NEWS_U";
|
||||
case NWM_UDS: return "nwm::UDS";
|
||||
case NFC: return "NFC";
|
||||
case NIM: return "NIM";
|
||||
case NIM_AOC: return "NIM:AOC";
|
||||
case NIM_U: return "NIM:U";
|
||||
case PTM_U: return "PTM:U";
|
||||
case PTM_SYSM: return "PTM:SYSM";
|
||||
case PTM_PLAY: return "PTM:PLAY";
|
||||
|
|
|
@ -65,6 +65,7 @@ namespace Log {
|
|||
static Logger<false> nwmUdsLogger;
|
||||
static Logger<false> nimLogger;
|
||||
static Logger<false> ndmLogger;
|
||||
static Logger<false> nsLogger;
|
||||
static Logger<false> ptmLogger;
|
||||
static Logger<false> socLogger;
|
||||
static Logger<false> sslLogger;
|
||||
|
|
|
@ -19,6 +19,7 @@ class ACService {
|
|||
void closeAsync(u32 messagePointer);
|
||||
void createDefaultConfig(u32 messagePointer);
|
||||
void getConnectingInfraPriority(u32 messagePointer);
|
||||
void getNZoneBeaconNotFoundEvent(u32 messagePointer);
|
||||
void getStatus(u32 messagePointer);
|
||||
void getLastErrorCode(u32 messagePointer);
|
||||
void getWifiStatus(u32 messagePointer);
|
||||
|
|
|
@ -13,9 +13,14 @@ class AMService {
|
|||
MAKE_LOG_FUNCTION(log, amLogger)
|
||||
|
||||
// Service commands
|
||||
void checkContentRights(u32 messagePointer);
|
||||
void getDLCTitleInfo(u32 messagePointer);
|
||||
void getPatchTitleInfo(u32 messagePointer);
|
||||
void getProgramInfos(u32 messagePointer);
|
||||
void getProgramList(u32 messagePointer);
|
||||
void getTicketList(u32 messagePointer);
|
||||
void listTitleInfo(u32 messagePointer);
|
||||
void needsCleanup(u32 messagePointer);
|
||||
|
||||
public:
|
||||
AMService(Memory& mem) : mem(mem) {}
|
||||
|
|
|
@ -65,15 +65,18 @@ class APTService {
|
|||
void checkNew3DSApp(u32 messagePointer);
|
||||
void enable(u32 messagePointer);
|
||||
void getAppletInfo(u32 messagePointer);
|
||||
void getCaptureInfo(u32 messagePointer);
|
||||
void getSharedFont(u32 messagePointer);
|
||||
void getWirelessRebootInfo(u32 messagePointer);
|
||||
void glanceParameter(u32 messagePointer);
|
||||
void initialize(u32 messagePointer);
|
||||
void inquireNotification(u32 messagePointer);
|
||||
void isRegistered(u32 messagePointer);
|
||||
void loadSysMenuArg(u32 messagePointer);
|
||||
void notifyToWait(u32 messagePointer);
|
||||
void preloadLibraryApplet(u32 messagePointer);
|
||||
void prepareToStartLibraryApplet(u32 messagePointer);
|
||||
void receiveDeliverArg(u32 messagePointer);
|
||||
void receiveParameter(u32 messagePointer);
|
||||
void replySleepQuery(u32 messagePointer);
|
||||
void setApplicationCpuTimeLimit(u32 messagePointer);
|
||||
|
|
|
@ -14,10 +14,14 @@ class BOSSService {
|
|||
|
||||
// Service commands
|
||||
void cancelTask(u32 messagePointer);
|
||||
void deleteNsData(u32 messagePointer);
|
||||
void initializeSession(u32 messagePointer);
|
||||
void getAppNewFlag(u32 messagePointer);
|
||||
void getErrorCode(u32 messagePointer);
|
||||
void getNsDataHeaderInfo(u32 messagePointer);
|
||||
void getNewArrivalFlag(u32 messagePointer);
|
||||
void getNsDataIdList(u32 messagePointer, u32 commandWord);
|
||||
void getNsDataLastUpdated(u32 messagePointer);
|
||||
void getOptoutFlag(u32 messagePointer);
|
||||
void getStorageEntryInfo(u32 messagePointer); // Unknown what this is, name taken from Citra
|
||||
void getTaskIdList(u32 messagePointer);
|
||||
|
@ -26,12 +30,15 @@ class BOSSService {
|
|||
void getTaskState(u32 messagePointer);
|
||||
void getTaskStatus(u32 messagePointer);
|
||||
void getTaskStorageInfo(u32 messagePointer);
|
||||
void readNsData(u32 messagePointer);
|
||||
void receiveProperty(u32 messagePointer);
|
||||
void registerNewArrivalEvent(u32 messagePointer);
|
||||
void registerStorageEntry(u32 messagePointer);
|
||||
void registerTask(u32 messagePointer);
|
||||
void sendProperty(u32 messagePointer);
|
||||
void setAppNewFlag(u32 messagePointer);
|
||||
void setOptoutFlag(u32 messagePointer);
|
||||
void startBgImmediate(u32 messagePointer);
|
||||
void startTask(u32 messagePointer);
|
||||
void unregisterStorage(u32 messagePointer);
|
||||
void unregisterTask(u32 messagePointer);
|
||||
|
|
|
@ -26,6 +26,8 @@ class CFGService {
|
|||
void genUniqueConsoleHash(u32 messagePointer);
|
||||
void secureInfoGetByte101(u32 messagePointer);
|
||||
void secureInfoGetRegion(u32 messagePointer);
|
||||
void setConfigInfoBlk4(u32 messagePointer);
|
||||
void updateConfigNANDSavegame(u32 messagePointer);
|
||||
void translateCountryInfo(u32 messagePointer);
|
||||
|
||||
void getConfigInfo(u32 output, u32 blockID, u32 size, u32 permissionMask);
|
||||
|
|
|
@ -70,6 +70,7 @@ class FSService {
|
|||
void getArchiveResource(u32 messagePointer);
|
||||
void getFreeBytes(u32 messagePointer);
|
||||
void getFormatInfo(u32 messagePointer);
|
||||
void getNumSeeds(u32 messagePointer);
|
||||
void getPriority(u32 messagePointer);
|
||||
void getSdmcArchiveResource(u32 messagePointer);
|
||||
void getThisSaveDataSecureValue(u32 messagePointer);
|
||||
|
|
|
@ -13,8 +13,9 @@ class LCDService {
|
|||
MAKE_LOG_FUNCTION(log, gspLCDLogger)
|
||||
|
||||
// Service commands
|
||||
void setLedForceOff(u32 messagePointer);
|
||||
|
||||
public:
|
||||
public:
|
||||
LCDService(Memory& mem) : mem(mem) {}
|
||||
void reset();
|
||||
void handleSyncRequest(u32 messagePointer);
|
||||
|
|
20
include/services/news_s.hpp
Normal file
20
include/services/news_s.hpp
Normal file
|
@ -0,0 +1,20 @@
|
|||
#pragma once
|
||||
#include "helpers.hpp"
|
||||
#include "kernel_types.hpp"
|
||||
#include "logger.hpp"
|
||||
#include "memory.hpp"
|
||||
|
||||
class NewsSService {
|
||||
using Handle = HorizonHandle;
|
||||
|
||||
Handle handle = KernelHandles::NEWS_S;
|
||||
Memory& mem;
|
||||
MAKE_LOG_FUNCTION(log, newsLogger)
|
||||
|
||||
// Service commands
|
||||
|
||||
public:
|
||||
NewsSService(Memory& mem) : mem(mem) {}
|
||||
void reset();
|
||||
void handleSyncRequest(u32 messagePointer);
|
||||
};
|
|
@ -5,18 +5,31 @@
|
|||
#include "memory.hpp"
|
||||
#include "result/result.hpp"
|
||||
|
||||
class Kernel;
|
||||
|
||||
class NIMService {
|
||||
using Handle = HorizonHandle;
|
||||
|
||||
Handle handle = KernelHandles::NIM;
|
||||
Memory& mem;
|
||||
Kernel& kernel;
|
||||
MAKE_LOG_FUNCTION(log, nimLogger)
|
||||
|
||||
std::optional<Handle> backgroundSystemUpdateEvent;
|
||||
|
||||
// Service commands
|
||||
void getAutoTitleDownloadTaskInfos(u32 messagePointer);
|
||||
void getBackgroundEventForMenu(u32 messagePointer);
|
||||
void getTaskInfos(u32 messagePointer);
|
||||
void initialize(u32 messagePointer);
|
||||
void isPendingAutoTitleDownloadTasks(u32 messagePointer);
|
||||
|
||||
public:
|
||||
NIMService(Memory& mem) : mem(mem) {}
|
||||
enum class Type {
|
||||
AOC, // nim:aoc
|
||||
U, // nim:u
|
||||
};
|
||||
|
||||
NIMService(Memory& mem, Kernel& kernel) : mem(mem), kernel(kernel) {}
|
||||
void reset();
|
||||
void handleSyncRequest(u32 messagePointer);
|
||||
void handleSyncRequest(u32 messagePointer, Type type);
|
||||
};
|
25
include/services/ns.hpp
Normal file
25
include/services/ns.hpp
Normal 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);
|
||||
};
|
|
@ -13,17 +13,21 @@ class PTMService {
|
|||
const EmulatorConfig& config;
|
||||
|
||||
// Service commands
|
||||
void clearSoftwareClosedFlag(u32 messagePointer);
|
||||
void configureNew3DSCPU(u32 messagePointer);
|
||||
void getAdapterState(u32 messagePointer);
|
||||
void getBatteryChargeState(u32 messagePointer);
|
||||
void getBatteryLevel(u32 messagePointer);
|
||||
void getSoftwareClosedFlag(u32 messagePointer);
|
||||
void getPedometerState(u32 messagePointer);
|
||||
void getStepHistory(u32 messagePointer);
|
||||
void getStepHistoryAll(u32 messagePointer);
|
||||
void getSystemTime(u32 messagePointer);
|
||||
void getTotalStepCount(u32 messagePointer);
|
||||
|
||||
public:
|
||||
enum class Type {
|
||||
GETS, // ptm:gets
|
||||
U, // ptm:u
|
||||
SYSM, // ptm:sysm
|
||||
PLAY, // ptm:play
|
||||
|
|
|
@ -28,10 +28,12 @@
|
|||
#include "services/mcu/mcu_hwc.hpp"
|
||||
#include "services/mic.hpp"
|
||||
#include "services/ndm.hpp"
|
||||
#include "services/nwm_uds.hpp"
|
||||
#include "services/news_s.hpp"
|
||||
#include "services/news_u.hpp"
|
||||
#include "services/nfc.hpp"
|
||||
#include "services/nim.hpp"
|
||||
#include "services/ns.hpp"
|
||||
#include "services/nwm_uds.hpp"
|
||||
#include "services/ptm.hpp"
|
||||
#include "services/soc.hpp"
|
||||
#include "services/ssl.hpp"
|
||||
|
@ -52,11 +54,11 @@ class ServiceManager {
|
|||
|
||||
MAKE_LOG_FUNCTION(log, srvLogger)
|
||||
|
||||
ACService ac;
|
||||
ACService ac;
|
||||
ACTService act;
|
||||
AMService am;
|
||||
AMService am;
|
||||
APTService apt;
|
||||
BOSSService boss;
|
||||
BOSSService boss;
|
||||
CAMService cam;
|
||||
CECDService cecd;
|
||||
CFGService cfg;
|
||||
|
@ -73,10 +75,12 @@ class ServiceManager {
|
|||
LDRService ldr;
|
||||
MICService mic;
|
||||
NDMService ndm;
|
||||
NewsSService news_s;
|
||||
NewsUService news_u;
|
||||
NFCService nfc;
|
||||
NwmUdsService nwm_uds;
|
||||
NIMService nim;
|
||||
NIMService nim;
|
||||
NSService ns;
|
||||
PTMService ptm;
|
||||
SOCService soc;
|
||||
SSLService ssl;
|
||||
|
|
|
@ -97,8 +97,10 @@ std::optional<u32> NCCHArchive::readFile(FileSession* file, u64 offset, u32 size
|
|||
} else if (highProgramID == systemDataArchive && lowProgramID == badWordList) {
|
||||
fileData = std::vector<u8>(std::begin(BAD_WORD_LIST_DATA), std::end(BAD_WORD_LIST_DATA));
|
||||
} else {
|
||||
Helpers::panic("[NCCH archive] Read from unimplemented NCCH archive file. High program ID: %08X, low ID: %08X",
|
||||
Helpers::warn("[NCCH archive] Read from unimplemented NCCH archive file. High program ID: %08X, low ID: %08X",
|
||||
highProgramID, lowProgramID);
|
||||
|
||||
return std::nullopt;
|
||||
}
|
||||
|
||||
if (offset >= fileData.size()) {
|
||||
|
|
|
@ -111,7 +111,8 @@ void Kernel::readFile(u32 messagePointer, Handle fileHandle) {
|
|||
auto archive = file->archive;
|
||||
std::optional<u32> bytesRead = archive->readFile(file, offset, size, dataPointer);
|
||||
if (!bytesRead.has_value()) {
|
||||
Helpers::panic("Kernel::ReadFile failed");
|
||||
Helpers::warn("Kernel::ReadFile failed");
|
||||
mem.write32(messagePointer + 4, 0xC8804478);
|
||||
} else {
|
||||
mem.write32(messagePointer + 4, Result::Success);
|
||||
mem.write32(messagePointer + 8, bytesRead.value());
|
||||
|
|
|
@ -108,6 +108,7 @@ u8 Memory::read8(u32 vaddr) {
|
|||
return getBatteryState(chargerPlugged, charging, batteryLevel);
|
||||
}
|
||||
case ConfigMem::EnvInfo: return envInfo;
|
||||
case ConfigMem::PrevFirm: return 1;
|
||||
case ConfigMem::HardwareType: return ConfigMem::HardwareCodes::Product;
|
||||
case ConfigMem::KernelVersionMinor: return u8(kernelVersion & 0xff);
|
||||
case ConfigMem::KernelVersionMajor: return u8(kernelVersion >> 8);
|
||||
|
|
|
@ -10,6 +10,7 @@ namespace ACCommands {
|
|||
GetStatus = 0x000C0000,
|
||||
GetWifiStatus = 0x000D0000,
|
||||
GetConnectingInfraPriority = 0x000F0000,
|
||||
GetNZoneBeaconNotFoundEvent = 0x002F0004,
|
||||
RegisterDisconnectEvent = 0x00300004,
|
||||
IsConnected = 0x003E0042,
|
||||
SetClientVersion = 0x00400042,
|
||||
|
@ -29,6 +30,7 @@ void ACService::handleSyncRequest(u32 messagePointer) {
|
|||
case ACCommands::CreateDefaultConfig: createDefaultConfig(messagePointer); break;
|
||||
case ACCommands::GetConnectingInfraPriority: getConnectingInfraPriority(messagePointer); break;
|
||||
case ACCommands::GetLastErrorCode: getLastErrorCode(messagePointer); break;
|
||||
case ACCommands::GetNZoneBeaconNotFoundEvent: getNZoneBeaconNotFoundEvent(messagePointer); break;
|
||||
case ACCommands::GetStatus: getStatus(messagePointer); break;
|
||||
case ACCommands::GetWifiStatus: getWifiStatus(messagePointer); break;
|
||||
case ACCommands::IsConnected: isConnected(messagePointer); break;
|
||||
|
@ -136,4 +138,13 @@ void ACService::registerDisconnectEvent(u32 messagePointer) {
|
|||
|
||||
mem.write32(messagePointer, IPC::responseHeader(0x30, 1, 0));
|
||||
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);
|
||||
}
|
|
@ -3,6 +3,11 @@
|
|||
|
||||
namespace AMCommands {
|
||||
enum : u32 {
|
||||
GetProgramList = 0x00020082,
|
||||
GetProgramInfos = 0x00030084,
|
||||
GetTicketList = 0x00090082,
|
||||
NeedsCleanup = 0x00130040,
|
||||
CheckContentRights = 0x002500C0,
|
||||
GetDLCTitleInfo = 0x10050084,
|
||||
ListTitleInfo = 0x10070102,
|
||||
GetPatchTitleInfo = 0x100D0084,
|
||||
|
@ -14,9 +19,14 @@ void AMService::reset() {}
|
|||
void AMService::handleSyncRequest(u32 messagePointer) {
|
||||
const u32 command = mem.read32(messagePointer);
|
||||
switch (command) {
|
||||
case AMCommands::CheckContentRights: checkContentRights(messagePointer); break;
|
||||
case AMCommands::GetPatchTitleInfo: getPatchTitleInfo(messagePointer); break;
|
||||
case AMCommands::GetDLCTitleInfo: getDLCTitleInfo(messagePointer); break;
|
||||
case AMCommands::GetProgramInfos: getProgramInfos(messagePointer); break;
|
||||
case AMCommands::GetProgramList: getProgramList(messagePointer); break;
|
||||
case AMCommands::GetTicketList: getTicketList(messagePointer); break;
|
||||
case AMCommands::ListTitleInfo: listTitleInfo(messagePointer); break;
|
||||
case AMCommands::NeedsCleanup: needsCleanup(messagePointer); break;
|
||||
default: Helpers::panic("AM service requested. Command: %08X\n", command);
|
||||
}
|
||||
}
|
||||
|
@ -56,4 +66,75 @@ void AMService::getPatchTitleInfo(u32 messagePointer) {
|
|||
|
||||
mem.write32(messagePointer, IPC::responseHeader(0x100D, 1, 4));
|
||||
mem.write32(messagePointer + 4, Result::FailurePlaceholder);
|
||||
}
|
||||
|
||||
void AMService::needsCleanup(u32 messagePointer) {
|
||||
const u32 mediaType = mem.read32(messagePointer + 4);
|
||||
log("AM::NeedsCleanup (media type = %X)\n", mediaType);
|
||||
|
||||
mem.write32(messagePointer, IPC::responseHeader(0x13, 2, 0));
|
||||
mem.write32(messagePointer + 4, Result::Success);
|
||||
mem.write8(messagePointer + 8, 0); // Doesn't need cleanup
|
||||
}
|
||||
|
||||
void AMService::getProgramInfos(u32 messagePointer) {
|
||||
const u8 mediaType = mem.read8(messagePointer + 4);
|
||||
const u32 titleCount = mem.read32(messagePointer + 8);
|
||||
const u32 titleIDs = mem.read32(messagePointer + 16);
|
||||
const u32 titleInfos = mem.read32(messagePointer + 24);
|
||||
log("AM::GetProgramInfos (media type = %X, title count = %X, title IDs pointer = %X, title infos pointer = %X) (Stubbed)\n", mediaType,
|
||||
titleCount, titleIDs, titleInfos);
|
||||
|
||||
for (u32 title = 0; title < titleCount; title++) {
|
||||
const u64 id = mem.read64(titleIDs + sizeof(u64) * title);
|
||||
|
||||
mem.write64(titleInfos + 0x18 * title, id); // Title ID
|
||||
mem.write64(titleInfos + 0x18 * title + 8, 0); // Size
|
||||
mem.write16(titleInfos + 0x18 * title + 16, 0); // Version
|
||||
mem.write16(titleInfos + 0x18 * title + 18, 0); // Padding
|
||||
mem.write32(titleInfos + 0x18 * title + 20, 0); // Type
|
||||
}
|
||||
|
||||
mem.write32(messagePointer, IPC::responseHeader(0x3, 1, 4));
|
||||
mem.write32(messagePointer + 4, Result::Success);
|
||||
mem.write32(messagePointer + 8, IPC::pointerHeader(0, sizeof(u64) * titleCount, IPC::BufferType::Send));
|
||||
mem.write32(messagePointer + 12, titleIDs);
|
||||
mem.write32(messagePointer + 16, IPC::pointerHeader(1, sizeof(u32) * titleCount, IPC::BufferType::Receive));
|
||||
mem.write32(messagePointer + 20, titleInfos);
|
||||
}
|
||||
|
||||
void AMService::getProgramList(u32 messagePointer) {
|
||||
const u32 titleCount = mem.read32(messagePointer + 4);
|
||||
const u8 mediaType = mem.read8(messagePointer + 8);
|
||||
const u32 titleIDs = mem.read32(messagePointer + 16);
|
||||
log("AM::GetProgramList (title count = %X, media type = %X, title ID pointer = %X) (stubbed)\n", titleCount, mediaType, titleIDs);
|
||||
|
||||
mem.write32(messagePointer, IPC::responseHeader(0x2, 2, 2));
|
||||
mem.write32(messagePointer + 4, Result::Success);
|
||||
mem.write32(messagePointer + 8, 0); // No title IDs read?
|
||||
mem.write32(messagePointer + 12, IPC::pointerHeader(0, sizeof(u64) * 0, IPC::BufferType::Receive));
|
||||
mem.write32(messagePointer + 16, titleIDs);
|
||||
}
|
||||
|
||||
void AMService::getTicketList(u32 messagePointer) {
|
||||
const u32 ticketCount = mem.read32(messagePointer + 4);
|
||||
const u32 numSkips = mem.read32(messagePointer + 8);
|
||||
const u32 titleIDs = mem.read32(messagePointer + 16);
|
||||
log("AM::GetTicketList (ticket count = %X, skipped tickets = %X, title ID pointer = %X) (stubbed)\n", ticketCount, numSkips, titleIDs);
|
||||
|
||||
mem.write32(messagePointer, IPC::responseHeader(0x9, 2, 2));
|
||||
mem.write32(messagePointer + 4, Result::Success);
|
||||
mem.write32(messagePointer + 8, 0); // No tickets read?
|
||||
mem.write32(messagePointer + 12, IPC::pointerHeader(0, sizeof(u64) * 0, IPC::BufferType::Receive));
|
||||
mem.write32(messagePointer + 16, titleIDs);
|
||||
}
|
||||
|
||||
void AMService::checkContentRights(u32 messagePointer) {
|
||||
const u64 titleID = mem.read64(messagePointer + 4);
|
||||
const u16 contentIndex = mem.read16(messagePointer + 12);
|
||||
log("AM::CheckContentRights (title ID = %llX, content index = %X) (stubbed)\n", titleID, contentIndex);
|
||||
|
||||
mem.write32(messagePointer, IPC::responseHeader(0x25, 2, 0));
|
||||
mem.write32(messagePointer + 4, Result::Success);
|
||||
mem.write8(messagePointer + 8, 1); // Has content rights
|
||||
}
|
|
@ -19,10 +19,13 @@ namespace APTCommands {
|
|||
PreloadLibraryApplet = 0x00160040,
|
||||
PrepareToStartLibraryApplet = 0x00180040,
|
||||
StartLibraryApplet = 0x001E0084,
|
||||
ReceiveDeliverArg = 0x00350080,
|
||||
LoadSysMenuArg = 0x00360040,
|
||||
ReplySleepQuery = 0x003E0080,
|
||||
NotifyToWait = 0x00430040,
|
||||
GetSharedFont = 0x00440000,
|
||||
GetWirelessRebootInfo = 0x00450040,
|
||||
GetCaptureInfo = 0x004A0040,
|
||||
AppletUtility = 0x004B00C2,
|
||||
SetApplicationCpuTimeLimit = 0x004F0080,
|
||||
GetApplicationCpuTimeLimit = 0x00500040,
|
||||
|
@ -58,12 +61,15 @@ void APTService::handleSyncRequest(u32 messagePointer) {
|
|||
case APTCommands::InquireNotification: [[likely]] inquireNotification(messagePointer); break;
|
||||
case APTCommands::IsRegistered: isRegistered(messagePointer); break;
|
||||
case APTCommands::GetApplicationCpuTimeLimit: getApplicationCpuTimeLimit(messagePointer); break;
|
||||
case APTCommands::GetCaptureInfo: getCaptureInfo(messagePointer); break;
|
||||
case APTCommands::GetLockHandle: getLockHandle(messagePointer); break;
|
||||
case APTCommands::GetWirelessRebootInfo: getWirelessRebootInfo(messagePointer); break;
|
||||
case APTCommands::GlanceParameter: glanceParameter(messagePointer); break;
|
||||
case APTCommands::LoadSysMenuArg: loadSysMenuArg(messagePointer); break;
|
||||
case APTCommands::NotifyToWait: notifyToWait(messagePointer); break;
|
||||
case APTCommands::PreloadLibraryApplet: preloadLibraryApplet(messagePointer); break;
|
||||
case APTCommands::PrepareToStartLibraryApplet: prepareToStartLibraryApplet(messagePointer); break;
|
||||
case APTCommands::ReceiveDeliverArg: receiveDeliverArg(messagePointer); break;
|
||||
case APTCommands::StartLibraryApplet: startLibraryApplet(messagePointer); break;
|
||||
case APTCommands::ReceiveParameter: [[likely]] receiveParameter(messagePointer); break;
|
||||
case APTCommands::ReplySleepQuery: replySleepQuery(messagePointer); break;
|
||||
|
@ -421,3 +427,64 @@ void APTService::getWirelessRebootInfo(u32 messagePointer) {
|
|||
mem.write8(messagePointer + 0x104 + i, 0); // Temporarily stub this until we add SetWirelessRebootInfo
|
||||
}
|
||||
}
|
||||
|
||||
void APTService::receiveDeliverArg(u32 messagePointer) {
|
||||
const u32 parameterSize = mem.read32(messagePointer + 4);
|
||||
const u32 hmacSize = mem.read32(messagePointer + 8);
|
||||
const u32 parameter = mem.read32(messagePointer + 0x104);
|
||||
const u32 hmac = mem.read32(messagePointer + 0x10C);
|
||||
log("APT::ReceiveDeliverArg (parameter size = %X, HMAC size = %X, parameter pointer = %X, HMAC pointer = %X) (stubbed)\n", parameterSize,
|
||||
hmacSize, parameter, hmac);
|
||||
|
||||
for (u32 i = 0; i < parameterSize; i += 4) {
|
||||
mem.write32(parameter + i, 0xDEADC0DE); // Does anything use this
|
||||
}
|
||||
|
||||
for (u32 i = 0; i < hmacSize; i += 4) {
|
||||
mem.write32(hmac + i, 0);
|
||||
}
|
||||
|
||||
mem.write32(messagePointer, IPC::responseHeader(0x35, 4, 4));
|
||||
mem.write32(messagePointer + 4, Result::Success);
|
||||
mem.write32(messagePointer + 8, 0); // Program ID
|
||||
mem.write8(messagePointer + 16, 1); // Is valid response
|
||||
mem.write32(messagePointer + 20, IPC::pointerHeader(0, parameterSize, IPC::BufferType::Send));
|
||||
mem.write32(messagePointer + 24, parameter);
|
||||
mem.write32(messagePointer + 28, IPC::pointerHeader(1, hmacSize, IPC::BufferType::Send));
|
||||
mem.write32(messagePointer + 32, hmac);
|
||||
}
|
||||
|
||||
void APTService::loadSysMenuArg(u32 messagePointer) {
|
||||
const u32 outputSize = mem.read32(messagePointer + 4);
|
||||
const u32 output = mem.read32(messagePointer + 0x104);
|
||||
log("APT::LoadSysMenuArg (output size = %X, output = %X) (stubbed)\n", outputSize, output);
|
||||
|
||||
for (u32 i = 0; i < outputSize; i += 4) {
|
||||
mem.write32(output + i, 0);
|
||||
}
|
||||
|
||||
mem.write32(messagePointer, IPC::responseHeader(0x35, 4, 4));
|
||||
mem.write32(messagePointer + 4, Result::Success);
|
||||
mem.write32(messagePointer + 8, IPC::pointerHeader(0, outputSize, IPC::BufferType::Send));
|
||||
mem.write32(messagePointer + 12, outputSize);
|
||||
}
|
||||
|
||||
void APTService::getCaptureInfo(u32 messagePointer) {
|
||||
const u32 size = mem.read32(messagePointer + 4);
|
||||
const u32 captureBufferInfo = mem.read32(messagePointer + 0x104);
|
||||
log("APT::GetCaptureInfo (size = %X, capture buffer info pointer = %X) (Stubbed)\n", size, captureBufferInfo);
|
||||
|
||||
mem.write32(captureBufferInfo, 0); // Size (of structure?)
|
||||
mem.write8(captureBufferInfo + 4, 0); // 1 = is 3D
|
||||
mem.write32(captureBufferInfo + 8, 0); // Main screen left offset
|
||||
mem.write32(captureBufferInfo + 12, 0); // Main screen right offset
|
||||
mem.write32(captureBufferInfo + 16, 0); // Main screen display buffer mode
|
||||
mem.write32(captureBufferInfo + 20, 0); // Sub screen left offset
|
||||
mem.write32(captureBufferInfo + 24, 0); // Sub screen right offset
|
||||
mem.write32(captureBufferInfo + 28, 0); // Sub screen display buffer mode
|
||||
|
||||
mem.write32(messagePointer, IPC::responseHeader(0x4A, 1, 2));
|
||||
mem.write32(messagePointer + 4, Result::Success);
|
||||
mem.write32(messagePointer + 8, IPC::pointerHeader(0, size, IPC::BufferType::Send));
|
||||
mem.write32(messagePointer + 12, captureBufferInfo);
|
||||
}
|
|
@ -25,9 +25,17 @@ namespace BOSSCommands {
|
|||
GetTaskState = 0x00200082,
|
||||
GetTaskStatus = 0x002300C2,
|
||||
GetTaskInfo = 0x00250082,
|
||||
DeleteNsData = 0x00260040,
|
||||
GetNsDataHeaderInfo = 0x002700C2,
|
||||
ReadNsData = 0x00280102,
|
||||
GetNsDataLastUpdated = 0x002D0040,
|
||||
GetErrorCode = 0x002E0040,
|
||||
RegisterStorageEntry = 0x002F0140,
|
||||
GetStorageEntryInfo = 0x00300000,
|
||||
StartBgImmediate = 0x00330042,
|
||||
InitializeSessionPrivileged = 0x04010082,
|
||||
GetAppNewFlag = 0x04040080,
|
||||
SetAppNewFlag = 0x040500C0, // Probably
|
||||
};
|
||||
}
|
||||
|
||||
|
@ -39,13 +47,16 @@ void BOSSService::handleSyncRequest(u32 messagePointer) {
|
|||
const u32 command = mem.read32(messagePointer);
|
||||
switch (command) {
|
||||
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::GetNsDataHeaderInfo: getNsDataHeaderInfo(messagePointer); break;
|
||||
case BOSSCommands::GetNewArrivalFlag: getNewArrivalFlag(messagePointer); break;
|
||||
case BOSSCommands::GetNsDataIdList:
|
||||
case BOSSCommands::GetNsDataIdList1:
|
||||
case BOSSCommands::GetNsDataIdList2:
|
||||
case BOSSCommands::GetNsDataIdList3:
|
||||
getNsDataIdList(messagePointer, command); break;
|
||||
case BOSSCommands::GetNsDataIdList3: getNsDataIdList(messagePointer, command); break;
|
||||
case BOSSCommands::GetNsDataLastUpdated: getNsDataLastUpdated(messagePointer); break;
|
||||
case BOSSCommands::GetOptoutFlag: getOptoutFlag(messagePointer); break;
|
||||
case BOSSCommands::GetStorageEntryInfo: getStorageEntryInfo(messagePointer); break;
|
||||
case BOSSCommands::GetTaskIdList: getTaskIdList(messagePointer); break;
|
||||
|
@ -54,16 +65,29 @@ void BOSSService::handleSyncRequest(u32 messagePointer) {
|
|||
case BOSSCommands::GetTaskState: getTaskState(messagePointer); break;
|
||||
case BOSSCommands::GetTaskStatus: getTaskStatus(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::RegisterNewArrivalEvent: registerNewArrivalEvent(messagePointer); break;
|
||||
case BOSSCommands::RegisterStorageEntry: registerStorageEntry(messagePointer); break;
|
||||
case BOSSCommands::RegisterTask: registerTask(messagePointer); break;
|
||||
case BOSSCommands::SendProperty: sendProperty(messagePointer); break;
|
||||
case BOSSCommands::SetAppNewFlag: setAppNewFlag(messagePointer); break;
|
||||
case BOSSCommands::SetOptoutFlag: setOptoutFlag(messagePointer); break;
|
||||
case BOSSCommands::StartBgImmediate: startBgImmediate(messagePointer); break;
|
||||
case BOSSCommands::StartTask: startTask(messagePointer); break;
|
||||
case BOSSCommands::UnregisterStorage: unregisterStorage(messagePointer); break;
|
||||
case BOSSCommands::UnregisterTask: unregisterTask(messagePointer); break;
|
||||
|
||||
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: Helpers::panic("BOSS service requested. Command: %08X\n", command);
|
||||
}
|
||||
}
|
||||
|
@ -253,4 +277,91 @@ void BOSSService::getNewArrivalFlag(u32 messagePointer) {
|
|||
mem.write32(messagePointer, IPC::responseHeader(0x7, 2, 0));
|
||||
mem.write32(messagePointer + 4, Result::Success);
|
||||
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);
|
||||
}
|
|
@ -18,6 +18,8 @@ namespace CFGCommands {
|
|||
GetSystemModel = 0x00050000,
|
||||
TranslateCountryInfo = 0x00080080,
|
||||
GetCountryCodeID = 0x000A0040,
|
||||
SetConfigInfoBlk4 = 0x04020082,
|
||||
UpdateConfigNANDSavegame = 0x04030000,
|
||||
|
||||
GetLocalFriendCodeSeed = 0x04050000,
|
||||
SecureInfoGetByte101 = 0x04070000,
|
||||
|
@ -44,6 +46,9 @@ void CFGService::handleSyncRequest(u32 messagePointer, CFGService::Type type) {
|
|||
case CFGCommands::GetConfigInfoBlk8: getConfigInfoBlk8(messagePointer); 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 {
|
||||
|
@ -76,8 +81,7 @@ void CFGService::getConfigInfoBlk2(u32 messagePointer) {
|
|||
u32 size = mem.read32(messagePointer + 4);
|
||||
u32 blockID = mem.read32(messagePointer + 8);
|
||||
u32 output = mem.read32(messagePointer + 16); // Pointer to write the output data to
|
||||
log("CFG::GetConfigInfoBlk2 (size = %X, block ID = %X, output pointer = %08X\n", size, blockID, output);
|
||||
|
||||
log("CFG::GetConfigInfoBlk2 (size = %X, block ID = %X, output pointer = %08X)\n", size, blockID, output);
|
||||
|
||||
getConfigInfo(output, blockID, size, 0x2);
|
||||
mem.write32(messagePointer, IPC::responseHeader(0x1, 1, 2));
|
||||
|
@ -88,7 +92,7 @@ void CFGService::getConfigInfoBlk8(u32 messagePointer) {
|
|||
u32 size = mem.read32(messagePointer + 4);
|
||||
u32 blockID = mem.read32(messagePointer + 8);
|
||||
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);
|
||||
mem.write32(messagePointer, IPC::responseHeader(0x401, 1, 2));
|
||||
|
@ -160,6 +164,18 @@ void CFGService::getConfigInfo(u32 output, u32 blockID, u32 size, u32 permission
|
|||
mem.write32(output, 0);
|
||||
} else if (size == 8 && blockID == 0x00090000) {
|
||||
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 {
|
||||
Helpers::panic("Unhandled GetConfigInfoBlk2 configuration. Size = %d, block = %X", size, blockID);
|
||||
}
|
||||
|
@ -260,6 +276,25 @@ void CFGService::getLocalFriendCodeSeed(u32 messagePointer) {
|
|||
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
|
||||
void CFGService::translateCountryInfo(u32 messagePointer) {
|
||||
const u32 country = mem.read32(messagePointer + 4);
|
||||
|
|
|
@ -44,6 +44,7 @@ namespace FSCommands {
|
|||
SetThisSaveDataSecureValue = 0x086E00C0,
|
||||
GetThisSaveDataSecureValue = 0x086F0040,
|
||||
TheGameboyVCFunction = 0x08750180,
|
||||
GetNumSeeds = 0x087D0000,
|
||||
};
|
||||
}
|
||||
|
||||
|
@ -202,6 +203,15 @@ void FSService::handleSyncRequest(u32 messagePointer) {
|
|||
case FSCommands::SetThisSaveDataSecureValue: setThisSaveDataSecureValue(messagePointer); break;
|
||||
case FSCommands::AbnegateAccessRight: abnegateAccessRight(messagePointer); break;
|
||||
case FSCommands::TheGameboyVCFunction: theGameboyVCFunction(messagePointer); break;
|
||||
case FSCommands::GetNumSeeds: getNumSeeds(messagePointer); break;
|
||||
case 0x08830000: // Home Menu uses this command, what is this?
|
||||
Helpers::warn("FS command 0x08830000");
|
||||
|
||||
mem.write32(messagePointer, IPC::responseHeader(0x883, 2, 0));
|
||||
mem.write32(messagePointer + 4, Result::Success);
|
||||
mem.write32(messagePointer + 8, 0);
|
||||
break;
|
||||
|
||||
default: Helpers::panic("FS service requested. Command: %08X\n", command);
|
||||
}
|
||||
}
|
||||
|
@ -246,6 +256,19 @@ void FSService::openArchive(u32 messagePointer) {
|
|||
auto archivePath = readPath(archivePathType, archivePathPointer, archivePathSize);
|
||||
log("FS::OpenArchive(archive ID = %d, archive path type = %d)\n", archiveID, archivePathType);
|
||||
|
||||
// Needed for HOME Menu
|
||||
if ((archiveID == 7) && (archivePathType == 2)) {
|
||||
const u32 id = *(u32*)&archivePath.binary[4];
|
||||
|
||||
if (id == 0xE0000000) {
|
||||
log("FS::OpenArchive: Failed to open archive\n");
|
||||
mem.write32(messagePointer + 4, 0xC8804478);
|
||||
mem.write64(messagePointer + 8, 0);
|
||||
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
Rust::Result<Handle, Result::HorizonResult> res = openArchiveHandle(archiveID, archivePath);
|
||||
mem.write32(messagePointer, IPC::responseHeader(0x80C, 3, 0));
|
||||
if (res.isOk()) {
|
||||
|
@ -731,6 +754,14 @@ void FSService::cardSlotIsInserted(u32 messagePointer) {
|
|||
mem.write8(messagePointer + 8, cardInserted ? 1 : 0);
|
||||
}
|
||||
|
||||
void FSService::getNumSeeds(u32 messagePointer) {
|
||||
log("FS::GetNumSeeds (stubbed)");
|
||||
|
||||
mem.write32(messagePointer, IPC::responseHeader(0x87D, 2, 0));
|
||||
mem.write32(messagePointer + 4, Result::Success);
|
||||
mem.write8(messagePointer + 8, 0); // Number of seeds?
|
||||
}
|
||||
|
||||
void FSService::renameFile(u32 messagePointer) {
|
||||
log("FS::RenameFile\n");
|
||||
|
||||
|
|
|
@ -3,6 +3,7 @@
|
|||
|
||||
namespace LCDCommands {
|
||||
enum : u32 {
|
||||
SetLedForceOff = 0x00130040,
|
||||
};
|
||||
}
|
||||
|
||||
|
@ -11,6 +12,16 @@ void LCDService::reset() {}
|
|||
void LCDService::handleSyncRequest(u32 messagePointer) {
|
||||
const u32 command = mem.read32(messagePointer);
|
||||
switch (command) {
|
||||
case LCDCommands::SetLedForceOff: setLedForceOff(messagePointer); break;
|
||||
|
||||
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);
|
||||
}
|
16
src/core/services/news_s.cpp
Normal file
16
src/core/services/news_s.cpp
Normal file
|
@ -0,0 +1,16 @@
|
|||
#include "services/news_s.hpp"
|
||||
|
||||
#include "ipc.hpp"
|
||||
|
||||
namespace NewsCommands {
|
||||
enum : u32 {};
|
||||
}
|
||||
|
||||
void NewsSService::reset() {}
|
||||
|
||||
void NewsSService::handleSyncRequest(u32 messagePointer) {
|
||||
const u32 command = mem.read32(messagePointer);
|
||||
switch (command) {
|
||||
default: Helpers::panic("news:s service requested. Command: %08X\n", command);
|
||||
}
|
||||
}
|
|
@ -1,19 +1,42 @@
|
|||
#include "services/nim.hpp"
|
||||
|
||||
#include "ipc.hpp"
|
||||
#include "kernel.hpp"
|
||||
|
||||
namespace NIMCommands {
|
||||
enum : u32 {
|
||||
Initialize = 0x00210000
|
||||
GetBackgroundEventForMenu = 0x00050000,
|
||||
GetTaskInfos = 0x000F0042,
|
||||
IsPendingAutoTitleDownloadTasks = 0x00150000,
|
||||
GetAutoTitleDownloadTaskInfos = 0x00170042,
|
||||
Initialize = 0x00210000,
|
||||
};
|
||||
}
|
||||
|
||||
void NIMService::reset() {}
|
||||
void NIMService::reset() { backgroundSystemUpdateEvent = std::nullopt; }
|
||||
|
||||
void NIMService::handleSyncRequest(u32 messagePointer) {
|
||||
void NIMService::handleSyncRequest(u32 messagePointer, Type type) {
|
||||
const u32 command = mem.read32(messagePointer);
|
||||
switch (command) {
|
||||
case NIMCommands::Initialize: initialize(messagePointer); break;
|
||||
default: Helpers::panic("NIM service requested. Command: %08X\n", command);
|
||||
default:
|
||||
if (type == Type::AOC) {
|
||||
switch (command) {
|
||||
case NIMCommands::Initialize: initialize(messagePointer); break;
|
||||
|
||||
default: Helpers::panic("NIM AOC service requested. Command: %08X\n", command);
|
||||
}
|
||||
} else if (type == Type::U) {
|
||||
switch (command) {
|
||||
case NIMCommands::GetAutoTitleDownloadTaskInfos: getAutoTitleDownloadTaskInfos(messagePointer); break;
|
||||
case NIMCommands::GetBackgroundEventForMenu: getBackgroundEventForMenu(messagePointer); break;
|
||||
case NIMCommands::GetTaskInfos: getTaskInfos(messagePointer); break;
|
||||
case NIMCommands::IsPendingAutoTitleDownloadTasks: isPendingAutoTitleDownloadTasks(messagePointer); break;
|
||||
|
||||
default: Helpers::panic("NIM U service requested. Command: %08X\n", command);
|
||||
}
|
||||
} else {
|
||||
Helpers::panic("NIM service requested. Command: %08X\n", command);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -21,4 +44,49 @@ void NIMService::initialize(u32 messagePointer) {
|
|||
log("NIM::Initialize\n");
|
||||
mem.write32(messagePointer, IPC::responseHeader(0x21, 1, 0));
|
||||
mem.write32(messagePointer + 4, Result::Success);
|
||||
}
|
||||
|
||||
void NIMService::getTaskInfos(u32 messagePointer) {
|
||||
const u32 numTaskInfos = mem.read32(messagePointer + 4);
|
||||
const u32 taskInfos = mem.read32(messagePointer + 12);
|
||||
log("NIM::GetTaskInfos (num task infos = %X, task infos pointer = %X) (stubbed)\n", numTaskInfos, taskInfos);
|
||||
|
||||
mem.write32(messagePointer, IPC::responseHeader(0xF, 2, 2));
|
||||
mem.write32(messagePointer + 4, Result::Success);
|
||||
mem.write32(messagePointer + 8, 0); // Read task infos?
|
||||
mem.write32(messagePointer + 12, IPC::pointerHeader(0, 0, IPC::BufferType::Receive));
|
||||
mem.write32(messagePointer + 16, taskInfos);
|
||||
}
|
||||
|
||||
void NIMService::getAutoTitleDownloadTaskInfos(u32 messagePointer) {
|
||||
const u32 numTaskInfos = mem.read32(messagePointer + 4);
|
||||
const u32 taskInfos = mem.read32(messagePointer + 12);
|
||||
log("NIM::GetAutoTitleDownloadTaskInfos (num task infos = %X, task infos pointer = %X) (stubbed)\n", numTaskInfos, taskInfos);
|
||||
|
||||
mem.write32(messagePointer, IPC::responseHeader(0x17, 2, 2));
|
||||
mem.write32(messagePointer + 4, Result::Success);
|
||||
mem.write32(messagePointer + 8, 0); // Read task infos?
|
||||
mem.write32(messagePointer + 12, IPC::pointerHeader(0, 0, IPC::BufferType::Receive));
|
||||
mem.write32(messagePointer + 16, taskInfos);
|
||||
}
|
||||
|
||||
void NIMService::isPendingAutoTitleDownloadTasks(u32 messagePointer) {
|
||||
log("NIM::IsPendingAutoTitleDownloadTasks\n");
|
||||
|
||||
mem.write32(messagePointer, IPC::responseHeader(0x15, 2, 0));
|
||||
mem.write32(messagePointer + 4, Result::Success);
|
||||
mem.write8(messagePointer + 8, 0); // Has pending tasks
|
||||
}
|
||||
|
||||
void NIMService::getBackgroundEventForMenu(u32 messagePointer) {
|
||||
log("NIM::GetBackgroundEventForMenu\n");
|
||||
|
||||
if (!backgroundSystemUpdateEvent.has_value()) {
|
||||
backgroundSystemUpdateEvent = kernel.makeEvent(ResetType::OneShot);
|
||||
}
|
||||
|
||||
mem.write32(messagePointer, IPC::responseHeader(0x5, 1, 2));
|
||||
mem.write32(messagePointer + 4, Result::Success);
|
||||
mem.write32(messagePointer + 8, 0x04000000);
|
||||
mem.write32(messagePointer + 12, backgroundSystemUpdateEvent.value());
|
||||
}
|
32
src/core/services/ns.cpp
Normal file
32
src/core/services/ns.cpp
Normal 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);
|
||||
log("NS::LaunchTitle (title ID = %llX, launch flags = %X) (stubbed)\n", titleID, launchFlags);
|
||||
|
||||
mem.write32(messagePointer, IPC::responseHeader(0x2, 2, 0));
|
||||
mem.write32(messagePointer + 4, Result::Success);
|
||||
mem.write32(messagePointer + 8, 0); // Process ID
|
||||
}
|
|
@ -12,11 +12,16 @@ namespace PTMCommands {
|
|||
GetStepHistoryAll = 0x000F0084,
|
||||
ConfigureNew3DSCPU = 0x08180040,
|
||||
|
||||
// ptm:gets functions
|
||||
GetSystemTime = 0x04010000,
|
||||
|
||||
// ptm:play functions
|
||||
GetPlayHistory = 0x08070082,
|
||||
GetPlayHistoryStart = 0x08080000,
|
||||
GetPlayHistoryLength = 0x08090000,
|
||||
CalcPlayHistoryStart = 0x080B0080,
|
||||
GetSoftwareClosedFlag = 0x080F0000,
|
||||
ClearSoftwareClosedFlag = 0x08100000,
|
||||
};
|
||||
}
|
||||
|
||||
|
@ -50,10 +55,23 @@ void PTMService::handleSyncRequest(u32 messagePointer, PTMService::Type type) {
|
|||
|
||||
default: Helpers::panic("PTM PLAY service requested. Command: %08X\n", command); break;
|
||||
}
|
||||
} else if (type == Type::GETS) {
|
||||
switch (command) {
|
||||
case PTMCommands::GetSystemTime: getSystemTime(messagePointer); break;
|
||||
|
||||
default: Helpers::panic("PTM GETS service requested. Command: %08X\n", command); break;
|
||||
}
|
||||
} else if (type == Type::SYSM) {
|
||||
switch (command) {
|
||||
case PTMCommands::GetSoftwareClosedFlag: getSoftwareClosedFlag(messagePointer); break;
|
||||
case PTMCommands::ClearSoftwareClosedFlag: clearSoftwareClosedFlag(messagePointer); break;
|
||||
|
||||
default: Helpers::panic("PTM SYSM service requested. Command: %08X\n", command); break;
|
||||
}
|
||||
} else {
|
||||
Helpers::panic("PTM service requested. Command: %08X\n", command);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void PTMService::getAdapterState(u32 messagePointer) {
|
||||
|
@ -114,4 +132,24 @@ void PTMService::configureNew3DSCPU(u32 messagePointer) {
|
|||
log("PTM::ConfigureNew3DSCPU [stubbed]\n");
|
||||
mem.write32(messagePointer, IPC::responseHeader(0x818, 1, 0));
|
||||
mem.write32(messagePointer + 4, Result::Success);
|
||||
}
|
||||
|
||||
void PTMService::getSystemTime(u32 messagePointer) {
|
||||
log("PTM::GetSystemTime [stubbed]\n");
|
||||
mem.write32(messagePointer, IPC::responseHeader(0x401, 3, 0));
|
||||
mem.write32(messagePointer + 4, Result::Success);
|
||||
mem.write64(messagePointer + 8, 0); // Milliseconds since 2000?
|
||||
}
|
||||
|
||||
void PTMService::getSoftwareClosedFlag(u32 messagePointer) {
|
||||
log("PTM::GetSoftwareClosedFlag\n");
|
||||
mem.write32(messagePointer, IPC::responseHeader(0x80F, 2, 0));
|
||||
mem.write32(messagePointer + 4, Result::Success);
|
||||
mem.write8(messagePointer + 8, 0); // Show software closed dialog
|
||||
}
|
||||
|
||||
void PTMService::clearSoftwareClosedFlag(u32 messagePointer) {
|
||||
log("PTM::ClearSoftwareClosedFlag\n");
|
||||
mem.write32(messagePointer, IPC::responseHeader(0x810, 1, 0));
|
||||
mem.write32(messagePointer + 4, Result::Success);
|
||||
}
|
|
@ -7,9 +7,10 @@
|
|||
|
||||
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),
|
||||
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),
|
||||
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),
|
||||
news_u(mem), nwm_uds(mem, kernel), ptm(mem, config), soc(mem), ssl(mem), y2r(mem, kernel) {}
|
||||
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), gsp_gpu(mem, gpu, kernel, currentPID), gsp_lcd(mem), ldr(mem, kernel), mcu_hwc(mem, config), mic(mem, kernel),
|
||||
nfc(mem, kernel), nim(mem, kernel), ndm(mem), news_s(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;
|
||||
|
||||
|
@ -37,9 +38,11 @@ void ServiceManager::reset() {
|
|||
mcu_hwc.reset();
|
||||
mic.reset();
|
||||
ndm.reset();
|
||||
news_s.reset();
|
||||
news_u.reset();
|
||||
nfc.reset();
|
||||
nim.reset();
|
||||
ns.reset();
|
||||
ptm.reset();
|
||||
soc.reset();
|
||||
ssl.reset();
|
||||
|
@ -102,7 +105,9 @@ static std::map<std::string, HorizonHandle> serviceMap = {
|
|||
{ "APT:A", KernelHandles::APT },
|
||||
{ "APT:U", KernelHandles::APT },
|
||||
{ "boss:U", KernelHandles::BOSS },
|
||||
{ "boss:P", KernelHandles::BOSS },
|
||||
{ "cam:u", KernelHandles::CAM },
|
||||
{ "cecd:s", KernelHandles::CECD },
|
||||
{ "cecd:u", KernelHandles::CECD },
|
||||
{ "cfg:u", KernelHandles::CFG_U },
|
||||
{ "cfg:i", KernelHandles::CFG_I },
|
||||
|
@ -111,6 +116,7 @@ static std::map<std::string, HorizonHandle> serviceMap = {
|
|||
{ "dlp:SRVR", KernelHandles::DLP_SRVR },
|
||||
{ "dsp::DSP", KernelHandles::DSP },
|
||||
{ "hid:USER", KernelHandles::HID },
|
||||
{ "hid:SPVR", KernelHandles::HID },
|
||||
{ "http:C", KernelHandles::HTTP },
|
||||
{ "ir:USER", KernelHandles::IR_USER },
|
||||
{ "frd:a", KernelHandles::FRD_A },
|
||||
|
@ -122,14 +128,17 @@ static std::map<std::string, HorizonHandle> serviceMap = {
|
|||
{ "mcu::HWC", KernelHandles::MCU_HWC },
|
||||
{ "mic:u", KernelHandles::MIC },
|
||||
{ "ndm:u", KernelHandles::NDM },
|
||||
{ "news:s", KernelHandles::NEWS_S },
|
||||
{ "news:u", KernelHandles::NEWS_U },
|
||||
{ "nfc:u", KernelHandles::NFC },
|
||||
{ "ns:s", KernelHandles::NS_S },
|
||||
{ "nwm::UDS", KernelHandles::NWM_UDS },
|
||||
{ "nim:aoc", KernelHandles::NIM },
|
||||
{ "nim:aoc", KernelHandles::NIM_AOC },
|
||||
{ "nim:u", KernelHandles::NIM_U },
|
||||
{ "ptm:u", KernelHandles::PTM_U }, // TODO: ptm:u and ptm:sysm have very different command sets
|
||||
{ "ptm:sysm", KernelHandles::PTM_SYSM },
|
||||
{ "ptm:play", KernelHandles::PTM_PLAY },
|
||||
{ "ptm:gets", KernelHandles::PTM_GETS },
|
||||
{ "soc:U", KernelHandles::SOC },
|
||||
{ "ssl:C", KernelHandles::SSL },
|
||||
{ "y2r:u", KernelHandles::Y2R },
|
||||
|
@ -224,11 +233,13 @@ void ServiceManager::sendCommandToService(u32 messagePointer, Handle handle) {
|
|||
case KernelHandles::MCU_HWC: mcu_hwc.handleSyncRequest(messagePointer); break;
|
||||
case KernelHandles::MIC: mic.handleSyncRequest(messagePointer); break;
|
||||
case KernelHandles::NFC: nfc.handleSyncRequest(messagePointer); break;
|
||||
case KernelHandles::NIM: nim.handleSyncRequest(messagePointer); break;
|
||||
case KernelHandles::NIM_AOC: nim.handleSyncRequest(messagePointer, NIMService::Type::AOC); break;
|
||||
case KernelHandles::NIM_U: nim.handleSyncRequest(messagePointer, NIMService::Type::U); break;
|
||||
case KernelHandles::NDM: ndm.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::PTM_GETS: ptm.handleSyncRequest(messagePointer, PTMService::Type::GETS); 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_U: ptm.handleSyncRequest(messagePointer, PTMService::Type::U); break;
|
||||
|
|
Loading…
Add table
Reference in a new issue