From 1b27f22cbcba62958d54daa3ec5ca3931a800e79 Mon Sep 17 00:00:00 2001 From: Bonta <40473493+Bonta0@users.noreply.github.com> Date: Sun, 4 Jul 2021 12:44:02 +0200 Subject: [PATCH] SI: Allow devices to schedule events --- Source/Core/Core/HW/SI/SI.cpp | 40 +++++++++++++++++++++++++--- Source/Core/Core/HW/SI/SI.h | 3 +++ Source/Core/Core/HW/SI/SI_Device.cpp | 4 +++ Source/Core/Core/HW/SI/SI_Device.h | 3 +++ 4 files changed, 47 insertions(+), 3 deletions(-) diff --git a/Source/Core/Core/HW/SI/SI.cpp b/Source/Core/Core/HW/SI/SI.cpp index 12d0790cb4..14e586fc05 100644 --- a/Source/Core/Core/HW/SI/SI.cpp +++ b/Source/Core/Core/HW/SI/SI.cpp @@ -209,6 +209,7 @@ union USIEXIClockCount static CoreTiming::EventType* s_change_device_event; static CoreTiming::EventType* s_tranfer_pending_event; +static std::array s_device_events; // User-configured device type. possibly overridden by TAS/Netplay static std::array, MAX_SI_CHANNELS> s_desired_device_types; @@ -369,8 +370,44 @@ void DoState(PointerWrap& p) p.Do(s_si_buffer); } +template +static void DeviceEventCallback(u64 userdata, s64 cyclesLate) +{ + s_channel[device_number].device->OnEvent(userdata, cyclesLate); +} + +static void RegisterEvents() +{ + s_change_device_event = CoreTiming::RegisterEvent("ChangeSIDevice", ChangeDeviceCallback); + s_tranfer_pending_event = CoreTiming::RegisterEvent("SITransferPending", RunSIBuffer); + + constexpr std::array event_callbacks = { + DeviceEventCallback<0>, + DeviceEventCallback<1>, + DeviceEventCallback<2>, + DeviceEventCallback<3>, + }; + for (int i = 0; i < MAX_SI_CHANNELS; ++i) + { + s_device_events[i] = + CoreTiming::RegisterEvent(fmt::format("SIEventChannel{}", i), event_callbacks[i]); + } +} + +void ScheduleEvent(int device_number, s64 cycles_into_future, u64 userdata) +{ + CoreTiming::ScheduleEvent(cycles_into_future, s_device_events[device_number], userdata); +} + +void RemoveEvent(int device_number) +{ + CoreTiming::RemoveEvent(s_device_events[device_number]); +} + void Init() { + RegisterEvents(); + for (int i = 0; i < MAX_SI_CHANNELS; i++) { s_channel[i].out.hex = 0; @@ -415,9 +452,6 @@ void Init() // s_exi_clock_count.LOCK = 1; s_si_buffer = {}; - - s_change_device_event = CoreTiming::RegisterEvent("ChangeSIDevice", ChangeDeviceCallback); - s_tranfer_pending_event = CoreTiming::RegisterEvent("SITransferPending", RunSIBuffer); } void Shutdown() diff --git a/Source/Core/Core/HW/SI/SI.h b/Source/Core/Core/HW/SI/SI.h index 89671fe04d..07ece208ce 100644 --- a/Source/Core/Core/HW/SI/SI.h +++ b/Source/Core/Core/HW/SI/SI.h @@ -30,6 +30,9 @@ void DoState(PointerWrap& p); void RegisterMMIO(MMIO::Mapping* mmio, u32 base); +void ScheduleEvent(int device_number, s64 cycles_into_future, u64 userdata = 0); +void RemoveEvent(int device_number); + void UpdateDevices(); void RemoveDevice(int device_number); diff --git a/Source/Core/Core/HW/SI/SI_Device.cpp b/Source/Core/Core/HW/SI/SI_Device.cpp index d13e64f602..5717fe10a9 100644 --- a/Source/Core/Core/HW/SI/SI_Device.cpp +++ b/Source/Core/Core/HW/SI/SI_Device.cpp @@ -97,6 +97,10 @@ void ISIDevice::DoState(PointerWrap& p) { } +void ISIDevice::OnEvent(u64 userdata, s64 cycles_late) +{ +} + // Check if a device class is inheriting from CSIDevice_GCController // The goal of this function is to avoid special casing a long list of // device types when there is no "real" input device, e.g. when playing diff --git a/Source/Core/Core/HW/SI/SI_Device.h b/Source/Core/Core/HW/SI/SI_Device.h index 9225195689..323f6c602a 100644 --- a/Source/Core/Core/HW/SI/SI_Device.h +++ b/Source/Core/Core/HW/SI/SI_Device.h @@ -88,6 +88,9 @@ public: // Savestate support virtual void DoState(PointerWrap& p); + // Schedulable event + virtual void OnEvent(u64 userdata, s64 cycles_late); + protected: int m_device_number; SIDevices m_device_type;