diff --git a/Core/CoreTiming.cpp b/Core/CoreTiming.cpp index ba5b50232d..df50415dea 100644 --- a/Core/CoreTiming.cpp +++ b/Core/CoreTiming.cpp @@ -326,7 +326,7 @@ s64 UnscheduleEvent(int event_type, u64 userdata) { if (first->type == event_type && first->userdata == userdata) { - result = first->time - globalTimer; + result = first->time - GetTicks(); Event *next = first->next; FreeEvent(first); @@ -345,7 +345,7 @@ s64 UnscheduleEvent(int event_type, u64 userdata) { if (ptr->type == event_type && ptr->userdata == userdata) { - result = ptr->time - globalTimer; + result = ptr->time - GetTicks(); prev->next = ptr->next; FreeEvent(ptr); @@ -371,7 +371,7 @@ s64 UnscheduleThreadsafeEvent(int event_type, u64 userdata) { if (tsFirst->type == event_type && tsFirst->userdata == userdata) { - result = tsFirst->time - globalTimer; + result = tsFirst->time - GetTicks(); Event *next = tsFirst->next; FreeTsEvent(tsFirst); @@ -394,7 +394,7 @@ s64 UnscheduleThreadsafeEvent(int event_type, u64 userdata) { if (ptr->type == event_type && ptr->userdata == userdata) { - result = ptr->time - globalTimer; + result = ptr->time - GetTicks(); prev->next = ptr->next; if (ptr == tsLast) diff --git a/Core/HLE/sceKernelAlarm.cpp b/Core/HLE/sceKernelAlarm.cpp index 6b1891686e..6bd1a89ee9 100644 --- a/Core/HLE/sceKernelAlarm.cpp +++ b/Core/HLE/sceKernelAlarm.cpp @@ -57,7 +57,7 @@ struct Alarm : public KernelObject NativeAlarm alm; }; -void __KernelScheduleAlarm(Alarm *alarm, u64 ticks); +void __KernelScheduleAlarm(Alarm *alarm, u64 micro); class AlarmIntrHandler : public IntrHandler { @@ -96,7 +96,7 @@ public: DEBUG_LOG(SCEKERNEL, "Rescheduling alarm %08x for +%dms", alarmID, result); u32 error; Alarm *alarm = kernelObjects.Get(alarmID, error); - __KernelScheduleAlarm(alarm, (u64) usToCycles(result)); + __KernelScheduleAlarm(alarm, result); } else { @@ -150,13 +150,13 @@ KernelObject *__KernelAlarmObject() return new Alarm; } -void __KernelScheduleAlarm(Alarm *alarm, u64 ticks) +void __KernelScheduleAlarm(Alarm *alarm, u64 micro) { - alarm->alm.schedule = CoreTiming::GetGlobalTimeUs() + ticks / (u64) CoreTiming::GetClockFrequencyMHz(); - CoreTiming::ScheduleEvent((int) ticks, alarmTimer, alarm->GetUID()); + alarm->alm.schedule = CoreTiming::GetGlobalTimeUs() + micro; + CoreTiming::ScheduleEvent(usToCycles(micro), alarmTimer, alarm->GetUID()); } -SceUID __KernelSetAlarm(u64 ticks, u32 handlerPtr, u32 commonPtr) +SceUID __KernelSetAlarm(u64 micro, u32 handlerPtr, u32 commonPtr) { if (!Memory::IsValidAddress(handlerPtr)) return SCE_KERNEL_ERROR_ILLEGAL_ADDR; @@ -168,14 +168,14 @@ SceUID __KernelSetAlarm(u64 ticks, u32 handlerPtr, u32 commonPtr) alarm->alm.handlerPtr = handlerPtr; alarm->alm.commonPtr = commonPtr; - __KernelScheduleAlarm(alarm, ticks); + __KernelScheduleAlarm(alarm, micro); return uid; } SceUID sceKernelSetAlarm(SceUInt micro, u32 handlerPtr, u32 commonPtr) { DEBUG_LOG(SCEKERNEL, "sceKernelSetAlarm(%d, %08x, %08x)", micro, handlerPtr, commonPtr); - return __KernelSetAlarm(usToCycles((u64) micro), handlerPtr, commonPtr); + return __KernelSetAlarm((u64) micro, handlerPtr, commonPtr); } SceUID sceKernelSetSysClockAlarm(u32 microPtr, u32 handlerPtr, u32 commonPtr) @@ -188,7 +188,7 @@ SceUID sceKernelSetSysClockAlarm(u32 microPtr, u32 handlerPtr, u32 commonPtr) return -1; DEBUG_LOG(SCEKERNEL, "sceKernelSetSysClockAlarm(%lld, %08x, %08x)", micro, handlerPtr, commonPtr); - return __KernelSetAlarm(usToCycles(micro), handlerPtr, commonPtr); + return __KernelSetAlarm(micro, handlerPtr, commonPtr); } int sceKernelCancelAlarm(SceUID uid) diff --git a/Core/HLE/sceKernelMemory.cpp b/Core/HLE/sceKernelMemory.cpp index bee423bf13..7d848ceb35 100644 --- a/Core/HLE/sceKernelMemory.cpp +++ b/Core/HLE/sceKernelMemory.cpp @@ -653,6 +653,7 @@ int sceKernelCreateFpl(const char *name, u32 mpid, u32 attr, u32 blockSize, u32 int sceKernelDeleteFpl(SceUID uid) { + hleEatCycles(600); u32 error; FPL *fpl = kernelObjects.Get(uid, error); if (fpl) @@ -833,6 +834,8 @@ retry: int sceKernelCancelFpl(SceUID uid, u32 numWaitThreadsPtr) { + hleEatCycles(600); + u32 error; FPL *fpl = kernelObjects.Get(uid, error); if (fpl) diff --git a/Core/HLE/sceKernelMsgPipe.cpp b/Core/HLE/sceKernelMsgPipe.cpp index ef4ecb3e28..98052c08f7 100644 --- a/Core/HLE/sceKernelMsgPipe.cpp +++ b/Core/HLE/sceKernelMsgPipe.cpp @@ -729,6 +729,8 @@ int sceKernelCreateMsgPipe(const char *name, int partition, u32 attr, u32 size, int sceKernelDeleteMsgPipe(SceUID uid) { + hleEatCycles(900); + u32 error; MsgPipe *m = kernelObjects.Get(uid, error); if (!m) @@ -737,6 +739,10 @@ int sceKernelDeleteMsgPipe(SceUID uid) return error; } + hleEatCycles(3100); + if (!m->sendWaitingThreads.empty() || !m->receiveWaitingThreads.empty()) + hleEatCycles(4000); + for (size_t i = 0; i < m->sendWaitingThreads.size(); i++) m->sendWaitingThreads[i].Cancel(uid, SCE_KERNEL_ERROR_WAIT_DELETE); for (size_t i = 0; i < m->receiveWaitingThreads.size(); i++) @@ -785,6 +791,8 @@ int __KernelValidateSendMsgPipe(SceUID uid, u32 sendBufAddr, u32 sendSize, int w int __KernelSendMsgPipe(MsgPipe *m, u32 sendBufAddr, u32 sendSize, int waitMode, u32 resultAddr, u32 timeoutPtr, bool cbEnabled, bool poll) { + hleEatCycles(2400); + bool needsResched = false; bool needsWait = false; @@ -962,6 +970,8 @@ int sceKernelTryReceiveMsgPipe(SceUID uid, u32 receiveBufAddr, u32 receiveSize, int sceKernelCancelMsgPipe(SceUID uid, u32 numSendThreadsAddr, u32 numReceiveThreadsAddr) { + hleEatCycles(900); + u32 error; MsgPipe *m = kernelObjects.Get(uid, error); if (!m) @@ -970,6 +980,10 @@ int sceKernelCancelMsgPipe(SceUID uid, u32 numSendThreadsAddr, u32 numReceiveThr return error; } + hleEatCycles(1100); + if (!m->sendWaitingThreads.empty() || !m->receiveWaitingThreads.empty()) + hleEatCycles(4000); + if (Memory::IsValidAddress(numSendThreadsAddr)) Memory::Write_U32((u32) m->sendWaitingThreads.size(), numSendThreadsAddr); if (Memory::IsValidAddress(numReceiveThreadsAddr)) diff --git a/Core/HLE/sceKernelSemaphore.cpp b/Core/HLE/sceKernelSemaphore.cpp index ae2f728d6c..236db2d20d 100644 --- a/Core/HLE/sceKernelSemaphore.cpp +++ b/Core/HLE/sceKernelSemaphore.cpp @@ -320,6 +320,7 @@ retry: if (wokeThreads) hleReSchedule("semaphore signaled"); + hleEatCycles(900); return 0; } else @@ -359,9 +360,9 @@ void __KernelSetSemaTimeout(Semaphore *s, u32 timeoutPtr) // This happens to be how the hardware seems to time things. if (micro <= 3) - micro = 25; + micro = 24; else if (micro <= 249) - micro = 250; + micro = 245; // This should call __KernelSemaTimeout() later, unless we cancel it. CoreTiming::ScheduleEvent(usToCycles(micro), semaWaitTimer, __KernelGetCurThread()); @@ -369,11 +370,18 @@ void __KernelSetSemaTimeout(Semaphore *s, u32 timeoutPtr) int __KernelWaitSema(SceUID id, int wantedCount, u32 timeoutPtr, bool processCallbacks) { + hleEatCycles(900); + + if (wantedCount <= 0) + return SCE_KERNEL_ERROR_ILLEGAL_COUNT; + + hleEatCycles(500); + u32 error; Semaphore *s = kernelObjects.Get(id, error); if (s) { - if (wantedCount > s->ns.maxCount || wantedCount <= 0) + if (wantedCount > s->ns.maxCount) return SCE_KERNEL_ERROR_ILLEGAL_COUNT; // If there are any callbacks, we always wait, and wake after the callbacks. diff --git a/Core/HLE/sceKernelThread.cpp b/Core/HLE/sceKernelThread.cpp index c20dcca984..dd6d1e04b9 100644 --- a/Core/HLE/sceKernelThread.cpp +++ b/Core/HLE/sceKernelThread.cpp @@ -2275,6 +2275,7 @@ int sceKernelStartThread(SceUID threadToStartID, int argSize, u32 argBlockPtr) } INFO_LOG(SCEKERNEL, "sceKernelStartThread(thread=%i, argSize=%i, argPtr=%08x)", threadToStartID, argSize, argBlockPtr); + hleEatCycles(3400); return __KernelStartThread(threadToStartID, argSize, argBlockPtr); } diff --git a/Core/HLE/sceKernelVTimer.cpp b/Core/HLE/sceKernelVTimer.cpp index 11244a0180..2ed7ac3a08 100644 --- a/Core/HLE/sceKernelVTimer.cpp +++ b/Core/HLE/sceKernelVTimer.cpp @@ -99,15 +99,15 @@ void __KernelScheduleVTimer(VTimer *vt, u64 schedule) { // The "real" base is base + current. But when setting the time, base is important. // The schedule is relative to those. u64 cyclesIntoFuture; - // It seems like the minimum is approximately 200us? - if (schedule < __getVTimerCurrentTime(vt)) - cyclesIntoFuture = usToCycles(200); - else { - u64 goalUs = vt->nvt.base + schedule - vt->nvt.current; - if (goalUs < CoreTiming::GetGlobalTimeUs()) - cyclesIntoFuture = usToCycles(200); - else - cyclesIntoFuture = usToCycles(goalUs - CoreTiming::GetGlobalTimeUs()); + if (schedule < 250) { + schedule = 250; + } + s64 goalUs = (u64)vt->nvt.base + schedule - (u64)vt->nvt.current; + s64 minGoalUs = CoreTiming::GetGlobalTimeUs() + 250; + if (goalUs < minGoalUs) { + cyclesIntoFuture = usToCycles(250); + } else { + cyclesIntoFuture = usToCycles(goalUs - CoreTiming::GetGlobalTimeUs()); } CoreTiming::ScheduleEvent(cyclesIntoFuture, vtimerTimer, vt->GetUID()); @@ -121,9 +121,6 @@ void __rescheduleVTimer(SceUID id, u32 delay) { if (error) return; - if (delay < 100) - delay = 100; - __KernelScheduleVTimer(vt, vt->nvt.schedule + delay); } @@ -377,6 +374,8 @@ void __startVTimer(VTimer *vt) { } u32 sceKernelStartVTimer(SceUID uid) { + hleEatCycles(12200); + if (uid == runningVTimer) { WARN_LOG(SCEKERNEL, "sceKernelStartVTimer(%08x): invalid vtimer", uid); return SCE_KERNEL_ERROR_ILLEGAL_VTID; @@ -427,6 +426,7 @@ u32 sceKernelStopVTimer(SceUID uid) { } u32 sceKernelSetVTimerHandler(SceUID uid, u32 scheduleAddr, u32 handlerFuncAddr, u32 commonAddr) { + hleEatCycles(900); if (uid == runningVTimer) { WARN_LOG(SCEKERNEL, "sceKernelSetVTimerHandler(%08x, %08x, %08x, %08x): invalid vtimer", uid, scheduleAddr, handlerFuncAddr, commonAddr); return SCE_KERNEL_ERROR_ILLEGAL_VTID; @@ -441,6 +441,7 @@ u32 sceKernelSetVTimerHandler(SceUID uid, u32 scheduleAddr, u32 handlerFuncAddr, } DEBUG_LOG(SCEKERNEL, "sceKernelSetVTimerHandler(%08x, %08x, %08x, %08x)", uid, scheduleAddr, handlerFuncAddr, commonAddr); + hleEatCycles(2000); u64 schedule = Memory::Read_U64(scheduleAddr); vt->nvt.handlerAddr = handlerFuncAddr; @@ -455,6 +456,7 @@ u32 sceKernelSetVTimerHandler(SceUID uid, u32 scheduleAddr, u32 handlerFuncAddr, } u32 sceKernelSetVTimerHandlerWide(SceUID uid, u64 schedule, u32 handlerFuncAddr, u32 commonAddr) { + hleEatCycles(900); if (uid == runningVTimer) { WARN_LOG(SCEKERNEL, "sceKernelSetVTimerHandlerWide(%08x, %llu, %08x, %08x): invalid vtimer", uid, schedule, handlerFuncAddr, commonAddr); return SCE_KERNEL_ERROR_ILLEGAL_VTID;