Fixing Magic Floor for GBA Movie Player's broken multiboot

Discussion of development of software for any "obsolete" computer or video game system.
Post Reply
Posts: 22054
Joined: Sun Sep 19, 2004 11:12 pm
Location: NE Indiana, USA (NTSC)

Fixing Magic Floor for GBA Movie Player's broken multiboot

Post by tepples » Sat Nov 10, 2018 9:40 pm

The GBA cartridge header has separate entry points for ROM at offset 0x00 (that is, address 0x08000000) and EWRAM at offset 0xC0 (that is, address 0x020000C0). However, the GBA Movie Player and some other flash solutions that support only multiboot programs appear not to respect this: they'll load the executable into EWRAM and jump to 0x02000000, which is supposed to be the ROM entry point.

Most homebrew multiboot programs support both cartridge and multiboot use by copying the code from ROM to RAM when run as a cartridge. But if the copy routine loads a constant source address of 0x08000000 (start of cartridge), it'll get tripped up and read open bus. The GBA version of Magic Floor by nocash is an example of a program that fails on GBA Movie Player and in the mGBA emulator.

I discovered a fix that allows a program that works on cart and multiboot to also work on GBAMP. I patched the copy routine to calculate the source address based on the program counter (r15), so that if it gets loaded into RAM and run with the cart entry point, it copies from 0x02000000 to 0x02000000, essentially a no-op.

The source address is loaded at start+0xC8:
mov r0, #0x08000000
The fix makes the copy source PC relative:
sub r0, pc, #0xD0

This can be applied to the source or to the binary. If you have no$gba installed, open MAGICFLR.A22 and make this change around line 185 of MAGICFLR.A22 near rom_start:, then reassemble.

Code: Select all

; Replace this
 mov  r0,8000000h  ;src/rom     ;\
; with this
 sub  r0,pc,0D0h   ;src/rom     ;\
Or with a hex editor, open MAGICFLR.GBA and replace the bytes at 0x00C8 with D0 00 4F E2.

The GBA init code in devkitARM handles it a different way. Because the init code is assembled once and linked into both cartridge and multiboot programs, it cannot conditionally assemble the copying code because that would cause "not constant" errors. Instead, it uses 12 bytes of Thumb code to compare __text_start (beginning of the main code section) and PC to decide whether to copy. (I've attached a copy of devkitARM's init code for the benefit of users whose operating system lacks a TLS 1.2 client.)
(9.43 KiB) Downloaded 693 times

Post Reply