mirror of
https://github.com/wheremyfoodat/Panda3DS.git
synced 2025-04-20 20:49:12 +12:00
Merge branch 'master' into sd-card
This commit is contained in:
commit
42bfcaf980
68 changed files with 3543 additions and 310 deletions
|
@ -8,11 +8,15 @@ namespace ACCommands {
|
|||
CloseAsync = 0x00080004,
|
||||
GetLastErrorCode = 0x000A0000,
|
||||
RegisterDisconnectEvent = 0x00300004,
|
||||
IsConnected = 0x003E0042,
|
||||
SetClientVersion = 0x00400042,
|
||||
};
|
||||
}
|
||||
|
||||
void ACService::reset() {}
|
||||
void ACService::reset() {
|
||||
connected = false;
|
||||
disconnectEvent = std::nullopt;
|
||||
}
|
||||
|
||||
void ACService::handleSyncRequest(u32 messagePointer) {
|
||||
const u32 command = mem.read32(messagePointer);
|
||||
|
@ -21,6 +25,7 @@ void ACService::handleSyncRequest(u32 messagePointer) {
|
|||
case ACCommands::CloseAsync: closeAsync(messagePointer); break;
|
||||
case ACCommands::CreateDefaultConfig: createDefaultConfig(messagePointer); break;
|
||||
case ACCommands::GetLastErrorCode: getLastErrorCode(messagePointer); break;
|
||||
case ACCommands::IsConnected: isConnected(messagePointer); break;
|
||||
case ACCommands::RegisterDisconnectEvent: registerDisconnectEvent(messagePointer); break;
|
||||
case ACCommands::SetClientVersion: setClientVersion(messagePointer); break;
|
||||
default: Helpers::panic("AC service requested. Command: %08X\n", command);
|
||||
|
@ -37,6 +42,11 @@ void ACService::cancelConnectAsync(u32 messagePointer) {
|
|||
|
||||
void ACService::closeAsync(u32 messagePointer) {
|
||||
log("AC::CloseAsync (stubbed)\n");
|
||||
connected = false;
|
||||
|
||||
if (disconnectEvent.has_value()) {
|
||||
Helpers::warn("AC::DisconnectEvent should be signalled but isn't implemented yet");
|
||||
}
|
||||
|
||||
// TODO: Verify if this response header is correct on hardware
|
||||
mem.write32(messagePointer, IPC::responseHeader(0x8, 1, 0));
|
||||
|
@ -59,6 +69,15 @@ void ACService::getLastErrorCode(u32 messagePointer) {
|
|||
mem.write32(messagePointer + 8, 0); // Hopefully this means no error?
|
||||
}
|
||||
|
||||
void ACService::isConnected(u32 messagePointer) {
|
||||
log("AC::IsConnected\n");
|
||||
// This has parameters according to the command word but it's unknown what they are
|
||||
|
||||
mem.write32(messagePointer, IPC::responseHeader(0x3E, 2, 0));
|
||||
mem.write32(messagePointer + 4, Result::Success);
|
||||
mem.write8(messagePointer + 8, connected ? 1 : 0);
|
||||
}
|
||||
|
||||
void ACService::setClientVersion(u32 messagePointer) {
|
||||
u32 version = mem.read32(messagePointer + 4);
|
||||
log("AC::SetClientVersion (version = %d)\n", version);
|
||||
|
@ -71,9 +90,11 @@ void ACService::registerDisconnectEvent(u32 messagePointer) {
|
|||
log("AC::RegisterDisconnectEvent (stubbed)\n");
|
||||
const u32 pidHeader = mem.read32(messagePointer + 4);
|
||||
const u32 copyHandleHeader = mem.read32(messagePointer + 12);
|
||||
// Event signaled when disconnecting from AC
|
||||
// Event signaled when disconnecting from AC. TODO: Properly implement it.
|
||||
const Handle eventHandle = mem.read32(messagePointer + 16);
|
||||
|
||||
disconnectEvent = eventHandle;
|
||||
|
||||
mem.write32(messagePointer, IPC::responseHeader(0x30, 1, 0));
|
||||
mem.write32(messagePointer + 4, Result::Success);
|
||||
}
|
|
@ -17,7 +17,10 @@ void ACTService::handleSyncRequest(u32 messagePointer) {
|
|||
case ACTCommands::GenerateUUID: generateUUID(messagePointer); break;
|
||||
case ACTCommands::GetAccountDataBlock: getAccountDataBlock(messagePointer); break;
|
||||
case ACTCommands::Initialize: initialize(messagePointer); break;
|
||||
default: Helpers::panic("ACT service requested. Command: %08X\n", command);
|
||||
default:
|
||||
Helpers::warn("Undocumented ACT service requested. Command: %08X", command);
|
||||
mem.write32(messagePointer + 4, Result::Success);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -9,10 +9,15 @@ namespace APTCommands {
|
|||
GetLockHandle = 0x00010040,
|
||||
Initialize = 0x00020080,
|
||||
Enable = 0x00030040,
|
||||
GetAppletInfo = 0x00060040,
|
||||
IsRegistered = 0x00090040,
|
||||
InquireNotification = 0x000B0040,
|
||||
SendParameter = 0x000C0104,
|
||||
ReceiveParameter = 0x000D0080,
|
||||
GlanceParameter = 0x000E0080,
|
||||
PreloadLibraryApplet = 0x00160040,
|
||||
PrepareToStartLibraryApplet = 0x00180040,
|
||||
StartLibraryApplet = 0x001E0084,
|
||||
ReplySleepQuery = 0x003E0080,
|
||||
NotifyToWait = 0x00430040,
|
||||
GetSharedFont = 0x00440000,
|
||||
|
@ -60,6 +65,8 @@ void APTService::reset() {
|
|||
lockHandle = std::nullopt;
|
||||
notificationEvent = std::nullopt;
|
||||
resumeEvent = std::nullopt;
|
||||
|
||||
appletManager.reset();
|
||||
}
|
||||
|
||||
void APTService::handleSyncRequest(u32 messagePointer) {
|
||||
|
@ -69,18 +76,22 @@ void APTService::handleSyncRequest(u32 messagePointer) {
|
|||
case APTCommands::CheckNew3DS: checkNew3DS(messagePointer); break;
|
||||
case APTCommands::CheckNew3DSApp: checkNew3DSApp(messagePointer); break;
|
||||
case APTCommands::Enable: enable(messagePointer); break;
|
||||
case APTCommands::GetAppletInfo: getAppletInfo(messagePointer); break;
|
||||
case APTCommands::GetSharedFont: getSharedFont(messagePointer); break;
|
||||
case APTCommands::Initialize: initialize(messagePointer); break;
|
||||
case APTCommands::InquireNotification: [[likely]] inquireNotification(messagePointer); break;
|
||||
case APTCommands::IsRegistered: isRegistered(messagePointer); break;
|
||||
case APTCommands::GetApplicationCpuTimeLimit: getApplicationCpuTimeLimit(messagePointer); break;
|
||||
case APTCommands::GetLockHandle: getLockHandle(messagePointer); break;
|
||||
case APTCommands::GetWirelessRebootInfo: getWirelessRebootInfo(messagePointer); break;
|
||||
case APTCommands::GlanceParameter: glanceParameter(messagePointer); break;
|
||||
case APTCommands::NotifyToWait: notifyToWait(messagePointer); break;
|
||||
case APTCommands::PreloadLibraryApplet: preloadLibraryApplet(messagePointer); break;
|
||||
case APTCommands::PrepareToStartLibraryApplet: prepareToStartLibraryApplet(messagePointer); break;
|
||||
case APTCommands::ReceiveParameter: [[likely]] receiveParameter(messagePointer); break;
|
||||
case APTCommands::ReplySleepQuery: replySleepQuery(messagePointer); break;
|
||||
case APTCommands::SetApplicationCpuTimeLimit: setApplicationCpuTimeLimit(messagePointer); break;
|
||||
case APTCommands::SendParameter: sendParameter(messagePointer); break;
|
||||
case APTCommands::SetScreencapPostPermission: setScreencapPostPermission(messagePointer); break;
|
||||
case APTCommands::TheSmashBrosFunction: theSmashBrosFunction(messagePointer); break;
|
||||
default:
|
||||
|
@ -116,9 +127,38 @@ void APTService::appletUtility(u32 messagePointer) {
|
|||
}
|
||||
}
|
||||
|
||||
void APTService::getAppletInfo(u32 messagePointer) {
|
||||
const u32 appID = mem.read32(messagePointer + 4);
|
||||
Helpers::warn("APT::GetAppletInfo (appID = %X)\n", appID);
|
||||
|
||||
mem.write32(messagePointer, IPC::responseHeader(0x06, 7, 0));
|
||||
mem.write32(messagePointer + 4, Result::Success);
|
||||
|
||||
mem.write8(messagePointer + 20, 1); // 1 = registered
|
||||
mem.write8(messagePointer + 24, 1); // 1 = loaded
|
||||
// TODO: The rest of this
|
||||
}
|
||||
|
||||
void APTService::isRegistered(u32 messagePointer) {
|
||||
const u32 appID = mem.read32(messagePointer + 4);
|
||||
Helpers::warn("APT::IsRegistered (appID = %X)", appID);
|
||||
|
||||
mem.write32(messagePointer, IPC::responseHeader(0x09, 2, 0));
|
||||
mem.write32(messagePointer + 4, Result::Success);
|
||||
mem.write8(messagePointer + 8, 1); // Return that the app is always registered. This might break with home menu?
|
||||
}
|
||||
|
||||
void APTService::preloadLibraryApplet(u32 messagePointer) {
|
||||
const u32 appID = mem.read32(messagePointer + 4);
|
||||
log("APT::PreloadLibraryApplet (app ID = %d) (stubbed)\n", appID);
|
||||
log("APT::PreloadLibraryApplet (app ID = %X) (stubbed)\n", appID);
|
||||
|
||||
mem.write32(messagePointer, IPC::responseHeader(0x16, 1, 0));
|
||||
mem.write32(messagePointer + 4, Result::Success);
|
||||
}
|
||||
|
||||
void APTService::prepareToStartLibraryApplet(u32 messagePointer) {
|
||||
const u32 appID = mem.read32(messagePointer + 4);
|
||||
log("APT::PrepareToStartLibraryApplet (app ID = %X) (stubbed)\n", appID);
|
||||
|
||||
mem.write32(messagePointer, IPC::responseHeader(0x16, 1, 0));
|
||||
mem.write32(messagePointer + 4, Result::Success);
|
||||
|
@ -193,6 +233,35 @@ void APTService::notifyToWait(u32 messagePointer) {
|
|||
mem.write32(messagePointer + 4, Result::Success);
|
||||
}
|
||||
|
||||
void APTService::sendParameter(u32 messagePointer) {
|
||||
const u32 sourceAppID = mem.read32(messagePointer + 4);
|
||||
const u32 destAppID = mem.read32(messagePointer + 8);
|
||||
const u32 cmd = mem.read32(messagePointer + 12);
|
||||
const u32 paramSize = mem.read32(messagePointer + 16);
|
||||
|
||||
const u32 parameterHandle = mem.read32(messagePointer + 24); // What dis?
|
||||
const u32 parameterPointer = mem.read32(messagePointer + 32);
|
||||
log("APT::SendParameter (source app = %X, dest app = %X, cmd = %X, size = %X) (Stubbed)", sourceAppID, destAppID, cmd, paramSize);
|
||||
|
||||
mem.write32(messagePointer, IPC::responseHeader(0x0C, 1, 0));
|
||||
mem.write32(messagePointer + 4, Result::Success);
|
||||
|
||||
if (sourceAppID != Applets::AppletIDs::Application) {
|
||||
Helpers::warn("APT::SendParameter: Unimplemented source applet ID");
|
||||
}
|
||||
|
||||
Applets::AppletBase* destApplet = appletManager.getApplet(destAppID);
|
||||
if (destApplet == nullptr) {
|
||||
Helpers::warn("APT::SendParameter: Unimplemented dest applet ID");
|
||||
} else {
|
||||
auto result = destApplet->receiveParameter();
|
||||
}
|
||||
|
||||
if (resumeEvent.has_value()) {
|
||||
kernel.signalEvent(resumeEvent.value());
|
||||
}
|
||||
}
|
||||
|
||||
void APTService::receiveParameter(u32 messagePointer) {
|
||||
const u32 app = mem.read32(messagePointer + 4);
|
||||
const u32 size = mem.read32(messagePointer + 8);
|
||||
|
|
|
@ -18,6 +18,9 @@ namespace FRDCommands {
|
|||
GetMyScreenName = 0x00090000,
|
||||
GetMyMii = 0x000A0000,
|
||||
GetFriendKeyList = 0x00110080,
|
||||
GetFriendPresence = 0x00120042,
|
||||
GetFriendProfile = 0x00150042,
|
||||
GetFriendAttributeFlags = 0x00170042,
|
||||
UpdateGameModeDescription = 0x001D0002,
|
||||
};
|
||||
}
|
||||
|
@ -28,7 +31,10 @@ void FRDService::handleSyncRequest(u32 messagePointer) {
|
|||
const u32 command = mem.read32(messagePointer);
|
||||
switch (command) {
|
||||
case FRDCommands::AttachToEventNotification: attachToEventNotification(messagePointer); break;
|
||||
case FRDCommands::GetFriendAttributeFlags: getFriendAttributeFlags(messagePointer); break;
|
||||
case FRDCommands::GetFriendKeyList: getFriendKeyList(messagePointer); break;
|
||||
case FRDCommands::GetFriendPresence: getFriendPresence(messagePointer); break;
|
||||
case FRDCommands::GetFriendProfile: getFriendProfile(messagePointer); break;
|
||||
case FRDCommands::GetMyFriendKey: getMyFriendKey(messagePointer); break;
|
||||
case FRDCommands::GetMyMii: getMyMii(messagePointer); break;
|
||||
case FRDCommands::GetMyPresence: getMyPresence(messagePointer); break;
|
||||
|
@ -83,6 +89,41 @@ void FRDService::getFriendKeyList(u32 messagePointer) {
|
|||
}
|
||||
}
|
||||
|
||||
void FRDService::getFriendProfile(u32 messagePointer) {
|
||||
log("FRD::GetFriendProfile\n");
|
||||
|
||||
const u32 count = mem.read32(messagePointer + 4);
|
||||
const u32 friendKeyList = mem.read32(messagePointer + 12); // Pointer to list of friend keys
|
||||
const u32 profile = mem.read32(messagePointer + 0x104); // Pointer to friend profile where we'll write info to
|
||||
|
||||
mem.write32(messagePointer, IPC::responseHeader(0x15, 1, 2));
|
||||
mem.write32(messagePointer + 4, Result::Success);
|
||||
|
||||
// Clear all profiles
|
||||
for (u32 i = 0; i < count; i++) {
|
||||
const u32 pointer = profile + (i * sizeof(Profile));
|
||||
for (u32 j = 0; j < sizeof(Profile); j++) {
|
||||
mem.write8(pointer + j, 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void FRDService::getFriendAttributeFlags(u32 messagePointer) {
|
||||
log("FRD::GetFriendAttributeFlags\n");
|
||||
|
||||
const u32 count = mem.read32(messagePointer + 4);
|
||||
const u32 friendKeyList = mem.read32(messagePointer + 12); // Pointer to list of friend keys
|
||||
const u32 profile = mem.read32(messagePointer + 0x104); // Pointer to friend profile where we'll write info to
|
||||
|
||||
mem.write32(messagePointer, IPC::responseHeader(0x17, 1, 2));
|
||||
mem.write32(messagePointer + 4, Result::Success);
|
||||
|
||||
// Clear flags
|
||||
for (u32 i = 0; i < count; i++) {
|
||||
mem.write8(profile + i, 0);
|
||||
}
|
||||
}
|
||||
|
||||
void FRDService::getMyPresence(u32 messagePointer) {
|
||||
static constexpr u32 presenceSize = 0x12C; // A presence seems to be 12C bytes of data, not sure what it contains
|
||||
log("FRD::GetMyPresence\n");
|
||||
|
@ -96,6 +137,14 @@ void FRDService::getMyPresence(u32 messagePointer) {
|
|||
mem.write32(messagePointer + 4, Result::Success);
|
||||
}
|
||||
|
||||
void FRDService::getFriendPresence(u32 messagePointer) {
|
||||
Helpers::warn("FRD::GetFriendPresence (stubbed)");
|
||||
|
||||
// TODO: Implement and document this,
|
||||
mem.write32(messagePointer, IPC::responseHeader(0x12, 1, 0));
|
||||
mem.write32(messagePointer + 4, Result::Success);
|
||||
}
|
||||
|
||||
void FRDService::getMyProfile(u32 messagePointer) {
|
||||
mem.write32(messagePointer, IPC::responseHeader(0x7, 3, 0)); // Not sure if the header here has the correct # of responses?
|
||||
mem.write32(messagePointer + 4, Result::Success);
|
||||
|
|
|
@ -26,13 +26,19 @@ namespace FSCommands {
|
|||
GetFreeBytes = 0x08120080,
|
||||
IsSdmcDetected = 0x08170000,
|
||||
IsSdmcWritable = 0x08180000,
|
||||
AbnegateAccessRight = 0x08400040,
|
||||
GetFormatInfo = 0x084500C2,
|
||||
GetArchiveResource = 0x08490040,
|
||||
FormatSaveData = 0x084C0242,
|
||||
CreateExtSaveData = 0x08510242,
|
||||
DeleteExtSaveData = 0x08520100,
|
||||
SetArchivePriority = 0x085A00C0,
|
||||
InitializeWithSdkVersion = 0x08610042,
|
||||
SetPriority = 0x08620040,
|
||||
GetPriority = 0x08630000
|
||||
GetPriority = 0x08630000,
|
||||
SetThisSaveDataSecureValue = 0x086E00C0,
|
||||
GetThisSaveDataSecureValue = 0x086F0040,
|
||||
TheGameboyVCFunction = 0x08750180,
|
||||
};
|
||||
}
|
||||
|
||||
|
@ -71,6 +77,8 @@ ArchiveBase* FSService::getArchiveFromID(u32 id, const FSPath& archivePath) {
|
|||
switch (id) {
|
||||
case ArchiveID::SelfNCCH: return &selfNcch;
|
||||
case ArchiveID::SaveData: return &saveData;
|
||||
case ArchiveID::UserSaveData2: return &userSaveData2;
|
||||
|
||||
case ArchiveID::ExtSaveData:
|
||||
return &extSaveData_sdmc;
|
||||
|
||||
|
@ -155,9 +163,11 @@ void FSService::handleSyncRequest(u32 messagePointer) {
|
|||
case FSCommands::DeleteFile: deleteFile(messagePointer); break;
|
||||
case FSCommands::FormatSaveData: formatSaveData(messagePointer); break;
|
||||
case FSCommands::FormatThisUserSaveData: formatThisUserSaveData(messagePointer); break;
|
||||
case FSCommands::GetArchiveResource: getArchiveResource(messagePointer); break;
|
||||
case FSCommands::GetFreeBytes: getFreeBytes(messagePointer); break;
|
||||
case FSCommands::GetFormatInfo: getFormatInfo(messagePointer); break;
|
||||
case FSCommands::GetPriority: getPriority(messagePointer); break;
|
||||
case FSCommands::GetThisSaveDataSecureValue: getThisSaveDataSecureValue(messagePointer); break;
|
||||
case FSCommands::Initialize: initialize(messagePointer); break;
|
||||
case FSCommands::InitializeWithSdkVersion: initializeWithSdkVersion(messagePointer); break;
|
||||
case FSCommands::IsSdmcDetected: isSdmcDetected(messagePointer); break;
|
||||
|
@ -166,7 +176,11 @@ void FSService::handleSyncRequest(u32 messagePointer) {
|
|||
case FSCommands::OpenDirectory: openDirectory(messagePointer); break;
|
||||
case FSCommands::OpenFile: [[likely]] openFile(messagePointer); break;
|
||||
case FSCommands::OpenFileDirectly: [[likely]] openFileDirectly(messagePointer); break;
|
||||
case FSCommands::SetArchivePriority: setArchivePriority(messagePointer); break;
|
||||
case FSCommands::SetPriority: setPriority(messagePointer); break;
|
||||
case FSCommands::SetThisSaveDataSecureValue: setThisSaveDataSecureValue(messagePointer); break;
|
||||
case FSCommands::AbnegateAccessRight: abnegateAccessRight(messagePointer); break;
|
||||
case FSCommands::TheGameboyVCFunction: theGameboyVCFunction(messagePointer); break;
|
||||
default: Helpers::panic("FS service requested. Command: %08X\n", command);
|
||||
}
|
||||
}
|
||||
|
@ -575,6 +589,36 @@ void FSService::getPriority(u32 messagePointer) {
|
|||
mem.write32(messagePointer + 8, priority);
|
||||
}
|
||||
|
||||
void FSService::getArchiveResource(u32 messagePointer) {
|
||||
const u32 mediaType = mem.read32(messagePointer + 4);
|
||||
log("FS::GetArchiveResource (media type = %d) (stubbed)\n");
|
||||
|
||||
// For the time being, return the same stubbed archive resource for every media type
|
||||
static constexpr ArchiveResource resource = {
|
||||
.sectorSize = 512,
|
||||
.clusterSize = 16_KB,
|
||||
.partitionCapacityInClusters = 0x80000, // 0x80000 * 16 KB = 8GB
|
||||
.freeSpaceInClusters = 0x80000, // Same here
|
||||
};
|
||||
|
||||
mem.write32(messagePointer, IPC::responseHeader(0x849, 5, 0));
|
||||
mem.write32(messagePointer + 4, Result::Success);
|
||||
|
||||
mem.write32(messagePointer + 8, resource.sectorSize);
|
||||
mem.write32(messagePointer + 12, resource.clusterSize);
|
||||
mem.write32(messagePointer + 16, resource.partitionCapacityInClusters);
|
||||
mem.write32(messagePointer + 20, resource.freeSpaceInClusters);
|
||||
}
|
||||
|
||||
void FSService::setArchivePriority(u32 messagePointer) {
|
||||
Handle archive = mem.read64(messagePointer + 4);
|
||||
const u32 value = mem.read32(messagePointer + 12);
|
||||
log("FS::SetArchivePriority (priority = %d, archive handle = %X)\n", value, handle);
|
||||
|
||||
mem.write32(messagePointer, IPC::responseHeader(0x85A, 1, 0));
|
||||
mem.write32(messagePointer + 4, Result::Success);
|
||||
}
|
||||
|
||||
void FSService::setPriority(u32 messagePointer) {
|
||||
const u32 value = mem.read32(messagePointer + 4);
|
||||
log("FS::SetPriority (priority = %d)\n", value);
|
||||
|
@ -584,6 +628,45 @@ void FSService::setPriority(u32 messagePointer) {
|
|||
priority = value;
|
||||
}
|
||||
|
||||
void FSService::abnegateAccessRight(u32 messagePointer) {
|
||||
const u32 right = mem.read32(messagePointer + 4);
|
||||
log("FS::AbnegateAccessRight (right = %d)\n", right);
|
||||
|
||||
if (right >= 0x38) {
|
||||
Helpers::warn("FS::AbnegateAccessRight: Invalid access right");
|
||||
}
|
||||
|
||||
mem.write32(messagePointer, IPC::responseHeader(0x840, 1, 0));
|
||||
mem.write32(messagePointer + 4, Result::Success);
|
||||
}
|
||||
|
||||
void FSService::getThisSaveDataSecureValue(u32 messagePointer) {
|
||||
Helpers::warn("Unimplemented FS::GetThisSaveDataSecureValue");
|
||||
|
||||
mem.write32(messagePointer, IPC::responseHeader(0x86F, 1, 0));
|
||||
mem.write32(messagePointer + 4, Result::Success);
|
||||
}
|
||||
|
||||
void FSService::setThisSaveDataSecureValue(u32 messagePointer) {
|
||||
const u64 value = mem.read32(messagePointer + 4);
|
||||
const u32 slot = mem.read32(messagePointer + 12);
|
||||
const u32 id = mem.read32(messagePointer + 16);
|
||||
const u8 variation = mem.read8(messagePointer + 20);
|
||||
|
||||
// TODO: Actually do something with this.
|
||||
Helpers::warn("Unimplemented FS::SetThisSaveDataSecureValue");
|
||||
|
||||
mem.write32(messagePointer, IPC::responseHeader(0x86E, 1, 0));
|
||||
mem.write32(messagePointer + 4, Result::Success);
|
||||
}
|
||||
|
||||
void FSService::theGameboyVCFunction(u32 messagePointer) {
|
||||
Helpers::warn("Unimplemented FS: function: 0x08750180");
|
||||
|
||||
mem.write32(messagePointer, IPC::responseHeader(0x875, 1, 0));
|
||||
mem.write32(messagePointer + 4, Result::Success);
|
||||
}
|
||||
|
||||
void FSService::isSdmcDetected(u32 messagePointer) {
|
||||
log("FS::IsSdmcDetected\n");
|
||||
|
||||
|
|
|
@ -15,6 +15,8 @@ namespace ServiceCommands {
|
|||
FlushDataCache = 0x00080082,
|
||||
SetLCDForceBlack = 0x000B0040,
|
||||
TriggerCmdReqQueue = 0x000C0000,
|
||||
ImportDisplayCaptureInfo = 0x00180000,
|
||||
SaveVramSysArea = 0x00190000,
|
||||
SetInternalPriorities = 0x001E0080,
|
||||
StoreDataCache = 0x001F0082
|
||||
};
|
||||
|
@ -42,15 +44,17 @@ void GPUService::reset() {
|
|||
void GPUService::handleSyncRequest(u32 messagePointer) {
|
||||
const u32 command = mem.read32(messagePointer);
|
||||
switch (command) {
|
||||
case ServiceCommands::TriggerCmdReqQueue: [[likely]] triggerCmdReqQueue(messagePointer); break;
|
||||
case ServiceCommands::AcquireRight: acquireRight(messagePointer); break;
|
||||
case ServiceCommands::FlushDataCache: flushDataCache(messagePointer); break;
|
||||
case ServiceCommands::ImportDisplayCaptureInfo: importDisplayCaptureInfo(messagePointer); break;
|
||||
case ServiceCommands::RegisterInterruptRelayQueue: registerInterruptRelayQueue(messagePointer); break;
|
||||
case ServiceCommands::SaveVramSysArea: saveVramSysArea(messagePointer); break;
|
||||
case ServiceCommands::SetAxiConfigQoSMode: setAxiConfigQoSMode(messagePointer); break;
|
||||
case ServiceCommands::SetBufferSwap: setBufferSwap(messagePointer); break;
|
||||
case ServiceCommands::SetInternalPriorities: setInternalPriorities(messagePointer); break;
|
||||
case ServiceCommands::SetLCDForceBlack: setLCDForceBlack(messagePointer); break;
|
||||
case ServiceCommands::StoreDataCache: storeDataCache(messagePointer); break;
|
||||
case ServiceCommands::TriggerCmdReqQueue: [[likely]] triggerCmdReqQueue(messagePointer); break;
|
||||
case ServiceCommands::WriteHwRegs: writeHwRegs(messagePointer); break;
|
||||
case ServiceCommands::WriteHwRegsWithMask: writeHwRegsWithMask(messagePointer); break;
|
||||
default: Helpers::panic("GPU service requested. Command: %08X\n", command);
|
||||
|
@ -456,3 +460,20 @@ void GPUService::triggerTextureCopy(u32* cmd) {
|
|||
// NSMB2 relies on this
|
||||
requestInterrupt(GPUInterrupt::PPF);
|
||||
}
|
||||
|
||||
// Used when transitioning from the app to an OS applet, such as software keyboard, mii maker, mii selector, etc
|
||||
// Stubbed until we decide to support LLE applets
|
||||
void GPUService::saveVramSysArea(u32 messagePointer) {
|
||||
Helpers::warn("GSP::GPU::SaveVramSysArea (stubbed)");
|
||||
|
||||
mem.write32(messagePointer, IPC::responseHeader(0x19, 1, 0));
|
||||
mem.write32(messagePointer + 4, Result::Success);
|
||||
}
|
||||
|
||||
// Used in similar fashion to the SaveVramSysArea function
|
||||
void GPUService::importDisplayCaptureInfo(u32 messagePointer) {
|
||||
Helpers::warn("GSP::GPU::ImportDisplayCaptureInfo (stubbed)");
|
||||
|
||||
mem.write32(messagePointer, IPC::responseHeader(0x18, 9, 0));
|
||||
mem.write32(messagePointer + 4, Result::Success);
|
||||
}
|
|
@ -1,14 +1,19 @@
|
|||
#include "services/mic.hpp"
|
||||
#include "ipc.hpp"
|
||||
#include "kernel/kernel.hpp"
|
||||
|
||||
namespace MICCommands {
|
||||
enum : u32 {
|
||||
MapSharedMem = 0x00010042,
|
||||
UnmapSharedMem = 0x00020000,
|
||||
StartSampling = 0x00030140,
|
||||
StopSampling = 0x00050000,
|
||||
IsSampling = 0x00060000,
|
||||
GetEventHandle = 0x00070000,
|
||||
SetGain = 0x00080040,
|
||||
GetGain = 0x00090000,
|
||||
SetPower = 0x000A0040,
|
||||
GetPower = 0x000B0000,
|
||||
SetIirFilter = 0x000C0042,
|
||||
SetClamp = 0x000D0040,
|
||||
CaptainToadFunction = 0x00100040,
|
||||
|
@ -18,14 +23,19 @@ namespace MICCommands {
|
|||
void MICService::reset() {
|
||||
micEnabled = false;
|
||||
shouldClamp = false;
|
||||
isSampling = false;
|
||||
currentlySampling = false;
|
||||
gain = 0;
|
||||
|
||||
eventHandle = std::nullopt;
|
||||
}
|
||||
|
||||
void MICService::handleSyncRequest(u32 messagePointer) {
|
||||
const u32 command = mem.read32(messagePointer);
|
||||
switch (command) {
|
||||
case MICCommands::GetEventHandle: getEventHandle(messagePointer); break;
|
||||
case MICCommands::GetGain: getGain(messagePointer); break;
|
||||
case MICCommands::GetPower: getPower(messagePointer); break;
|
||||
case MICCommands::IsSampling: isSampling(messagePointer); break;
|
||||
case MICCommands::MapSharedMem: mapSharedMem(messagePointer); break;
|
||||
case MICCommands::SetClamp: setClamp(messagePointer); break;
|
||||
case MICCommands::SetGain: setGain(messagePointer); break;
|
||||
|
@ -33,6 +43,7 @@ void MICService::handleSyncRequest(u32 messagePointer) {
|
|||
case MICCommands::SetPower: setPower(messagePointer); break;
|
||||
case MICCommands::StartSampling: startSampling(messagePointer); break;
|
||||
case MICCommands::StopSampling: stopSampling(messagePointer); break;
|
||||
case MICCommands::UnmapSharedMem: unmapSharedMem(messagePointer); break;
|
||||
case MICCommands::CaptainToadFunction: theCaptainToadFunction(messagePointer); break;
|
||||
default: Helpers::panic("MIC service requested. Command: %08X\n", command);
|
||||
}
|
||||
|
@ -47,6 +58,27 @@ void MICService::mapSharedMem(u32 messagePointer) {
|
|||
mem.write32(messagePointer + 4, Result::Success);
|
||||
}
|
||||
|
||||
void MICService::unmapSharedMem(u32 messagePointer) {
|
||||
log("MIC::UnmapSharedMem (stubbed)\n");
|
||||
|
||||
mem.write32(messagePointer, IPC::responseHeader(0x2, 1, 0));
|
||||
mem.write32(messagePointer + 4, Result::Success);
|
||||
}
|
||||
|
||||
void MICService::getEventHandle(u32 messagePointer) {
|
||||
log("MIC::GetEventHandle\n");
|
||||
Helpers::warn("Acquire MIC event handle");
|
||||
|
||||
if (!eventHandle.has_value()) {
|
||||
eventHandle = kernel.makeEvent(ResetType::OneShot);
|
||||
}
|
||||
|
||||
mem.write32(messagePointer, IPC::responseHeader(0x7, 1, 2));
|
||||
mem.write32(messagePointer + 4, Result::Success);
|
||||
// TODO: Translation descriptor
|
||||
mem.write32(messagePointer + 12, eventHandle.value());
|
||||
}
|
||||
|
||||
void MICService::getGain(u32 messagePointer) {
|
||||
log("MIC::GetGain\n");
|
||||
mem.write32(messagePointer, IPC::responseHeader(0x9, 2, 0));
|
||||
|
@ -71,6 +103,14 @@ void MICService::setPower(u32 messagePointer) {
|
|||
mem.write32(messagePointer + 4, Result::Success);
|
||||
}
|
||||
|
||||
void MICService::getPower(u32 messagePointer) {
|
||||
log("MIC::GetPower\n");
|
||||
|
||||
mem.write32(messagePointer, IPC::responseHeader(0xB, 2, 0));
|
||||
mem.write32(messagePointer + 4, Result::Success);
|
||||
mem.write8(messagePointer + 8, micEnabled ? 1 : 0);
|
||||
}
|
||||
|
||||
void MICService::setClamp(u32 messagePointer) {
|
||||
u8 val = mem.read8(messagePointer + 4);
|
||||
log("MIC::SetClamp (value = %d)\n", val);
|
||||
|
@ -91,19 +131,27 @@ void MICService::startSampling(u32 messagePointer) {
|
|||
encoding, sampleRate, offset, dataSize, loop ? "yes" : "no"
|
||||
);
|
||||
|
||||
isSampling = true;
|
||||
currentlySampling = true;
|
||||
mem.write32(messagePointer, IPC::responseHeader(0x3, 1, 0));
|
||||
mem.write32(messagePointer + 4, Result::Success);
|
||||
}
|
||||
|
||||
void MICService::stopSampling(u32 messagePointer) {
|
||||
log("MIC::StopSampling\n");
|
||||
isSampling = false;
|
||||
currentlySampling = false;
|
||||
|
||||
mem.write32(messagePointer, IPC::responseHeader(0x5, 1, 0));
|
||||
mem.write32(messagePointer + 4, Result::Success);
|
||||
}
|
||||
|
||||
void MICService::isSampling(u32 messagePointer) {
|
||||
log("MIC::IsSampling");
|
||||
|
||||
mem.write32(messagePointer, IPC::responseHeader(0x6, 2, 0));
|
||||
mem.write32(messagePointer + 4, Result::Success);
|
||||
mem.write8(messagePointer + 8, currentlySampling ? 1 : 0);
|
||||
}
|
||||
|
||||
void MICService::setIirFilter(u32 messagePointer) {
|
||||
const u32 size = mem.read32(messagePointer + 4);
|
||||
const u32 pointer = mem.read32(messagePointer + 12);
|
||||
|
|
|
@ -5,8 +5,10 @@
|
|||
namespace NFCCommands {
|
||||
enum : u32 {
|
||||
Initialize = 0x00010040,
|
||||
Shutdown = 0x00020040,
|
||||
StartCommunication = 0x00030000,
|
||||
StopCommunication = 0x00040000,
|
||||
StartTagScanning = 0x00050040,
|
||||
GetTagInRangeEvent = 0x000B0000,
|
||||
GetTagOutOfRangeEvent = 0x000C0000,
|
||||
GetTagState = 0x000D0000,
|
||||
|
@ -32,7 +34,9 @@ void NFCService::handleSyncRequest(u32 messagePointer) {
|
|||
case NFCCommands::GetTagInRangeEvent: getTagInRangeEvent(messagePointer); break;
|
||||
case NFCCommands::GetTagOutOfRangeEvent: getTagOutOfRangeEvent(messagePointer); break;
|
||||
case NFCCommands::GetTagState: getTagState(messagePointer); break;
|
||||
case NFCCommands::Shutdown: shutdown(messagePointer); break;
|
||||
case NFCCommands::StartCommunication: startCommunication(messagePointer); break;
|
||||
case NFCCommands::StartTagScanning: startTagScanning(messagePointer); break;
|
||||
case NFCCommands::StopCommunication: stopCommunication(messagePointer); break;
|
||||
default: Helpers::panic("NFC service requested. Command: %08X\n", command);
|
||||
}
|
||||
|
@ -50,6 +54,16 @@ void NFCService::initialize(u32 messagePointer) {
|
|||
mem.write32(messagePointer + 4, Result::Success);
|
||||
}
|
||||
|
||||
void NFCService::shutdown(u32 messagePointer) {
|
||||
log("MFC::Shutdown");
|
||||
const u8 mode = mem.read8(messagePointer + 4);
|
||||
|
||||
Helpers::warn("NFC::Shutdown: Unimplemented mode: %d", mode);
|
||||
|
||||
mem.write32(messagePointer, IPC::responseHeader(0x2, 1, 0));
|
||||
mem.write32(messagePointer + 4, Result::Success);
|
||||
}
|
||||
|
||||
/*
|
||||
The NFC service provides userland with 2 events. One that is signaled when an NFC tag gets in range,
|
||||
And one that is signaled when it gets out of range. Userland can have a thread sleep on this so it will be alerted
|
||||
|
@ -114,6 +128,14 @@ void NFCService::startCommunication(u32 messagePointer) {
|
|||
mem.write32(messagePointer + 4, Result::Success);
|
||||
}
|
||||
|
||||
void NFCService::startTagScanning(u32 messagePointer) {
|
||||
log("NFC::StartTagScanning\n");
|
||||
tagStatus = TagStatus::Scanning;
|
||||
|
||||
mem.write32(messagePointer, IPC::responseHeader(0x5, 1, 0));
|
||||
mem.write32(messagePointer + 4, Result::Success);
|
||||
}
|
||||
|
||||
void NFCService::stopCommunication(u32 messagePointer) {
|
||||
log("NFC::StopCommunication\n");
|
||||
adapterStatus = Old3DSAdapterStatus::InitializationComplete;
|
||||
|
|
|
@ -8,7 +8,7 @@
|
|||
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),
|
||||
dlp_srvr(mem), dsp(mem, kernel), 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), mcu_hwc(mem, config), mic(mem), nfc(mem, kernel), nim(mem), ndm(mem),
|
||||
gsp_gpu(mem, gpu, kernel, currentPID), gsp_lcd(mem), ldr(mem), mcu_hwc(mem, config), mic(mem, kernel), nfc(mem, kernel), nim(mem), ndm(mem),
|
||||
news_u(mem), ptm(mem, config), soc(mem), ssl(mem), y2r(mem, kernel) {}
|
||||
|
||||
static constexpr int MAX_NOTIFICATION_COUNT = 16;
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
#include "services/y2r.hpp"
|
||||
|
||||
#include "ipc.hpp"
|
||||
#include "kernel.hpp"
|
||||
|
||||
|
@ -6,8 +7,10 @@ namespace Y2RCommands {
|
|||
enum : u32 {
|
||||
SetInputFormat = 0x00010040,
|
||||
SetOutputFormat = 0x00030040,
|
||||
GetOutputFormat = 0x00040000,
|
||||
SetRotation = 0x00050040,
|
||||
SetBlockAlignment = 0x00070040,
|
||||
GetBlockAlignment = 0x00080000,
|
||||
SetSpacialDithering = 0x00090040,
|
||||
SetTemporalDithering = 0x000B0040,
|
||||
SetTransferEndInterrupt = 0x000D0040,
|
||||
|
@ -17,7 +20,9 @@ namespace Y2RCommands {
|
|||
SetSendingV = 0x00120102,
|
||||
SetReceiving = 0x00180102,
|
||||
SetInputLineWidth = 0x001A0040,
|
||||
GetInputLineWidth = 0x001B0000,
|
||||
SetInputLines = 0x001C0040,
|
||||
GetInputLines = 0x001D0000,
|
||||
SetStandardCoeff = 0x00200040,
|
||||
SetAlpha = 0x00220040,
|
||||
StartConversion = 0x00260000,
|
||||
|
@ -26,7 +31,7 @@ namespace Y2RCommands {
|
|||
SetPackageParameter = 0x002901C0,
|
||||
PingProcess = 0x002A0000,
|
||||
DriverInitialize = 0x002B0000,
|
||||
DriverFinalize = 0x002C0000
|
||||
DriverFinalize = 0x002C0000,
|
||||
};
|
||||
}
|
||||
|
||||
|
@ -52,6 +57,10 @@ void Y2RService::handleSyncRequest(u32 messagePointer) {
|
|||
switch (command) {
|
||||
case Y2RCommands::DriverInitialize: driverInitialize(messagePointer); break;
|
||||
case Y2RCommands::DriverFinalize: driverFinalize(messagePointer); break;
|
||||
case Y2RCommands::GetBlockAlignment: getBlockAlignment(messagePointer); break;
|
||||
case Y2RCommands::GetInputLines: getInputLines(messagePointer); break;
|
||||
case Y2RCommands::GetInputLineWidth: getInputLineWidth(messagePointer); break;
|
||||
case Y2RCommands::GetOutputFormat: getOutputFormat(messagePointer); break;
|
||||
case Y2RCommands::GetTransferEndEvent: getTransferEndEvent(messagePointer); break;
|
||||
case Y2RCommands::IsBusyConversion: isBusyConversion(messagePointer); break;
|
||||
case Y2RCommands::PingProcess: pingProcess(messagePointer); break;
|
||||
|
@ -81,7 +90,7 @@ void Y2RService::pingProcess(u32 messagePointer) {
|
|||
log("Y2R::PingProcess\n");
|
||||
mem.write32(messagePointer, IPC::responseHeader(0x2A, 2, 0));
|
||||
mem.write32(messagePointer + 4, Result::Success);
|
||||
mem.write32(messagePointer + 8, 0); // Connected number
|
||||
mem.write32(messagePointer + 8, 0); // Connected number
|
||||
}
|
||||
|
||||
void Y2RService::driverInitialize(u32 messagePointer) {
|
||||
|
@ -98,8 +107,9 @@ void Y2RService::driverFinalize(u32 messagePointer) {
|
|||
|
||||
void Y2RService::getTransferEndEvent(u32 messagePointer) {
|
||||
log("Y2R::GetTransferEndEvent\n");
|
||||
if (!transferEndEvent.has_value())
|
||||
if (!transferEndEvent.has_value()) {
|
||||
transferEndEvent = kernel.makeEvent(ResetType::OneShot);
|
||||
}
|
||||
|
||||
mem.write32(messagePointer, IPC::responseHeader(0xF, 1, 2));
|
||||
mem.write32(messagePointer + 4, Result::Success);
|
||||
|
@ -150,6 +160,14 @@ void Y2RService::setBlockAlignment(u32 messagePointer) {
|
|||
mem.write32(messagePointer + 4, Result::Success);
|
||||
}
|
||||
|
||||
void Y2RService::getBlockAlignment(u32 messagePointer) {
|
||||
log("Y2R::GetBlockAlignment\n");
|
||||
|
||||
mem.write32(messagePointer, IPC::responseHeader(0x8, 2, 0));
|
||||
mem.write32(messagePointer + 4, Result::Success);
|
||||
mem.write32(messagePointer + 8, static_cast<u32>(alignment));
|
||||
}
|
||||
|
||||
void Y2RService::setInputFormat(u32 messagePointer) {
|
||||
const u32 format = mem.read32(messagePointer + 4);
|
||||
log("Y2R::SetInputFormat (format = %d)\n", format);
|
||||
|
@ -178,6 +196,14 @@ void Y2RService::setOutputFormat(u32 messagePointer) {
|
|||
mem.write32(messagePointer + 4, Result::Success);
|
||||
}
|
||||
|
||||
void Y2RService::getOutputFormat(u32 messagePointer) {
|
||||
log("Y2R::GetOutputFormat\n");
|
||||
|
||||
mem.write32(messagePointer, IPC::responseHeader(0x4, 2, 0));
|
||||
mem.write32(messagePointer + 4, Result::Success);
|
||||
mem.write32(messagePointer + 8, static_cast<u32>(outputFmt));
|
||||
}
|
||||
|
||||
void Y2RService::setPackageParameter(u32 messagePointer) {
|
||||
// Package parameter is 3 words
|
||||
const u32 word1 = mem.read32(messagePointer + 4);
|
||||
|
@ -243,6 +269,13 @@ void Y2RService::setInputLineWidth(u32 messagePointer) {
|
|||
}
|
||||
}
|
||||
|
||||
void Y2RService::getInputLineWidth(u32 messagePointer) {
|
||||
log("Y2R::GetInputLineWidth\n");
|
||||
|
||||
mem.write32(messagePointer, IPC::responseHeader(0x1B, 2, 0));
|
||||
mem.write32(messagePointer + 4, Result::Success);
|
||||
mem.write32(messagePointer + 8, inputLineWidth);
|
||||
}
|
||||
void Y2RService::setInputLines(u32 messagePointer) {
|
||||
const u16 lines = mem.read16(messagePointer + 4);
|
||||
log("Y2R::SetInputLines (lines = %d)\n", lines);
|
||||
|
@ -253,19 +286,30 @@ void Y2RService::setInputLines(u32 messagePointer) {
|
|||
Helpers::panic("Y2R: Invalid input line count");
|
||||
} else {
|
||||
// According to Citra, the Y2R module seems to accidentally skip setting the line # if it's 1024
|
||||
if (lines != 1024)
|
||||
if (lines != 1024) {
|
||||
inputLines = lines;
|
||||
}
|
||||
mem.write32(messagePointer + 4, Result::Success);
|
||||
}
|
||||
}
|
||||
|
||||
void Y2RService::getInputLines(u32 messagePointer) {
|
||||
log("Y2R::GetInputLines\n");
|
||||
|
||||
mem.write32(messagePointer, IPC::responseHeader(0x1D, 2, 0));
|
||||
mem.write32(messagePointer + 4, Result::Success);
|
||||
mem.write32(messagePointer + 8, inputLines);
|
||||
}
|
||||
|
||||
void Y2RService::setStandardCoeff(u32 messagePointer) {
|
||||
const u32 coeff = mem.read32(messagePointer + 4);
|
||||
log("Y2R::SetStandardCoeff (coefficient = %d)\n", coeff);
|
||||
mem.write32(messagePointer, IPC::responseHeader(0x20, 1, 0));
|
||||
|
||||
if (coeff > 3)
|
||||
Helpers::panic("Y2R: Invalid standard coefficient");
|
||||
if (coeff > 3) {
|
||||
Helpers::panic("Y2R: Invalid standard coefficient (coefficient = %d)\n", coeff);
|
||||
}
|
||||
|
||||
else {
|
||||
Helpers::warn("Unimplemented: Y2R standard coefficient");
|
||||
mem.write32(messagePointer + 4, Result::Success);
|
||||
|
@ -316,4 +360,4 @@ void Y2RService::startConversion(u32 messagePointer) {
|
|||
if (transferEndEvent.has_value()) {
|
||||
kernel.signalEvent(transferEndEvent.value());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue