実機での起動に当たって
GBA BIOSは、ROMヘッダ内の0x0004〜0x009Fに存在するNintendoロゴデータを、BIOS内部に保存された正規データと比較しています。
一致しない場合は起動せず、Nintendoロゴ画面で停止します。
当時なりの不正複製対策でしょう。そこで有志が配布している実際に実機で起動する自作ROM等からロゴデータを取り出します。
著作権の問題でQIITAにそのまま載せるのはあまり宜しくないので、取り出したデータのダンプは載せません。
dd if=test.gba of=logo.bin bs=1 skip=4 count=156
hexdump -C logo.bin
検証用コード
header.s
.arm
.section .text
.global _start
.global ResetHandler
.org 0x00000000
_start:
b ResetHandler
.incbin "logo.bin" @ 0x0004-0x009F
/* --- ゲームに関する情報(0x00A0〜0x00BF) --- */
.org 0x000000A0
.ascii "GBADEMO " @ 名前 12文字
.byte 0x00,0x00,0x00,0x00 @ ゲームコード 4バイト
.byte 0x00,0x00 @ メーカーコード 2バイト
.byte 0x96 @ 固定値
.byte 0x00 @ メインユニットコード
.byte 0x00 @ 機器の種類
.space 7 @ 予約領域
.byte 0x00,0x00 @ 補完チェック・マスクROMバージョン
.space 2 @ 残り予約領域
.align 2
ResetHandler:
ldr sp, =0x03007F00
bl main @ Cへ 跳ぶ
InfiniteLoop:
b InfiniteLoop
main.c
typedef unsigned short u16;
typedef unsigned int u32;
#define REG_DISPCNT (*(volatile u16*)0x04000000) // 画面制御レジスタ
#define VRAM ((volatile u16*)0x06000000)
void main(void)
{
// Mode3 + BG2
REG_DISPCNT = 0x0403;
u16 color = 0x07C0; // 緑
for (int i = 0; i < 240 * 160; i++) {
VRAM[i] = color;
}
while (1);
}
link.ld
ENTRY(_start)
SECTIONS
{
. = 0x00000000;
.text :
{
*(.text)
*(.rodata)
}
.data :
{
*(.data)
}
.bss :
{
*(.bss)
*(COMMON)
}
}
ビルド
arm-none-eabi-as header.s -o header.o
arm-none-eabi-gcc -c main.c -o main.o -nostdlib -ffreestanding
arm-none-eabi-ld header.o main.o -T link.ld -o out.elf
arm-none-eabi-objcopy -O binary out.elf out.gba
実機での起動
生成したout.gbaをGBAから起動したところ、少し見づらいですが画面いっぱいに緑色が表示されました。
20260511追記
以下のように書かないと広域変数を使った場合に失敗した。
link.ld
ENTRY(_start)
SECTIONS
{
. = 0x08000000;
.text :
{
*(.text)
*(.rodata)
}
.data :
{
*(.data)
}
.bss :
{
*(.bss)
*(COMMON)
}
}