mirror of
https://github.com/hrydgard/ppsspp.git
synced 2025-02-02 11:43:31 +00:00
Don't trash a list the GE interrupt handler needs.
Even after it's marked COMPLETED, the CPU needs it to start and finish the interrupt. Fixes #2956, where an existing completed list was not having its interrupt run correctly.
This commit is contained in:
parent
cfbf83eeab
commit
8998a1b303
@ -55,6 +55,11 @@ public:
|
||||
{
|
||||
GeInterruptData intrdata = ge_pending_cb.front();
|
||||
DisplayList* dl = gpu->getList(intrdata.listid);
|
||||
if (!dl->interruptsEnabled)
|
||||
{
|
||||
ERROR_LOG_REPORT(HLE, "Unable to run GE interrupt: list has interrupts disabled, should not happen");
|
||||
return false;
|
||||
}
|
||||
|
||||
if (dl == NULL)
|
||||
{
|
||||
@ -120,6 +125,11 @@ public:
|
||||
ge_pending_cb.pop_front();
|
||||
|
||||
DisplayList* dl = gpu->getList(intrdata.listid);
|
||||
if (!dl->interruptsEnabled)
|
||||
{
|
||||
ERROR_LOG_REPORT(HLE, "Unable to finish GE interrupt: list has interrupts disabled, should not happen");
|
||||
return;
|
||||
}
|
||||
|
||||
switch (dl->signal)
|
||||
{
|
||||
|
@ -187,13 +187,13 @@ u32 GPUCommon::EnqueueList(u32 listpc, u32 stall, int subIntrBase, bool head) {
|
||||
// return 0x80000021;
|
||||
//}
|
||||
}
|
||||
if (dls[i].state == PSP_GE_DL_STATE_NONE)
|
||||
if (dls[i].state == PSP_GE_DL_STATE_NONE && !dls[i].pendingInterrupt)
|
||||
{
|
||||
// Prefer a list that isn't used
|
||||
id = i;
|
||||
break;
|
||||
}
|
||||
if (id < 0 && dls[i].state == PSP_GE_DL_STATE_COMPLETED && dls[i].waitTicks < currentTicks)
|
||||
if (id < 0 && dls[i].state == PSP_GE_DL_STATE_COMPLETED && !dls[i].pendingInterrupt && dls[i].waitTicks < currentTicks)
|
||||
{
|
||||
id = i;
|
||||
}
|
||||
@ -806,8 +806,10 @@ void GPUCommon::ExecuteOp(u32 op, u32 diff) {
|
||||
}
|
||||
// TODO: Technically, jump/call/ret should generate an interrupt, but before the pc change maybe?
|
||||
if (currentList->interruptsEnabled && trigger) {
|
||||
if (__GeTriggerInterrupt(currentList->id, currentList->pc, startingTicks + cyclesExecuted))
|
||||
if (__GeTriggerInterrupt(currentList->id, currentList->pc, startingTicks + cyclesExecuted)) {
|
||||
currentList->pendingInterrupt = true;
|
||||
UpdateState(GPUSTATE_INTERRUPT);
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
@ -815,8 +817,10 @@ void GPUCommon::ExecuteOp(u32 op, u32 diff) {
|
||||
switch (currentList->signal) {
|
||||
case PSP_GE_SIGNAL_HANDLER_PAUSE:
|
||||
if (currentList->interruptsEnabled) {
|
||||
if (__GeTriggerInterrupt(currentList->id, currentList->pc, startingTicks + cyclesExecuted))
|
||||
if (__GeTriggerInterrupt(currentList->id, currentList->pc, startingTicks + cyclesExecuted)) {
|
||||
currentList->pendingInterrupt = true;
|
||||
UpdateState(GPUSTATE_INTERRUPT);
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
@ -829,7 +833,9 @@ void GPUCommon::ExecuteOp(u32 op, u32 diff) {
|
||||
currentList->subIntrToken = prev & 0xFFFF;
|
||||
currentList->state = PSP_GE_DL_STATE_COMPLETED;
|
||||
UpdateState(GPUSTATE_DONE);
|
||||
if (!currentList->interruptsEnabled || !__GeTriggerInterrupt(currentList->id, currentList->pc, startingTicks + cyclesExecuted)) {
|
||||
if (currentList->interruptsEnabled && __GeTriggerInterrupt(currentList->id, currentList->pc, startingTicks + cyclesExecuted)) {
|
||||
currentList->pendingInterrupt = true;
|
||||
} else {
|
||||
currentList->waitTicks = startingTicks + cyclesExecuted;
|
||||
busyTicks = std::max(busyTicks, currentList->waitTicks);
|
||||
__GeTriggerSync(WAITTYPE_GELISTSYNC, currentList->id, currentList->waitTicks);
|
||||
@ -883,6 +889,7 @@ void GPUCommon::InterruptEnd(int listid) {
|
||||
isbreak = false;
|
||||
|
||||
DisplayList &dl = dls[listid];
|
||||
dl.pendingInterrupt = false;
|
||||
// TODO: Unless the signal handler could change it?
|
||||
if (dl.state == PSP_GE_DL_STATE_COMPLETED || dl.state == PSP_GE_DL_STATE_NONE) {
|
||||
dl.waitTicks = 0;
|
||||
|
@ -129,6 +129,7 @@ struct DisplayList
|
||||
bool interrupted;
|
||||
u64 waitTicks;
|
||||
bool interruptsEnabled;
|
||||
bool pendingInterrupt;
|
||||
};
|
||||
|
||||
enum GPUInvalidationType {
|
||||
|
Loading…
x
Reference in New Issue
Block a user