Properly handle DSP interrupts in HLE

This commit is contained in:
wheremyfoodat 2024-02-19 18:50:41 +02:00
parent 7a5bb2859e
commit f7c6ec3b57
7 changed files with 43 additions and 22 deletions

View file

@ -1,5 +1,7 @@
#include "audio/null_core.hpp"
#include "services/dsp.hpp"
namespace Audio {
namespace DSPPipeType {
enum : u32 {
@ -45,11 +47,41 @@ namespace Audio {
}
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
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) {
if (regId != 0) {
@ -84,6 +116,8 @@ namespace Audio {
// TODO: Other initialization stuff here
dspState = DSPState::On;
resetAudioPipe();
dspService.triggerPipeEvent(DSPPipeType::Audio);
break;
case StateChange::Shutdown:
@ -98,6 +132,9 @@ namespace Audio {
case DSPPipeType::Binary:
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;
default: log("Audio::NullDSP: Wrote to unimplemented pipe %d\n", channel); break;

View file

@ -262,16 +262,6 @@ void DSPService::invalidateDCache(u32 messagePointer) {
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) {
if (index < pipeCount && pipeEvents[index].has_value()) {
kernel.signalEvent(*pipeEvents[index]);

View file

@ -123,10 +123,6 @@ void GPUService::registerInterruptRelayQueue(u32 messagePointer) {
}
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
return;
}