aboutsummaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorGravatar bunnei <bunneidev@gmail.com>2015-01-05 00:19:28 -0500
committerGravatar bunnei <bunneidev@gmail.com>2015-01-05 00:25:37 -0500
commite9650f1c6197baa7e532559964f42578bdde42d5 (patch)
treeedbe5489f5ce966d76f71fa68d11ba8b79fcffe6
parentcc23269ff4d4dbd38d6e76aa6c2f1d76c53f2e30 (diff)
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.
-rw-r--r--src/core/hle/service/dsp_dsp.cpp22
-rw-r--r--src/core/hle/service/dsp_dsp.h3
-rw-r--r--src/core/hw/gpu.cpp8
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();
}
}
}