From e9650f1c6197baa7e532559964f42578bdde42d5 Mon Sep 17 00:00:00 2001 From: bunnei Date: Mon, 5 Jan 2015 00:19:28 -0500 Subject: DSP: Signal (faked) interrupt on every frame. - Hack to work around games checking that the DSP event has been signaled by a real DSP interrupt. --- src/core/hle/service/dsp_dsp.cpp | 22 ++++++++++++++++++---- src/core/hle/service/dsp_dsp.h | 3 +++ src/core/hw/gpu.cpp | 8 +++++++- 3 files changed, 28 insertions(+), 5 deletions(-) diff --git a/src/core/hle/service/dsp_dsp.cpp b/src/core/hle/service/dsp_dsp.cpp index 2cf4d118..d4affdfb 100644 --- a/src/core/hle/service/dsp_dsp.cpp +++ b/src/core/hle/service/dsp_dsp.cpp @@ -12,9 +12,23 @@ namespace DSP_DSP { -static u32 read_pipe_count; -static Handle semaphore_event; -static Handle interrupt_event; +static u32 read_pipe_count = 0; +static Handle semaphore_event = 0; +static Handle interrupt_event = 0; + +void SignalInterrupt() { + // TODO(bunnei): This is just a stub, it does not do anything other than signal to the emulated + // application that a DSP interrupt occurred, without specifying which one. Since we do not + // emulate the DSP yet (and how it works is largely unknown), this is a work around to get games + // that check the DSP interrupt signal event to run. We should figure out the different types of + // DSP interrupts, and trigger them at the appropriate times. + + if (interrupt_event == 0) { + LOG_WARNING(Service_DSP, "cannot signal interrupt until DSP event has been created!"); + return; + } + Kernel::SignalEvent(interrupt_event); +} /** * DSP_DSP::ConvertProcessAddressFromDspDram service function @@ -102,7 +116,7 @@ void RegisterInterruptEvents(Service::Interface* self) { void WriteReg0x10(Service::Interface* self) { u32* cmd_buff = Kernel::GetCommandBuffer(); - Kernel::SignalEvent(interrupt_event); + SignalInterrupt(); cmd_buff[1] = 0; // No error diff --git a/src/core/hle/service/dsp_dsp.h b/src/core/hle/service/dsp_dsp.h index 0b8b6460..fa13bfb7 100644 --- a/src/core/hle/service/dsp_dsp.h +++ b/src/core/hle/service/dsp_dsp.h @@ -20,4 +20,7 @@ public: } }; +/// Signals that a DSP interrupt has occurred to userland code +void SignalInterrupt(); + } // namespace diff --git a/src/core/hw/gpu.cpp b/src/core/hw/gpu.cpp index 0ff6c6cd..e346e0ad 100644 --- a/src/core/hw/gpu.cpp +++ b/src/core/hw/gpu.cpp @@ -10,6 +10,7 @@ #include "core/hle/hle.h" #include "core/hle/service/gsp_gpu.h" +#include "core/hle/service/dsp_dsp.h" #include "core/hw/gpu.h" @@ -214,13 +215,18 @@ void Update() { // - If frameskip == 0 (disabled), always swap buffers // - If frameskip == 1, swap buffers every other frame (starting from the first frame) // - If frameskip > 1, swap buffers every frameskip^n frames (starting from the second frame) - if ((((Settings::values.frame_skip != 1) ^ last_skip_frame) && last_skip_frame != g_skip_frame) || Settings::values.frame_skip == 0) { VideoCore::g_renderer->SwapBuffers(); } + // Signal to GSP that GPU interrupt has occurred GSP_GPU::SignalInterrupt(GSP_GPU::InterruptId::PDC1); + + // TODO(bunnei): Fake a DSP interrupt on each frame. This does not belong here, but + // until we can emulate DSP interrupts, this is probably the only reasonable place to do + // this. Certain games expect this to be periodically signaled. + DSP_DSP::SignalInterrupt(); } } } -- cgit v1.2.3