mirror of
https://github.com/wheremyfoodat/Panda3DS.git
synced 2025-04-07 14:45:41 +12:00
[DSP] HLE DSP state & some of the audio pipe
This commit is contained in:
parent
4dc04be350
commit
e7085dd830
2 changed files with 81 additions and 1 deletions
|
@ -43,6 +43,12 @@ public:
|
|||
}
|
||||
};
|
||||
|
||||
namespace DSPPipeType {
|
||||
enum : u32 {
|
||||
Debug = 0, DMA = 1, Audio = 2, Binary = 3
|
||||
};
|
||||
}
|
||||
|
||||
// Circular dependencies!
|
||||
class Kernel;
|
||||
|
||||
|
@ -52,9 +58,14 @@ class DSPService {
|
|||
Kernel& kernel;
|
||||
MAKE_LOG_FUNCTION(log, dspServiceLogger)
|
||||
|
||||
enum class DSPState : u32 {
|
||||
Off, On, Slep
|
||||
};
|
||||
|
||||
// Number of DSP pipes
|
||||
static constexpr size_t pipeCount = 8;
|
||||
DSPPipe audioPipe;
|
||||
DSPState dspState;
|
||||
|
||||
// DSP service event handles
|
||||
using DSPEvent = std::optional<Handle>;
|
||||
|
@ -78,6 +89,8 @@ class DSPService {
|
|||
void invalidateDCache(u32 messagePointer);
|
||||
void loadComponent(u32 messagePointer);
|
||||
void readPipeIfPossible(u32 messagePointer);
|
||||
void recvData(u32 messagePointer);
|
||||
void recvDataIsReady(u32 messagePointer);
|
||||
void registerInterruptEvents(u32 messagePointer);
|
||||
void setSemaphore(u32 messagePointer);
|
||||
void setSemaphoreMask(u32 messagePointer);
|
||||
|
|
|
@ -4,6 +4,8 @@
|
|||
|
||||
namespace DSPCommands {
|
||||
enum : u32 {
|
||||
RecvData = 0x00010040,
|
||||
RecvDataIsReady = 0x00020040,
|
||||
SetSemaphore = 0x00070040,
|
||||
ConvertProcessAddressFromDspDram = 0x000C0040,
|
||||
WriteProcessPipe = 0x000D0082,
|
||||
|
@ -29,6 +31,7 @@ namespace Result {
|
|||
void DSPService::reset() {
|
||||
audioPipe.reset();
|
||||
totalEventCount = 0;
|
||||
dspState = DSPState::Off;
|
||||
|
||||
semaphoreEvent = std::nullopt;
|
||||
interrupt0 = std::nullopt;
|
||||
|
@ -49,6 +52,8 @@ void DSPService::handleSyncRequest(u32 messagePointer) {
|
|||
case DSPCommands::GetSemaphoreEventHandle: getSemaphoreEventHandle(messagePointer); break;
|
||||
case DSPCommands::LoadComponent: loadComponent(messagePointer); break;
|
||||
case DSPCommands::ReadPipeIfPossible: readPipeIfPossible(messagePointer); break;
|
||||
case DSPCommands::RecvData: recvData(messagePointer); break;
|
||||
case DSPCommands::RecvDataIsReady: recvDataIsReady(messagePointer); break;
|
||||
case DSPCommands::RegisterInterruptEvents: registerInterruptEvents(messagePointer); break;
|
||||
case DSPCommands::SetSemaphore: setSemaphore(messagePointer); break;
|
||||
case DSPCommands::SetSemaphoreMask: setSemaphoreMask(messagePointer); break;
|
||||
|
@ -107,6 +112,29 @@ void DSPService::readPipeIfPossible(u32 messagePointer) {
|
|||
mem.write16(messagePointer + 8, i); // Number of bytes read
|
||||
}
|
||||
|
||||
void DSPService::recvData(u32 messagePointer) {
|
||||
const u32 registerIndex = mem.read32(messagePointer + 4);
|
||||
log("DSP::RecvData (register = %d)\n", registerIndex);
|
||||
if (registerIndex != 0) Helpers::panic("Unknown register in DSP::RecvData");
|
||||
|
||||
// Return 0 if the DSP is running, otherwise 1
|
||||
const u16 ret = dspState == DSPState::On ? 0 : 1;
|
||||
|
||||
mem.write32(messagePointer, IPC::responseHeader(0x01, 2, 0));
|
||||
mem.write32(messagePointer + 4, Result::Success);
|
||||
mem.write16(messagePointer + 8, ret); // Always return that the DSP is on
|
||||
}
|
||||
|
||||
void DSPService::recvDataIsReady(u32 messagePointer) {
|
||||
const u32 registerIndex = mem.read32(messagePointer + 4);
|
||||
log("DSP::RecvDataIsReady (register = %d)\n", registerIndex);
|
||||
if (registerIndex != 0) Helpers::panic("Unknown register in DSP::RecvDataIsReady");
|
||||
|
||||
mem.write32(messagePointer, IPC::responseHeader(0x02, 2, 0));
|
||||
mem.write32(messagePointer + 4, Result::Success);
|
||||
mem.write32(messagePointer + 8, 1); // Always return that the register is ready for now
|
||||
}
|
||||
|
||||
DSPService::DSPEvent& DSPService::getEventRef(u32 type, u32 pipe) {
|
||||
switch (type) {
|
||||
case 0: return interrupt0;
|
||||
|
@ -192,8 +220,47 @@ void DSPService::writeProcessPipe(u32 messagePointer) {
|
|||
const u32 channel = mem.read32(messagePointer + 4);
|
||||
const u32 size = mem.read32(messagePointer + 8);
|
||||
const u32 buffer = mem.read32(messagePointer + 16);
|
||||
|
||||
log("DSP::writeProcessPipe (channel = %d, size = %X, buffer = %08X)\n", channel, size, buffer);
|
||||
|
||||
enum class StateChange : u8 {
|
||||
Initialize = 0,
|
||||
Shutdown = 1,
|
||||
Wakeup = 2,
|
||||
Sleep = 3,
|
||||
};
|
||||
|
||||
switch (channel) {
|
||||
case DSPPipeType::Audio: {
|
||||
if (size != 4) {
|
||||
printf("Invalid size written to DSP Audio Pipe\n");
|
||||
break;
|
||||
}
|
||||
|
||||
// Get new state
|
||||
const u8 state = mem.read8(buffer);
|
||||
if (state > 3) {
|
||||
log("WriteProcessPipe::Audio: Unknown state change type");
|
||||
} else {
|
||||
switch (static_cast<StateChange>(state)) {
|
||||
case StateChange::Initialize:
|
||||
// TODO: Other initialization stuff here
|
||||
dspState = DSPState::On;
|
||||
break;
|
||||
|
||||
case StateChange::Shutdown:
|
||||
dspState = DSPState::Off;
|
||||
break;
|
||||
|
||||
default: Helpers::panic("Unimplemented DSP audio pipe state change %d", state);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
default:
|
||||
log("DSP: Wrote to unimplemented pipe %d\n", channel);
|
||||
break;
|
||||
}
|
||||
|
||||
mem.write32(messagePointer, IPC::responseHeader(0xD, 1, 0));
|
||||
mem.write32(messagePointer + 4, Result::Success);
|
||||
}
|
||||
|
|
Loading…
Add table
Reference in a new issue