From 8a082f91ccebf7c23f1346f936567d9ccfb988bc Mon Sep 17 00:00:00 2001 From: Henrik Rydgard Date: Tue, 6 Nov 2012 18:14:09 +0100 Subject: [PATCH] Ge Callbacks seem to be working now. --- Core/HLE/sceDisplay.cpp | 12 ++--- Core/HLE/sceGe.cpp | 10 +--- Core/HLE/sceKernelInterrupt.cpp | 82 +++++++++++++++++++++-------- Core/HLE/sceKernelInterrupt.h | 4 +- GPU/GLES/DisplayListInterpreter.cpp | 34 ++++-------- GPU/GLES/DisplayListInterpreter.h | 1 + GPU/GPUInterface.h | 1 + GPU/Null/NullGpu.cpp | 37 ++++++------- GPU/Null/NullGpu.h | 1 + 9 files changed, 99 insertions(+), 83 deletions(-) diff --git a/Core/HLE/sceDisplay.cpp b/Core/HLE/sceDisplay.cpp index 8a497b27b4..aaacddecfd 100644 --- a/Core/HLE/sceDisplay.cpp +++ b/Core/HLE/sceDisplay.cpp @@ -282,12 +282,12 @@ float sceDisplayGetFramePerSec() const HLEFunction sceDisplay[] = { - {0x0E20F177,&WrapU_UUU, "sceDisplaySetMode"}, - {0x289D82FE,sceDisplaySetFramebuf, "sceDisplaySetFramebuf"}, - {0x36CDFADE,sceDisplayWaitVblank, "sceDisplayWaitVblank"}, - {0x984C27E7,sceDisplayWaitVblankStart, "sceDisplayWaitVblankStart"}, - {0x46F186C3,sceDisplayWaitVblankStartCB,"sceDisplayWaitVblankStartCB"}, - {0x8EB9EC49,sceDisplayWaitVblankStartCB,"sceDisplayWaitVblankCB"}, + {0x0E20F177,&WrapU_UUU, "sceDisplaySetMode"}, + {0x289D82FE,sceDisplaySetFramebuf, "sceDisplaySetFramebuf"}, + {0x36CDFADE,sceDisplayWaitVblank, "sceDisplayWaitVblank"}, + {0x984C27E7,sceDisplayWaitVblankStart, "sceDisplayWaitVblankStart"}, + {0x46F186C3,sceDisplayWaitVblankStartCB, "sceDisplayWaitVblankStartCB"}, + {0x8EB9EC49,sceDisplayWaitVblankStartCB, "sceDisplayWaitVblankCB"}, {0xdba6c4c4,&WrapF_V,"sceDisplayGetFramePerSec"}, {0x773dd3a3,sceDisplayGetCurrentHcount,"sceDisplayGetCurrentHcount"}, diff --git a/Core/HLE/sceGe.cpp b/Core/HLE/sceGe.cpp index 2b27e833eb..09bfffa97f 100644 --- a/Core/HLE/sceGe.cpp +++ b/Core/HLE/sceGe.cpp @@ -108,14 +108,8 @@ u32 sceGeDrawSync(u32) //wait/check entire drawing state u32 mode = PARAM(0); //0 : wait for completion 1:check and return DEBUG_LOG(HLE,"FAKE sceGeDrawSync(mode=%d) (0=wait for completion)",mode); - if (mode == 1) - { - return 0; - } - else - { - return 0; - } + gpu->DrawSync(mode); + return 0; } void sceGeBreak() diff --git a/Core/HLE/sceKernelInterrupt.cpp b/Core/HLE/sceKernelInterrupt.cpp index 7db8000a13..1e2f422ffa 100644 --- a/Core/HLE/sceKernelInterrupt.cpp +++ b/Core/HLE/sceKernelInterrupt.cpp @@ -35,6 +35,8 @@ struct Interrupt // Yeah, this bit is a bit silly. static int interruptsEnabled = 1; +static bool inInterrupt; + void __InterruptsInit() { interruptsEnabled = 1; @@ -60,8 +62,6 @@ bool __InterruptsEnabled() } - - // InterruptsManager ////////////////////////////////////////////////////////////////////////// // INTERRUPT MANAGEMENT @@ -116,8 +116,6 @@ void sceKernelCpuResumeIntrWithSync(u32 enable) -static bool inInterrupt; - bool __IsInInterrupt() { return inInterrupt; @@ -128,30 +126,51 @@ bool __CanExecuteInterrupt() return !inInterrupt; } +class AllegrexInterruptHandler; + +struct PendingInterrupt { + AllegrexInterruptHandler *handler; + int arg; + bool hasArg; +}; + class AllegrexInterruptHandler { public: virtual ~AllegrexInterruptHandler() {} - virtual void copyArgsToCPU() = 0; + virtual void copyArgsToCPU(const PendingInterrupt &pend) = 0; virtual void queueUp() = 0; + virtual void queueUpWithArg(int arg) = 0; }; - -std::list pendingInterrupts; +std::list pendingInterrupts; class SubIntrHandler : public AllegrexInterruptHandler { public: - virtual void queueUp() + SubIntrHandler() {} + virtual void queueUp() { - pendingInterrupts.push_back(this); + PendingInterrupt pend; + pend.handler = this; + pend.hasArg = false; + pendingInterrupts.push_back(pend); + } + virtual void queueUpWithArg(int arg) + { + PendingInterrupt pend; + pend.handler = this; + pend.arg = arg; + pend.hasArg = true; + pendingInterrupts.push_back(pend); } - virtual void copyArgsToCPU() + virtual void copyArgsToCPU(const PendingInterrupt &pend) { + DEBUG_LOG(CPU, "Entering interrupt handler %08x", handlerAddress); currentMIPS->pc = handlerAddress; - currentMIPS->r[MIPS_REG_A0] = number; + currentMIPS->r[MIPS_REG_A0] = pend.hasArg ? pend.arg : number; currentMIPS->r[MIPS_REG_A1] = handlerArg; // RA is already taken care of } @@ -162,8 +181,6 @@ public: u32 handlerArg; }; - - class IntrHandler { public: void add(int subIntrNum, SubIntrHandler handler) @@ -185,13 +202,25 @@ public: // what to do, what to do... } - void queueUp() + void queueUp(int subintr) { // Just call execute on all the subintr handlers for this interrupt. // They will get queued up. for (std::map::iterator iter = subIntrHandlers.begin(); iter != subIntrHandlers.end(); ++iter) { - iter->second.queueUp(); + if (subintr == -1 || iter->first == subintr) + iter->second.queueUp(); + } + } + + void queueUpWithArg(int subintr, int arg) + { + // Just call execute on all the subintr handlers for this interrupt. + // They will get queued up. + for (std::map::iterator iter = subIntrHandlers.begin(); iter != subIntrHandlers.end(); ++iter) + { + if (subintr == -1 || iter->first == subintr) + iter->second.queueUpWithArg(arg); } } @@ -242,13 +271,13 @@ bool __RunOnePendingInterrupt() // Can easily prioritize between different kinds of interrupts if necessary. if (pendingInterrupts.size()) { - AllegrexInterruptHandler *front = pendingInterrupts.front(); + PendingInterrupt pend = pendingInterrupts.front(); pendingInterrupts.pop_front(); intState.save(); - front->copyArgsToCPU(); + pend.handler->copyArgsToCPU(pend); + currentMIPS->r[MIPS_REG_RA] = __KernelInterruptReturnAddress(); inInterrupt = true; - DEBUG_LOG(CPU, "Entering interrupt handler"); return true; } else @@ -258,17 +287,25 @@ bool __RunOnePendingInterrupt() } } -void __TriggerInterrupt(PSPInterrupt intno) +void __TriggerInterrupt(PSPInterrupt intno, int subintr) { - intrHandlers[intno].queueUp(); - DEBUG_LOG(HLE, "Triggering subinterrupts for interrupt %i (%i in queue)", intno, pendingInterrupts.size()); + intrHandlers[intno].queueUp(subintr); + DEBUG_LOG(HLE, "Triggering subinterrupts for interrupt %i sub %i (%i in queue)", intno, subintr, pendingInterrupts.size()); + if (!inInterrupt) + __RunOnePendingInterrupt(); +} + +void __TriggerInterruptWithArg(PSPInterrupt intno, int subintr, int arg) +{ + intrHandlers[intno].queueUpWithArg(subintr, arg); + DEBUG_LOG(HLE, "Triggering subinterrupts for interrupt %i sub %i with arg %i (%i in queue)", intno, subintr, arg, pendingInterrupts.size()); if (!inInterrupt) __RunOnePendingInterrupt(); } void _sceKernelReturnFromInterrupt() { - DEBUG_LOG(CPU, "Left interrupt handler"); + DEBUG_LOG(CPU, "Left interrupt handler at %08x", currentMIPS->pc); inInterrupt = false; // Restore context after running the interrupt. intState.restore(); @@ -296,7 +333,6 @@ u32 sceKernelRegisterSubIntrHandler(u32 intrNumber, u32 subIntrNumber, u32 handl subIntrHandler.handlerAddress = handler; subIntrHandler.handlerArg = handlerArg; intrHandlers[intrNumber].add(subIntrNumber, subIntrHandler); - return 0; } diff --git a/Core/HLE/sceKernelInterrupt.h b/Core/HLE/sceKernelInterrupt.h index 4bd72ab9af..f4eaf349a4 100644 --- a/Core/HLE/sceKernelInterrupt.h +++ b/Core/HLE/sceKernelInterrupt.h @@ -57,7 +57,9 @@ enum PSPGeSubInterrupts { bool __IsInInterrupt(); void __InterruptsInit(); void __InterruptsShutdown(); -void __TriggerInterrupt(PSPInterrupt intno); +void __TriggerInterrupt(PSPInterrupt intno, int subInterrupts = -1); +void __TriggerInterruptWithArg(PSPInterrupt intno, int subintr, int arg); // For GE "callbacks" +bool __RunOnePendingInterrupt(); void _sceKernelReturnFromInterrupt(); u32 sceKernelRegisterSubIntrHandler(u32 intrNumber, u32 subIntrNumber, u32 handler, u32 handlerArg); diff --git a/GPU/GLES/DisplayListInterpreter.cpp b/GPU/GLES/DisplayListInterpreter.cpp index 775adc965b..7b3f0c496b 100644 --- a/GPU/GLES/DisplayListInterpreter.cpp +++ b/GPU/GLES/DisplayListInterpreter.cpp @@ -130,6 +130,11 @@ void GLES_GPU::UpdateStall(int listid, u32 newstall) ProcessDLQueue(); } +void GLES_GPU::DrawSync(int mode) +{ + +} + // Just to get something on the screen, we'll just not subdivide correctly. void drawBezier(int ucount, int vcount) { @@ -338,21 +343,13 @@ void GLES_GPU::ExecuteOp(u32 op, u32 diff) break; case GE_CMD_SIGNAL: - ERROR_LOG(G3D, "DL GE_CMD_SIGNAL %08x", data & 0xFFFFFF); { - // int behaviour = (data >> 16) & 0xFF; - // int signal = data & 0xFFFF; + ERROR_LOG(G3D, "DL GE_CMD_SIGNAL %08x", data & 0xFFFFFF); + int behaviour = (data >> 16) & 0xFF; + int signal = data & 0xFFFF; + + __TriggerInterruptWithArg(PSP_GE_INTR, PSP_GE_SUBINTR_SIGNAL, signal); } - - // This should generate a GE Interrupt - // __TriggerInterrupt(PSP_GE_INTR); - - // Apparently, these callbacks should be done in a special interrupt way. - //for (size_t i = 0; i < signalCallbacks.size(); i++) - //{ - // __KernelNotifyCallback(-1, signalCallbacks[i].first, signal); - //} - break; case GE_CMD_BJUMP: @@ -385,18 +382,9 @@ void GLES_GPU::ExecuteOp(u32 op, u32 diff) // offsetAddr = data<<8; break; - case GE_CMD_FINISH: DEBUG_LOG(G3D,"DL CMD FINISH"); - // Trigger the finish callbacks - { - // Apparently, these callbacks should be done in a special interrupt way. - - //for (size_t i = 0; i < finishCallbacks.size(); i++) - //{ - // __KernelNotifyCallback(-1, finishCallbacks[i].first, 0); - //} - } + __TriggerInterruptWithArg(PSP_GE_INTR, PSP_GE_SUBINTR_FINISH, 0); break; case GE_CMD_END: diff --git a/GPU/GLES/DisplayListInterpreter.h b/GPU/GLES/DisplayListInterpreter.h index 4d0de36722..179655e519 100644 --- a/GPU/GLES/DisplayListInterpreter.h +++ b/GPU/GLES/DisplayListInterpreter.h @@ -28,6 +28,7 @@ public: virtual void UpdateStall(int listid, u32 newstall); virtual void ExecuteOp(u32 op, u32 diff); virtual bool InterpretList(); + virtual void DrawSync(int mode); private: bool ProcessDLQueue(); }; diff --git a/GPU/GPUInterface.h b/GPU/GPUInterface.h index bfb4dca497..943141bd3b 100644 --- a/GPU/GPUInterface.h +++ b/GPU/GPUInterface.h @@ -26,4 +26,5 @@ public: virtual void UpdateStall(int listid, u32 newstall) = 0; virtual void ExecuteOp(u32 op, u32 diff) = 0; virtual bool InterpretList() = 0; + virtual void DrawSync(int mode) = 0; }; diff --git a/GPU/Null/NullGpu.cpp b/GPU/Null/NullGpu.cpp index 94403a52f5..66f92c520a 100644 --- a/GPU/Null/NullGpu.cpp +++ b/GPU/Null/NullGpu.cpp @@ -20,6 +20,7 @@ #include "../GPUState.h" #include "../ge_constants.h" #include "../../Core/MemMap.h" +#include "../../Core/HLE/sceKernelInterrupt.h" struct DisplayState { @@ -99,6 +100,14 @@ void NullGPU::UpdateStall(int listid, u32 newstall) ProcessDLQueue(); } +void NullGPU::DrawSync(int mode) +{ + if (mode == 0) // Wait for completion + { + __RunOnePendingInterrupt(); + } +} + void NullGPU::ExecuteOp(u32 op, u32 diff) { u32 cmd = op >> 24; @@ -186,21 +195,13 @@ void NullGPU::ExecuteOp(u32 op, u32 diff) break; case GE_CMD_SIGNAL: - ERROR_LOG(G3D, "DL GE_CMD_SIGNAL %08x", data & 0xFFFFFF); { - // int behaviour = (data >> 16) & 0xFF; - // int signal = data & 0xFFFF; + ERROR_LOG(G3D, "DL GE_CMD_SIGNAL %08x", data & 0xFFFFFF); + int behaviour = (data >> 16) & 0xFF; + int signal = data & 0xFFFF; + + __TriggerInterruptWithArg(PSP_GE_INTR, PSP_GE_SUBINTR_SIGNAL, signal); } - - // This should generate a GE Interrupt - // __TriggerInterrupt(PSP_GE_INTR); - - // Apparently, these callbacks should be done in a special interrupt way. - //for (size_t i = 0; i < signalCallbacks.size(); i++) - //{ - // __KernelNotifyCallback(-1, signalCallbacks[i].first, signal); - //} - break; case GE_CMD_BJUMP: @@ -229,15 +230,7 @@ void NullGPU::ExecuteOp(u32 op, u32 diff) case GE_CMD_FINISH: DEBUG_LOG(G3D,"DL CMD FINISH"); - // Trigger the finish callbacks - { - // Apparently, these callbacks should be done in a special interrupt way. - - //for (size_t i = 0; i < finishCallbacks.size(); i++) - //{ - // __KernelNotifyCallback(-1, finishCallbacks[i].first, 0); - //} - } + __TriggerInterruptWithArg(PSP_GE_INTR, PSP_GE_SUBINTR_FINISH, 0); break; case GE_CMD_END: diff --git a/GPU/Null/NullGpu.h b/GPU/Null/NullGpu.h index d20040dc45..26e49c53cb 100644 --- a/GPU/Null/NullGpu.h +++ b/GPU/Null/NullGpu.h @@ -28,6 +28,7 @@ public: virtual void UpdateStall(int listid, u32 newstall); virtual void ExecuteOp(u32 op, u32 diff); virtual bool InterpretList(); + virtual void DrawSync(int mode); private: bool ProcessDLQueue(); };