mirror of
https://github.com/wheremyfoodat/Panda3DS.git
synced 2025-04-08 07:05:40 +12:00
Merge pull request #285 from wheremyfoodat/system-appz
Add HLE stuff to boot more OS apps
This commit is contained in:
commit
3cf917f749
8 changed files with 163 additions and 37 deletions
|
@ -16,6 +16,8 @@ class ACService {
|
||||||
void cancelConnectAsync(u32 messagePointer);
|
void cancelConnectAsync(u32 messagePointer);
|
||||||
void closeAsync(u32 messagePointer);
|
void closeAsync(u32 messagePointer);
|
||||||
void createDefaultConfig(u32 messagePointer);
|
void createDefaultConfig(u32 messagePointer);
|
||||||
|
void getConnectingInfraPriority(u32 messagePointer);
|
||||||
|
void getStatus(u32 messagePointer);
|
||||||
void getLastErrorCode(u32 messagePointer);
|
void getLastErrorCode(u32 messagePointer);
|
||||||
void isConnected(u32 messagePointer);
|
void isConnected(u32 messagePointer);
|
||||||
void registerDisconnectEvent(u32 messagePointer);
|
void registerDisconnectEvent(u32 messagePointer);
|
||||||
|
|
|
@ -15,6 +15,7 @@ class CFGService {
|
||||||
|
|
||||||
// Service functions
|
// Service functions
|
||||||
void getConfigInfoBlk2(u32 messagePointer);
|
void getConfigInfoBlk2(u32 messagePointer);
|
||||||
|
void getConfigInfoBlk8(u32 messagePointer);
|
||||||
void getCountryCodeID(u32 messagePointer);
|
void getCountryCodeID(u32 messagePointer);
|
||||||
void getLocalFriendCodeSeed(u32 messagePointer);
|
void getLocalFriendCodeSeed(u32 messagePointer);
|
||||||
void getRegionCanadaUSA(u32 messagePointer);
|
void getRegionCanadaUSA(u32 messagePointer);
|
||||||
|
@ -23,6 +24,8 @@ class CFGService {
|
||||||
void secureInfoGetByte101(u32 messagePointer);
|
void secureInfoGetByte101(u32 messagePointer);
|
||||||
void secureInfoGetRegion(u32 messagePointer);
|
void secureInfoGetRegion(u32 messagePointer);
|
||||||
|
|
||||||
|
void getConfigInfo(u32 output, u32 blockID, u32 size, u32 permissionMask);
|
||||||
|
|
||||||
public:
|
public:
|
||||||
enum class Type {
|
enum class Type {
|
||||||
U, // cfg:u
|
U, // cfg:u
|
||||||
|
|
|
@ -26,16 +26,20 @@ class FRDService {
|
||||||
void getFriendKeyList(u32 messagePointer);
|
void getFriendKeyList(u32 messagePointer);
|
||||||
void getFriendPresence(u32 messagePointer);
|
void getFriendPresence(u32 messagePointer);
|
||||||
void getFriendProfile(u32 messagePointer);
|
void getFriendProfile(u32 messagePointer);
|
||||||
|
void getMyComment(u32 messagePointer);
|
||||||
|
void getMyFavoriteGame(u32 messagePointer);
|
||||||
void getMyFriendKey(u32 messagePointer);
|
void getMyFriendKey(u32 messagePointer);
|
||||||
void getMyMii(u32 messagePointer);
|
void getMyMii(u32 messagePointer);
|
||||||
void getMyPresence(u32 messagePointer);
|
void getMyPresence(u32 messagePointer);
|
||||||
void getMyProfile(u32 messagePointer);
|
void getMyProfile(u32 messagePointer);
|
||||||
void getMyScreenName(u32 messsagePointer);
|
void getMyScreenName(u32 messsagePointer);
|
||||||
void hasLoggedIn(u32 messagePointer);
|
void hasLoggedIn(u32 messagePointer);
|
||||||
|
void isOnline(u32 messagePointer);
|
||||||
void logout(u32 messagePointer);
|
void logout(u32 messagePointer);
|
||||||
void setClientSDKVersion(u32 messagePointer);
|
void setClientSDKVersion(u32 messagePointer);
|
||||||
void setNotificationMask(u32 messagePointer);
|
void setNotificationMask(u32 messagePointer);
|
||||||
void updateGameModeDescription(u32 messagePointer);
|
void updateGameModeDescription(u32 messagePointer);
|
||||||
|
void updateMii(u32 messagePointer);
|
||||||
|
|
||||||
struct Profile {
|
struct Profile {
|
||||||
u8 region;
|
u8 region;
|
||||||
|
|
|
@ -6,6 +6,8 @@
|
||||||
#include "result/result.hpp"
|
#include "result/result.hpp"
|
||||||
|
|
||||||
class NDMService {
|
class NDMService {
|
||||||
|
enum class ExclusiveState : u32 { None = 0, Infrastructure = 1, LocalComms = 2, StreetPass = 3, StreetPassData = 4 };
|
||||||
|
|
||||||
Handle handle = KernelHandles::NDM;
|
Handle handle = KernelHandles::NDM;
|
||||||
Memory& mem;
|
Memory& mem;
|
||||||
MAKE_LOG_FUNCTION(log, ndmLogger)
|
MAKE_LOG_FUNCTION(log, ndmLogger)
|
||||||
|
@ -15,11 +17,14 @@ class NDMService {
|
||||||
void enterExclusiveState(u32 messagePointer);
|
void enterExclusiveState(u32 messagePointer);
|
||||||
void exitExclusiveState(u32 messagePointer);
|
void exitExclusiveState(u32 messagePointer);
|
||||||
void overrideDefaultDaemons(u32 messagePointer);
|
void overrideDefaultDaemons(u32 messagePointer);
|
||||||
|
void queryExclusiveState(u32 messagePointer);
|
||||||
void resumeDaemons(u32 messagePointer);
|
void resumeDaemons(u32 messagePointer);
|
||||||
void resumeScheduler(u32 messagePointer);
|
void resumeScheduler(u32 messagePointer);
|
||||||
void suspendDaemons(u32 messagePointer);
|
void suspendDaemons(u32 messagePointer);
|
||||||
void suspendScheduler(u32 messagePointer);
|
void suspendScheduler(u32 messagePointer);
|
||||||
|
|
||||||
|
ExclusiveState exclusiveState = ExclusiveState::None;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
NDMService(Memory& mem) : mem(mem) {}
|
NDMService(Memory& mem) : mem(mem) {}
|
||||||
void reset();
|
void reset();
|
||||||
|
|
|
@ -7,6 +7,8 @@ namespace ACCommands {
|
||||||
CancelConnectAsync = 0x00070002,
|
CancelConnectAsync = 0x00070002,
|
||||||
CloseAsync = 0x00080004,
|
CloseAsync = 0x00080004,
|
||||||
GetLastErrorCode = 0x000A0000,
|
GetLastErrorCode = 0x000A0000,
|
||||||
|
GetStatus = 0x000C0000,
|
||||||
|
GetConnectingInfraPriority = 0x000F0000,
|
||||||
RegisterDisconnectEvent = 0x00300004,
|
RegisterDisconnectEvent = 0x00300004,
|
||||||
IsConnected = 0x003E0042,
|
IsConnected = 0x003E0042,
|
||||||
SetClientVersion = 0x00400042,
|
SetClientVersion = 0x00400042,
|
||||||
|
@ -24,7 +26,9 @@ void ACService::handleSyncRequest(u32 messagePointer) {
|
||||||
case ACCommands::CancelConnectAsync: cancelConnectAsync(messagePointer); break;
|
case ACCommands::CancelConnectAsync: cancelConnectAsync(messagePointer); break;
|
||||||
case ACCommands::CloseAsync: closeAsync(messagePointer); break;
|
case ACCommands::CloseAsync: closeAsync(messagePointer); break;
|
||||||
case ACCommands::CreateDefaultConfig: createDefaultConfig(messagePointer); break;
|
case ACCommands::CreateDefaultConfig: createDefaultConfig(messagePointer); break;
|
||||||
|
case ACCommands::GetConnectingInfraPriority: getConnectingInfraPriority(messagePointer); break;
|
||||||
case ACCommands::GetLastErrorCode: getLastErrorCode(messagePointer); break;
|
case ACCommands::GetLastErrorCode: getLastErrorCode(messagePointer); break;
|
||||||
|
case ACCommands::GetStatus: getStatus(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;
|
||||||
|
@ -69,6 +73,25 @@ void ACService::getLastErrorCode(u32 messagePointer) {
|
||||||
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) {
|
||||||
|
log("AC::GetConnectingInfraPriority (stubbed)\n");
|
||||||
|
|
||||||
|
// TODO: Find out what this is
|
||||||
|
mem.write32(messagePointer, IPC::responseHeader(0x0F, 2, 0));
|
||||||
|
mem.write32(messagePointer + 4, Result::Success);
|
||||||
|
mem.write32(messagePointer + 8, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
void ACService::getStatus(u32 messagePointer) {
|
||||||
|
log("AC::GetStatus (stubbed)\n");
|
||||||
|
|
||||||
|
// TODO: Find out what this is
|
||||||
|
mem.write32(messagePointer, IPC::responseHeader(0x0C, 2, 0));
|
||||||
|
mem.write32(messagePointer + 4, Result::Success);
|
||||||
|
mem.write32(messagePointer + 8, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
void ACService::isConnected(u32 messagePointer) {
|
void ACService::isConnected(u32 messagePointer) {
|
||||||
log("AC::IsConnected\n");
|
log("AC::IsConnected\n");
|
||||||
// This has parameters according to the command word but it's unknown what they are
|
// This has parameters according to the command word but it's unknown what they are
|
||||||
|
|
|
@ -11,6 +11,7 @@
|
||||||
namespace CFGCommands {
|
namespace CFGCommands {
|
||||||
enum : u32 {
|
enum : u32 {
|
||||||
GetConfigInfoBlk2 = 0x00010082,
|
GetConfigInfoBlk2 = 0x00010082,
|
||||||
|
GetConfigInfoBlk8 = 0x04010082,
|
||||||
SecureInfoGetRegion = 0x00020000,
|
SecureInfoGetRegion = 0x00020000,
|
||||||
GenHashConsoleUnique = 0x00030040,
|
GenHashConsoleUnique = 0x00030040,
|
||||||
GetRegionCanadaUSA = 0x00040000,
|
GetRegionCanadaUSA = 0x00040000,
|
||||||
|
@ -61,77 +62,91 @@ void CFGService::getConfigInfoBlk2(u32 messagePointer) {
|
||||||
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::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));
|
||||||
|
mem.write32(messagePointer + 4, Result::Success);
|
||||||
|
}
|
||||||
|
|
||||||
|
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);
|
||||||
|
|
||||||
|
getConfigInfo(output, blockID, size, 0x8);
|
||||||
|
mem.write32(messagePointer, IPC::responseHeader(0x401, 1, 2));
|
||||||
|
mem.write32(messagePointer + 4, Result::Success);
|
||||||
|
}
|
||||||
|
|
||||||
|
void CFGService::getConfigInfo(u32 output, u32 blockID, u32 size, u32 permissionMask) {
|
||||||
// TODO: Make this not bad
|
// TODO: Make this not bad
|
||||||
if (size == 1 && blockID == 0x70001) { // Sound output mode
|
if (size == 1 && blockID == 0x70001) { // Sound output mode
|
||||||
mem.write8(output, static_cast<u8>(DSPService::SoundOutputMode::Stereo));
|
mem.write8(output, static_cast<u8>(DSPService::SoundOutputMode::Stereo));
|
||||||
} else if (size == 1 && blockID == 0xA0002){ // System language
|
} else if (size == 1 && blockID == 0xA0002) { // System language
|
||||||
mem.write8(output, static_cast<u8>(LanguageCodes::English));
|
mem.write8(output, static_cast<u8>(LanguageCodes::English));
|
||||||
} else if (size == 4 && blockID == 0xB0000) { // Country info
|
} else if (size == 4 && blockID == 0xB0000) { // Country info
|
||||||
mem.write8(output, 0); // Unknown
|
mem.write8(output, 0); // Unknown
|
||||||
mem.write8(output + 1, 0); // Unknown
|
mem.write8(output + 1, 0); // Unknown
|
||||||
mem.write8(output + 2, 2); // Province (Temporarily stubbed to Washington DC like Citra)
|
mem.write8(output + 2, 2); // Province (Temporarily stubbed to Washington DC like Citra)
|
||||||
mem.write8(output + 3, static_cast<u8>(country)); // Country code
|
mem.write8(output + 3, static_cast<u8>(country)); // Country code
|
||||||
} else if (size == 0x20 && blockID == 0x50005) {
|
} else if (size == 0x20 && blockID == 0x50005) {
|
||||||
// "Stereo Camera settings"
|
// "Stereo Camera settings"
|
||||||
// Implementing this properly fixes NaN uniforms in some games. Values taken from 3dmoo & Citra
|
// Implementing this properly fixes NaN uniforms in some games. Values taken from 3dmoo & Citra
|
||||||
static constexpr std::array<float, 8> STEREO_CAMERA_SETTINGS = {
|
static constexpr std::array<float, 8> STEREO_CAMERA_SETTINGS = {
|
||||||
62.0f, 289.0f, 76.80000305175781f, 46.08000183105469f,
|
62.0f, 289.0f, 76.80000305175781f, 46.08000183105469f, 10.0f, 5.0f, 55.58000183105469f, 21.56999969482422f,
|
||||||
10.0f, 5.0f, 55.58000183105469f, 21.56999969482422f
|
|
||||||
};
|
};
|
||||||
|
|
||||||
for (int i = 0; i < 8; i++) {
|
for (int i = 0; i < 8; i++) {
|
||||||
mem.write32(output + i * 4, Helpers::bit_cast<u32, float>(STEREO_CAMERA_SETTINGS[i]));
|
mem.write32(output + i * 4, Helpers::bit_cast<u32, float>(STEREO_CAMERA_SETTINGS[i]));
|
||||||
}
|
}
|
||||||
} else if (size == 0x1C && blockID == 0xA0000) { // Username
|
} else if (size == 0x1C && blockID == 0xA0000) { // Username
|
||||||
writeStringU16(output, u"Pander");
|
writeStringU16(output, u"Pander");
|
||||||
} else if (size == 0xC0 && blockID == 0xC0000) { // Parental restrictions info
|
} else if (size == 0xC0 && blockID == 0xC0000) { // Parental restrictions info
|
||||||
for (int i = 0; i < 0xC0; i++)
|
for (int i = 0; i < 0xC0; i++) mem.write8(output + i, 0);
|
||||||
mem.write8(output + i, 0);
|
} else if (size == 4 && blockID == 0xD0000) { // Agreed EULA version (first 2 bytes) and latest EULA version (next 2 bytes)
|
||||||
} else if (size == 4 && blockID == 0xD0000) { // Agreed EULA version (first 2 bytes) and latest EULA version (next 2 bytes)
|
|
||||||
log("Read EULA info\n");
|
log("Read EULA info\n");
|
||||||
mem.write16(output, 0x0202); // Agreed EULA version = 2.2 (Random number. TODO: Check)
|
mem.write16(output, 0x0202); // Agreed EULA version = 2.2 (Random number. TODO: Check)
|
||||||
mem.write16(output + 2, 0x0202); // Latest EULA version = 2.2
|
mem.write16(output + 2, 0x0202); // Latest EULA version = 2.2
|
||||||
} else if (size == 0x800 && blockID == 0xB0001) { // UTF-16 name for our country in every language at 0x80 byte intervals
|
} else if (size == 0x800 && blockID == 0xB0001) { // UTF-16 name for our country in every language at 0x80 byte intervals
|
||||||
constexpr size_t languageCount = 16;
|
constexpr size_t languageCount = 16;
|
||||||
constexpr size_t nameSize = 0x80; // Max size of each name in bytes
|
constexpr size_t nameSize = 0x80; // Max size of each name in bytes
|
||||||
std::u16string name = u"PandaLand (Home of PandaSemi LLC) (aka Pandistan)"; // Note: This + the null terminator needs to fit in 0x80 bytes
|
std::u16string name = u"PandaLand (Home of PandaSemi LLC) (aka Pandistan)"; // Note: This + the null terminator needs to fit in 0x80 bytes
|
||||||
|
|
||||||
for (int i = 0; i < languageCount; i++) {
|
for (int i = 0; i < languageCount; i++) {
|
||||||
u32 pointer = output + i * nameSize;
|
u32 pointer = output + i * nameSize;
|
||||||
writeStringU16(pointer, name);
|
writeStringU16(pointer, name);
|
||||||
}
|
}
|
||||||
} else if (size == 0x800 && blockID == 0xB0002) { // UTF-16 name for our state in every language at 0x80 byte intervals
|
} else if (size == 0x800 && blockID == 0xB0002) { // UTF-16 name for our state in every language at 0x80 byte intervals
|
||||||
constexpr size_t languageCount = 16;
|
constexpr size_t languageCount = 16;
|
||||||
constexpr size_t nameSize = 0x80; // Max size of each name in bytes
|
constexpr size_t nameSize = 0x80; // Max size of each name in bytes
|
||||||
std::u16string name = u"Pandington"; // Note: This + the null terminator needs to fit in 0x80 bytes
|
std::u16string name = u"Pandington"; // Note: This + the null terminator needs to fit in 0x80 bytes
|
||||||
|
|
||||||
for (int i = 0; i < languageCount; i++) {
|
for (int i = 0; i < languageCount; i++) {
|
||||||
u32 pointer = output + i * nameSize;
|
u32 pointer = output + i * nameSize;
|
||||||
writeStringU16(pointer, name);
|
writeStringU16(pointer, name);
|
||||||
}
|
}
|
||||||
} else if (size == 4 && blockID == 0xB0003) { // Coordinates (latidude and longtitude) as s16
|
} else if (size == 4 && blockID == 0xB0003) { // Coordinates (latidude and longtitude) as s16
|
||||||
mem.write16(output, 0); // Latitude
|
mem.write16(output, 0); // Latitude
|
||||||
mem.write16(output + 2, 0); // Longtitude
|
mem.write16(output + 2, 0); // Longtitude
|
||||||
} else if (size == 2 && blockID == 0xA0001) { // Birthday
|
} else if (size == 2 && blockID == 0xA0001) { // Birthday
|
||||||
mem.write8(output, 5); // Month (May)
|
mem.write8(output, 5); // Month (May)
|
||||||
mem.write8(output + 1, 5); // Day (Fifth)
|
mem.write8(output + 1, 5); // Day (Fifth)
|
||||||
} else if (size == 8 && blockID == 0x30001) { // User time offset
|
} else if (size == 8 && blockID == 0x30001) { // User time offset
|
||||||
printf("Read from user time offset field in NAND. TODO: What is this\n");
|
printf("Read from user time offset field in NAND. TODO: What is this\n");
|
||||||
mem.write64(output, 0);
|
mem.write64(output, 0);
|
||||||
} else if (size == 20 && blockID == 0xC0001) { // COPPACS restriction data, used by games when they detect a USA/Canada region for market restriction stuff
|
} else if (size == 20 && blockID == 0xC0001) { // COPPACS restriction data, used by games when they detect a USA/Canada region for market
|
||||||
|
// restriction stuff
|
||||||
for (u32 i = 0; i < size; i += 4) {
|
for (u32 i = 0; i < size; i += 4) {
|
||||||
mem.write32(output + i, 0);
|
mem.write32(output + i, 0);
|
||||||
}
|
}
|
||||||
} else if (size == 4 && blockID == 0x170000) { // Miiverse access key
|
} else if (size == 4 && blockID == 0x170000) { // Miiverse access key
|
||||||
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 {
|
} else {
|
||||||
Helpers::panic("Unhandled GetConfigInfoBlk2 configuration. Size = %d, block = %X", size, blockID);
|
Helpers::panic("Unhandled GetConfigInfoBlk2 configuration. Size = %d, block = %X", size, blockID);
|
||||||
}
|
}
|
||||||
|
|
||||||
mem.write32(messagePointer, IPC::responseHeader(0x1, 1, 2));
|
|
||||||
mem.write32(messagePointer + 4, Result::Success);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void CFGService::secureInfoGetRegion(u32 messagePointer) {
|
void CFGService::secureInfoGetRegion(u32 messagePointer) {
|
||||||
|
|
|
@ -8,6 +8,7 @@
|
||||||
namespace FRDCommands {
|
namespace FRDCommands {
|
||||||
enum : u32 {
|
enum : u32 {
|
||||||
HasLoggedIn = 0x00010000,
|
HasLoggedIn = 0x00010000,
|
||||||
|
IsOnline = 0x00020000,
|
||||||
AttachToEventNotification = 0x00200002,
|
AttachToEventNotification = 0x00200002,
|
||||||
SetNotificationMask = 0x00210040,
|
SetNotificationMask = 0x00210040,
|
||||||
SetClientSdkVersion = 0x00320042,
|
SetClientSdkVersion = 0x00320042,
|
||||||
|
@ -17,11 +18,15 @@ namespace FRDCommands {
|
||||||
GetMyPresence = 0x00080000,
|
GetMyPresence = 0x00080000,
|
||||||
GetMyScreenName = 0x00090000,
|
GetMyScreenName = 0x00090000,
|
||||||
GetMyMii = 0x000A0000,
|
GetMyMii = 0x000A0000,
|
||||||
|
GetMyFavoriteGame = 0x000D0000,
|
||||||
|
GetMyComment = 0x000F0000,
|
||||||
GetFriendKeyList = 0x00110080,
|
GetFriendKeyList = 0x00110080,
|
||||||
GetFriendPresence = 0x00120042,
|
GetFriendPresence = 0x00120042,
|
||||||
GetFriendProfile = 0x00150042,
|
GetFriendProfile = 0x00150042,
|
||||||
GetFriendAttributeFlags = 0x00170042,
|
GetFriendAttributeFlags = 0x00170042,
|
||||||
UpdateGameModeDescription = 0x001D0002,
|
UpdateGameModeDescription = 0x001D0002,
|
||||||
|
|
||||||
|
UpdateMii = 0x040C0800,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -35,17 +40,32 @@ void FRDService::handleSyncRequest(u32 messagePointer, FRDService::Type type) {
|
||||||
case FRDCommands::GetFriendKeyList: getFriendKeyList(messagePointer); break;
|
case FRDCommands::GetFriendKeyList: getFriendKeyList(messagePointer); break;
|
||||||
case FRDCommands::GetFriendPresence: getFriendPresence(messagePointer); break;
|
case FRDCommands::GetFriendPresence: getFriendPresence(messagePointer); break;
|
||||||
case FRDCommands::GetFriendProfile: getFriendProfile(messagePointer); break;
|
case FRDCommands::GetFriendProfile: getFriendProfile(messagePointer); break;
|
||||||
|
case FRDCommands::GetMyComment: getMyComment(messagePointer); break;
|
||||||
case FRDCommands::GetMyFriendKey: getMyFriendKey(messagePointer); break;
|
case FRDCommands::GetMyFriendKey: getMyFriendKey(messagePointer); break;
|
||||||
case FRDCommands::GetMyMii: getMyMii(messagePointer); break;
|
case FRDCommands::GetMyMii: getMyMii(messagePointer); break;
|
||||||
|
case FRDCommands::GetMyFavoriteGame: getMyFavoriteGame(messagePointer); break;
|
||||||
case FRDCommands::GetMyPresence: getMyPresence(messagePointer); break;
|
case FRDCommands::GetMyPresence: getMyPresence(messagePointer); break;
|
||||||
case FRDCommands::GetMyProfile: getMyProfile(messagePointer); break;
|
case FRDCommands::GetMyProfile: getMyProfile(messagePointer); break;
|
||||||
case FRDCommands::GetMyScreenName: getMyScreenName(messagePointer); break;
|
case FRDCommands::GetMyScreenName: getMyScreenName(messagePointer); break;
|
||||||
case FRDCommands::HasLoggedIn: hasLoggedIn(messagePointer); break;
|
case FRDCommands::HasLoggedIn: hasLoggedIn(messagePointer); break;
|
||||||
|
case FRDCommands::IsOnline: isOnline(messagePointer); break;
|
||||||
case FRDCommands::Logout: logout(messagePointer); break;
|
case FRDCommands::Logout: logout(messagePointer); break;
|
||||||
case FRDCommands::SetClientSdkVersion: setClientSDKVersion(messagePointer); break;
|
case FRDCommands::SetClientSdkVersion: setClientSDKVersion(messagePointer); break;
|
||||||
case FRDCommands::SetNotificationMask: setNotificationMask(messagePointer); break;
|
case FRDCommands::SetNotificationMask: setNotificationMask(messagePointer); break;
|
||||||
case FRDCommands::UpdateGameModeDescription: updateGameModeDescription(messagePointer); break;
|
case FRDCommands::UpdateGameModeDescription: updateGameModeDescription(messagePointer); break;
|
||||||
default: Helpers::panic("FRD service requested. Command: %08X\n", command);
|
|
||||||
|
default:
|
||||||
|
// FRD:A functions
|
||||||
|
if (type == Type::A) {
|
||||||
|
switch (command) {
|
||||||
|
case FRDCommands::UpdateMii: updateMii(messagePointer); break;
|
||||||
|
default: Helpers::panic("FRD:A service requested. Command: %08X\n", command); break;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
Helpers::panic("FRD service requested. Command: %08X\n", command);
|
||||||
|
}
|
||||||
|
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -201,6 +221,23 @@ void FRDService::getMyMii(u32 messagePointer) {
|
||||||
mem.write32(messagePointer + 4, Result::Success);
|
mem.write32(messagePointer + 4, Result::Success);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void FRDService::getMyFavoriteGame(u32 messagePointer) {
|
||||||
|
log("FRD::GetMyFavoriteGame (stubbed)\n");
|
||||||
|
constexpr u64 titleID = 0;
|
||||||
|
|
||||||
|
mem.write32(messagePointer, IPC::responseHeader(0xD, 3, 0));
|
||||||
|
mem.write32(messagePointer + 4, Result::Success);
|
||||||
|
mem.write64(messagePointer + 8, titleID);
|
||||||
|
}
|
||||||
|
|
||||||
|
void FRDService::getMyComment(u32 messagePointer) {
|
||||||
|
log("FRD::GetMyComment");
|
||||||
|
|
||||||
|
mem.write32(messagePointer, IPC::responseHeader(0xF, 2, 0));
|
||||||
|
mem.write32(messagePointer + 4, Result::Success);
|
||||||
|
mem.write32(messagePointer + 8, 0);
|
||||||
|
}
|
||||||
|
|
||||||
void FRDService::hasLoggedIn(u32 messagePointer) {
|
void FRDService::hasLoggedIn(u32 messagePointer) {
|
||||||
log("FRD::HasLoggedIn\n");
|
log("FRD::HasLoggedIn\n");
|
||||||
|
|
||||||
|
@ -209,6 +246,15 @@ void FRDService::hasLoggedIn(u32 messagePointer) {
|
||||||
mem.write8(messagePointer + 8, loggedIn ? 1 : 0);
|
mem.write8(messagePointer + 8, loggedIn ? 1 : 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void FRDService::isOnline(u32 messagePointer) {
|
||||||
|
log("FRD::IsOnline\n");
|
||||||
|
|
||||||
|
mem.write32(messagePointer, IPC::responseHeader(0x2, 2, 0));
|
||||||
|
mem.write32(messagePointer + 4, Result::Success);
|
||||||
|
// TODO: When is this 0?
|
||||||
|
mem.write8(messagePointer + 8, 1);
|
||||||
|
}
|
||||||
|
|
||||||
void FRDService::logout(u32 messagePointer) {
|
void FRDService::logout(u32 messagePointer) {
|
||||||
log("FRD::Logout\n");
|
log("FRD::Logout\n");
|
||||||
loggedIn = false;
|
loggedIn = false;
|
||||||
|
@ -216,3 +262,10 @@ void FRDService::logout(u32 messagePointer) {
|
||||||
mem.write32(messagePointer, IPC::responseHeader(0x4, 1, 0));
|
mem.write32(messagePointer, IPC::responseHeader(0x4, 1, 0));
|
||||||
mem.write32(messagePointer + 4, Result::Success);
|
mem.write32(messagePointer + 4, Result::Success);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void FRDService::updateMii(u32 messagePointer) {
|
||||||
|
log("FRD::UpdateMii (stubbed)\n");
|
||||||
|
|
||||||
|
mem.write32(messagePointer, IPC::responseHeader(0x40C, 1, 0));
|
||||||
|
mem.write32(messagePointer + 4, Result::Success);
|
||||||
|
}
|
|
@ -5,6 +5,7 @@ namespace NDMCommands {
|
||||||
enum : u32 {
|
enum : u32 {
|
||||||
EnterExclusiveState = 0x00010042,
|
EnterExclusiveState = 0x00010042,
|
||||||
ExitExclusiveState = 0x00020002,
|
ExitExclusiveState = 0x00020002,
|
||||||
|
QueryExclusiveMode = 0x00030000,
|
||||||
OverrideDefaultDaemons = 0x00140040,
|
OverrideDefaultDaemons = 0x00140040,
|
||||||
SuspendDaemons = 0x00060040,
|
SuspendDaemons = 0x00060040,
|
||||||
ResumeDaemons = 0x00070040,
|
ResumeDaemons = 0x00070040,
|
||||||
|
@ -14,7 +15,7 @@ namespace NDMCommands {
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
void NDMService::reset() {}
|
void NDMService::reset() { exclusiveState = ExclusiveState::None; }
|
||||||
|
|
||||||
void NDMService::handleSyncRequest(u32 messagePointer) {
|
void NDMService::handleSyncRequest(u32 messagePointer) {
|
||||||
const u32 command = mem.read32(messagePointer);
|
const u32 command = mem.read32(messagePointer);
|
||||||
|
@ -23,6 +24,7 @@ void NDMService::handleSyncRequest(u32 messagePointer) {
|
||||||
case NDMCommands::ExitExclusiveState: exitExclusiveState(messagePointer); break;
|
case NDMCommands::ExitExclusiveState: exitExclusiveState(messagePointer); break;
|
||||||
case NDMCommands::ClearHalfAwakeMacFilter: clearHalfAwakeMacFilter(messagePointer); break;
|
case NDMCommands::ClearHalfAwakeMacFilter: clearHalfAwakeMacFilter(messagePointer); break;
|
||||||
case NDMCommands::OverrideDefaultDaemons: overrideDefaultDaemons(messagePointer); break;
|
case NDMCommands::OverrideDefaultDaemons: overrideDefaultDaemons(messagePointer); break;
|
||||||
|
case NDMCommands::QueryExclusiveMode: queryExclusiveState(messagePointer); break;
|
||||||
case NDMCommands::ResumeDaemons: resumeDaemons(messagePointer); break;
|
case NDMCommands::ResumeDaemons: resumeDaemons(messagePointer); break;
|
||||||
case NDMCommands::ResumeScheduler: resumeScheduler(messagePointer); break;
|
case NDMCommands::ResumeScheduler: resumeScheduler(messagePointer); break;
|
||||||
case NDMCommands::SuspendDaemons: suspendDaemons(messagePointer); break;
|
case NDMCommands::SuspendDaemons: suspendDaemons(messagePointer); break;
|
||||||
|
@ -33,16 +35,35 @@ void NDMService::handleSyncRequest(u32 messagePointer) {
|
||||||
|
|
||||||
void NDMService::enterExclusiveState(u32 messagePointer) {
|
void NDMService::enterExclusiveState(u32 messagePointer) {
|
||||||
log("NDM::EnterExclusiveState (stubbed)\n");
|
log("NDM::EnterExclusiveState (stubbed)\n");
|
||||||
|
const u32 state = mem.read32(messagePointer + 4);
|
||||||
|
|
||||||
|
// Check that the exclusive state config is valid
|
||||||
|
if (state > 4) {
|
||||||
|
Helpers::warn("NDM::EnterExclusiveState: Invalid state %d", state);
|
||||||
|
} else {
|
||||||
|
exclusiveState = static_cast<ExclusiveState>(state);
|
||||||
|
}
|
||||||
|
|
||||||
mem.write32(messagePointer, IPC::responseHeader(0x1, 1, 0));
|
mem.write32(messagePointer, IPC::responseHeader(0x1, 1, 0));
|
||||||
mem.write32(messagePointer + 4, Result::Success);
|
mem.write32(messagePointer + 4, Result::Success);
|
||||||
}
|
}
|
||||||
|
|
||||||
void NDMService::exitExclusiveState(u32 messagePointer) {
|
void NDMService::exitExclusiveState(u32 messagePointer) {
|
||||||
log("NDM::ExitExclusiveState (stubbed)\n");
|
log("NDM::ExitExclusiveState (stubbed)\n");
|
||||||
|
exclusiveState = ExclusiveState::None;
|
||||||
|
|
||||||
mem.write32(messagePointer, IPC::responseHeader(0x2, 1, 0));
|
mem.write32(messagePointer, IPC::responseHeader(0x2, 1, 0));
|
||||||
mem.write32(messagePointer + 4, Result::Success);
|
mem.write32(messagePointer + 4, Result::Success);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void NDMService::queryExclusiveState(u32 messagePointer) {
|
||||||
|
log("NDM::QueryExclusiveState\n");
|
||||||
|
|
||||||
|
mem.write32(messagePointer, IPC::responseHeader(0x3, 1, 0));
|
||||||
|
mem.write32(messagePointer + 4, Result::Success);
|
||||||
|
mem.write32(messagePointer + 8, static_cast<u32>(exclusiveState));
|
||||||
|
}
|
||||||
|
|
||||||
void NDMService::overrideDefaultDaemons(u32 messagePointer) {
|
void NDMService::overrideDefaultDaemons(u32 messagePointer) {
|
||||||
log("NDM::OverrideDefaultDaemons (stubbed)\n");
|
log("NDM::OverrideDefaultDaemons (stubbed)\n");
|
||||||
mem.write32(messagePointer, IPC::responseHeader(0x14, 1, 0));
|
mem.write32(messagePointer, IPC::responseHeader(0x14, 1, 0));
|
||||||
|
|
Loading…
Add table
Reference in a new issue