初めに
開発環境の導入は以下の記事に記録しています。
アセンブリでGBAプログラミング:ARM7でVRAM塗り潰し
Aボタンが押されたら画面全体を赤くするだけの検証用プログラムを書きました。
ソース
コンパイル方法は以下の通り。
arm-none-eabi-as -mcpu=arm7tdmi -march=armv4t -g main.s -o main.o
arm-none-eabi-ld -nostdlib -Ttext=0x00000000 -o main.elf main.o
arm-none-eabi-objcopy -O binary main.elf main.gba
main.s
.arm
.section .text
.global _start
/* --- 入口 --- */
.org 0x00000000
_start:
b ResetHandler @ ResetHandlerへジャンプ
/* --- 任天堂ロゴ (0x0004〜0x009F, 156バイト) --- */
.byte 0x24,0xff,0xae,0x51,0x69,0x9a,0xa2,0x21
.byte 0x3d,0x84,0x82,0x0a,0x84,0xe4,0x09,0xad
.byte 0x11,0x24,0x8b,0x98,0xc0,0x81,0x7f,0x21
.byte 0xa3,0x52,0xbe,0x19,0x93,0x09,0xce,0x20
.byte 0x10,0x46,0x4a,0x4a,0xf8,0x27,0x31,0xec
.byte 0x58,0xc7,0xe8,0x33,0x82,0xe3,0xce,0xbf
.byte 0x85,0xf4,0xdf,0x94,0xce,0x4b,0x09,0xc1
.byte 0x94,0x56,0x8a,0xc0,0x13,0x72,0xa7,0xfc
.byte 0x9f,0x84,0x4d,0x73,0xa3,0xca,0x9a,0x61
.byte 0x58,0x97,0xa3,0x27,0xfc,0x03,0x98,0x76
.byte 0x23,0x1d,0xc7,0x61,0x03,0x04,0xae,0x56
.byte 0xbf,0x38,0x84,0x00,0x40,0xa7,0x0e,0xfd
.byte 0xff,0x52,0xfe,0x03,0x6f,0x95,0x30,0xf1
.byte 0x97,0xfb,0xc0,0x85,0x60,0xd6,0x80,0x25
.byte 0xa9,0x63,0xbe,0x03,0x01,0x4e,0x38,0xe2
.byte 0xf9,0xa2,0x34,0xff,0xbb,0x3e,0x03,0x44
.byte 0x78,0x00,0x90,0xcb,0x88,0x11,0x3a,0x94
.byte 0x65,0xc0,0x7c,0x63,0x87,0xf0,0x3c,0xaf
/* --- タイトル・ゲームコード・メーカーコード (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:
@ 画面モード設定 (Mode3 + BG2)
ldr r0, =0x04000000
ldr r1, =0x0403
strh r1, [r0]
MainLoop:
@ KEYINPUT 読み取り
ldr r0, =0x04000130 @ 0x04000130(アドレス)をr0へ格納
ldrh r1, [r0] @ 0x04000130の値を → r1レジスタへビット読みこむ
@ Aボタン(bit0)が押されたか確認 (押されると0)
tst r1, #1 @ #1 = 0x00000001
bne MainLoop @ 押されてなければループ
@ 押されたら塗り潰し
bl FillScreenRed
WaitRelease:
@ 離されるまで待つ
ldr r0, =0x04000130
ldrh r1, [r0]
tst r1, #1
beq WaitRelease
b MainLoop
FillScreenRed:
push {lr}
@ VRAM = 0x06000000
ldr r0, =0x06000000
mov r1, #0x1F @ 赤 (RGB15)
ldr r2, =38400 @ 240*160
FillLoop:
strh r1, [r0], #2
subs r2, r2, #1
bne FillLoop
pop {lr}
bx lr
解説
0x04000130にボタンが押されているかを記録するレジスタが対応しています。
それぞれのビットにボタンが対応しています。例えばAボタンなら第0ビット目が対応しています。
それぞれのビットが0なら押されている、1なら押されていない。
以下の2行を実行すると0x04000130から16ビットの値を取得してr1レジスタに格納します。
ldr r0, =0x04000130
ldrh r1, [r0]
0ビット目が0だとゼロフラグが立ち、bneでMainLoopに跳ばずbl FillScreenRedが実行される。
tst r1, #1
bne MainLoop
動作確認
Aボタンを押すと画面全体が赤くなった
開発環境
ThinkPad x280
OS: Ubuntu 22.04.5 LTS (Jammy Jellyfish)
Kernel: Linux 6.8.0-84-generic
CPU: Intel Core i5-8250U, 4 cores, 8 threads, Little Endian
Architecture: x86_64

