Ge Callbacks seem to be working now.

This commit is contained in:
Henrik Rydgard 2012-11-06 18:14:09 +01:00
parent 1ae7528de1
commit 8a082f91cc
9 changed files with 99 additions and 83 deletions

View file

@ -108,15 +108,9 @@ u32 sceGeDrawSync(u32)
//wait/check entire drawing state //wait/check entire drawing state
u32 mode = PARAM(0); //0 : wait for completion 1:check and return u32 mode = PARAM(0); //0 : wait for completion 1:check and return
DEBUG_LOG(HLE,"FAKE sceGeDrawSync(mode=%d) (0=wait for completion)",mode); DEBUG_LOG(HLE,"FAKE sceGeDrawSync(mode=%d) (0=wait for completion)",mode);
if (mode == 1) gpu->DrawSync(mode);
{
return 0; return 0;
} }
else
{
return 0;
}
}
void sceGeBreak() void sceGeBreak()
{ {

View file

@ -35,6 +35,8 @@ struct Interrupt
// Yeah, this bit is a bit silly. // Yeah, this bit is a bit silly.
static int interruptsEnabled = 1; static int interruptsEnabled = 1;
static bool inInterrupt;
void __InterruptsInit() void __InterruptsInit()
{ {
interruptsEnabled = 1; interruptsEnabled = 1;
@ -60,8 +62,6 @@ bool __InterruptsEnabled()
} }
// InterruptsManager // InterruptsManager
////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////
// INTERRUPT MANAGEMENT // INTERRUPT MANAGEMENT
@ -116,8 +116,6 @@ void sceKernelCpuResumeIntrWithSync(u32 enable)
static bool inInterrupt;
bool __IsInInterrupt() bool __IsInInterrupt()
{ {
return inInterrupt; return inInterrupt;
@ -128,30 +126,51 @@ bool __CanExecuteInterrupt()
return !inInterrupt; return !inInterrupt;
} }
class AllegrexInterruptHandler;
struct PendingInterrupt {
AllegrexInterruptHandler *handler;
int arg;
bool hasArg;
};
class AllegrexInterruptHandler class AllegrexInterruptHandler
{ {
public: public:
virtual ~AllegrexInterruptHandler() {} virtual ~AllegrexInterruptHandler() {}
virtual void copyArgsToCPU() = 0; virtual void copyArgsToCPU(const PendingInterrupt &pend) = 0;
virtual void queueUp() = 0; virtual void queueUp() = 0;
virtual void queueUpWithArg(int arg) = 0;
}; };
std::list<PendingInterrupt> pendingInterrupts;
std::list<AllegrexInterruptHandler *> pendingInterrupts;
class SubIntrHandler : public AllegrexInterruptHandler class SubIntrHandler : public AllegrexInterruptHandler
{ {
public: public:
SubIntrHandler() {}
virtual void queueUp() 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->pc = handlerAddress;
currentMIPS->r[MIPS_REG_A0] = number; currentMIPS->r[MIPS_REG_A0] = pend.hasArg ? pend.arg : number;
currentMIPS->r[MIPS_REG_A1] = handlerArg; currentMIPS->r[MIPS_REG_A1] = handlerArg;
// RA is already taken care of // RA is already taken care of
} }
@ -162,8 +181,6 @@ public:
u32 handlerArg; u32 handlerArg;
}; };
class IntrHandler { class IntrHandler {
public: public:
void add(int subIntrNum, SubIntrHandler handler) void add(int subIntrNum, SubIntrHandler handler)
@ -185,16 +202,28 @@ public:
// what to do, what to do... // what to do, what to do...
} }
void queueUp() void queueUp(int subintr)
{ {
// Just call execute on all the subintr handlers for this interrupt. // Just call execute on all the subintr handlers for this interrupt.
// They will get queued up. // They will get queued up.
for (std::map<int, SubIntrHandler>::iterator iter = subIntrHandlers.begin(); iter != subIntrHandlers.end(); ++iter) for (std::map<int, SubIntrHandler>::iterator iter = subIntrHandlers.begin(); iter != subIntrHandlers.end(); ++iter)
{ {
if (subintr == -1 || iter->first == subintr)
iter->second.queueUp(); 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<int, SubIntrHandler>::iterator iter = subIntrHandlers.begin(); iter != subIntrHandlers.end(); ++iter)
{
if (subintr == -1 || iter->first == subintr)
iter->second.queueUpWithArg(arg);
}
}
private: private:
std::map<int, SubIntrHandler> subIntrHandlers; std::map<int, SubIntrHandler> subIntrHandlers;
}; };
@ -242,13 +271,13 @@ bool __RunOnePendingInterrupt()
// Can easily prioritize between different kinds of interrupts if necessary. // Can easily prioritize between different kinds of interrupts if necessary.
if (pendingInterrupts.size()) if (pendingInterrupts.size())
{ {
AllegrexInterruptHandler *front = pendingInterrupts.front(); PendingInterrupt pend = pendingInterrupts.front();
pendingInterrupts.pop_front(); pendingInterrupts.pop_front();
intState.save(); intState.save();
front->copyArgsToCPU(); pend.handler->copyArgsToCPU(pend);
currentMIPS->r[MIPS_REG_RA] = __KernelInterruptReturnAddress(); currentMIPS->r[MIPS_REG_RA] = __KernelInterruptReturnAddress();
inInterrupt = true; inInterrupt = true;
DEBUG_LOG(CPU, "Entering interrupt handler");
return true; return true;
} }
else else
@ -258,17 +287,25 @@ bool __RunOnePendingInterrupt()
} }
} }
void __TriggerInterrupt(PSPInterrupt intno) void __TriggerInterrupt(PSPInterrupt intno, int subintr)
{ {
intrHandlers[intno].queueUp(); intrHandlers[intno].queueUp(subintr);
DEBUG_LOG(HLE, "Triggering subinterrupts for interrupt %i (%i in queue)", intno, pendingInterrupts.size()); 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) if (!inInterrupt)
__RunOnePendingInterrupt(); __RunOnePendingInterrupt();
} }
void _sceKernelReturnFromInterrupt() void _sceKernelReturnFromInterrupt()
{ {
DEBUG_LOG(CPU, "Left interrupt handler"); DEBUG_LOG(CPU, "Left interrupt handler at %08x", currentMIPS->pc);
inInterrupt = false; inInterrupt = false;
// Restore context after running the interrupt. // Restore context after running the interrupt.
intState.restore(); intState.restore();
@ -296,7 +333,6 @@ u32 sceKernelRegisterSubIntrHandler(u32 intrNumber, u32 subIntrNumber, u32 handl
subIntrHandler.handlerAddress = handler; subIntrHandler.handlerAddress = handler;
subIntrHandler.handlerArg = handlerArg; subIntrHandler.handlerArg = handlerArg;
intrHandlers[intrNumber].add(subIntrNumber, subIntrHandler); intrHandlers[intrNumber].add(subIntrNumber, subIntrHandler);
return 0; return 0;
} }

View file

@ -57,7 +57,9 @@ enum PSPGeSubInterrupts {
bool __IsInInterrupt(); bool __IsInInterrupt();
void __InterruptsInit(); void __InterruptsInit();
void __InterruptsShutdown(); 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(); void _sceKernelReturnFromInterrupt();
u32 sceKernelRegisterSubIntrHandler(u32 intrNumber, u32 subIntrNumber, u32 handler, u32 handlerArg); u32 sceKernelRegisterSubIntrHandler(u32 intrNumber, u32 subIntrNumber, u32 handler, u32 handlerArg);

View file

@ -130,6 +130,11 @@ void GLES_GPU::UpdateStall(int listid, u32 newstall)
ProcessDLQueue(); ProcessDLQueue();
} }
void GLES_GPU::DrawSync(int mode)
{
}
// Just to get something on the screen, we'll just not subdivide correctly. // Just to get something on the screen, we'll just not subdivide correctly.
void drawBezier(int ucount, int vcount) void drawBezier(int ucount, int vcount)
{ {
@ -338,21 +343,13 @@ void GLES_GPU::ExecuteOp(u32 op, u32 diff)
break; break;
case GE_CMD_SIGNAL: case GE_CMD_SIGNAL:
ERROR_LOG(G3D, "DL GE_CMD_SIGNAL %08x", data & 0xFFFFFF);
{ {
// int behaviour = (data >> 16) & 0xFF; ERROR_LOG(G3D, "DL GE_CMD_SIGNAL %08x", data & 0xFFFFFF);
// int signal = data & 0xFFFF; 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; break;
case GE_CMD_BJUMP: case GE_CMD_BJUMP:
@ -385,18 +382,9 @@ void GLES_GPU::ExecuteOp(u32 op, u32 diff)
// offsetAddr = data<<8; // offsetAddr = data<<8;
break; break;
case GE_CMD_FINISH: case GE_CMD_FINISH:
DEBUG_LOG(G3D,"DL CMD FINISH"); DEBUG_LOG(G3D,"DL CMD FINISH");
// Trigger the finish callbacks __TriggerInterruptWithArg(PSP_GE_INTR, PSP_GE_SUBINTR_FINISH, 0);
{
// 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);
//}
}
break; break;
case GE_CMD_END: case GE_CMD_END:

View file

@ -28,6 +28,7 @@ public:
virtual void UpdateStall(int listid, u32 newstall); virtual void UpdateStall(int listid, u32 newstall);
virtual void ExecuteOp(u32 op, u32 diff); virtual void ExecuteOp(u32 op, u32 diff);
virtual bool InterpretList(); virtual bool InterpretList();
virtual void DrawSync(int mode);
private: private:
bool ProcessDLQueue(); bool ProcessDLQueue();
}; };

View file

@ -26,4 +26,5 @@ public:
virtual void UpdateStall(int listid, u32 newstall) = 0; virtual void UpdateStall(int listid, u32 newstall) = 0;
virtual void ExecuteOp(u32 op, u32 diff) = 0; virtual void ExecuteOp(u32 op, u32 diff) = 0;
virtual bool InterpretList() = 0; virtual bool InterpretList() = 0;
virtual void DrawSync(int mode) = 0;
}; };

