gba
gba copied to clipboard
Support building Multiboot-ROMs
I'm currently dabbling with the GBA's support for loading ROMs from serial (i.e. multibooting).
To build a Multiboot ROM, one must put .text
and .rodata
into ~~IWRAM~~ EWRAM (with the entrypoint at 0x0200_0000
).
Would it be possible to support this usecase in this crate?
I can imagine the following approach:
- Supply a Multiboot start script (
rsrt0_multiboot.S
). - Build it by default in
build.rs
- Instruct the user to adapt their linker scripts to include the multiboot rutime instead of
rsrt0.o
and put everything in ~~IWRAM~~ EWRAM.
Yes.
I don't recall who, but I recall one user getting multi-boot working with this crate by modifying the linker script and boot shim. They were able to make some pixels show up on actual GBA hardware by using a GBA/GCN link cable hooked to a Wii using some sort of Homebrew thing to send the rom from the Wii to the GBA.
So, it's possible.
I got it to work:
Looking at the libgba
linker scripts, the only modifications I had to make were the following (in linker.ld
):
- Change VMA for sections
.text
and.rodata
from>rom
to>ewram
- Change LMA for section
.iwram
fromAT>rom
toAT>ewram
so.data
gets loaded from EWRAM to IWRAM
I did not have to touch the start script (rsrt0.S
). For some reason mgba
would not load the ROM, but I guess this is just Multiboot autodetection being flakey; it works on real hardware.
Should this be documented somewhere? I can make a PR if you point me in the correct direction.
I for now just make a file called multiboot.md
in the repository root and write up the steps there. Keeping things like this in markdown files seems like the simplest way to get started with it.
I've been dabbling in this lately - I recently wrote a sample that deploys an already-written multiboot payload to another GBA over MultiPlay: https://github.com/TheHans255/rust-gba-multiboot-test. Ideally, we'd have a way to build a multiboot executable that shares code with a cartridge executable to let us efficiently make updates to both, which would likely happen via a shared library crate and two executable crates.
I did not have to touch the start script (rsrt0.S). For some reason mgba would not load the ROM, but I guess this is just Multiboot autodetection being flakey; it works on real hardware.
I believe this is correct for SPI mode, but not for MultiPlay (GBA Link Cable) or JOYBUS (Wii/GameCube) mode. Execution starts at 0x0200_00c0
for a Multiboot payload from SPI or MultiPlay, but the GBA BIOS writes to 0x0200_00c4
and 0x0200_00c5
in MultiPlay mode to indicate the boot mode and the player number, respectively, which will corrupt any instructions written there. As for JOYBUS mode, execution starts further down at 0x0200_00e0
. A proper rsrt0.S
start script will have its header augmented to add b
instructions to those locations.
Also, an idea that I saw in the GBATEK document (https://www.problemkaputt.de/gbatek.htm#biosmultibootsinglegamepak) is that if a game is less than 256K, it could be compiled in a "hybrid" mode where the same payload is valid for both cartridge and multiboot - in this mode, the cartridge entry point at 0x0800_0000
leads to a small shim that copies the cartridge into EWRAM. If we need to provide sample linker scripts and start scripts for multiboot, it might be interesting to consider adding samples for the hybrid mode as well.