mirror of
https://github.com/wheremyfoodat/Panda3DS.git
synced 2025-04-07 14:45:41 +12:00
Properly handle DSP interrupts in HLE
This commit is contained in:
parent
7a5bb2859e
commit
f7c6ec3b57
7 changed files with 43 additions and 22 deletions
|
@ -20,12 +20,14 @@ namespace Audio {
|
||||||
std::array<u8, Memory::DSP_RAM_SIZE> dspRam;
|
std::array<u8, Memory::DSP_RAM_SIZE> dspRam;
|
||||||
|
|
||||||
void resetAudioPipe();
|
void resetAudioPipe();
|
||||||
|
bool loaded = false; // Have we loaded a component?
|
||||||
|
|
||||||
public:
|
public:
|
||||||
NullDSP(Memory& mem, Scheduler& scheduler, DSPService& dspService) : DSPCore(mem, scheduler, dspService) {}
|
NullDSP(Memory& mem, Scheduler& scheduler, DSPService& dspService) : DSPCore(mem, scheduler, dspService) {}
|
||||||
|
|
||||||
void reset() override;
|
void reset() override;
|
||||||
void runAudioFrame() override {}
|
void runAudioFrame() override;
|
||||||
|
|
||||||
u8* getDspMemory() override { return dspRam.data(); }
|
u8* getDspMemory() override { return dspRam.data(); }
|
||||||
|
|
||||||
u16 recvData(u32 regId) override;
|
u16 recvData(u32 regId) override;
|
||||||
|
@ -34,8 +36,8 @@ namespace Audio {
|
||||||
std::vector<u8> readPipe(u32 channel, u32 peer, u32 size, u32 buffer) override;
|
std::vector<u8> readPipe(u32 channel, u32 peer, u32 size, u32 buffer) override;
|
||||||
|
|
||||||
// NOPs for null DSP core
|
// NOPs for null DSP core
|
||||||
void loadComponent(std::vector<u8>& data, u32 programMask, u32 dataMask) override {}
|
void loadComponent(std::vector<u8>& data, u32 programMask, u32 dataMask) override;
|
||||||
void unloadComponent() override {}
|
void unloadComponent() override;
|
||||||
void setSemaphore(u16 value) override {}
|
void setSemaphore(u16 value) override {}
|
||||||
void setSemaphoreMask(u16 value) override {}
|
void setSemaphoreMask(u16 value) override {}
|
||||||
};
|
};
|
||||||
|
|
|
@ -245,6 +245,5 @@ public:
|
||||||
ServiceManager& getServiceManager() { return serviceManager; }
|
ServiceManager& getServiceManager() { return serviceManager; }
|
||||||
|
|
||||||
void sendGPUInterrupt(GPUInterrupt type) { serviceManager.sendGPUInterrupt(type); }
|
void sendGPUInterrupt(GPUInterrupt type) { serviceManager.sendGPUInterrupt(type); }
|
||||||
void signalDSPEvents() { serviceManager.signalDSPEvents(); }
|
|
||||||
void clearInstructionCache();
|
void clearInstructionCache();
|
||||||
};
|
};
|
|
@ -66,7 +66,6 @@ public:
|
||||||
Surround = 2
|
Surround = 2
|
||||||
};
|
};
|
||||||
|
|
||||||
void signalEvents();
|
|
||||||
void triggerPipeEvent(int index);
|
void triggerPipeEvent(int index);
|
||||||
void triggerSemaphoreEvent();
|
void triggerSemaphoreEvent();
|
||||||
void triggerInterrupt0();
|
void triggerInterrupt0();
|
||||||
|
|
|
@ -105,8 +105,6 @@ class ServiceManager {
|
||||||
void setHIDSharedMem(u8* ptr) { hid.setSharedMem(ptr); }
|
void setHIDSharedMem(u8* ptr) { hid.setSharedMem(ptr); }
|
||||||
void setCSNDSharedMem(u8* ptr) { csnd.setSharedMemory(ptr); }
|
void setCSNDSharedMem(u8* ptr) { csnd.setSharedMemory(ptr); }
|
||||||
|
|
||||||
void signalDSPEvents() { dsp.signalEvents(); }
|
|
||||||
|
|
||||||
// Input function wrappers
|
// Input function wrappers
|
||||||
HIDService& getHID() { return hid; }
|
HIDService& getHID() { return hid; }
|
||||||
NFCService& getNFC() { return nfc; }
|
NFCService& getNFC() { return nfc; }
|
||||||
|
|
|
@ -1,5 +1,7 @@
|
||||||
#include "audio/null_core.hpp"
|
#include "audio/null_core.hpp"
|
||||||
|
|
||||||
|
#include "services/dsp.hpp"
|
||||||
|
|
||||||
namespace Audio {
|
namespace Audio {
|
||||||
namespace DSPPipeType {
|
namespace DSPPipeType {
|
||||||
enum : u32 {
|
enum : u32 {
|
||||||
|
@ -45,11 +47,41 @@ namespace Audio {
|
||||||
}
|
}
|
||||||
|
|
||||||
void NullDSP::reset() {
|
void NullDSP::reset() {
|
||||||
for (auto& e : pipeData) e.clear();
|
loaded = false;
|
||||||
|
for (auto& e : pipeData) {
|
||||||
|
e.clear();
|
||||||
|
}
|
||||||
|
|
||||||
// Note: Reset audio pipe AFTER resetting all pipes, otherwise the new data will be yeeted
|
// Note: Reset audio pipe AFTER resetting all pipes, otherwise the new data will be yeeted
|
||||||
resetAudioPipe();
|
resetAudioPipe();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void NullDSP::loadComponent(std::vector<u8>& data, u32 programMask, u32 dataMask) {
|
||||||
|
if (loaded) {
|
||||||
|
Helpers::warn("Loading DSP component when already loaded");
|
||||||
|
}
|
||||||
|
|
||||||
|
loaded = true;
|
||||||
|
scheduler.addEvent(Scheduler::EventType::RunDSP, scheduler.currentTimestamp + Audio::cyclesPerFrame);
|
||||||
|
}
|
||||||
|
|
||||||
|
void NullDSP::unloadComponent() {
|
||||||
|
if (!loaded) {
|
||||||
|
Helpers::warn("Audio: unloadComponent called without a running program");
|
||||||
|
}
|
||||||
|
|
||||||
|
loaded = false;
|
||||||
|
scheduler.removeEvent(Scheduler::EventType::RunDSP);
|
||||||
|
}
|
||||||
|
|
||||||
|
void NullDSP::runAudioFrame() {
|
||||||
|
// Signal audio pipe when an audio frame is done
|
||||||
|
if (dspState == DSPState::On) [[likely]] {
|
||||||
|
dspService.triggerPipeEvent(DSPPipeType::Audio);
|
||||||
|
}
|
||||||
|
|
||||||
|
scheduler.addEvent(Scheduler::EventType::RunDSP, scheduler.currentTimestamp + Audio::cyclesPerFrame);
|
||||||
|
}
|
||||||
|
|
||||||
u16 NullDSP::recvData(u32 regId) {
|
u16 NullDSP::recvData(u32 regId) {
|
||||||
if (regId != 0) {
|
if (regId != 0) {
|
||||||
|
@ -84,6 +116,8 @@ namespace Audio {
|
||||||
// TODO: Other initialization stuff here
|
// TODO: Other initialization stuff here
|
||||||
dspState = DSPState::On;
|
dspState = DSPState::On;
|
||||||
resetAudioPipe();
|
resetAudioPipe();
|
||||||
|
|
||||||
|
dspService.triggerPipeEvent(DSPPipeType::Audio);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case StateChange::Shutdown:
|
case StateChange::Shutdown:
|
||||||
|
@ -98,6 +132,9 @@ namespace Audio {
|
||||||
|
|
||||||
case DSPPipeType::Binary:
|
case DSPPipeType::Binary:
|
||||||
Helpers::warn("Unimplemented write to binary pipe! Size: %d\n", size);
|
Helpers::warn("Unimplemented write to binary pipe! Size: %d\n", size);
|
||||||
|
|
||||||
|
// This pipe and interrupt are normally used for requests like AAC decode
|
||||||
|
dspService.triggerPipeEvent(DSPPipeType::Binary);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
default: log("Audio::NullDSP: Wrote to unimplemented pipe %d\n", channel); break;
|
default: log("Audio::NullDSP: Wrote to unimplemented pipe %d\n", channel); break;
|
||||||
|
|
|
@ -262,16 +262,6 @@ void DSPService::invalidateDCache(u32 messagePointer) {
|
||||||
mem.write32(messagePointer + 4, Result::Success);
|
mem.write32(messagePointer + 4, Result::Success);
|
||||||
}
|
}
|
||||||
|
|
||||||
void DSPService::signalEvents() {
|
|
||||||
for (const DSPEvent& e : pipeEvents) {
|
|
||||||
if (e.has_value()) { kernel.signalEvent(e.value()); }
|
|
||||||
}
|
|
||||||
|
|
||||||
if (semaphoreEvent.has_value()) { kernel.signalEvent(semaphoreEvent.value()); }
|
|
||||||
if (interrupt0.has_value()) { kernel.signalEvent(interrupt0.value()); }
|
|
||||||
if (interrupt1.has_value()) { kernel.signalEvent(interrupt1.value()); }
|
|
||||||
}
|
|
||||||
|
|
||||||
void DSPService::triggerPipeEvent(int index) {
|
void DSPService::triggerPipeEvent(int index) {
|
||||||
if (index < pipeCount && pipeEvents[index].has_value()) {
|
if (index < pipeCount && pipeEvents[index].has_value()) {
|
||||||
kernel.signalEvent(*pipeEvents[index]);
|
kernel.signalEvent(*pipeEvents[index]);
|
||||||
|
|
|
@ -123,10 +123,6 @@ void GPUService::registerInterruptRelayQueue(u32 messagePointer) {
|
||||||
}
|
}
|
||||||
|
|
||||||
void GPUService::requestInterrupt(GPUInterrupt type) {
|
void GPUService::requestInterrupt(GPUInterrupt type) {
|
||||||
// HACK: Signal DSP events on GPU interrupt for now until we have the DSP since games need DSP events
|
|
||||||
// Maybe there's a better alternative?
|
|
||||||
//kernel.signalDSPEvents();
|
|
||||||
|
|
||||||
if (sharedMem == nullptr) [[unlikely]] { // Shared memory hasn't been set up yet
|
if (sharedMem == nullptr) [[unlikely]] { // Shared memory hasn't been set up yet
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Reference in a new issue