summaryrefslogtreecommitdiff
path: root/Source/Core
diff options
context:
space:
mode:
authorJMC47 <JMC4789@gmail.com>2026-03-30 12:30:37 -0400
committerGitHub <noreply@github.com>2026-03-30 12:30:37 -0400
commitc93c9dd4073ff3c54490d4ced90edc4d97cf2deb (patch)
tree075f3a1dc3f92b71a904eaa30c66789b29a5d801 /Source/Core
parent6ba804416abbfbf80e6d5a5bf1bc91dbc96e96aa (diff)
parent84dd2304d60a47816bee348272b4dc0946dbbfea (diff)
Merge pull request #14526 from jordan-woyak/gbacore-stuff
HW/GBACore: Improvements.
Diffstat (limited to 'Source/Core')
-rw-r--r--Source/Core/Core/HW/GBACore.cpp57
-rw-r--r--Source/Core/Core/HW/GBACore.h29
-rw-r--r--Source/Core/Core/State.cpp2
3 files changed, 60 insertions, 28 deletions
diff --git a/Source/Core/Core/HW/GBACore.cpp b/Source/Core/Core/HW/GBACore.cpp
index 6d1d14b239..d95617b9b3 100644
--- a/Source/Core/Core/HW/GBACore.cpp
+++ b/Source/Core/Core/HW/GBACore.cpp
@@ -27,9 +27,9 @@
#include "Common/Crypto/SHA1.h"
#include "Common/FileUtil.h"
#include "Common/IOFile.h"
+#include "Common/Logging/Log.h"
#include "Common/MinizipUtil.h"
#include "Common/ScopeGuard.h"
-#include "Common/Thread.h"
#include "Core/Config/MainSettings.h"
#include "Core/ConfigManager.h"
@@ -114,7 +114,7 @@ static VFile* OpenROM_Zip(const char* path)
continue;
vf = VFileMemChunk(buffer.data(), info->uncompressed_size);
- if (mCoreIsCompatible(vf) == mPLATFORM_GBA)
+ if (mCoreIsCompatible(vf) != mPLATFORM_NONE)
{
vf->seek(vf, 0, SEEK_SET);
break;
@@ -209,10 +209,9 @@ bool Core::Start(u64 gc_ticks)
mCoreConfigSetIntValue(&m_core->config, "useBios", 0);
mCoreConfigSetIntValue(&m_core->config, "skipBios", 0);
- if (m_core->platform(m_core) == mPLATFORM_GBA &&
- !LoadBIOS(File::GetUserPath(F_GBABIOS_IDX).c_str()))
+ if (m_core->platform(m_core) == mPLATFORM_GBA)
{
- return false;
+ LoadBIOS(File::GetUserPath(F_GBABIOS_IDX).c_str());
}
if (rom)
@@ -338,13 +337,13 @@ bool Core::LoadBIOS(const char* bios_path)
VFile* vf = VFileOpen(bios_path, O_RDONLY);
if (!vf)
{
- PanicAlertFmtT("Error: GBA{0} failed to open the BIOS in {1}", m_device_number + 1, bios_path);
+ ERROR_LOG_FMT(CORE, "GBA{0} failed to open the BIOS in {1}", m_device_number + 1, bios_path);
return false;
}
if (!m_core->loadBIOS(m_core, vf, 0))
{
- PanicAlertFmtT("Error: GBA{0} failed to load the BIOS in {1}", m_device_number + 1, bios_path);
+ ERROR_LOG_FMT(CORE, "GBA{0} failed to load the BIOS in {1}", m_device_number + 1, bios_path);
vf->close(vf);
return false;
}
@@ -471,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,
});
}
@@ -492,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,
});
}
@@ -511,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);
@@ -519,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)
@@ -633,11 +650,13 @@ void Core::ExportSave(std::string_view save_path)
void Core::DoState(PointerWrap& p)
{
Flush();
- if (!IsStarted())
+
+ bool is_started = IsStarted();
+ p.Do(is_started);
+
+ if (!is_started)
{
- ::Core::DisplayMessage(fmt::format("GBA{} core not started. Aborting.", m_device_number + 1),
- 3000);
- p.SetVerifyMode();
+ Stop();
return;
}
@@ -658,6 +677,8 @@ void Core::DoState(PointerWrap& p)
return;
}
+ Start(0);
+
p.Do(m_video_buffer);
p.Do(m_last_gc_ticks);
p.Do(m_gc_ticks_remainder);
diff --git a/Source/Core/Core/HW/GBACore.h b/Source/Core/Core/HW/GBACore.h
index 64f61a0eb7..47f5a3102e 100644
--- a/Source/Core/Core/HW/GBACore.h
+++ b/Source/Core/Core/HW/GBACore.h
@@ -7,6 +7,7 @@
#include <array>
#include <memory>
+#include <span>
#include <string>
#include <string_view>
#include <vector>
@@ -72,10 +73,20 @@ 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);
+ // Wait for requested GBA emulation to complete.
+ void Flush();
+
+ mAudioBuffer* GetAudioBuffer() { return m_core->getAudioBuffer(m_core); }
+ std::span<const u32> GetVideoBuffer() const { return m_video_buffer; }
+
+ mPlatform GetPlatform() const { return m_core->platform(m_core); }
+ u32 GetAudioSampleRate() const { return m_core->audioSampleRate(m_core); }
+
void ImportState(std::string_view state_path);
void ExportState(std::string_view state_path);
void ImportSave(std::string_view save_path);
@@ -88,21 +99,21 @@ public:
private:
void RunUntil(u64 gc_ticks);
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 +148,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 +160,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;
};
diff --git a/Source/Core/Core/State.cpp b/Source/Core/Core/State.cpp
index b9f655e578..e121dcfb7b 100644
--- a/Source/Core/Core/State.cpp
+++ b/Source/Core/Core/State.cpp
@@ -95,7 +95,7 @@ struct CompressAndDumpStateArgs
static Common::WorkQueueThreadSP<CompressAndDumpStateArgs> s_compress_and_dump_thread;
// Don't forget to increase this after doing changes on the savestate system
-constexpr u32 STATE_VERSION = 184; // Last changed in PR 14110
+constexpr u32 STATE_VERSION = 185; // Last changed in PR 14526
// Increase this if the StateExtendedHeader definition changes
constexpr u32 EXTENDED_HEADER_VERSION = 1; // Last changed in PR 12217