mirror of
https://github.com/libretro/ppsspp.git
synced 2025-03-01 13:16:37 +00:00
Thread: Better/minor accuracy for sysclock delay.
Certain negative values shouldn't cause a delay, could help if a game has a bug.
This commit is contained in:
parent
baac12b327
commit
197f3393df
@ -734,8 +734,8 @@ const HLEFunction ThreadManForUser[] =
|
||||
{0X71BC9871, &WrapI_II<sceKernelChangeThreadPriority>, "sceKernelChangeThreadPriority", 'i', "ii" },
|
||||
{0X446D8DE6, &WrapI_CUUIUU<sceKernelCreateThread>, "sceKernelCreateThread", 'i', "sxxixx", HLE_NOT_IN_INTERRUPT },
|
||||
{0X9FA03CD3, &WrapI_I<sceKernelDeleteThread>, "sceKernelDeleteThread", 'i', "i" },
|
||||
{0XBD123D9E, &WrapI_U<sceKernelDelaySysClockThread>, "sceKernelDelaySysClockThread", 'i', "x", HLE_NOT_IN_INTERRUPT | HLE_NOT_DISPATCH_SUSPENDED },
|
||||
{0X1181E963, &WrapI_U<sceKernelDelaySysClockThreadCB>, "sceKernelDelaySysClockThreadCB", 'i', "x", HLE_NOT_IN_INTERRUPT | HLE_NOT_DISPATCH_SUSPENDED },
|
||||
{0XBD123D9E, &WrapI_U<sceKernelDelaySysClockThread>, "sceKernelDelaySysClockThread", 'i', "P", HLE_NOT_IN_INTERRUPT | HLE_NOT_DISPATCH_SUSPENDED },
|
||||
{0X1181E963, &WrapI_U<sceKernelDelaySysClockThreadCB>, "sceKernelDelaySysClockThreadCB", 'i', "P", HLE_NOT_IN_INTERRUPT | HLE_NOT_DISPATCH_SUSPENDED },
|
||||
{0XCEADEB47, &WrapI_U<sceKernelDelayThread>, "sceKernelDelayThread", 'i', "x", HLE_NOT_IN_INTERRUPT | HLE_NOT_DISPATCH_SUSPENDED },
|
||||
{0X68DA9E36, &WrapI_U<sceKernelDelayThreadCB>, "sceKernelDelayThreadCB", 'i', "x", HLE_NOT_IN_INTERRUPT | HLE_NOT_DISPATCH_SUSPENDED },
|
||||
{0XAA73C935, &WrapV_I<sceKernelExitThread>, "sceKernelExitThread", 'v', "i" },
|
||||
|
@ -2413,6 +2413,17 @@ static s64 __KernelDelayThreadUs(u64 usec) {
|
||||
if (usec < 200) {
|
||||
return 210;
|
||||
}
|
||||
|
||||
if (usec > 0x8000000000000000ULL) {
|
||||
// Wrap around (behavior seen on firmware) and potentially wake up soon.
|
||||
usec -= 0x8000000000000000ULL;
|
||||
}
|
||||
if (usec > 0x0010000000000000ULL) {
|
||||
// This will probably overflow when we convert to cycles.
|
||||
// Note: converting millenia to hundreds of years. Should be safe, basically perma-delay.
|
||||
usec >>= 12;
|
||||
}
|
||||
|
||||
// It never wakes up right away. It usually takes at least 15 extra us, but let's be nicer.
|
||||
return usec + 10;
|
||||
}
|
||||
@ -2439,40 +2450,38 @@ int sceKernelDelayThread(u32 usec) {
|
||||
return hleLogSuccessI(SCEKERNEL, 0, "delaying %lld usecs", delayUs);
|
||||
}
|
||||
|
||||
int sceKernelDelaySysClockThreadCB(u32 sysclockAddr)
|
||||
{
|
||||
int sceKernelDelaySysClockThreadCB(u32 sysclockAddr) {
|
||||
auto sysclock = PSPPointer<SceKernelSysClock>::Create(sysclockAddr);
|
||||
if (!sysclock.IsValid()) {
|
||||
ERROR_LOG(SCEKERNEL, "sceKernelDelaySysClockThreadCB(%08x) - bad pointer", sysclockAddr);
|
||||
return -1;
|
||||
// Note: crashes on real firmware.
|
||||
return hleLogError(SCEKERNEL, SCE_KERNEL_ERROR_ILLEGAL_ADDRESS, "bad pointer");
|
||||
}
|
||||
|
||||
// TODO: Which unit?
|
||||
// This is just a u64 of usecs. All bits are respected, but overflow can happen for very large values.
|
||||
u64 usec = sysclock->lo | ((u64)sysclock->hi << 32);
|
||||
DEBUG_LOG(SCEKERNEL, "sceKernelDelaySysClockThreadCB(%08x (%llu))", sysclockAddr, usec);
|
||||
|
||||
SceUID curThread = __KernelGetCurThread();
|
||||
__KernelScheduleWakeup(curThread, __KernelDelayThreadUs(usec));
|
||||
s64 delayUs = __KernelDelayThreadUs(usec);
|
||||
__KernelScheduleWakeup(curThread, delayUs);
|
||||
__KernelWaitCurThread(WAITTYPE_DELAY, curThread, 0, 0, true, "thread delayed");
|
||||
return 0;
|
||||
return hleLogSuccessI(SCEKERNEL, 0, "delaying %lld usecs", delayUs);
|
||||
}
|
||||
|
||||
int sceKernelDelaySysClockThread(u32 sysclockAddr)
|
||||
{
|
||||
int sceKernelDelaySysClockThread(u32 sysclockAddr) {
|
||||
auto sysclock = PSPPointer<SceKernelSysClock>::Create(sysclockAddr);
|
||||
if (!sysclock.IsValid()) {
|
||||
ERROR_LOG(SCEKERNEL, "sceKernelDelaySysClockThread(%08x) - bad pointer", sysclockAddr);
|
||||
return -1;
|
||||
// Note: crashes on real firmware.
|
||||
return hleLogError(SCEKERNEL, SCE_KERNEL_ERROR_ILLEGAL_ADDRESS, "bad pointer");
|
||||
}
|
||||
|
||||
// TODO: Which unit?
|
||||
// This is just a u64 of usecs. All bits are respected, but overflow can happen for very large values.
|
||||
u64 usec = sysclock->lo | ((u64)sysclock->hi << 32);
|
||||
DEBUG_LOG(SCEKERNEL, "sceKernelDelaySysClockThread(%08x (%llu))", sysclockAddr, usec);
|
||||
|
||||
SceUID curThread = __KernelGetCurThread();
|
||||
__KernelScheduleWakeup(curThread, __KernelDelayThreadUs(usec));
|
||||
s64 delayUs = __KernelDelayThreadUs(usec);
|
||||
__KernelScheduleWakeup(curThread, delayUs);
|
||||
__KernelWaitCurThread(WAITTYPE_DELAY, curThread, 0, 0, false, "thread delayed");
|
||||
return 0;
|
||||
return hleLogSuccessI(SCEKERNEL, 0, "delaying %lld usecs", delayUs);
|
||||
}
|
||||
|
||||
u32 __KernelGetThreadPrio(SceUID id)
|
||||
|
Loading…
x
Reference in New Issue
Block a user