summaryrefslogtreecommitdiff
path: root/Source/Core
diff options
context:
space:
mode:
authorJordan Woyak <jordan.woyak@gmail.com>2026-03-28 14:03:34 -0500
committerJordan Woyak <jordan.woyak@gmail.com>2026-03-29 11:15:03 -0500
commitf103155658e1041bed914abd67327396ebf58fad (patch)
tree007de1436683320e573f6e491463e53036b23e14 /Source/Core
parent1ab57199e615f971732eeb0f1dd88b3a13ce94af (diff)
HW/GBACore: Expose the ability to run for a single frame.
Diffstat (limited to 'Source/Core')
-rw-r--r--Source/Core/Core/HW/GBACore.cpp32
-rw-r--r--Source/Core/Core/HW/GBACore.h18
2 files changed, 35 insertions, 15 deletions
diff --git a/Source/Core/Core/HW/GBACore.cpp b/Source/Core/Core/HW/GBACore.cpp
index 5eaf204b21..5f2c3ff5b6 100644
--- a/Source/Core/Core/HW/GBACore.cpp
+++ b/Source/Core/Core/HW/GBACore.cpp
@@ -470,12 +470,20 @@ void Core::SetupEvent()
m_event.priority = 0x80;
}
+void Core::RunFrame(u16 keys)
+{
+ PushEvent({
+ .event_type = SyncEventType::RunFrame,
+ .keys = keys,
+ });
+}
+
void Core::SyncJoybus(u64 gc_ticks, u16 keys)
{
PushEvent({
- .run_until_ticks = gc_ticks,
+ .event_type = SyncEventType::TimeSync,
.keys = keys,
- .event_type = JoybusEventType::TimeSync,
+ .run_until_ticks = gc_ticks,
});
}
@@ -491,9 +499,9 @@ void Core::SendJoybusCommand(u64 gc_ticks, int transfer_time, u8* buffer, u16 ke
m_command_pending.store(true, std::memory_order_relaxed);
PushEvent({
- .run_until_ticks = gc_ticks,
+ .event_type = SyncEventType::RunCommand,
.keys = keys,
- .event_type = JoybusEventType::RunCommand,
+ .run_until_ticks = gc_ticks,
});
}
@@ -510,7 +518,7 @@ void Core::Flush()
m_event_thread.WaitForCompletion();
}
-void Core::PushEvent(JoybusEvent event)
+void Core::PushEvent(SyncEvent event)
{
if (m_event_thread.IsRunning())
m_event_thread.Push(event);
@@ -518,12 +526,22 @@ void Core::PushEvent(JoybusEvent event)
HandleEvent(event);
}
-void Core::HandleEvent(JoybusEvent event)
+void Core::HandleEvent(SyncEvent event)
{
m_keys = event.keys;
+
+ if (event.event_type == SyncEventType::RunFrame)
+ {
+ m_last_gc_ticks = m_system.GetCoreTiming().GetTicks();
+ m_gc_ticks_remainder = 0;
+
+ m_core->runFrame(m_core);
+ return;
+ }
+
RunUntil(event.run_until_ticks);
- if (event.event_type != JoybusEventType::RunCommand)
+ if (event.event_type != SyncEventType::RunCommand)
return;
if (m_link_enabled && !m_force_disconnect)
diff --git a/Source/Core/Core/HW/GBACore.h b/Source/Core/Core/HW/GBACore.h
index 64f61a0eb7..110b79a16a 100644
--- a/Source/Core/Core/HW/GBACore.h
+++ b/Source/Core/Core/HW/GBACore.h
@@ -72,6 +72,7 @@ public:
void SetForceDisconnect(bool force_disconnect);
void EReaderQueueCard(std::string_view card_path);
+ void RunFrame(u16 keys);
void SyncJoybus(u64 gc_ticks, u16 keys);
void SendJoybusCommand(u64 gc_ticks, int transfer_time, u8* buffer, u16 keys);
int GetJoybusResponse(u8* data_out);
@@ -90,19 +91,20 @@ private:
void RunFor(u64 gc_ticks);
void Flush();
- enum class JoybusEventType : u8
+ enum class SyncEventType : u8
{
TimeSync,
RunCommand,
+ RunFrame,
};
- struct JoybusEvent
+ struct SyncEvent
{
- u64 run_until_ticks{};
+ SyncEventType event_type{};
u16 keys{};
- JoybusEventType event_type{};
+ u64 run_until_ticks{}; // Not used by SyncEventType::RunFrame.
};
- void PushEvent(JoybusEvent event);
- void HandleEvent(JoybusEvent event);
+ void PushEvent(SyncEvent event);
+ void HandleEvent(SyncEvent event);
bool LoadBIOS(const char* bios_path);
bool LoadSave(const char* save_path);
@@ -137,7 +139,7 @@ private:
std::weak_ptr<GBAHostInterface> m_host;
- // Set by the GC thread before issuing a JoybusEventType::RunCommand.
+ // Set by the GC thread before issuing a SyncEventType::RunCommand.
int m_joybus_command_transfer_time{};
GBASIOJOYCommand m_joybus_command{};
@@ -149,7 +151,7 @@ private:
std::atomic_bool m_command_pending{};
// The entire threaded GBA runs within events pushed to this queue.
- Common::WorkQueueThreadSP<JoybusEvent> m_event_thread;
+ Common::WorkQueueThreadSP<SyncEvent> m_event_thread;
::Core::System& m_system;
};