diff --git a/Core/CoreTiming.h b/Core/CoreTiming.h index f771d7e484..f8883d9b35 100644 --- a/Core/CoreTiming.h +++ b/Core/CoreTiming.h @@ -58,6 +58,10 @@ inline int usToCycles(int us) { return (int)(CPU_HZ / 1000000 * us); } +inline u64 usToCycles(u64 us) { + return (u64)(CPU_HZ / 1000000ULL * us); +} + inline u64 cyclesToUs(u64 cycles) { return cycles / (CPU_HZ / 1000000); } diff --git a/Core/HLE/sceKernelAlarm.cpp b/Core/HLE/sceKernelAlarm.cpp index ee6657e670..984c558e04 100644 --- a/Core/HLE/sceKernelAlarm.cpp +++ b/Core/HLE/sceKernelAlarm.cpp @@ -21,6 +21,8 @@ #include "HLE.h" #include "../../Core/CoreTiming.h" +const int NATIVEALARM_SIZE = 20; + struct NativeAlarm { SceSize size; @@ -38,7 +40,7 @@ struct Alarm : public KernelObject NativeAlarm alm; }; -void __KernelScheduleAlarm(Alarm *alarm, int ticks); +void __KernelScheduleAlarm(Alarm *alarm, u64 ticks); class AlarmIntrHandler : public SubIntrHandler { @@ -60,11 +62,17 @@ public: virtual void handleResult(int result) { // A non-zero result means to reschedule. - // TODO: Do sysclock alarms return a different value unit? if (result > 0) - __KernelScheduleAlarm(alarm, usToCycles(result)); - else if (result < 0) - WARN_LOG(HLE, "Alarm requested reschedule for negative value %u, ignoring", (unsigned) result); + __KernelScheduleAlarm(alarm, (u64) usToCycles(result)); + else + { + if (result < 0) + WARN_LOG(HLE, "Alarm requested reschedule for negative value %u, ignoring", (unsigned) result); + + // Delete the alarm if it's not rescheduled. + __ReleaseSubInterruptHandler(PSP_SYSTIMER0_INTR, alarm->GetUID()); + kernelObjects.Destroy(alarm->GetUID()); + } } Alarm *alarm; @@ -92,9 +100,9 @@ void __KernelTriggerAlarm(u64 userdata, int cyclesLate) __TriggerInterrupt(PSP_INTR_IMMEDIATE, PSP_SYSTIMER0_INTR, uid); } -void __KernelScheduleAlarm(Alarm *alarm, int ticks) +void __KernelScheduleAlarm(Alarm *alarm, u64 ticks) { - alarm->alm.schedule = CoreTiming::GetTicks() + ticks; + alarm->alm.schedule = (CoreTiming::GetTicks() + ticks) / (u64) CoreTiming::GetClockFrequencyMHz(); CoreTiming::ScheduleEvent((int) ticks, alarmTimer, alarm->GetUID()); } @@ -103,11 +111,13 @@ SceUID __KernelSetAlarm(u64 ticks, u32 handlerPtr, u32 commonPtr) if (!alarmInitComplete) __KernelAlarmInit(); + if (!Memory::IsValidAddress(handlerPtr)) + return SCE_KERNEL_ERROR_ILLEGAL_ADDR; + Alarm *alarm = new Alarm; SceUID uid = kernelObjects.Create(alarm); - alarm->alm.size = sizeof(NativeAlarm); - alarm->alm.schedule = CoreTiming::GetTicks() + ticks; + alarm->alm.size = NATIVEALARM_SIZE; alarm->alm.handlerPtr = handlerPtr; alarm->alm.commonPtr = commonPtr; @@ -115,29 +125,27 @@ SceUID __KernelSetAlarm(u64 ticks, u32 handlerPtr, u32 commonPtr) if (error != 0) return error; - __KernelScheduleAlarm(alarm, (int) ticks); + __KernelScheduleAlarm(alarm, ticks); return uid; } SceUID sceKernelSetAlarm(SceUInt micro, u32 handlerPtr, u32 commonPtr) { DEBUG_LOG(HLE, "sceKernelSetAlarm(%d, %08x, %08x)", micro, handlerPtr, commonPtr); - return __KernelSetAlarm(usToCycles((int) micro), handlerPtr, commonPtr); + return __KernelSetAlarm(usToCycles((u64) micro), handlerPtr, commonPtr); } -SceUID sceKernelSetSysClockAlarm(u32 ticksPtr, u32 handlerPtr, u32 commonPtr) +SceUID sceKernelSetSysClockAlarm(u32 microPtr, u32 handlerPtr, u32 commonPtr) { - u64 ticks; + u64 micro; - if (Memory::IsValidAddress(ticksPtr)) - ticks = Memory::Read_U64(ticksPtr); - // TODO: What to do when invalid? + if (Memory::IsValidAddress(microPtr)) + micro = Memory::Read_U64(microPtr); else return -1; - ERROR_LOG(HLE, "UNTESTED sceKernelSetSysClockAlarm(%lld, %08x, %08x)", ticks, handlerPtr, commonPtr); - // TODO: Is this precise or is this relative? - return __KernelSetAlarm(ticks, handlerPtr, commonPtr); + DEBUG_LOG(HLE, "sceKernelSetSysClockAlarm(%lld, %08x, %08x)", micro, handlerPtr, commonPtr); + return __KernelSetAlarm(usToCycles(micro), handlerPtr, commonPtr); } int sceKernelCancelAlarm(SceUID uid) @@ -152,6 +160,30 @@ int sceKernelCancelAlarm(SceUID uid) int sceKernelReferAlarmStatus(SceUID uid, u32 infoPtr) { - ERROR_LOG(HLE, "UNIMPL sceKernelReferAlarmStatus(%08x, %08x)", uid, infoPtr); - return -1; + u32 error; + Alarm *alarm = kernelObjects.Get(uid, error); + if (!alarm) + { + ERROR_LOG(HLE, "sceKernelReferAlarmStatus(%08x, %08x): invalid alarm", uid, infoPtr); + return error; + } + + DEBUG_LOG(HLE, "sceKernelReferAlarmStatus(%08x, %08x)", uid, infoPtr); + + if (!Memory::IsValidAddress(infoPtr)) + return -1; + + u32 size = Memory::Read_U32(infoPtr); + + // Alarms actually respect size and write (kinda) what it can hold. + if (size > 0) + Memory::Write_U32(alarm->alm.size, infoPtr); + if (size > 4) + Memory::Write_U64(alarm->alm.schedule, infoPtr + 4); + if (size > 12) + Memory::Write_U32(alarm->alm.handlerPtr, infoPtr + 12); + if (size > 16) + Memory::Write_U32(alarm->alm.commonPtr, infoPtr + 16); + + return 0; } \ No newline at end of file diff --git a/GPU/GLES/IndexGenerator.h b/GPU/GLES/IndexGenerator.h index 2b491c6789..2ed1d03d5a 100644 --- a/GPU/GLES/IndexGenerator.h +++ b/GPU/GLES/IndexGenerator.h @@ -52,15 +52,14 @@ public: void TranslateRectangles(int numVerts, const u8 *inds, int offset); void TranslateRectangles(int numVerts, const u16 *inds, int offset); - void TranslateList(int numVerts, const u8 *inds, int offset); void TranslateStrip(int numVerts, const u8 *inds, int offset); void TranslateFan(int numVerts, const u8 *inds, int offset); void TranslateList(int numVerts, const u16 *inds, int offset); void TranslateStrip(int numVerts, const u16 *inds, int offset); void TranslateFan(int numVerts, const u16 *inds, int offset); - - int MaxIndex() { return index_; } + + int MaxIndex() { return index_; } int VertexCount() { return count_; } bool Empty() { return index_ == 0; } diff --git a/Windows/WndMainWindow.cpp b/Windows/WndMainWindow.cpp index 679459b1d6..ec3868b027 100644 --- a/Windows/WndMainWindow.cpp +++ b/Windows/WndMainWindow.cpp @@ -498,6 +498,10 @@ namespace MainWindow g_Config.bDisplayFramebuffer = !g_Config.bDisplayFramebuffer; UpdateMenus(); break; + case ID_OPTIONS_FASTMEMORY: + g_Config.bFastMemory = !g_Config.bFastMemory; + UpdateMenus(); + break; ////////////////////////////////////////////////////////////////////////// diff --git a/pspautotests b/pspautotests index 6bd9d261e6..54acddd544 160000 --- a/pspautotests +++ b/pspautotests @@ -1 +1 @@ -Subproject commit 6bd9d261e6014d371b917e50d2e18d5fc986a8c3 +Subproject commit 54acddd54469a88aadbaf0e69088aad504b5e1e4 diff --git a/test.py b/test.py index 14f3746193..f352ccf50f 100755 --- a/test.py +++ b/test.py @@ -59,6 +59,9 @@ tests_good = [ "string/string", "gpu/callbacks/ge_callbacks", "threads/alarm/alarm", + "threads/alarm/cancel/cancel", + "threads/alarm/refer/refer", + "threads/alarm/set/set", "threads/events/events", "threads/events/cancel/cancel", "threads/events/clear/clear",