From aadbe50357dd94e88c9156bc390ec35983dcde99 Mon Sep 17 00:00:00 2001 From: "Unknown W. Brackets" Date: Tue, 18 Dec 2012 23:47:57 -0800 Subject: [PATCH] Implement the basic functionality of alarms. They only fire the once though, and the use of subintr might be a bit naive, may need internal funcs. --- Core/HLE/sceKernel.cpp | 8 +-- Core/HLE/sceKernelAlarm.cpp | 100 +++++++++++++++++++++++++++++++----- Core/HLE/sceKernelAlarm.h | 8 +-- 3 files changed, 96 insertions(+), 20 deletions(-) diff --git a/Core/HLE/sceKernel.cpp b/Core/HLE/sceKernel.cpp index 9e8fd755db..cb876fc381 100644 --- a/Core/HLE/sceKernel.cpp +++ b/Core/HLE/sceKernel.cpp @@ -412,10 +412,10 @@ const HLEFunction ThreadManForUser[] = {0x64D4540E,0,"sceKernelReferThreadProfiler"}, //Fifa Street 2 uses alarms - {0x6652b8ca,sceKernelSetAlarm,"sceKernelSetAlarm"}, - {0xB2C25152,sceKernelSetSysClockAlarm,"sceKernelSetSysClockAlarm"}, - {0x7e65b999,sceKernelCancelAlarm,"sceKernelCancelAlarm"}, - {0xDAA3F564,sceKernelReferAlarmStatus,"sceKernelReferAlarmStatus"}, + {0x6652b8ca,WrapI_UUU,"sceKernelSetAlarm"}, + {0xB2C25152,WrapI_UUU,"sceKernelSetSysClockAlarm"}, + {0x7e65b999,WrapI_I,"sceKernelCancelAlarm"}, + {0xDAA3F564,WrapI_IU,"sceKernelReferAlarmStatus"}, {0xba6b92e2,sceKernelSysClock2USec,"sceKernelSysClock2USec"}, {0x110DEC9A,0,"sceKernelUSec2SysClock"}, diff --git a/Core/HLE/sceKernelAlarm.cpp b/Core/HLE/sceKernelAlarm.cpp index 8f4cd961b2..ed46393c2e 100644 --- a/Core/HLE/sceKernelAlarm.cpp +++ b/Core/HLE/sceKernelAlarm.cpp @@ -17,28 +17,104 @@ #include "sceKernel.h" #include "sceKernelAlarm.h" +#include "sceKernelInterrupt.h" #include "HLE.h" +#include "../../Core/CoreTiming.h" -void sceKernelSetAlarm() +struct NativeAlarm { - ERROR_LOG(HLE,"UNIMPL sceKernelSetAlarm"); - RETURN(-1); + SceSize size; + u64 schedule; + u32 handlerPtr; + u32 commonPtr; +}; + +struct Alarm : public KernelObject +{ + const char *GetName() {return "[Alarm]";} + const char *GetTypeName() {return "Alarm";} + static u32 GetMissingErrorCode() { return SCE_KERNEL_ERROR_UNKNOWN_ALMID; } + int GetIDType() const { return SCE_KERNEL_TMID_Alarm; } + NativeAlarm alm; +}; + +bool alarmInitComplete = false; +int alarmTimer = 0; + +void __KernelTriggerAlarm(u64 userdata, int cyclesLate); + +void __KernelAlarmInit() +{ + alarmTimer = CoreTiming::RegisterEvent("Alarm", __KernelTriggerAlarm); + + alarmInitComplete = true; } -void sceKernelSetSysClockAlarm() +void __KernelTriggerAlarm(u64 userdata, int cyclesLate) { - ERROR_LOG(HLE,"UNIMPL sceKernelSetSysClockAlarm"); - RETURN(-1); + int uid = (int) userdata; + + u32 error; + Alarm *alarm = kernelObjects.Get(uid, error); + + // TODO: Need to find out the return value. + if (alarm) + __TriggerInterruptWithArg(PSP_SYSTIMER0_INTR, uid, alarm->alm.commonPtr); } -void sceKernelCancelAlarm() +SceUID __KernelSetAlarm(u64 ticks, u32 handlerPtr, u32 commonPtr) { - ERROR_LOG(HLE,"UNIMPL sceKernelCancelAlarm"); - RETURN(-1); + if (!alarmInitComplete) + __KernelAlarmInit(); + + Alarm *alarm = new Alarm; + SceUID uid = kernelObjects.Create(alarm); + + alarm->alm.size = sizeof(NativeAlarm); + alarm->alm.schedule = CoreTiming::GetTicks() + ticks; + alarm->alm.handlerPtr = handlerPtr; + alarm->alm.commonPtr = commonPtr; + + sceKernelRegisterSubIntrHandler(PSP_SYSTIMER0_INTR, uid, handlerPtr, commonPtr); + sceKernelEnableSubIntr(PSP_SYSTIMER0_INTR, uid); + CoreTiming::ScheduleEvent(ticks, alarmTimer, uid); + + return uid; } -void sceKernelReferAlarmStatus() +SceUID sceKernelSetAlarm(SceUInt micro, u32 handlerPtr, u32 commonPtr) { - ERROR_LOG(HLE,"UNIMPL sceKernelReferAlarmStatus"); - RETURN(-1); + ERROR_LOG(HLE, "HACK sceKernelSetAlarm(%d, %08x, %08x)", micro, handlerPtr, commonPtr); + return __KernelSetAlarm(usToCycles((int) micro), handlerPtr, commonPtr); +} + +SceUID sceKernelSetSysClockAlarm(u32 ticksPtr, u32 handlerPtr, u32 commonPtr) +{ + u64 ticks; + + if (Memory::IsValidAddress(ticksPtr)) + ticks = Memory::Read_U64(ticksPtr); + // TODO: What to do when invalid? + else + return -1; + + ERROR_LOG(HLE, "UNIMPL sceKernelSetSysClockAlarm(%lld, %08x, %08x)", ticks, handlerPtr, commonPtr); + // TODO: Is this precise or is this relative? + return __KernelSetAlarm(ticks, handlerPtr, commonPtr); +} + +int sceKernelCancelAlarm(SceUID uid) +{ + DEBUG_LOG(HLE, "sceKernelCancelAlarm(%08x)", uid); + + CoreTiming::UnscheduleEvent(alarmTimer, uid); + sceKernelReleaseSubIntrHandler(PSP_SYSTIMER0_INTR, uid); + + return kernelObjects.Destroy(uid); +} + +int sceKernelReferAlarmStatus(SceUID uid, u32 infoPtr) +{ + ERROR_LOG(HLE, "UNIMPL sceKernelReferAlarmStatus(%08x, %08x)", uid, infoPtr); + return -1; } \ No newline at end of file diff --git a/Core/HLE/sceKernelAlarm.h b/Core/HLE/sceKernelAlarm.h index 56b004f0fc..f430a20da9 100644 --- a/Core/HLE/sceKernelAlarm.h +++ b/Core/HLE/sceKernelAlarm.h @@ -17,7 +17,7 @@ #pragma once -void sceKernelSetAlarm(); -void sceKernelSetSysClockAlarm(); -void sceKernelCancelAlarm(); -void sceKernelReferAlarmStatus(); \ No newline at end of file +SceUID sceKernelSetAlarm(SceUInt clock, u32 handlerPtr, u32 commonPtr); +SceUID sceKernelSetSysClockAlarm(u32 sysClockPtr, u32 handlerPtr, u32 commonPtr); +int sceKernelCancelAlarm(SceUID uid); +int sceKernelReferAlarmStatus(SceUID uid, u32 infoPtr); \ No newline at end of file