Ge Callbacks seem to be working now.
This commit is contained in:
parent
1ae7528de1
commit
8a082f91cc
9 changed files with 99 additions and 83 deletions
|
@ -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()
|
||||||
{
|
{
|
||||||
|
|
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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);
|
||||||
|
|
|
@ -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:
|
||||||
|
|
|
@ -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();
|
||||||
};
|
};
|
||||||
|
|
|
@ -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;
|
||||||
};
|
};
|
||||||
|
|
|
@ -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:
|
||||||
|
|
|
@ -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();
|
||||||
};
|
};
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue