mirror of
https://github.com/wheremyfoodat/Panda3DS.git
synced 2025-07-17 04:21:44 +12:00
metal: initial support
This commit is contained in:
parent
29d9ed7224
commit
f0547d1a71
167 changed files with 28839 additions and 1271 deletions
|
@ -1,4 +1,5 @@
|
|||
#include "services/ac.hpp"
|
||||
|
||||
#include "ipc.hpp"
|
||||
|
||||
namespace ACCommands {
|
||||
|
@ -72,7 +73,7 @@ void ACService::getLastErrorCode(u32 messagePointer) {
|
|||
|
||||
mem.write32(messagePointer, IPC::responseHeader(0x0A, 2, 0));
|
||||
mem.write32(messagePointer + 4, Result::Success);
|
||||
mem.write32(messagePointer + 8, 0); // Hopefully this means no error?
|
||||
mem.write32(messagePointer + 8, 0); // Hopefully this means no error?
|
||||
}
|
||||
|
||||
void ACService::getConnectingInfraPriority(u32 messagePointer) {
|
||||
|
@ -130,10 +131,10 @@ void ACService::registerDisconnectEvent(u32 messagePointer) {
|
|||
const u32 pidHeader = mem.read32(messagePointer + 4);
|
||||
const u32 copyHandleHeader = mem.read32(messagePointer + 12);
|
||||
// Event signaled when disconnecting from AC. TODO: Properly implement it.
|
||||
const Handle eventHandle = mem.read32(messagePointer + 16);
|
||||
const HandleType eventHandle = mem.read32(messagePointer + 16);
|
||||
|
||||
disconnectEvent = eventHandle;
|
||||
|
||||
mem.write32(messagePointer, IPC::responseHeader(0x30, 1, 0));
|
||||
mem.write32(messagePointer + 4, Result::Success);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,10 +1,11 @@
|
|||
#include "services/apt.hpp"
|
||||
#include "ipc.hpp"
|
||||
#include "kernel.hpp"
|
||||
|
||||
#include <algorithm>
|
||||
#include <vector>
|
||||
|
||||
#include "ipc.hpp"
|
||||
#include "kernel.hpp"
|
||||
|
||||
namespace APTCommands {
|
||||
enum : u32 {
|
||||
GetLockHandle = 0x00010040,
|
||||
|
@ -84,8 +85,7 @@ void APTService::appletUtility(u32 messagePointer) {
|
|||
u32 outputSize = mem.read32(messagePointer + 12);
|
||||
u32 inputPointer = mem.read32(messagePointer + 20);
|
||||
|
||||
log("APT::AppletUtility(utility = %d, input size = %x, output size = %x, inputPointer = %08X)\n", utility, inputSize, outputSize,
|
||||
inputPointer);
|
||||
log("APT::AppletUtility(utility = %d, input size = %x, output size = %x, inputPointer = %08X)\n", utility, inputSize, outputSize, inputPointer);
|
||||
|
||||
std::vector<u8> out(outputSize);
|
||||
const u32 outputBuffer = mem.read32(messagePointer + 0x104);
|
||||
|
@ -111,9 +111,9 @@ void APTService::getAppletInfo(u32 messagePointer) {
|
|||
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
|
||||
mem.write8(messagePointer + 20, 1); // 1 = registered
|
||||
mem.write8(messagePointer + 24, 1); // 1 = loaded
|
||||
// TODO: The rest of this
|
||||
}
|
||||
|
||||
void APTService::isRegistered(u32 messagePointer) {
|
||||
|
@ -122,7 +122,7 @@ void APTService::isRegistered(u32 messagePointer) {
|
|||
|
||||
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?
|
||||
mem.write8(messagePointer + 8, 1); // Return that the app is always registered. This might break with home menu?
|
||||
}
|
||||
|
||||
void APTService::preloadLibraryApplet(u32 messagePointer) {
|
||||
|
@ -144,7 +144,7 @@ void APTService::prepareToStartLibraryApplet(u32 messagePointer) {
|
|||
void APTService::startLibraryApplet(u32 messagePointer) {
|
||||
const u32 appID = mem.read32(messagePointer + 4);
|
||||
const u32 bufferSize = mem.read32(messagePointer + 8);
|
||||
const Handle parameters = mem.read32(messagePointer + 16);
|
||||
const HandleType parameters = mem.read32(messagePointer + 16);
|
||||
const u32 buffer = mem.read32(messagePointer + 24);
|
||||
log("APT::StartLibraryApplet (app ID = %X)\n", appID);
|
||||
|
||||
|
@ -178,7 +178,7 @@ void APTService::checkNew3DS(u32 messagePointer) {
|
|||
log("APT::CheckNew3DS\n");
|
||||
mem.write32(messagePointer, IPC::responseHeader(0x102, 2, 0));
|
||||
mem.write32(messagePointer + 4, Result::Success);
|
||||
mem.write8(messagePointer + 8, (model == ConsoleModel::New3DS) ? 1 : 0); // u8, Status (0 = Old 3DS, 1 = New 3DS)
|
||||
mem.write8(messagePointer + 8, (model == ConsoleModel::New3DS) ? 1 : 0); // u8, Status (0 = Old 3DS, 1 = New 3DS)
|
||||
}
|
||||
|
||||
// TODO: Figure out the slight way this differs from APT::CheckNew3DS
|
||||
|
@ -186,7 +186,7 @@ void APTService::checkNew3DSApp(u32 messagePointer) {
|
|||
log("APT::CheckNew3DSApp\n");
|
||||
mem.write32(messagePointer, IPC::responseHeader(0x101, 2, 0));
|
||||
mem.write32(messagePointer + 4, Result::Success);
|
||||
mem.write8(messagePointer + 8, (model == ConsoleModel::New3DS) ? 1 : 0); // u8, Status (0 = Old 3DS, 1 = New 3DS)
|
||||
mem.write8(messagePointer + 8, (model == ConsoleModel::New3DS) ? 1 : 0); // u8, Status (0 = Old 3DS, 1 = New 3DS)
|
||||
}
|
||||
|
||||
void APTService::enable(u32 messagePointer) {
|
||||
|
@ -207,14 +207,14 @@ void APTService::initialize(u32 messagePointer) {
|
|||
notificationEvent = kernel.makeEvent(ResetType::OneShot);
|
||||
resumeEvent = kernel.makeEvent(ResetType::OneShot);
|
||||
|
||||
kernel.signalEvent(resumeEvent.value()); // Seems to be signalled on startup
|
||||
kernel.signalEvent(resumeEvent.value()); // Seems to be signalled on startup
|
||||
}
|
||||
|
||||
mem.write32(messagePointer, IPC::responseHeader(0x2, 1, 3));
|
||||
mem.write32(messagePointer + 4, Result::Success);
|
||||
mem.write32(messagePointer + 8, 0x04000000); // Translation descriptor
|
||||
mem.write32(messagePointer + 12, notificationEvent.value()); // Notification Event Handle
|
||||
mem.write32(messagePointer + 16, resumeEvent.value()); // Resume Event Handle
|
||||
mem.write32(messagePointer + 8, 0x04000000); // Translation descriptor
|
||||
mem.write32(messagePointer + 12, notificationEvent.value()); // Notification Event HandleType
|
||||
mem.write32(messagePointer + 16, resumeEvent.value()); // Resume Event HandleType
|
||||
}
|
||||
|
||||
void APTService::inquireNotification(u32 messagePointer) {
|
||||
|
@ -234,11 +234,11 @@ void APTService::getLockHandle(u32 messagePointer) {
|
|||
}
|
||||
|
||||
mem.write32(messagePointer, IPC::responseHeader(0x1, 3, 2));
|
||||
mem.write32(messagePointer + 4, Result::Success); // Result code
|
||||
mem.write32(messagePointer + 8, 0); // AppletAttr
|
||||
mem.write32(messagePointer + 12, 0); // APT State (bit0 = Power Button State, bit1 = Order To Close State)
|
||||
mem.write32(messagePointer + 16, 0); // Translation descriptor
|
||||
mem.write32(messagePointer + 20, lockHandle.value()); // Lock handle
|
||||
mem.write32(messagePointer + 4, Result::Success); // Result code
|
||||
mem.write32(messagePointer + 8, 0); // AppletAttr
|
||||
mem.write32(messagePointer + 12, 0); // APT State (bit0 = Power Button State, bit1 = Order To Close State)
|
||||
mem.write32(messagePointer + 16, 0); // Translation descriptor
|
||||
mem.write32(messagePointer + 20, lockHandle.value()); // Lock handle
|
||||
}
|
||||
|
||||
// This apparently does nothing on the original kernel either?
|
||||
|
@ -254,7 +254,7 @@ void APTService::sendParameter(u32 messagePointer) {
|
|||
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 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)", sourceAppID, destAppID, cmd, paramSize);
|
||||
|
||||
|
@ -355,8 +355,8 @@ void APTService::replySleepQuery(u32 messagePointer) {
|
|||
}
|
||||
|
||||
void APTService::setApplicationCpuTimeLimit(u32 messagePointer) {
|
||||
u32 fixed = mem.read32(messagePointer + 4); // MUST be 1.
|
||||
u32 percentage = mem.read32(messagePointer + 8); // CPU time percentage between 5% and 89%
|
||||
u32 fixed = mem.read32(messagePointer + 4); // MUST be 1.
|
||||
u32 percentage = mem.read32(messagePointer + 8); // CPU time percentage between 5% and 89%
|
||||
log("APT::SetApplicationCpuTimeLimit (percentage = %d%%)\n", percentage);
|
||||
|
||||
mem.write32(messagePointer, IPC::responseHeader(0x4F, 1, 0));
|
||||
|
@ -409,15 +409,14 @@ void APTService::theSmashBrosFunction(u32 messagePointer) {
|
|||
}
|
||||
|
||||
void APTService::getWirelessRebootInfo(u32 messagePointer) {
|
||||
const u32 size = mem.read32(messagePointer + 4); // Size of data to read
|
||||
const u32 size = mem.read32(messagePointer + 4); // Size of data to read
|
||||
log("APT::GetWirelessRebootInfo (size = %X)\n", size);
|
||||
|
||||
if (size > 0x10)
|
||||
Helpers::panic("APT::GetWirelessInfo with size > 0x10 bytes");
|
||||
if (size > 0x10) Helpers::panic("APT::GetWirelessInfo with size > 0x10 bytes");
|
||||
|
||||
mem.write32(messagePointer, IPC::responseHeader(0x45, 1, 2));
|
||||
mem.write32(messagePointer + 4, Result::Success);
|
||||
for (u32 i = 0; i < size; i++) {
|
||||
mem.write8(messagePointer + 0x104 + i, 0); // Temporarily stub this until we add SetWirelessRebootInfo
|
||||
mem.write8(messagePointer + 0x104 + i, 0); // Temporarily stub this until we add SetWirelessRebootInfo
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
#include "services/boss.hpp"
|
||||
|
||||
#include "ipc.hpp"
|
||||
|
||||
namespace BOSSCommands {
|
||||
|
@ -31,9 +32,7 @@ namespace BOSSCommands {
|
|||
};
|
||||
}
|
||||
|
||||
void BOSSService::reset() {
|
||||
optoutFlag = 0;
|
||||
}
|
||||
void BOSSService::reset() { optoutFlag = 0; }
|
||||
|
||||
void BOSSService::handleSyncRequest(u32 messagePointer) {
|
||||
const u32 command = mem.read32(messagePointer);
|
||||
|
@ -44,8 +43,7 @@ void BOSSService::handleSyncRequest(u32 messagePointer) {
|
|||
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::GetOptoutFlag: getOptoutFlag(messagePointer); break;
|
||||
case BOSSCommands::GetStorageEntryInfo: getStorageEntryInfo(messagePointer); break;
|
||||
case BOSSCommands::GetTaskIdList: getTaskIdList(messagePointer); break;
|
||||
|
@ -99,7 +97,7 @@ void BOSSService::getTaskState(u32 messagePointer) {
|
|||
mem.write32(messagePointer + 4, Result::Success);
|
||||
mem.write8(messagePointer + 8, 0); // TaskStatus: Report the task finished successfully
|
||||
mem.write32(messagePointer + 12, 0); // Current state value for task PropertyID 0x4
|
||||
mem.write8(messagePointer + 16, 0); // TODO: Figure out what this should be
|
||||
mem.write8(messagePointer + 16, 0); // TODO: Figure out what this should be
|
||||
}
|
||||
|
||||
void BOSSService::getTaskStatus(u32 messagePointer) {
|
||||
|
@ -150,15 +148,15 @@ void BOSSService::getErrorCode(u32 messagePointer) {
|
|||
log("BOSS::GetErrorCode (stubbed)\n");
|
||||
mem.write32(messagePointer, IPC::responseHeader(0x2E, 2, 0));
|
||||
mem.write32(messagePointer + 4, Result::Success);
|
||||
mem.write32(messagePointer + 8, Result::Success); // No error code
|
||||
mem.write32(messagePointer + 8, Result::Success); // No error code
|
||||
}
|
||||
|
||||
void BOSSService::getStorageEntryInfo(u32 messagePointer) {
|
||||
log("BOSS::GetStorageEntryInfo (undocumented)\n");
|
||||
mem.write32(messagePointer, IPC::responseHeader(0x30, 3, 0));
|
||||
mem.write32(messagePointer + 4, Result::Success);
|
||||
mem.write32(messagePointer + 8, 0); // u32, unknown meaning
|
||||
mem.write16(messagePointer + 12, 0); // s16, unknown meaning
|
||||
mem.write32(messagePointer + 8, 0); // u32, unknown meaning
|
||||
mem.write16(messagePointer + 12, 0); // s16, unknown meaning
|
||||
}
|
||||
|
||||
void BOSSService::sendProperty(u32 messagePointer) {
|
||||
|
@ -170,10 +168,9 @@ void BOSSService::sendProperty(u32 messagePointer) {
|
|||
mem.write32(messagePointer, IPC::responseHeader(0x14, 1, 2));
|
||||
mem.write32(messagePointer + 4, Result::Success);
|
||||
mem.write32(messagePointer + 8, 0); // Read size
|
||||
// TODO: Should this do anything else?
|
||||
// TODO: Should this do anything else?
|
||||
}
|
||||
|
||||
|
||||
void BOSSService::receiveProperty(u32 messagePointer) {
|
||||
const u32 id = mem.read32(messagePointer + 4);
|
||||
const u32 size = mem.read32(messagePointer + 8);
|
||||
|
@ -182,13 +179,13 @@ void BOSSService::receiveProperty(u32 messagePointer) {
|
|||
log("BOSS::ReceiveProperty (id = %d, size = %08X, ptr = %08X) (stubbed)\n", id, size, ptr);
|
||||
mem.write32(messagePointer, IPC::responseHeader(0x16, 2, 2));
|
||||
mem.write32(messagePointer + 4, Result::Success);
|
||||
mem.write32(messagePointer + 8, 0); // Read size
|
||||
mem.write32(messagePointer + 8, 0); // Read size
|
||||
}
|
||||
|
||||
// This seems to accept a KEvent as a parameter and register it for something Spotpass related
|
||||
// I need to update the 3DBrew page when it's known what it does properly
|
||||
void BOSSService::registerNewArrivalEvent(u32 messagePointer) {
|
||||
const Handle eventHandle = mem.read32(messagePointer + 4); // Kernel event handle to register
|
||||
const HandleType eventHandle = mem.read32(messagePointer + 4); // Kernel event handle to register
|
||||
log("BOSS::RegisterNewArrivalEvent (handle = %X)\n", eventHandle);
|
||||
|
||||
mem.write32(messagePointer, IPC::responseHeader(0x8, 1, 0));
|
||||
|
@ -252,5 +249,5 @@ void BOSSService::getNewArrivalFlag(u32 messagePointer) {
|
|||
log("BOSS::GetNewArrivalFlag (stubbed)\n");
|
||||
mem.write32(messagePointer, IPC::responseHeader(0x7, 2, 0));
|
||||
mem.write32(messagePointer + 4, Result::Success);
|
||||
mem.write8(messagePointer + 8, 0); // Flag
|
||||
}
|
||||
mem.write8(messagePointer + 8, 0); // Flag
|
||||
}
|
||||
|
|
|
@ -312,7 +312,7 @@ void CAMService::setReceiving(u32 messagePointer) {
|
|||
const u32 portIndex = mem.read8(messagePointer + 8);
|
||||
const u32 size = mem.read32(messagePointer + 12);
|
||||
const u16 transferUnit = mem.read16(messagePointer + 16);
|
||||
const Handle process = mem.read32(messagePointer + 24);
|
||||
const HandleType process = mem.read32(messagePointer + 24);
|
||||
|
||||
const PortSelect port(portIndex);
|
||||
log("CAM::SetReceiving (port = %d)\n", portIndex);
|
||||
|
|
|
@ -1,10 +1,11 @@
|
|||
#include "services/dsp.hpp"
|
||||
#include "ipc.hpp"
|
||||
#include "kernel.hpp"
|
||||
|
||||
#include <algorithm>
|
||||
#include <fstream>
|
||||
|
||||
#include "ipc.hpp"
|
||||
#include "kernel.hpp"
|
||||
|
||||
namespace DSPCommands {
|
||||
enum : u32 {
|
||||
RecvData = 0x00010040,
|
||||
|
@ -25,10 +26,7 @@ namespace DSPCommands {
|
|||
}
|
||||
|
||||
namespace Result {
|
||||
enum : u32 {
|
||||
HeadphonesNotInserted = 0,
|
||||
HeadphonesInserted = 1
|
||||
};
|
||||
enum : u32 { HeadphonesNotInserted = 0, HeadphonesInserted = 1 };
|
||||
}
|
||||
|
||||
void DSPService::reset() {
|
||||
|
@ -74,7 +72,7 @@ void DSPService::convertProcessAddressFromDspDram(u32 messagePointer) {
|
|||
|
||||
mem.write32(messagePointer, IPC::responseHeader(0xC, 2, 0));
|
||||
mem.write32(messagePointer + 4, Result::Success);
|
||||
mem.write32(messagePointer + 8, converted); // Converted address
|
||||
mem.write32(messagePointer + 8, converted); // Converted address
|
||||
}
|
||||
|
||||
void DSPService::loadComponent(u32 messagePointer) {
|
||||
|
@ -94,9 +92,9 @@ void DSPService::loadComponent(u32 messagePointer) {
|
|||
|
||||
mem.write32(messagePointer, IPC::responseHeader(0x11, 2, 2));
|
||||
mem.write32(messagePointer + 4, Result::Success);
|
||||
mem.write32(messagePointer + 8, 1); // Component loaded
|
||||
mem.write32(messagePointer + 8, 1); // Component loaded
|
||||
mem.write32(messagePointer + 12, (size << 4) | 0xA);
|
||||
mem.write32(messagePointer + 16, mem.read32(messagePointer + 20)); // Component buffer
|
||||
mem.write32(messagePointer + 16, mem.read32(messagePointer + 20)); // Component buffer
|
||||
}
|
||||
|
||||
void DSPService::unloadComponent(u32 messagePointer) {
|
||||
|
@ -121,7 +119,7 @@ void DSPService::readPipeIfPossible(u32 messagePointer) {
|
|||
}
|
||||
|
||||
mem.write32(messagePointer + 4, Result::Success);
|
||||
mem.write16(messagePointer + 8, u16(data.size())); // Number of bytes read
|
||||
mem.write16(messagePointer + 8, u16(data.size())); // Number of bytes read
|
||||
}
|
||||
|
||||
void DSPService::recvData(u32 messagePointer) {
|
||||
|
@ -153,12 +151,10 @@ DSPService::DSPEvent& DSPService::getEventRef(u32 type, u32 pipe) {
|
|||
case 1: return interrupt1;
|
||||
|
||||
case 2:
|
||||
if (pipe >= pipeCount)
|
||||
Helpers::panic("Tried to access the event of an invalid pipe");
|
||||
if (pipe >= pipeCount) Helpers::panic("Tried to access the event of an invalid pipe");
|
||||
return pipeEvents[pipe];
|
||||
|
||||
default:
|
||||
Helpers::panic("Unknown type for DSP::getEventRef");
|
||||
default: Helpers::panic("Unknown type for DSP::getEventRef");
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -170,8 +166,8 @@ void DSPService::registerInterruptEvents(u32 messagePointer) {
|
|||
|
||||
// The event handle being 0 means we're removing an event
|
||||
if (eventHandle == 0) {
|
||||
DSPEvent& e = getEventRef(interrupt, channel); // Get event
|
||||
if (e.has_value()) { // Remove if it exists
|
||||
DSPEvent& e = getEventRef(interrupt, channel); // Get event
|
||||
if (e.has_value()) { // Remove if it exists
|
||||
totalEventCount--;
|
||||
e = std::nullopt;
|
||||
}
|
||||
|
@ -198,7 +194,7 @@ void DSPService::getHeadphoneStatus(u32 messagePointer) {
|
|||
|
||||
mem.write32(messagePointer, IPC::responseHeader(0x1F, 2, 0));
|
||||
mem.write32(messagePointer + 4, Result::Success);
|
||||
mem.write32(messagePointer + 8, Result::HeadphonesInserted); // This should be toggleable for shits and giggles
|
||||
mem.write32(messagePointer + 8, Result::HeadphonesInserted); // This should be toggleable for shits and giggles
|
||||
}
|
||||
|
||||
void DSPService::getSemaphoreEventHandle(u32 messagePointer) {
|
||||
|
@ -211,7 +207,7 @@ void DSPService::getSemaphoreEventHandle(u32 messagePointer) {
|
|||
mem.write32(messagePointer, IPC::responseHeader(0x16, 1, 2));
|
||||
mem.write32(messagePointer + 4, Result::Success);
|
||||
// TODO: Translation descriptor here?
|
||||
mem.write32(messagePointer + 12, semaphoreEvent.value()); // Semaphore event handle
|
||||
mem.write32(messagePointer + 12, semaphoreEvent.value()); // Semaphore event handle
|
||||
kernel.signalEvent(semaphoreEvent.value());
|
||||
}
|
||||
|
||||
|
@ -249,7 +245,7 @@ void DSPService::writeProcessPipe(u32 messagePointer) {
|
|||
void DSPService::flushDataCache(u32 messagePointer) {
|
||||
const u32 address = mem.read32(messagePointer + 4);
|
||||
const u32 size = mem.read32(messagePointer + 8);
|
||||
const Handle process = mem.read32(messagePointer + 16);
|
||||
const HandleType process = mem.read32(messagePointer + 16);
|
||||
|
||||
log("DSP::FlushDataCache (addr = %08X, size = %08X, process = %X)\n", address, size, process);
|
||||
mem.write32(messagePointer, IPC::responseHeader(0x13, 1, 0));
|
||||
|
@ -259,7 +255,7 @@ void DSPService::flushDataCache(u32 messagePointer) {
|
|||
void DSPService::invalidateDCache(u32 messagePointer) {
|
||||
const u32 address = mem.read32(messagePointer + 4);
|
||||
const u32 size = mem.read32(messagePointer + 8);
|
||||
const Handle process = mem.read32(messagePointer + 16);
|
||||
const HandleType process = mem.read32(messagePointer + 16);
|
||||
|
||||
log("DSP::InvalidateDataCache (addr = %08X, size = %08X, process = %X)\n", address, size, process);
|
||||
mem.write32(messagePointer, IPC::responseHeader(0x14, 1, 0));
|
||||
|
@ -303,4 +299,4 @@ void DSPService::triggerInterrupt1() {
|
|||
if (interrupt1.has_value()) {
|
||||
kernel.signalEvent(*interrupt1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,10 +1,11 @@
|
|||
#include "services/fs.hpp"
|
||||
#include "kernel/kernel.hpp"
|
||||
|
||||
#include "io_file.hpp"
|
||||
#include "ipc.hpp"
|
||||
#include "kernel/kernel.hpp"
|
||||
#include "result/result.hpp"
|
||||
|
||||
#ifdef CreateFile // windows.h defines CreateFile & DeleteFile because of course it does.
|
||||
#ifdef CreateFile // windows.h defines CreateFile & DeleteFile because of course it does.
|
||||
#undef CreateDirectory
|
||||
#undef CreateFile
|
||||
#undef DeleteFile
|
||||
|
@ -47,21 +48,18 @@ namespace FSCommands {
|
|||
};
|
||||
}
|
||||
|
||||
void FSService::reset() {
|
||||
priority = 0;
|
||||
}
|
||||
void FSService::reset() { priority = 0; }
|
||||
|
||||
// Creates directories for NAND, ExtSaveData, etc if they don't already exist. Should be executed after loading a new ROM.
|
||||
void FSService::initializeFilesystem() {
|
||||
const auto sdmcPath = IOFile::getAppData() / "SDMC"; // Create SDMC directory
|
||||
const auto sdmcPath = IOFile::getAppData() / "SDMC"; // Create SDMC directory
|
||||
const auto nandSharedpath = IOFile::getAppData() / ".." / "SharedFiles" / "NAND";
|
||||
|
||||
const auto savePath = IOFile::getAppData() / "SaveData"; // Create SaveData
|
||||
const auto formatPath = IOFile::getAppData() / "FormatInfo"; // Create folder for storing archive formatting info
|
||||
const auto savePath = IOFile::getAppData() / "SaveData"; // Create SaveData
|
||||
const auto formatPath = IOFile::getAppData() / "FormatInfo"; // Create folder for storing archive formatting info
|
||||
const auto systemSaveDataPath = IOFile::getAppData() / ".." / "SharedFiles" / "SystemSaveData";
|
||||
namespace fs = std::filesystem;
|
||||
|
||||
|
||||
if (!fs::is_directory(nandSharedpath)) {
|
||||
fs::create_directories(nandSharedpath);
|
||||
}
|
||||
|
@ -89,25 +87,21 @@ ArchiveBase* FSService::getArchiveFromID(u32 id, const FSPath& archivePath) {
|
|||
case ArchiveID::SaveData: return &saveData;
|
||||
case ArchiveID::UserSaveData2: return &userSaveData2;
|
||||
|
||||
case ArchiveID::ExtSaveData:
|
||||
return &extSaveData_sdmc;
|
||||
case ArchiveID::ExtSaveData: return &extSaveData_sdmc;
|
||||
|
||||
case ArchiveID::SharedExtSaveData:
|
||||
return &sharedExtSaveData_nand;
|
||||
case ArchiveID::SharedExtSaveData: return &sharedExtSaveData_nand;
|
||||
|
||||
case ArchiveID::SystemSaveData: return &systemSaveData;
|
||||
case ArchiveID::SDMC: return &sdmc;
|
||||
case ArchiveID::SDMCWriteOnly: return &sdmcWriteOnly;
|
||||
case ArchiveID::SavedataAndNcch: return &ncch; // This can only access NCCH outside of FSPXI
|
||||
default:
|
||||
Helpers::panic("Unknown archive. ID: %d\n", id);
|
||||
return nullptr;
|
||||
case ArchiveID::SavedataAndNcch: return &ncch; // This can only access NCCH outside of FSPXI
|
||||
default: Helpers::panic("Unknown archive. ID: %d\n", id); return nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
std::optional<Handle> FSService::openFileHandle(ArchiveBase* archive, const FSPath& path, const FSPath& archivePath, const FilePerms& perms) {
|
||||
std::optional<HandleType> FSService::openFileHandle(ArchiveBase* archive, const FSPath& path, const FSPath& archivePath, const FilePerms& perms) {
|
||||
FileDescriptor opened = archive->openFile(path, perms);
|
||||
if (opened.has_value()) { // If opened doesn't have a value, we failed to open the file
|
||||
if (opened.has_value()) { // If opened doesn't have a value, we failed to open the file
|
||||
auto handle = kernel.makeObject(KernelObjectType::File);
|
||||
|
||||
auto& file = kernel.getObjects()[handle];
|
||||
|
@ -119,9 +113,9 @@ std::optional<Handle> FSService::openFileHandle(ArchiveBase* archive, const FSPa
|
|||
}
|
||||
}
|
||||
|
||||
Rust::Result<Handle, Result::HorizonResult> FSService::openDirectoryHandle(ArchiveBase* archive, const FSPath& path) {
|
||||
Rust::Result<HandleType, Result::HorizonResult> FSService::openDirectoryHandle(ArchiveBase* archive, const FSPath& path) {
|
||||
Rust::Result<DirectorySession, Result::HorizonResult> opened = archive->openDirectory(path);
|
||||
if (opened.isOk()) { // If opened doesn't have a value, we failed to open the directory
|
||||
if (opened.isOk()) { // If opened doesn't have a value, we failed to open the directory
|
||||
auto handle = kernel.makeObject(KernelObjectType::Directory);
|
||||
auto& object = kernel.getObjects()[handle];
|
||||
object.data = new DirectorySession(opened.unwrap());
|
||||
|
@ -132,7 +126,7 @@ Rust::Result<Handle, Result::HorizonResult> FSService::openDirectoryHandle(Archi
|
|||
}
|
||||
}
|
||||
|
||||
Rust::Result<Handle, Result::HorizonResult> FSService::openArchiveHandle(u32 archiveID, const FSPath& path) {
|
||||
Rust::Result<HandleType, Result::HorizonResult> FSService::openArchiveHandle(u32 archiveID, const FSPath& path) {
|
||||
ArchiveBase* archive = getArchiveFromID(archiveID, path);
|
||||
|
||||
if (archive == nullptr) [[unlikely]] {
|
||||
|
@ -147,8 +141,7 @@ Rust::Result<Handle, Result::HorizonResult> FSService::openArchiveHandle(u32 arc
|
|||
archiveObject.data = new ArchiveSession(res.unwrap(), path);
|
||||
|
||||
return Ok(handle);
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
return Err(res.unwrapErr());
|
||||
}
|
||||
}
|
||||
|
@ -157,8 +150,7 @@ FSPath FSService::readPath(u32 type, u32 pointer, u32 size) {
|
|||
std::vector<u8> data;
|
||||
data.resize(size);
|
||||
|
||||
for (u32 i = 0; i < size; i++)
|
||||
data[i] = mem.read8(pointer + i);
|
||||
for (u32 i = 0; i < size; i++) data[i] = mem.read8(pointer + i);
|
||||
|
||||
return FSPath(type, data);
|
||||
}
|
||||
|
@ -217,7 +209,7 @@ void FSService::initializeWithSdkVersion(u32 messagePointer) {
|
|||
}
|
||||
|
||||
void FSService::closeArchive(u32 messagePointer) {
|
||||
const Handle handle = static_cast<u32>(mem.read64(messagePointer + 4)); // TODO: archive handles should be 64-bit
|
||||
const HandleType handle = static_cast<u32>(mem.read64(messagePointer + 4)); // TODO: archive handles should be 64-bit
|
||||
const auto object = kernel.getObject(handle, KernelObjectType::Archive);
|
||||
log("FSService::CloseArchive(handle = %X)\n", handle);
|
||||
|
||||
|
@ -241,7 +233,7 @@ void FSService::openArchive(u32 messagePointer) {
|
|||
auto archivePath = readPath(archivePathType, archivePathPointer, archivePathSize);
|
||||
log("FS::OpenArchive(archive ID = %d, archive path type = %d)\n", archiveID, archivePathType);
|
||||
|
||||
Rust::Result<Handle, Result::HorizonResult> res = openArchiveHandle(archiveID, archivePath);
|
||||
Rust::Result<HandleType, Result::HorizonResult> res = openArchiveHandle(archiveID, archivePath);
|
||||
mem.write32(messagePointer, IPC::responseHeader(0x80C, 3, 0));
|
||||
if (res.isOk()) {
|
||||
mem.write32(messagePointer + 4, Result::Success);
|
||||
|
@ -254,7 +246,7 @@ void FSService::openArchive(u32 messagePointer) {
|
|||
}
|
||||
|
||||
void FSService::openFile(u32 messagePointer) {
|
||||
const Handle archiveHandle = Handle(mem.read64(messagePointer + 8));
|
||||
const HandleType archiveHandle = HandleType(mem.read64(messagePointer + 8));
|
||||
const u32 filePathType = mem.read32(messagePointer + 16);
|
||||
const u32 filePathSize = mem.read32(messagePointer + 20);
|
||||
const u32 openFlags = mem.read32(messagePointer + 24);
|
||||
|
@ -276,14 +268,14 @@ void FSService::openFile(u32 messagePointer) {
|
|||
auto filePath = readPath(filePathType, filePathPointer, filePathSize);
|
||||
const FilePerms perms(openFlags);
|
||||
|
||||
std::optional<Handle> handle = openFileHandle(archive, filePath, archivePath, perms);
|
||||
std::optional<HandleType> handle = openFileHandle(archive, filePath, archivePath, perms);
|
||||
mem.write32(messagePointer, IPC::responseHeader(0x802, 1, 2));
|
||||
if (!handle.has_value()) {
|
||||
printf("OpenFile failed\n");
|
||||
mem.write32(messagePointer + 4, Result::FS::FileNotFound);
|
||||
} else {
|
||||
mem.write32(messagePointer + 4, Result::Success);
|
||||
mem.write32(messagePointer + 8, 0x10); // "Move handle descriptor"
|
||||
mem.write32(messagePointer + 8, 0x10); // "Move handle descriptor"
|
||||
mem.write32(messagePointer + 12, handle.value());
|
||||
}
|
||||
}
|
||||
|
@ -291,7 +283,7 @@ void FSService::openFile(u32 messagePointer) {
|
|||
void FSService::createDirectory(u32 messagePointer) {
|
||||
log("FS::CreateDirectory\n");
|
||||
|
||||
const Handle archiveHandle = (Handle)mem.read64(messagePointer + 8);
|
||||
const HandleType archiveHandle = (HandleType)mem.read64(messagePointer + 8);
|
||||
const u32 pathType = mem.read32(messagePointer + 16);
|
||||
const u32 pathSize = mem.read32(messagePointer + 20);
|
||||
const u32 pathPointer = mem.read32(messagePointer + 32);
|
||||
|
@ -313,7 +305,7 @@ void FSService::createDirectory(u32 messagePointer) {
|
|||
|
||||
void FSService::openDirectory(u32 messagePointer) {
|
||||
log("FS::OpenDirectory\n");
|
||||
const Handle archiveHandle = (Handle)mem.read64(messagePointer + 4);
|
||||
const HandleType archiveHandle = (HandleType)mem.read64(messagePointer + 4);
|
||||
const u32 pathType = mem.read32(messagePointer + 12);
|
||||
const u32 pathSize = mem.read32(messagePointer + 16);
|
||||
const u32 pathPointer = mem.read32(messagePointer + 24);
|
||||
|
@ -366,7 +358,7 @@ void FSService::openFileDirectly(u32 messagePointer) {
|
|||
}
|
||||
archive = res.unwrap();
|
||||
|
||||
std::optional<Handle> handle = openFileHandle(archive, filePath, archivePath, perms);
|
||||
std::optional<HandleType> handle = openFileHandle(archive, filePath, archivePath, perms);
|
||||
mem.write32(messagePointer, IPC::responseHeader(0x803, 1, 2));
|
||||
if (!handle.has_value()) {
|
||||
printf("OpenFileDirectly failed\n");
|
||||
|
@ -378,7 +370,7 @@ void FSService::openFileDirectly(u32 messagePointer) {
|
|||
}
|
||||
|
||||
void FSService::createFile(u32 messagePointer) {
|
||||
const Handle archiveHandle = Handle(mem.read64(messagePointer + 8));
|
||||
const HandleType archiveHandle = HandleType(mem.read64(messagePointer + 8));
|
||||
const u32 filePathType = mem.read32(messagePointer + 16);
|
||||
const u32 filePathSize = mem.read32(messagePointer + 20);
|
||||
const u32 attributes = mem.read32(messagePointer + 24);
|
||||
|
@ -403,7 +395,7 @@ void FSService::createFile(u32 messagePointer) {
|
|||
}
|
||||
|
||||
void FSService::deleteFile(u32 messagePointer) {
|
||||
const Handle archiveHandle = Handle(mem.read64(messagePointer + 8));
|
||||
const HandleType archiveHandle = HandleType(mem.read64(messagePointer + 8));
|
||||
const u32 filePathType = mem.read32(messagePointer + 16);
|
||||
const u32 filePathSize = mem.read32(messagePointer + 20);
|
||||
const u32 filePathPointer = mem.read32(messagePointer + 28);
|
||||
|
@ -425,7 +417,7 @@ void FSService::deleteFile(u32 messagePointer) {
|
|||
}
|
||||
|
||||
void FSService::deleteDirectory(u32 messagePointer) {
|
||||
const Handle archiveHandle = Handle(mem.read64(messagePointer + 8));
|
||||
const HandleType archiveHandle = HandleType(mem.read64(messagePointer + 8));
|
||||
const u32 filePathType = mem.read32(messagePointer + 16);
|
||||
const u32 filePathSize = mem.read32(messagePointer + 20);
|
||||
const u32 filePathPointer = mem.read32(messagePointer + 28);
|
||||
|
@ -470,8 +462,7 @@ void FSService::formatSaveData(u32 messagePointer) {
|
|||
log("FS::FormatSaveData\n");
|
||||
|
||||
const u32 archiveID = mem.read32(messagePointer + 4);
|
||||
if (archiveID != ArchiveID::SaveData)
|
||||
Helpers::panic("FS::FormatSaveData: Archive is not SaveData");
|
||||
if (archiveID != ArchiveID::SaveData) Helpers::panic("FS::FormatSaveData: Archive is not SaveData");
|
||||
|
||||
// Read path and path info
|
||||
const u32 pathType = mem.read32(messagePointer + 8);
|
||||
|
@ -481,21 +472,15 @@ void FSService::formatSaveData(u32 messagePointer) {
|
|||
// Size of a block. Seems to always be 0x200
|
||||
const u32 blockSize = mem.read32(messagePointer + 16);
|
||||
|
||||
if (blockSize != 0x200 && blockSize != 0x1000)
|
||||
Helpers::panic("FS::FormatSaveData: Invalid SaveData block size");
|
||||
if (blockSize != 0x200 && blockSize != 0x1000) Helpers::panic("FS::FormatSaveData: Invalid SaveData block size");
|
||||
|
||||
const u32 directoryNum = mem.read32(messagePointer + 20); // Max number of directories
|
||||
const u32 fileNum = mem.read32(messagePointer + 24); // Max number of files
|
||||
const u32 directoryBucketNum = mem.read32(messagePointer + 28); // Not sure what a directory bucket is...?
|
||||
const u32 fileBucketNum = mem.read32(messagePointer + 32); // Same here
|
||||
const u32 directoryNum = mem.read32(messagePointer + 20); // Max number of directories
|
||||
const u32 fileNum = mem.read32(messagePointer + 24); // Max number of files
|
||||
const u32 directoryBucketNum = mem.read32(messagePointer + 28); // Not sure what a directory bucket is...?
|
||||
const u32 fileBucketNum = mem.read32(messagePointer + 32); // Same here
|
||||
const bool duplicateData = mem.read8(messagePointer + 36) != 0;
|
||||
|
||||
ArchiveBase::FormatInfo info {
|
||||
.size = blockSize * 0x200,
|
||||
.numOfDirectories = directoryNum,
|
||||
.numOfFiles = fileNum,
|
||||
.duplicateData = duplicateData
|
||||
};
|
||||
ArchiveBase::FormatInfo info{.size = blockSize * 0x200, .numOfDirectories = directoryNum, .numOfFiles = fileNum, .duplicateData = duplicateData};
|
||||
|
||||
saveData.format(path, info);
|
||||
|
||||
|
@ -512,8 +497,8 @@ void FSService::deleteExtSaveData(u32 messagePointer) {
|
|||
log("FS::DeleteExtSaveData (media type = %d, saveID = %llx) (stubbed)\n", mediaType, saveID);
|
||||
|
||||
mem.write32(messagePointer, IPC::responseHeader(0x0852, 1, 0));
|
||||
// TODO: We can't properly implement this yet until we properly support title/save IDs. We will stub this and insert a warning for now. Required for Planet Robobot
|
||||
// When we properly implement it, it will just be a recursive directory deletion
|
||||
// TODO: We can't properly implement this yet until we properly support title/save IDs. We will stub this and insert a warning for now. Required
|
||||
// for Planet Robobot When we properly implement it, it will just be a recursive directory deletion
|
||||
mem.write32(messagePointer + 4, Result::Success);
|
||||
}
|
||||
|
||||
|
@ -521,7 +506,8 @@ void FSService::createExtSaveData(u32 messagePointer) {
|
|||
Helpers::warn("Stubbed call to FS::CreateExtSaveData!");
|
||||
// First 4 words of parameters are the ExtSaveData info
|
||||
// https://www.3dbrew.org/wiki/Filesystem_services#ExtSaveDataInfo
|
||||
// This creates the ExtSaveData with the specified saveid in the specified media type. It stores the SMDH as "icon" in the root of the created directory.
|
||||
// This creates the ExtSaveData with the specified saveid in the specified media type. It stores the SMDH as "icon" in the root of the created
|
||||
// directory.
|
||||
const u8 mediaType = mem.read8(messagePointer + 4);
|
||||
const u64 saveID = mem.read64(messagePointer + 8);
|
||||
const u32 numOfDirectories = mem.read32(messagePointer + 20);
|
||||
|
@ -541,18 +527,13 @@ void FSService::formatThisUserSaveData(u32 messagePointer) {
|
|||
log("FS::FormatThisUserSaveData\n");
|
||||
|
||||
const u32 blockSize = mem.read32(messagePointer + 4);
|
||||
const u32 directoryNum = mem.read32(messagePointer + 8); // Max number of directories
|
||||
const u32 fileNum = mem.read32(messagePointer + 12); // Max number of files
|
||||
const u32 directoryBucketNum = mem.read32(messagePointer + 16); // Not sure what a directory bucket is...?
|
||||
const u32 fileBucketNum = mem.read32(messagePointer + 20); // Same here
|
||||
const u32 directoryNum = mem.read32(messagePointer + 8); // Max number of directories
|
||||
const u32 fileNum = mem.read32(messagePointer + 12); // Max number of files
|
||||
const u32 directoryBucketNum = mem.read32(messagePointer + 16); // Not sure what a directory bucket is...?
|
||||
const u32 fileBucketNum = mem.read32(messagePointer + 20); // Same here
|
||||
const bool duplicateData = mem.read8(messagePointer + 24) != 0;
|
||||
|
||||
ArchiveBase::FormatInfo info {
|
||||
.size = blockSize * 0x200,
|
||||
.numOfDirectories = directoryNum,
|
||||
.numOfFiles = fileNum,
|
||||
.duplicateData = duplicateData
|
||||
};
|
||||
ArchiveBase::FormatInfo info{.size = blockSize * 0x200, .numOfDirectories = directoryNum, .numOfFiles = fileNum, .duplicateData = duplicateData};
|
||||
FSPath emptyPath;
|
||||
|
||||
mem.write32(messagePointer, IPC::responseHeader(0x080F, 1, 0));
|
||||
|
@ -560,7 +541,7 @@ void FSService::formatThisUserSaveData(u32 messagePointer) {
|
|||
}
|
||||
|
||||
void FSService::controlArchive(u32 messagePointer) {
|
||||
const Handle archiveHandle = Handle(mem.read64(messagePointer + 4));
|
||||
const HandleType archiveHandle = HandleType(mem.read64(messagePointer + 4));
|
||||
const u32 action = mem.read32(messagePointer + 12);
|
||||
const u32 inputSize = mem.read32(messagePointer + 16);
|
||||
const u32 outputSize = mem.read32(messagePointer + 20);
|
||||
|
@ -578,24 +559,22 @@ void FSService::controlArchive(u32 messagePointer) {
|
|||
}
|
||||
|
||||
switch (action) {
|
||||
case 0: // Commit save data changes. Shouldn't need us to do anything
|
||||
case 0: // Commit save data changes. Shouldn't need us to do anything
|
||||
mem.write32(messagePointer + 4, Result::Success);
|
||||
break;
|
||||
|
||||
case 1: // Retrieves a file's last-modified timestamp. Seen in DDLC, stubbed for the moment
|
||||
case 1: // Retrieves a file's last-modified timestamp. Seen in DDLC, stubbed for the moment
|
||||
Helpers::warn("FS::ControlArchive: Tried to retrieve a file's last-modified timestamp");
|
||||
mem.write32(messagePointer + 4, Result::Success);
|
||||
break;
|
||||
|
||||
default:
|
||||
Helpers::panic("Unimplemented action for ControlArchive (action = %X)\n", action);
|
||||
break;
|
||||
default: Helpers::panic("Unimplemented action for ControlArchive (action = %X)\n", action); break;
|
||||
}
|
||||
}
|
||||
|
||||
void FSService::getFreeBytes(u32 messagePointer) {
|
||||
log("FS::GetFreeBytes\n");
|
||||
const Handle archiveHandle = (Handle)mem.read64(messagePointer + 4);
|
||||
const HandleType archiveHandle = (HandleType)mem.read64(messagePointer + 4);
|
||||
auto session = kernel.getObject(archiveHandle, KernelObjectType::Archive);
|
||||
|
||||
mem.write32(messagePointer, IPC::responseHeader(0x812, 3, 0));
|
||||
|
@ -639,7 +618,7 @@ void FSService::getArchiveResource(u32 messagePointer) {
|
|||
}
|
||||
|
||||
void FSService::setArchivePriority(u32 messagePointer) {
|
||||
Handle archive = mem.read64(messagePointer + 4);
|
||||
HandleType archive = mem.read64(messagePointer + 4);
|
||||
const u32 value = mem.read32(messagePointer + 12);
|
||||
log("FS::SetArchivePriority (priority = %d, archive handle = %X)\n", value, handle);
|
||||
|
||||
|
@ -673,9 +652,9 @@ void FSService::getThisSaveDataSecureValue(u32 messagePointer) {
|
|||
|
||||
mem.write32(messagePointer, IPC::responseHeader(0x86F, 1, 0));
|
||||
mem.write32(messagePointer + 4, Result::Success);
|
||||
mem.write8(messagePointer + 8, 0); // Secure value does not exist
|
||||
mem.write8(messagePointer + 12, 1); // TODO: What is this?
|
||||
mem.write64(messagePointer + 16, 0); // Secure value
|
||||
mem.write8(messagePointer + 8, 0); // Secure value does not exist
|
||||
mem.write8(messagePointer + 12, 1); // TODO: What is this?
|
||||
mem.write64(messagePointer + 16, 0); // Secure value
|
||||
}
|
||||
|
||||
void FSService::setThisSaveDataSecureValue(u32 messagePointer) {
|
||||
|
@ -731,8 +710,8 @@ void FSService::renameFile(u32 messagePointer) {
|
|||
|
||||
mem.write32(messagePointer, IPC::responseHeader(0x805, 1, 0));
|
||||
|
||||
const Handle sourceArchiveHandle = mem.read64(messagePointer + 8);
|
||||
const Handle destArchiveHandle = mem.read64(messagePointer + 24);
|
||||
const HandleType sourceArchiveHandle = mem.read64(messagePointer + 8);
|
||||
const HandleType destArchiveHandle = mem.read64(messagePointer + 24);
|
||||
|
||||
// Read path info
|
||||
const u32 sourcePathType = mem.read32(messagePointer + 16);
|
||||
|
@ -785,4 +764,4 @@ void FSService::getSdmcArchiveResource(u32 messagePointer) {
|
|||
mem.write32(messagePointer + 12, resource.clusterSize);
|
||||
mem.write32(messagePointer + 16, resource.partitionCapacityInClusters);
|
||||
mem.write32(messagePointer + 20, resource.freeSpaceInClusters);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,7 +1,9 @@
|
|||
#include "services/hid.hpp"
|
||||
|
||||
#include <bit>
|
||||
|
||||
#include "ipc.hpp"
|
||||
#include "kernel.hpp"
|
||||
#include <bit>
|
||||
|
||||
namespace HIDCommands {
|
||||
enum : u32 {
|
||||
|
@ -86,24 +88,24 @@ void HIDService::disableGyroscopeLow(u32 messagePointer) {
|
|||
|
||||
void HIDService::getGyroscopeLowCalibrateParam(u32 messagePointer) {
|
||||
log("HID::GetGyroscopeLowCalibrateParam\n");
|
||||
constexpr s16 unit = 6700; // Approximately from Citra which took it from hardware
|
||||
constexpr s16 unit = 6700; // Approximately from Citra which took it from hardware
|
||||
|
||||
mem.write32(messagePointer, IPC::responseHeader(0x16, 6, 0));
|
||||
mem.write32(messagePointer + 4, Result::Success);
|
||||
// Fill calibration data (for x/y/z depending on i)
|
||||
for (int i = 0; i < 3; i++) {
|
||||
const u32 pointer = messagePointer + 8 + i * 3 * sizeof(u16); // Pointer to write the calibration info for the current coordinate
|
||||
const u32 pointer = messagePointer + 8 + i * 3 * sizeof(u16); // Pointer to write the calibration info for the current coordinate
|
||||
|
||||
mem.write16(pointer, 0); // Zero point
|
||||
mem.write16(pointer + 1 * sizeof(u16), unit); // Positive unit point
|
||||
mem.write16(pointer + 2 * sizeof(u16), -unit); // Negative unit point
|
||||
mem.write16(pointer, 0); // Zero point
|
||||
mem.write16(pointer + 1 * sizeof(u16), unit); // Positive unit point
|
||||
mem.write16(pointer + 2 * sizeof(u16), -unit); // Negative unit point
|
||||
}
|
||||
}
|
||||
|
||||
void HIDService::getGyroscopeCoefficient(u32 messagePointer) {
|
||||
log("HID::GetGyroscopeLowRawToDpsCoefficient\n");
|
||||
|
||||
constexpr float gyroscopeCoeff = 14.375f; // Same as retail 3DS
|
||||
constexpr float gyroscopeCoeff = 14.375f; // Same as retail 3DS
|
||||
mem.write32(messagePointer, IPC::responseHeader(0x15, 2, 0));
|
||||
mem.write32(messagePointer + 4, Result::Success);
|
||||
mem.write32(messagePointer + 8, Helpers::bit_cast<u32, float>(gyroscopeCoeff));
|
||||
|
@ -134,13 +136,13 @@ void HIDService::getIPCHandles(u32 messagePointer) {
|
|||
}
|
||||
|
||||
mem.write32(messagePointer, IPC::responseHeader(0xA, 1, 7));
|
||||
mem.write32(messagePointer + 4, Result::Success); // Result code
|
||||
mem.write32(messagePointer + 8, 0x14000000); // Translation descriptor
|
||||
mem.write32(messagePointer + 12, KernelHandles::HIDSharedMemHandle); // Shared memory handle
|
||||
mem.write32(messagePointer + 4, Result::Success); // Result code
|
||||
mem.write32(messagePointer + 8, 0x14000000); // Translation descriptor
|
||||
mem.write32(messagePointer + 12, KernelHandles::HIDSharedMemHandle); // Shared memory handle
|
||||
|
||||
// Write HID event handles
|
||||
for (int i = 0; i < events.size(); i++) {
|
||||
mem.write32(messagePointer + 16 + sizeof(Handle) * i, events[i].value());
|
||||
mem.write32(messagePointer + 16 + sizeof(HandleType) * i, events[i].value());
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -149,20 +151,20 @@ void HIDService::updateInputs(u64 currentTick) {
|
|||
if (sharedMem) {
|
||||
// First, update the pad state
|
||||
if (nextPadIndex == 0) {
|
||||
writeSharedMem<u64>(0x8, readSharedMem<u64>(0x0)); // Copy previous tick count
|
||||
writeSharedMem<u64>(0x0, currentTick); // Write new tick count
|
||||
writeSharedMem<u64>(0x8, readSharedMem<u64>(0x0)); // Copy previous tick count
|
||||
writeSharedMem<u64>(0x0, currentTick); // Write new tick count
|
||||
}
|
||||
|
||||
writeSharedMem<u32>(0x10, nextPadIndex); // Index last updated by the HID module
|
||||
writeSharedMem<u32>(0x1C, newButtons); // Current PAD state
|
||||
writeSharedMem<s16>(0x20, circlePadX); // Current circle pad state
|
||||
writeSharedMem<u32>(0x10, nextPadIndex); // Index last updated by the HID module
|
||||
writeSharedMem<u32>(0x1C, newButtons); // Current PAD state
|
||||
writeSharedMem<s16>(0x20, circlePadX); // Current circle pad state
|
||||
writeSharedMem<s16>(0x22, circlePadY);
|
||||
|
||||
const size_t padEntryOffset = 0x28 + (nextPadIndex * 0x10); // Offset in the array of 8 pad entries
|
||||
nextPadIndex = (nextPadIndex + 1) % 8; // Move to next entry
|
||||
const size_t padEntryOffset = 0x28 + (nextPadIndex * 0x10); // Offset in the array of 8 pad entries
|
||||
nextPadIndex = (nextPadIndex + 1) % 8; // Move to next entry
|
||||
|
||||
const u32 pressed = (newButtons ^ oldButtons) & newButtons; // Pressed buttons
|
||||
const u32 released = (newButtons ^ oldButtons) & oldButtons; // Released buttons
|
||||
const u32 pressed = (newButtons ^ oldButtons) & newButtons; // Pressed buttons
|
||||
const u32 released = (newButtons ^ oldButtons) & oldButtons; // Released buttons
|
||||
oldButtons = newButtons;
|
||||
|
||||
writeSharedMem<u32>(padEntryOffset, newButtons);
|
||||
|
@ -173,12 +175,12 @@ void HIDService::updateInputs(u64 currentTick) {
|
|||
|
||||
// Next, update touchscreen state
|
||||
if (nextTouchscreenIndex == 0) {
|
||||
writeSharedMem<u64>(0xB0, readSharedMem<u64>(0xA8)); // Copy previous tick count
|
||||
writeSharedMem<u64>(0xA8, currentTick); // Write new tick count
|
||||
writeSharedMem<u64>(0xB0, readSharedMem<u64>(0xA8)); // Copy previous tick count
|
||||
writeSharedMem<u64>(0xA8, currentTick); // Write new tick count
|
||||
}
|
||||
writeSharedMem<u32>(0xB8, nextTouchscreenIndex); // Index last updated by the HID module
|
||||
const size_t touchEntryOffset = 0xC8 + (nextTouchscreenIndex * 8); // Offset in the array of 8 touchscreen entries
|
||||
nextTouchscreenIndex = (nextTouchscreenIndex + 1) % 8; // Move to next entry
|
||||
writeSharedMem<u32>(0xB8, nextTouchscreenIndex); // Index last updated by the HID module
|
||||
const size_t touchEntryOffset = 0xC8 + (nextTouchscreenIndex * 8); // Offset in the array of 8 touchscreen entries
|
||||
nextTouchscreenIndex = (nextTouchscreenIndex + 1) % 8; // Move to next entry
|
||||
|
||||
writeSharedMem<u16>(touchEntryOffset, touchScreenX);
|
||||
writeSharedMem<u16>(touchEntryOffset + 2, touchScreenY);
|
||||
|
@ -186,16 +188,16 @@ void HIDService::updateInputs(u64 currentTick) {
|
|||
|
||||
// Next, update accelerometer state
|
||||
if (nextAccelerometerIndex == 0) {
|
||||
writeSharedMem<u64>(0x110, readSharedMem<u64>(0x108)); // Copy previous tick count
|
||||
writeSharedMem<u64>(0x108, currentTick); // Write new tick count
|
||||
writeSharedMem<u64>(0x110, readSharedMem<u64>(0x108)); // Copy previous tick count
|
||||
writeSharedMem<u64>(0x108, currentTick); // Write new tick count
|
||||
}
|
||||
writeSharedMem<u32>(0x118, nextAccelerometerIndex); // Index last updated by the HID module
|
||||
nextAccelerometerIndex = (nextAccelerometerIndex + 1) % 8; // Move to next entry
|
||||
writeSharedMem<u32>(0x118, nextAccelerometerIndex); // Index last updated by the HID module
|
||||
nextAccelerometerIndex = (nextAccelerometerIndex + 1) % 8; // Move to next entry
|
||||
|
||||
// Next, update gyro state
|
||||
if (nextGyroIndex == 0) {
|
||||
writeSharedMem<u64>(0x160, readSharedMem<u64>(0x158)); // Copy previous tick count
|
||||
writeSharedMem<u64>(0x158, currentTick); // Write new tick count
|
||||
writeSharedMem<u64>(0x160, readSharedMem<u64>(0x158)); // Copy previous tick count
|
||||
writeSharedMem<u64>(0x158, currentTick); // Write new tick count
|
||||
}
|
||||
const size_t gyroEntryOffset = 0x178 + (nextGyroIndex * 6); // Offset in the array of 8 touchscreen entries
|
||||
writeSharedMem<u16>(gyroEntryOffset, pitch);
|
||||
|
@ -205,8 +207,8 @@ void HIDService::updateInputs(u64 currentTick) {
|
|||
// Since gyroscope euler angles are relative, we zero them out here and the frontend will update them again when we receive a new rotation
|
||||
roll = pitch = yaw = 0;
|
||||
|
||||
writeSharedMem<u32>(0x168, nextGyroIndex); // Index last updated by the HID module
|
||||
nextGyroIndex = (nextGyroIndex + 1) % 32; // Move to next entry
|
||||
writeSharedMem<u32>(0x168, nextGyroIndex); // Index last updated by the HID module
|
||||
nextGyroIndex = (nextGyroIndex + 1) % 32; // Move to next entry
|
||||
}
|
||||
|
||||
// For some reason, the original developers decided to signal the HID events each time the OS rescanned inputs
|
||||
|
@ -218,4 +220,4 @@ void HIDService::updateInputs(u64 currentTick) {
|
|||
kernel.signalEvent(e.value());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,10 +1,11 @@
|
|||
#include "services/ldr_ro.hpp"
|
||||
#include "ipc.hpp"
|
||||
#include "kernel.hpp"
|
||||
|
||||
#include <cstdio>
|
||||
#include <string>
|
||||
|
||||
#include "ipc.hpp"
|
||||
#include "kernel.hpp"
|
||||
|
||||
namespace LDRCommands {
|
||||
enum : u32 {
|
||||
Initialize = 0x000100C2,
|
||||
|
@ -65,10 +66,13 @@ namespace SegmentTable {
|
|||
|
||||
namespace SegmentID {
|
||||
enum : u32 {
|
||||
TEXT, RODATA, DATA, BSS,
|
||||
TEXT,
|
||||
RODATA,
|
||||
DATA,
|
||||
BSS,
|
||||
};
|
||||
}
|
||||
}
|
||||
} // namespace SegmentTable
|
||||
|
||||
namespace NamedExportTable {
|
||||
enum : u32 {
|
||||
|
@ -118,8 +122,8 @@ namespace RelocationPatch {
|
|||
enum : u32 {
|
||||
SegmentOffset = 0,
|
||||
PatchType = 4,
|
||||
IsLastEntry = 5, // For import patches
|
||||
SegmentIndex = 5, // For relocation patches
|
||||
IsLastEntry = 5, // For import patches
|
||||
SegmentIndex = 5, // For relocation patches
|
||||
IsResolved = 6,
|
||||
Addend = 8,
|
||||
};
|
||||
|
@ -129,7 +133,7 @@ namespace RelocationPatch {
|
|||
AbsoluteAddress = 2,
|
||||
};
|
||||
};
|
||||
};
|
||||
}; // namespace RelocationPatch
|
||||
|
||||
struct CROHeaderEntry {
|
||||
u32 offset, size;
|
||||
|
@ -144,12 +148,12 @@ static const std::string CRR_MAGIC("CRR0");
|
|||
class CRO {
|
||||
Memory &mem;
|
||||
|
||||
u32 croPointer; // Origin address of CRO in RAM
|
||||
u32 croPointer; // Origin address of CRO in RAM
|
||||
u32 oldDataSegmentOffset;
|
||||
|
||||
bool isCRO; // False if CRS
|
||||
bool isCRO; // False if CRS
|
||||
|
||||
public:
|
||||
public:
|
||||
CRO(Memory &mem, u32 croPointer, bool isCRO) : mem(mem), croPointer(croPointer), oldDataSegmentOffset(0), isCRO(isCRO) {}
|
||||
~CRO() = default;
|
||||
|
||||
|
@ -159,21 +163,13 @@ public:
|
|||
return mem.readString(moduleName.offset, moduleName.size);
|
||||
}
|
||||
|
||||
u32 getNextCRO() {
|
||||
return mem.read32(croPointer + CROHeader::NextCRO);
|
||||
}
|
||||
|
||||
u32 getPrevCRO() {
|
||||
return mem.read32(croPointer + CROHeader::PrevCRO);
|
||||
}
|
||||
u32 getNextCRO() { return mem.read32(croPointer + CROHeader::NextCRO); }
|
||||
|
||||
void setNextCRO(u32 nextCRO) {
|
||||
mem.write32(croPointer + CROHeader::NextCRO, nextCRO);
|
||||
}
|
||||
u32 getPrevCRO() { return mem.read32(croPointer + CROHeader::PrevCRO); }
|
||||
|
||||
void setPrevCRO(u32 prevCRO) {
|
||||
mem.write32(croPointer + CROHeader::PrevCRO, prevCRO);
|
||||
}
|
||||
void setNextCRO(u32 nextCRO) { mem.write32(croPointer + CROHeader::NextCRO, nextCRO); }
|
||||
|
||||
void setPrevCRO(u32 prevCRO) { mem.write32(croPointer + CROHeader::PrevCRO, prevCRO); }
|
||||
|
||||
void write32(u32 addr, u32 value) {
|
||||
// Note: some games export symbols to the static module, which doesn't contain any segments.
|
||||
|
@ -181,11 +177,11 @@ public:
|
|||
// can't be accessed via mem.write32()
|
||||
auto writePointer = mem.getWritePointer(addr);
|
||||
if (writePointer) {
|
||||
*(u32*)writePointer = value;
|
||||
*(u32 *)writePointer = value;
|
||||
} else {
|
||||
auto readPointer = mem.getReadPointer(addr);
|
||||
if (readPointer) {
|
||||
*(u32*)readPointer = value;
|
||||
*(u32 *)readPointer = value;
|
||||
} else {
|
||||
Helpers::panic("LDR_RO write to invalid address = %X\n", addr);
|
||||
}
|
||||
|
@ -219,11 +215,9 @@ public:
|
|||
return entryOffset + offset;
|
||||
}
|
||||
|
||||
u32 getOnUnresolvedAddr() {
|
||||
return getSegmentAddr(mem.read32(croPointer + CROHeader::OnUnresolved));
|
||||
}
|
||||
u32 getOnUnresolvedAddr() { return getSegmentAddr(mem.read32(croPointer + CROHeader::OnUnresolved)); }
|
||||
|
||||
u32 getNamedExportSymbolAddr(const std::string& symbolName) {
|
||||
u32 getNamedExportSymbolAddr(const std::string &symbolName) {
|
||||
// Note: The CRO contains a trie for fast symbol lookup. For simplicity,
|
||||
// we won't use it and instead look up the symbol in the named export symbol table
|
||||
|
||||
|
@ -233,7 +227,7 @@ public:
|
|||
|
||||
for (u32 namedExport = 0; namedExport < namedExportTable.size; namedExport++) {
|
||||
const u32 nameOffset = mem.read32(namedExportTable.offset + 8 * namedExport + NamedExportTable::NameOffset);
|
||||
|
||||
|
||||
const std::string exportSymbolName = mem.readString(nameOffset, exportStringSize);
|
||||
|
||||
if (symbolName.compare(exportSymbolName) == 0) {
|
||||
|
@ -437,13 +431,16 @@ public:
|
|||
const u32 segmentID = mem.read32(segmentTable.offset + 12 * segment + SegmentTable::ID);
|
||||
switch (segmentID) {
|
||||
case SegmentTable::SegmentID::DATA:
|
||||
*oldDataVaddr = segmentOffset + croPointer; oldDataSegmentOffset = segmentOffset; segmentOffset = dataVaddr; break;
|
||||
*oldDataVaddr = segmentOffset + croPointer;
|
||||
oldDataSegmentOffset = segmentOffset;
|
||||
segmentOffset = dataVaddr;
|
||||
break;
|
||||
case SegmentTable::SegmentID::BSS: segmentOffset = bssVaddr; break;
|
||||
case SegmentTable::SegmentID::TEXT:
|
||||
case SegmentTable::SegmentID::RODATA:
|
||||
if (segmentOffset != 0) segmentOffset += croPointer; break;
|
||||
default:
|
||||
Helpers::panic("Unknown segment ID = %u", segmentID);
|
||||
if (segmentOffset != 0) segmentOffset += croPointer;
|
||||
break;
|
||||
default: Helpers::panic("Unknown segment ID = %u", segmentID);
|
||||
}
|
||||
|
||||
mem.write32(segmentTable.offset + 12 * segment + SegmentTable::Offset, segmentOffset);
|
||||
|
@ -464,9 +461,9 @@ public:
|
|||
case SegmentTable::SegmentID::BSS: segmentOffset = 0; break;
|
||||
case SegmentTable::SegmentID::TEXT:
|
||||
case SegmentTable::SegmentID::RODATA:
|
||||
if (segmentOffset != 0) segmentOffset -= croPointer; break;
|
||||
default:
|
||||
Helpers::panic("Unknown segment ID = %u", segmentID);
|
||||
if (segmentOffset != 0) segmentOffset -= croPointer;
|
||||
break;
|
||||
default: Helpers::panic("Unknown segment ID = %u", segmentID);
|
||||
}
|
||||
|
||||
mem.write32(segmentTable.offset + 12 * segment + SegmentTable::Offset, segmentOffset);
|
||||
|
@ -630,7 +627,9 @@ public:
|
|||
u32 relocationOffset = mem.read32(anonymousImportTable.offset + 8 * anonymousImport + AnonymousImportTable::RelocationOffset);
|
||||
|
||||
if (relocationOffset != 0) {
|
||||
mem.write32(anonymousImportTable.offset + 8 * anonymousImport + AnonymousImportTable::RelocationOffset, relocationOffset + croPointer);
|
||||
mem.write32(
|
||||
anonymousImportTable.offset + 8 * anonymousImport + AnonymousImportTable::RelocationOffset, relocationOffset + croPointer
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -644,7 +643,9 @@ public:
|
|||
u32 relocationOffset = mem.read32(anonymousImportTable.offset + 8 * anonymousImport + AnonymousImportTable::RelocationOffset);
|
||||
|
||||
if (relocationOffset != 0) {
|
||||
mem.write32(anonymousImportTable.offset + 8 * anonymousImport + AnonymousImportTable::RelocationOffset, relocationOffset - croPointer);
|
||||
mem.write32(
|
||||
anonymousImportTable.offset + 8 * anonymousImport + AnonymousImportTable::RelocationOffset, relocationOffset - croPointer
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -652,7 +653,7 @@ public:
|
|||
}
|
||||
|
||||
bool relocateInternalSymbols(u32 oldDataVaddr) {
|
||||
const u8* header = (u8*)mem.getReadPointer(croPointer);
|
||||
const u8 *header = (u8 *)mem.getReadPointer(croPointer);
|
||||
|
||||
const CROHeaderEntry relocationPatchTable = getHeaderEntry(CROHeader::RelocationPatchTableOffset);
|
||||
const CROHeaderEntry segmentTable = getHeaderEntry(CROHeader::SegmentTableOffset);
|
||||
|
@ -708,7 +709,7 @@ public:
|
|||
for (u32 namedImport = 0; namedImport < namedImportTable.size; namedImport++) {
|
||||
const u32 nameOffset = mem.read32(namedImportTable.offset + 8 * namedImport + NamedImportTable::NameOffset);
|
||||
const u32 relocationOffset = mem.read32(namedImportTable.offset + 8 * namedImport + NamedImportTable::RelocationOffset);
|
||||
|
||||
|
||||
const std::string symbolName = mem.readString(nameOffset, importStringSize);
|
||||
|
||||
if (symbolName.compare(std::string("__aeabi_atexit")) == 0) {
|
||||
|
@ -720,7 +721,7 @@ public:
|
|||
const u32 exportSymbolAddr = cro.getNamedExportSymbolAddr(std::string("nnroAeabiAtexit_"));
|
||||
if (exportSymbolAddr != 0) {
|
||||
patchBatch(relocationOffset, exportSymbolAddr);
|
||||
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -750,7 +751,7 @@ public:
|
|||
|
||||
if (isResolved == 0) {
|
||||
const u32 nameOffset = mem.read32(namedImportTable.offset + 8 * namedImport + NamedImportTable::NameOffset);
|
||||
|
||||
|
||||
const std::string symbolName = mem.readString(nameOffset, importStringSize);
|
||||
|
||||
// Check every loaded CRO for the symbol (the pain)
|
||||
|
@ -859,7 +860,7 @@ public:
|
|||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
bool clearModules() {
|
||||
const u32 onUnresolvedAddr = getOnUnresolvedAddr();
|
||||
|
||||
|
@ -874,7 +875,7 @@ public:
|
|||
if (indexedOffset == 0) {
|
||||
Helpers::panic("Indexed symbol offset is NULL");
|
||||
}
|
||||
|
||||
|
||||
const u32 relocationOffset = mem.read32(indexedOffset + 8 * indexedImport + IndexedImportTable::RelocationOffset);
|
||||
|
||||
patchBatch(relocationOffset, onUnresolvedAddr, true);
|
||||
|
@ -919,7 +920,7 @@ public:
|
|||
|
||||
if (isResolved == 0) {
|
||||
const u32 nameOffset = mem.read32(namedImportTable.offset + 8 * namedImport + NamedImportTable::NameOffset);
|
||||
|
||||
|
||||
const std::string symbolName = mem.readString(nameOffset, importStringSize);
|
||||
|
||||
// Check our current CRO for the symbol
|
||||
|
@ -983,7 +984,7 @@ public:
|
|||
u32 currentCROPointer = loadedCRS;
|
||||
while (currentCROPointer != 0) {
|
||||
CRO cro(mem, currentCROPointer, true);
|
||||
|
||||
|
||||
const u32 onUnresolvedAddr = cro.getOnUnresolvedAddr();
|
||||
|
||||
const u32 importStringSize = mem.read32(currentCROPointer + CROHeader::ImportStringSize);
|
||||
|
@ -998,7 +999,7 @@ public:
|
|||
|
||||
if (isResolved != 0) {
|
||||
const u32 nameOffset = mem.read32(namedImportTable.offset + 8 * namedImport + NamedImportTable::NameOffset);
|
||||
|
||||
|
||||
const std::string symbolName = mem.readString(nameOffset, importStringSize);
|
||||
|
||||
// Check our current CRO for the symbol
|
||||
|
@ -1106,7 +1107,7 @@ public:
|
|||
}
|
||||
|
||||
CRO crs(mem, loadedCRS, false);
|
||||
|
||||
|
||||
u32 headAddr = crs.getPrevCRO();
|
||||
if (autoLink) {
|
||||
headAddr = crs.getNextCRO();
|
||||
|
@ -1189,9 +1190,7 @@ public:
|
|||
}
|
||||
};
|
||||
|
||||
void LDRService::reset() {
|
||||
loadedCRS = 0;
|
||||
}
|
||||
void LDRService::reset() { loadedCRS = 0; }
|
||||
|
||||
void LDRService::handleSyncRequest(u32 messagePointer) {
|
||||
const u32 command = mem.read32(messagePointer);
|
||||
|
@ -1210,7 +1209,7 @@ void LDRService::initialize(u32 messagePointer) {
|
|||
const u32 crsPointer = mem.read32(messagePointer + 4);
|
||||
const u32 size = mem.read32(messagePointer + 8);
|
||||
const u32 mapVaddr = mem.read32(messagePointer + 12);
|
||||
const Handle process = mem.read32(messagePointer + 20);
|
||||
const HandleType process = mem.read32(messagePointer + 20);
|
||||
|
||||
log("LDR_RO::Initialize (buffer = %08X, size = %08X, vaddr = %08X, process = %X)\n", crsPointer, size, mapVaddr, process);
|
||||
|
||||
|
@ -1258,7 +1257,7 @@ void LDRService::initialize(u32 messagePointer) {
|
|||
|
||||
void LDRService::linkCRO(u32 messagePointer) {
|
||||
const u32 mapVaddr = mem.read32(messagePointer + 4);
|
||||
const Handle process = mem.read32(messagePointer + 12);
|
||||
const HandleType process = mem.read32(messagePointer + 12);
|
||||
|
||||
log("LDR_RO::LinkCRO (vaddr = %X, process = %X)\n", mapVaddr, process);
|
||||
|
||||
|
@ -1287,7 +1286,7 @@ void LDRService::linkCRO(u32 messagePointer) {
|
|||
void LDRService::loadCRR(u32 messagePointer) {
|
||||
const u32 crrPointer = mem.read32(messagePointer + 4);
|
||||
const u32 size = mem.read32(messagePointer + 8);
|
||||
const Handle process = mem.read32(messagePointer + 20);
|
||||
const HandleType process = mem.read32(messagePointer + 20);
|
||||
|
||||
log("LDR_RO::LoadCRR (buffer = %08X, size = %08X, process = %X)\n", crrPointer, size, process);
|
||||
mem.write32(messagePointer, IPC::responseHeader(0x2, 1, 0));
|
||||
|
@ -1304,9 +1303,11 @@ void LDRService::loadCRO(u32 messagePointer, bool isNew) {
|
|||
const u32 bssSize = mem.read32(messagePointer + 32);
|
||||
const bool autoLink = mem.read32(messagePointer + 36) != 0;
|
||||
const u32 fixLevel = mem.read32(messagePointer + 40);
|
||||
const Handle process = mem.read32(messagePointer + 52);
|
||||
const HandleType process = mem.read32(messagePointer + 52);
|
||||
|
||||
log("LDR_RO::LoadCRO (isNew = %d, buffer = %08X, vaddr = %08X, size = %08X, .data vaddr = %08X, .data size = %08X, .bss vaddr = %08X, .bss size = %08X, auto link = %d, fix level = %X, process = %X)\n", isNew, croPointer, mapVaddr, size, dataVaddr, dataSize, bssVaddr, bssSize, autoLink, fixLevel, process);
|
||||
log("LDR_RO::LoadCRO (isNew = %d, buffer = %08X, vaddr = %08X, size = %08X, .data vaddr = %08X, .data size = %08X, .bss vaddr = %08X, .bss size "
|
||||
"= %08X, auto link = %d, fix level = %X, process = %X)\n",
|
||||
isNew, croPointer, mapVaddr, size, dataVaddr, dataSize, bssVaddr, bssSize, autoLink, fixLevel, process);
|
||||
|
||||
// Sanity checks
|
||||
if (size < CRO_HEADER_SIZE) {
|
||||
|
@ -1362,7 +1363,7 @@ void LDRService::loadCRO(u32 messagePointer, bool isNew) {
|
|||
void LDRService::unloadCRO(u32 messagePointer) {
|
||||
const u32 mapVaddr = mem.read32(messagePointer + 4);
|
||||
const u32 croPointer = mem.read32(messagePointer + 12);
|
||||
const Handle process = mem.read32(messagePointer + 20);
|
||||
const HandleType process = mem.read32(messagePointer + 20);
|
||||
|
||||
log("LDR_RO::UnloadCRO (vaddr = %08X, buffer = %08X, process = %X)\n", mapVaddr, croPointer, process);
|
||||
|
||||
|
@ -1392,4 +1393,4 @@ void LDRService::unloadCRO(u32 messagePointer) {
|
|||
|
||||
mem.write32(messagePointer, IPC::responseHeader(0x5, 1, 0));
|
||||
mem.write32(messagePointer + 4, Result::Success);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -8,8 +8,8 @@
|
|||
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), 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) {}
|
||||
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) {}
|
||||
|
||||
static constexpr int MAX_NOTIFICATION_COUNT = 16;
|
||||
|
||||
|
@ -68,7 +68,7 @@ namespace Commands {
|
|||
};
|
||||
}
|
||||
|
||||
// Handle an IPC message issued using the SendSyncRequest SVC
|
||||
// HandleType an IPC message issued using the SendSyncRequest SVC
|
||||
// The parameters are stored in thread-local storage in this format: https://www.3dbrew.org/wiki/IPC#Message_Structure
|
||||
// messagePointer: The base pointer for the IPC message
|
||||
void ServiceManager::handleSyncRequest(u32 messagePointer) {
|
||||
|
@ -93,7 +93,7 @@ void ServiceManager::registerClient(u32 messagePointer) {
|
|||
}
|
||||
|
||||
// clang-format off
|
||||
static std::map<std::string, Handle> serviceMap = {
|
||||
static std::map<std::string, HandleType> serviceMap = {
|
||||
{ "ac:u", KernelHandles::AC },
|
||||
{ "act:a", KernelHandles::ACT },
|
||||
{ "act:u", KernelHandles::ACT },
|
||||
|
@ -165,9 +165,9 @@ void ServiceManager::enableNotification(u32 messagePointer) {
|
|||
}
|
||||
|
||||
mem.write32(messagePointer, IPC::responseHeader(0x2, 1, 2));
|
||||
mem.write32(messagePointer + 4, Result::Success); // Result code
|
||||
mem.write32(messagePointer + 8, 0); // Translation descriptor
|
||||
// Handle to semaphore signaled on process notification
|
||||
mem.write32(messagePointer + 4, Result::Success); // Result code
|
||||
mem.write32(messagePointer + 8, 0); // Translation descriptor
|
||||
// HandleType to semaphore signaled on process notification
|
||||
mem.write32(messagePointer + 12, notificationSemaphore.value());
|
||||
}
|
||||
|
||||
|
@ -175,8 +175,8 @@ void ServiceManager::receiveNotification(u32 messagePointer) {
|
|||
log("srv::ReceiveNotification() (STUBBED)\n");
|
||||
|
||||
mem.write32(messagePointer, IPC::responseHeader(0xB, 2, 0));
|
||||
mem.write32(messagePointer + 4, Result::Success); // Result code
|
||||
mem.write32(messagePointer + 8, 0); // Notification ID
|
||||
mem.write32(messagePointer + 4, Result::Success); // Result code
|
||||
mem.write32(messagePointer + 8, 0); // Notification ID
|
||||
}
|
||||
|
||||
void ServiceManager::subscribe(u32 messagePointer) {
|
||||
|
@ -195,7 +195,7 @@ void ServiceManager::unsubscribe(u32 messagePointer) {
|
|||
mem.write32(messagePointer + 4, Result::Success);
|
||||
}
|
||||
|
||||
void ServiceManager::sendCommandToService(u32 messagePointer, Handle handle) {
|
||||
void ServiceManager::sendCommandToService(u32 messagePointer, HandleType handle) {
|
||||
switch (handle) {
|
||||
// Breaking alphabetical order a bit to place the ones I think are most common at the top
|
||||
case KernelHandles::GPU: [[likely]] gsp_gpu.handleSyncRequest(messagePointer); break;
|
||||
|
@ -237,4 +237,4 @@ void ServiceManager::sendCommandToService(u32 messagePointer, Handle handle) {
|
|||
case KernelHandles::Y2R: y2r.handleSyncRequest(messagePointer); break;
|
||||
default: Helpers::panic("Sent IPC message to unknown service %08X\n Command: %08X", handle, mem.read32(messagePointer));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -21,7 +21,7 @@ void SOCService::handleSyncRequest(u32 messagePointer) {
|
|||
|
||||
void SOCService::initializeSockets(u32 messagePointer) {
|
||||
const u32 memoryBlockSize = mem.read32(messagePointer + 4);
|
||||
const Handle sharedMemHandle = mem.read32(messagePointer + 20);
|
||||
const HandleType sharedMemHandle = mem.read32(messagePointer + 20);
|
||||
log("SOC::InitializeSockets (memory block size = %08X, shared mem handle = %08X)\n", memoryBlockSize, sharedMemHandle);
|
||||
|
||||
// TODO: Does double initialization return an error code?
|
||||
|
@ -30,4 +30,4 @@ void SOCService::initializeSockets(u32 messagePointer) {
|
|||
|
||||
mem.write32(messagePointer, IPC::responseHeader(0x01, 1, 0));
|
||||
mem.write32(messagePointer + 4, Result::Success);
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue