@@ -20,6 +20,8 @@ extern "C" {
2020#include " system/InputTypes.hpp"
2121#include " system/RomFormat.hpp"
2222#include " system/SystemBase.hpp"
23+ #include " system/mesen/GbaConfig.hpp"
24+ #include " system/mesen/GbaSystem.hpp"
2325#include " system/mesen/MesenConfig.hpp"
2426#include " system/mesen/MesenSystem.hpp"
2527#include " system/sameboy/SameBoyConfig.hpp"
@@ -178,19 +180,17 @@ SystemBase* PluginJsBridge::buildSystemFromPath(const std::string& path) {
178180 return nullptr ;
179181 }
180182
181- // Content-based dispatch: iNES magic → MesenSystem, Game Boy Nintendo
182- // logo → SameBoySystem, anything else → reject. Matching by magic bytes
183- // (not extension) means a mislabelled ROM still goes to the right
184- // backend, and totally unrelated files (a .sh script, a JPEG, …)
185- // surface as "rom-error" instead of being executed as instructions
186- // by whichever backend caught them. The pre-detector code fell through
187- // to SameBoy for anything not ending in `.nes`, which produced a stream
188- // of "Wrote XX to YYYY (RAM Mirror)" log spam from the GB CPU
189- // executing garbage.
183+ // Content-based dispatch: iNES magic → MesenSystem, GBA Nintendo logo
184+ // at $0004 → GbaSystem, Game Boy Nintendo logo at $0104 → SameBoySystem,
185+ // anything else → reject. Matching by magic bytes (not extension) means
186+ // a mislabelled ROM still goes to the right backend, and totally
187+ // unrelated files (a .sh script, a JPEG, …) surface as "rom-error"
188+ // instead of being executed as instructions by whichever backend caught
189+ // them.
190190 const RomFormat fmt = detectRomFormat (bytes);
191191 if (fmt == RomFormat::Unknown) {
192192 std::fprintf (stderr,
193- " buildSystemFromPath: '%s' is not a recognised Game Boy or NES ROM\n " ,
193+ " buildSystemFromPath: '%s' is not a recognised Game Boy, NES, or GBA ROM\n " ,
194194 path.c_str ());
195195 emitRomEvent (engine, " rom-error" , path);
196196 return nullptr ;
@@ -207,6 +207,20 @@ SystemBase* PluginJsBridge::buildSystemFromPath(const std::string& path) {
207207 return sys.release ();
208208 }
209209
210+ if (fmt == RomFormat::Gba) {
211+ GbaSystemConfig cfg;
212+ cfg.romPath = path;
213+ // BIOS lookup: pass through anything the host has dropped into the
214+ // build firmware dir. If absent, GbaSystem falls back to HLE
215+ // (Mesen-zeroed boot ROM) and most non-trivial ROMs will hang on
216+ // their first BIOS SWI. Plumbing a UI-side BIOS picker is a
217+ // follow-up.
218+ cfg.biosPath = " build/firmware/gba_bios.bin" ;
219+ auto sys = std::make_unique<GbaSystem>(id, cfg, std::move (bytes));
220+ sys->onActivate (sr);
221+ return sys.release ();
222+ }
223+
210224 SameBoyConfig cfg;
211225 cfg.romPath = path;
212226 cfg.model = SameBoyModel::CgbC;
0 commit comments