mirror of
https://github.com/wheremyfoodat/Panda3DS.git
synced 2025-04-09 23:55:40 +12:00
[DSP] HLE DSP state & some of the audio pipe
This commit is contained in:
parent
a44ac89c78
commit
fdeb45d188
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!
|
// Circular dependencies!
|
||||||
class Kernel;
|
class Kernel;
|
||||||
|
|
||||||
|
@ -52,9 +58,14 @@ class DSPService {
|
||||||
Kernel& kernel;
|
Kernel& kernel;
|
||||||
MAKE_LOG_FUNCTION(log, dspServiceLogger)
|
MAKE_LOG_FUNCTION(log, dspServiceLogger)
|
||||||
|
|
||||||
|
enum class DSPState : u32 {
|
||||||
|
Off, On, Slep
|
||||||
|
};
|
||||||
|
|
||||||
// Number of DSP pipes
|
// Number of DSP pipes
|
||||||
static constexpr size_t pipeCount = 8;
|
static constexpr size_t pipeCount = 8;
|
||||||
DSPPipe audioPipe;
|
DSPPipe audioPipe;
|
||||||
|
DSPState dspState;
|
||||||
|
|
||||||
// DSP service event handles
|
// DSP service event handles
|
||||||
using DSPEvent = std::optional<Handle>;
|
using DSPEvent = std::optional<Handle>;
|
||||||
|
@ -78,6 +89,8 @@ class DSPService {
|
||||||
void invalidateDCache(u32 messagePointer);
|
void invalidateDCache(u32 messagePointer);
|
||||||
void loadComponent(u32 messagePointer);
|
void loadComponent(u32 messagePointer);
|
||||||
void readPipeIfPossible(u32 messagePointer);
|
void readPipeIfPossible(u32 messagePointer);
|
||||||
|
void recvData(u32 messagePointer);
|
||||||
|
void recvDataIsReady(u32 messagePointer);
|
||||||
void registerInterruptEvents(u32 messagePointer);
|
void registerInterruptEvents(u32 messagePointer);
|
||||||
void setSemaphore(u32 messagePointer);
|
void setSemaphore(u32 messagePointer);
|
||||||
void setSemaphoreMask(u32 messagePointer);
|
void setSemaphoreMask(u32 messagePointer);
|
||||||
|
|
|
@ -4,6 +4,8 @@
|
||||||
|
|
||||||
namespace DSPCommands {
|
namespace DSPCommands {
|
||||||
enum : u32 {
|
enum : u32 {
|
||||||
|
RecvData = 0x00010040,
|
||||||
|
RecvDataIsReady = 0x00020040,
|
||||||
SetSemaphore = 0x00070040,
|
SetSemaphore = 0x00070040,
|
||||||
ConvertProcessAddressFromDspDram = 0x000C0040,
|
ConvertProcessAddressFromDspDram = 0x000C0040,
|
||||||
WriteProcessPipe = 0x000D0082,
|
WriteProcessPipe = 0x000D0082,
|
||||||
|
@ -29,6 +31,7 @@ namespace Result {
|
||||||
void DSPService::reset() {
|
void DSPService::reset() {
|
||||||
audioPipe.reset();
|
audioPipe.reset();
|
||||||
totalEventCount = 0;
|
totalEventCount = 0;
|
||||||
|
dspState = DSPState::Off;
|
||||||
|
|
||||||
semaphoreEvent = std::nullopt;
|
semaphoreEvent = std::nullopt;
|
||||||
interrupt0 = std::nullopt;
|
interrupt0 = std::nullopt;
|
||||||
|
@ -49,6 +52,8 @@ void DSPService::handleSyncRequest(u32 messagePointer) {
|
||||||
case DSPCommands::GetSemaphoreEventHandle: getSemaphoreEventHandle(messagePointer); break;
|
case DSPCommands::GetSemaphoreEventHandle: getSemaphoreEventHandle(messagePointer); break;
|
||||||
case DSPCommands::LoadComponent: loadComponent(messagePointer); break;
|
case DSPCommands::LoadComponent: loadComponent(messagePointer); break;
|
||||||
case DSPCommands::ReadPipeIfPossible: readPipeIfPossible(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::RegisterInterruptEvents: registerInterruptEvents(messagePointer); break;
|
||||||
case DSPCommands::SetSemaphore: setSemaphore(messagePointer); break;
|
case DSPCommands::SetSemaphore: setSemaphore(messagePointer); break;
|
||||||
case DSPCommands::SetSemaphoreMask: setSemaphoreMask(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
|
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) {
|
DSPService::DSPEvent& DSPService::getEventRef(u32 type, u32 pipe) {
|
||||||
switch (type) {
|
switch (type) {
|
||||||
case 0: return interrupt0;
|
case 0: return interrupt0;
|
||||||
|
@ -192,8 +220,47 @@ void DSPService::writeProcessPipe(u32 messagePointer) {
|
||||||
const u32 channel = mem.read32(messagePointer + 4);
|
const u32 channel = mem.read32(messagePointer + 4);
|
||||||
const u32 size = mem.read32(messagePointer + 8);
|
const u32 size = mem.read32(messagePointer + 8);
|
||||||
const u32 buffer = mem.read32(messagePointer + 16);
|
const u32 buffer = mem.read32(messagePointer + 16);
|
||||||
|
|
||||||
log("DSP::writeProcessPipe (channel = %d, size = %X, buffer = %08X)\n", channel, size, buffer);
|
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, IPC::responseHeader(0xD, 1, 0));
|
||||||
mem.write32(messagePointer + 4, Result::Success);
|
mem.write32(messagePointer + 4, Result::Success);
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Reference in a new issue