HW/GBACore: Expose the ability to run for a single frame.

This commit is contained in:
Jordan Woyak 2026-03-28 14:03:34 -05:00
parent 1ab57199e6
commit f103155658
2 changed files with 35 additions and 15 deletions

View File

@ -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)

View File

@ -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;
};