mirror of
https://github.com/hrydgard/ppsspp.git
synced 2024-11-23 13:30:02 +00:00
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:
parent
19391541fb
commit
aadbe50357
@ -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"},
|
||||
|
@ -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;
|
||||
}
|
@ -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);
|
Loading…
Reference in New Issue
Block a user