2020-01-24 04:53:40 +00:00
|
|
|
#pragma once
|
|
|
|
#include <functional>
|
|
|
|
#include <memory>
|
2020-02-15 02:34:57 +00:00
|
|
|
#include <string>
|
2020-01-24 04:53:40 +00:00
|
|
|
#include <vector>
|
|
|
|
|
|
|
|
#include "types.h"
|
|
|
|
|
2020-07-31 07:09:18 +00:00
|
|
|
class StateWrapper;
|
2020-01-24 04:53:40 +00:00
|
|
|
|
|
|
|
// Event callback type. Second parameter is the number of cycles the event was executed "late".
|
2021-01-09 15:43:59 +00:00
|
|
|
using TimingEventCallback = void (*)(void* param, TickCount ticks, TickCount ticks_late);
|
2020-01-24 04:53:40 +00:00
|
|
|
|
|
|
|
class TimingEvent
|
|
|
|
{
|
|
|
|
public:
|
2021-01-09 15:43:59 +00:00
|
|
|
TimingEvent(std::string name, TickCount period, TickCount interval, TimingEventCallback callback,
|
|
|
|
void* callback_param);
|
2020-01-24 04:53:40 +00:00
|
|
|
~TimingEvent();
|
|
|
|
|
2021-01-09 15:38:39 +00:00
|
|
|
ALWAYS_INLINE const std::string& GetName() const { return m_name; }
|
|
|
|
ALWAYS_INLINE bool IsActive() const { return m_active; }
|
2020-01-24 04:53:40 +00:00
|
|
|
|
|
|
|
// Returns the number of ticks between each event.
|
2020-07-31 07:09:18 +00:00
|
|
|
ALWAYS_INLINE TickCount GetPeriod() const { return m_period; }
|
|
|
|
ALWAYS_INLINE TickCount GetInterval() const { return m_interval; }
|
|
|
|
ALWAYS_INLINE TickCount GetDowncount() const { return m_downcount; }
|
2020-01-24 04:53:40 +00:00
|
|
|
|
|
|
|
// Includes pending time.
|
|
|
|
TickCount GetTicksSinceLastExecution() const;
|
|
|
|
TickCount GetTicksUntilNextExecution() const;
|
|
|
|
|
2021-06-14 04:55:20 +00:00
|
|
|
// Adds ticks to current execution.
|
|
|
|
void Delay(TickCount ticks);
|
|
|
|
|
2020-01-24 04:53:40 +00:00
|
|
|
void Schedule(TickCount ticks);
|
|
|
|
void SetIntervalAndSchedule(TickCount ticks);
|
|
|
|
void SetPeriodAndSchedule(TickCount ticks);
|
|
|
|
|
|
|
|
void Reset();
|
|
|
|
|
|
|
|
// Services the event with the current accmulated time. If force is set, when not enough time is pending to
|
|
|
|
// simulate a single cycle, the callback will still be invoked, otherwise it won't be.
|
|
|
|
void InvokeEarly(bool force = false);
|
|
|
|
|
|
|
|
// Deactivates the event, preventing it from firing again.
|
|
|
|
// Do not call within a callback, return Deactivate instead.
|
|
|
|
void Activate();
|
|
|
|
void Deactivate();
|
|
|
|
|
|
|
|
ALWAYS_INLINE void SetState(bool active)
|
|
|
|
{
|
|
|
|
if (active)
|
|
|
|
Activate();
|
|
|
|
else
|
|
|
|
Deactivate();
|
|
|
|
}
|
|
|
|
|
|
|
|
// Directly alters the interval of the event.
|
|
|
|
void SetInterval(TickCount interval) { m_interval = interval; }
|
|
|
|
void SetPeriod(TickCount period) { m_period = period; }
|
|
|
|
|
2020-08-31 10:54:59 +00:00
|
|
|
TimingEvent* prev = nullptr;
|
|
|
|
TimingEvent* next = nullptr;
|
|
|
|
|
2021-01-09 15:43:59 +00:00
|
|
|
TimingEventCallback m_callback;
|
|
|
|
void* m_callback_param;
|
|
|
|
|
2020-01-24 04:53:40 +00:00
|
|
|
TickCount m_downcount;
|
|
|
|
TickCount m_time_since_last_run;
|
|
|
|
TickCount m_period;
|
|
|
|
TickCount m_interval;
|
2021-02-06 09:19:55 +00:00
|
|
|
bool m_active = false;
|
2020-01-24 04:53:40 +00:00
|
|
|
|
|
|
|
std::string m_name;
|
|
|
|
};
|
2020-07-31 07:09:18 +00:00
|
|
|
|
|
|
|
namespace TimingEvents {
|
|
|
|
|
|
|
|
u32 GetGlobalTickCounter();
|
|
|
|
|
|
|
|
void Initialize();
|
|
|
|
void Reset();
|
|
|
|
void Shutdown();
|
|
|
|
|
|
|
|
/// Creates a new event.
|
|
|
|
std::unique_ptr<TimingEvent> CreateTimingEvent(std::string name, TickCount period, TickCount interval,
|
2021-01-09 15:43:59 +00:00
|
|
|
TimingEventCallback callback, void* callback_param, bool activate);
|
2020-07-31 07:09:18 +00:00
|
|
|
|
|
|
|
/// Serialization.
|
2020-08-15 04:56:20 +00:00
|
|
|
bool DoState(StateWrapper& sw);
|
2020-07-31 07:09:18 +00:00
|
|
|
|
|
|
|
void RunEvents();
|
|
|
|
|
|
|
|
void UpdateCPUDowncount();
|
|
|
|
|
2020-10-18 04:43:09 +00:00
|
|
|
TimingEvent** GetHeadEventPtr();
|
|
|
|
|
2021-01-09 15:43:59 +00:00
|
|
|
} // namespace TimingEvents
|