mirror of
https://github.com/hrydgard/ppsspp.git
synced 2024-11-23 05:19:56 +00:00
Defer HLE interrupts, vblank only when enabled.
Based on tests, vblank doesn't queue up (makes sense) while interrupts are disabled. I'm not 100% sure about the GPU stuff but it seems to only come from HLE via sceGe, so this should fix those return values.
This commit is contained in:
parent
99b24720b8
commit
9034cfbfd3
@ -26,6 +26,7 @@
|
||||
#include "sceAudio.h"
|
||||
#include "sceKernelMemory.h"
|
||||
#include "sceKernelThread.h"
|
||||
#include "sceKernelInterrupt.h"
|
||||
#include "../MIPS/MIPSCodeUtils.h"
|
||||
|
||||
enum
|
||||
@ -40,6 +41,8 @@ enum
|
||||
HLE_AFTER_ALL_CALLBACKS = 0x04,
|
||||
// Reschedule and process current thread's callbacks after the syscall.
|
||||
HLE_AFTER_RESCHED_CALLBACKS = 0x08,
|
||||
// Run interrupts (and probably reschedule) after the syscall.
|
||||
HLE_AFTER_RUN_INTERRUPTS = 0x10,
|
||||
};
|
||||
|
||||
static std::vector<HLEModule> moduleDB;
|
||||
@ -231,11 +234,19 @@ void hleReSchedule(bool callbacks, const char *reason)
|
||||
hleAfterSyscall |= HLE_AFTER_RESCHED_CALLBACKS;
|
||||
}
|
||||
|
||||
void hleRunInterrupts()
|
||||
{
|
||||
hleAfterSyscall |= HLE_AFTER_RUN_INTERRUPTS;
|
||||
}
|
||||
|
||||
inline void hleFinishSyscall()
|
||||
{
|
||||
if ((hleAfterSyscall & HLE_AFTER_CURRENT_CALLBACKS) != 0)
|
||||
__KernelForceCallbacks();
|
||||
|
||||
if ((hleAfterSyscall & HLE_AFTER_RUN_INTERRUPTS) != 0)
|
||||
__RunOnePendingInterrupt();
|
||||
|
||||
// Rescheduling will also do HLE_AFTER_ALL_CALLBACKS.
|
||||
if ((hleAfterSyscall & HLE_AFTER_RESCHED_CALLBACKS) != 0)
|
||||
__KernelReSchedule(true, hleAfterSyscallReschedReason);
|
||||
|
@ -81,6 +81,8 @@ void hleCheckAllCallbacks();
|
||||
void hleReSchedule(const char *reason);
|
||||
// Reschedule and go into a callback processing state after the syscall finishes.
|
||||
void hleReSchedule(bool callbacks, const char *reason);
|
||||
// Run interrupts after the syscall finishes.
|
||||
void hleRunInterrupts();
|
||||
|
||||
void HLEInit();
|
||||
void HLEShutdown();
|
||||
|
@ -151,7 +151,7 @@ void hleEnterVblank(u64 userdata, int cyclesLate)
|
||||
vblankWaitingThreads.clear();
|
||||
|
||||
// Trigger VBlank interrupt handlers.
|
||||
__TriggerInterrupt(PSP_VBLANK_INTR);
|
||||
__TriggerInterrupt(PSP_INTR_IMMEDIATE | PSP_INTR_ONLY_IF_ENABLED, PSP_VBLANK_INTR);
|
||||
|
||||
CoreTiming::ScheduleEvent(msToCycles(vblankMs) - cyclesLate, leaveVblankEvent, vbCount+1);
|
||||
|
||||
|
@ -88,10 +88,8 @@ void __KernelTriggerAlarm(u64 userdata, int cyclesLate)
|
||||
|
||||
u32 error;
|
||||
Alarm *alarm = kernelObjects.Get<Alarm>(uid, error);
|
||||
|
||||
// TODO: Need to find out the return value.
|
||||
if (alarm)
|
||||
__TriggerInterrupt(PSP_SYSTIMER0_INTR, uid);
|
||||
__TriggerInterrupt(PSP_INTR_IMMEDIATE, PSP_SYSTIMER0_INTR, uid);
|
||||
}
|
||||
|
||||
void __KernelScheduleAlarm(Alarm *alarm, int ticks)
|
||||
|
@ -273,20 +273,36 @@ bool __RunOnePendingInterrupt()
|
||||
}
|
||||
}
|
||||
|
||||
void __TriggerInterrupt(PSPInterrupt intno, int subintr)
|
||||
void __TriggerInterrupt(int type, PSPInterrupt intno, int subintr)
|
||||
{
|
||||
intrHandlers[intno].queueUp(subintr);
|
||||
DEBUG_LOG(HLE, "Triggering subinterrupts for interrupt %i sub %i (%i in queue)", intno, subintr, pendingInterrupts.size());
|
||||
if (!inInterrupt)
|
||||
__RunOnePendingInterrupt();
|
||||
if (interruptsEnabled || (type & PSP_INTR_ONLY_IF_ENABLED) == 0)
|
||||
{
|
||||
intrHandlers[intno].queueUp(subintr);
|
||||
DEBUG_LOG(HLE, "Triggering subinterrupts for interrupt %i sub %i (%i in queue)", intno, subintr, pendingInterrupts.size());
|
||||
if (!inInterrupt)
|
||||
{
|
||||
if ((type & PSP_INTR_HLE) != 0)
|
||||
hleRunInterrupts();
|
||||
else
|
||||
__RunOnePendingInterrupt();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void __TriggerInterruptWithArg(PSPInterrupt intno, int subintr, int arg)
|
||||
void __TriggerInterruptWithArg(int type, 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();
|
||||
if (interruptsEnabled || (type & PSP_INTR_ONLY_IF_ENABLED) == 0)
|
||||
{
|
||||
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 ((type & PSP_INTR_HLE) != 0)
|
||||
hleRunInterrupts();
|
||||
else
|
||||
__RunOnePendingInterrupt();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void __KernelReturnFromInterrupt()
|
||||
|
@ -54,6 +54,15 @@ enum PSPGeSubInterrupts {
|
||||
PSP_GE_SUBINTR_SIGNAL = 15
|
||||
};
|
||||
|
||||
enum PSPInterruptTriggerType {
|
||||
// Trigger immediately, for CoreTiming events.
|
||||
PSP_INTR_IMMEDIATE = 0x0,
|
||||
// Trigger after the HLE syscall finishes.
|
||||
PSP_INTR_HLE = 0x1,
|
||||
// Only trigger (as above) if interrupts are not suspended.
|
||||
PSP_INTR_ONLY_IF_ENABLED = 0x2,
|
||||
};
|
||||
|
||||
class AllegrexInterruptHandler;
|
||||
|
||||
struct PendingInterrupt {
|
||||
@ -91,8 +100,8 @@ public:
|
||||
bool __IsInInterrupt();
|
||||
void __InterruptsInit();
|
||||
void __InterruptsShutdown();
|
||||
void __TriggerInterrupt(PSPInterrupt intno, int subInterrupts = -1);
|
||||
void __TriggerInterruptWithArg(PSPInterrupt intno, int subintr, int arg); // For GE "callbacks"
|
||||
void __TriggerInterrupt(int type, PSPInterrupt intno, int subInterrupts = -1);
|
||||
void __TriggerInterruptWithArg(int type, PSPInterrupt intno, int subintr, int arg); // For GE "callbacks"
|
||||
bool __RunOnePendingInterrupt();
|
||||
void __KernelReturnFromInterrupt();
|
||||
|
||||
|
@ -488,8 +488,9 @@ void GLES_GPU::ExecuteOp(u32 op, u32 diff)
|
||||
|
||||
case GE_CMD_FINISH:
|
||||
DEBUG_LOG(G3D,"DL CMD FINISH");
|
||||
// TODO: Should this run while interrupts are suspended?
|
||||
if (interruptsEnabled_)
|
||||
__TriggerInterruptWithArg(PSP_GE_INTR, PSP_GE_SUBINTR_FINISH, 0);
|
||||
__TriggerInterruptWithArg(PSP_INTR_HLE, PSP_GE_INTR, PSP_GE_SUBINTR_FINISH, 0);
|
||||
break;
|
||||
|
||||
case GE_CMD_END:
|
||||
@ -525,8 +526,9 @@ void GLES_GPU::ExecuteOp(u32 op, u32 diff)
|
||||
ERROR_LOG(G3D, "UNKNOWN Signal UNIMPLEMENTED %i ! signal/end: %04x %04x", behaviour, signal, enddata);
|
||||
break;
|
||||
}
|
||||
// TODO: Should this run while interrupts are suspended?
|
||||
if (interruptsEnabled_)
|
||||
__TriggerInterruptWithArg(PSP_GE_INTR, PSP_GE_SUBINTR_SIGNAL, signal);
|
||||
__TriggerInterruptWithArg(PSP_INTR_HLE, PSP_GE_INTR, PSP_GE_SUBINTR_SIGNAL, signal);
|
||||
}
|
||||
break;
|
||||
case GE_CMD_FINISH:
|
||||
|
@ -206,8 +206,9 @@ void NullGPU::ExecuteOp(u32 op, u32 diff)
|
||||
int behaviour = (data >> 16) & 0xFF;
|
||||
int signal = data & 0xFFFF;
|
||||
|
||||
// TODO: Should this run while interrupts are suspended?
|
||||
if (interruptsEnabled_)
|
||||
__TriggerInterruptWithArg(PSP_GE_INTR, PSP_GE_SUBINTR_SIGNAL, signal);
|
||||
__TriggerInterruptWithArg(PSP_INTR_HLE, PSP_GE_INTR, PSP_GE_SUBINTR_SIGNAL, signal);
|
||||
}
|
||||
break;
|
||||
|
||||
@ -237,8 +238,9 @@ void NullGPU::ExecuteOp(u32 op, u32 diff)
|
||||
|
||||
case GE_CMD_FINISH:
|
||||
DEBUG_LOG(G3D,"DL CMD FINISH");
|
||||
// TODO: Should this run while interrupts are suspended?
|
||||
if (interruptsEnabled_)
|
||||
__TriggerInterruptWithArg(PSP_GE_INTR, PSP_GE_SUBINTR_FINISH, 0);
|
||||
__TriggerInterruptWithArg(PSP_INTR_HLE, PSP_GE_INTR, PSP_GE_SUBINTR_FINISH, 0);
|
||||
break;
|
||||
|
||||
case GE_CMD_END:
|
||||
|
Loading…
Reference in New Issue
Block a user