View file

@ -20,6 +20,7 @@
#include "../GPUState.h" #include "../GPUState.h"
#include "../ge_constants.h" #include "../ge_constants.h"
#include "../../Core/MemMap.h" #include "../../Core/MemMap.h"
#include "../../Core/HLE/sceKernelInterrupt.h"
struct DisplayState struct DisplayState
{ {
@ -99,6 +100,14 @@ void NullGPU::UpdateStall(int listid, u32 newstall)
ProcessDLQueue(); ProcessDLQueue();
} }
void NullGPU::DrawSync(int mode)
{
if (mode == 0) // Wait for completion
{
__RunOnePendingInterrupt();
}
}
void NullGPU::ExecuteOp(u32 op, u32 diff) void NullGPU::ExecuteOp(u32 op, u32 diff)
{ {
u32 cmd = op >> 24; u32 cmd = op >> 24;
@ -186,21 +195,13 @@ void NullGPU::ExecuteOp(u32 op, u32 diff)
break; break;
case GE_CMD_SIGNAL: case GE_CMD_SIGNAL:
ERROR_LOG(G3D, "DL GE_CMD_SIGNAL %08x", data & 0xFFFFFF);
{ {
// int behaviour = (data >> 16) & 0xFF; ERROR_LOG(G3D, "DL GE_CMD_SIGNAL %08x", data & 0xFFFFFF);
// int signal = data & 0xFFFF; 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; break;
case GE_CMD_BJUMP: case GE_CMD_BJUMP:
@ -229,15 +230,7 @@ void NullGPU::ExecuteOp(u32 op, u32 diff)
case GE_CMD_FINISH: case GE_CMD_FINISH:
DEBUG_LOG(G3D,"DL CMD FINISH"); DEBUG_LOG(G3D,"DL CMD FINISH");
// Trigger the finish callbacks __TriggerInterruptWithArg(PSP_GE_INTR, PSP_GE_SUBINTR_FINISH, 0);
{
// 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);
//}
}
break; break;
case GE_CMD_END: case GE_CMD_END:

View file

@ -28,6 +28,7 @@ public:
virtual void UpdateStall(int listid, u32 newstall); virtual void UpdateStall(int listid, u32 newstall);
virtual void ExecuteOp(u32 op, u32 diff); virtual void ExecuteOp(u32 op, u32 diff);
virtual bool InterpretList(); virtual bool InterpretList();
virtual void DrawSync(int mode);
private: private:
bool ProcessDLQueue(); bool ProcessDLQueue();
}; };