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.
This commit is contained in:
Unknown W. Brackets 2012-12-18 23:47:57 -08:00
parent 19391541fb
commit aadbe50357
3 changed files with 96 additions and 20 deletions

View File

@ -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>,"sceKernelSetAlarm"},
{0xB2C25152,WrapI_UUU<sceKernelSetSysClockAlarm>,"sceKernelSetSysClockAlarm"},
{0x7e65b999,WrapI_I<sceKernelCancelAlarm>,"sceKernelCancelAlarm"},
{0xDAA3F564,WrapI_IU<sceKernelReferAlarmStatus>,"sceKernelReferAlarmStatus"},
{0xba6b92e2,sceKernelSysClock2USec,"sceKernelSysClock2USec"},
{0x110DEC9A,0,"sceKernelUSec2SysClock"},

View File

@ -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<Alarm>(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<Alarm>(uid);
}
int sceKernelReferAlarmStatus(SceUID uid, u32 infoPtr)
{
ERROR_LOG(HLE, "UNIMPL sceKernelReferAlarmStatus(%08x, %08x)", uid, infoPtr);
return -1;
}

View File

@ -17,7 +17,7 @@
#pragma once
void sceKernelSetAlarm();
void sceKernelSetSysClockAlarm();
void sceKernelCancelAlarm();
void sceKernelReferAlarmStatus();
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);