gba icon indicating copy to clipboard operation
gba copied to clipboard

Support building Multiboot-ROMs

Open phijor opened this issue 3 years ago • 5 comments

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:

  1. Supply a Multiboot start script (rsrt0_multiboot.S).
  2. Build it by default in build.rs
  3. Instruct the user to adapt their linker scripts to include the multiboot rutime instead of rsrt0.o and put everything in ~~IWRAM~~ EWRAM.

phijor avatar Mar 21 '21 22:03 phijor

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.

Lokathor avatar Mar 21 '21 22:03 Lokathor

I got it to work:

Multiboot ROM output

Looking at the libgba linker scripts, the only modifications I had to make were the following (in linker.ld):

  1. Change VMA for sections .text and .rodata from >rom to >ewram
  2. Change LMA for section .iwram from AT>rom to AT>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.

phijor avatar Mar 22 '21 10:03 phijor

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.

Lokathor avatar Mar 22 '21 20:03 Lokathor

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.

TheHans255 avatar Sep 01 '22 19:09 TheHans255

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.

TheHans255 avatar Sep 01 '22 19:09 TheHans255