[DSP] HLE DSP state & some of the audio pipe

This commit is contained in:
wheremyfoodat 2023-05-17 01:17:10 +03:00
parent 4dc04be350
commit e7085dd830
2 changed files with 81 additions and 1 deletions

View file

@ -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);

View file

@ -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);
}