目的
GBAのROMはメモリの0x08000000から配置されているらしい。(実際にはメモリには読み込まずROMの領域にメモリのアドレスが振られているらしい)。
そこで今回はmain関数の開始アドレスを表示して本当に0x08000000付近になっているかを確かめる。
検証結果
ビルドの手順は筆者の以下の記事を参考
GBA自作コードを実機で動作させる手順
main関数は080002C8から始まっているので、ROMが0x08000000から始まるというのは正しいことが証明出来た。
検証用コード
main.c
typedef unsigned char uint8_t;
typedef unsigned short uint16_t;
typedef unsigned int uint32_t;
#define REG_DISPCNT (*(volatile unsigned int*)0x04000000)
#define MODE3 3
#define BG2_ENABLE (1 << 10)
#define VRAM ((volatile uint16_t*)0x06000000)
volatile const uint8_t font[16][8] = {
// 0
{0b00111100, // ████
0b01100110, // ██ ██
0b01100110, // ██ ██
0b01100110, // ██ ██
0b01100110, // ██ ██
0b01100110, // ██ ██
0b00111100, // ████
0b00000000}, //
// 1
{0b00011000, // ██
0b00111000, // ███
0b00011000, // ██
0b00011000, // ██
0b00011000, // ██
0b00011000, // ██
0b00111100, // ████
0b00000000}, //
// 2
{0b00111100, // ██████
0b01100110, // ██ ██
0b00000110, // ██
0b00011100, // ██
0b00110000, // ██
0b01100000, // ██
0b01111110, // ████████
0b00000000}, //
// 3
{0b00111100, // ██████
0b01100110, // ██ ██
0b00000110, // ██
0b00011100, // ███
0b00000110, // ██
0b01100110, // ██ ██
0b00111100, // ██████
0b00000000}, //
// 4
{0b00001100, // ██
0b00011100, // ███
0b00111100, // ████
0b01101100, // ██ ██
0b01111110, // ████████
0b00001100, // ██
0b00001100, // ██
0b00000000}, //
// 5
{0b01111110, // ████████
0b01100000, // ██
0b01111100, // ██████
0b00000110, // ██
0b00000110, // ██
0b01100110, // ██ ██
0b00111100, // ██████
0b00000000}, //
// 6
{0b00011100, // ████
0b00110000, // ██
0b01100000, // ██
0b01111100, // ██████
0b01100110, // ██ ██
0b01100110, // ██ ██
0b00111100, // ██████
0b00000000}, //
// 7
{0b01111110, // ████████
0b00000110, // ██
0b00001100, // ██
0b00011000, // ██
0b00110000, // ██
0b00110000, // ██
0b00110000, // ██
0b00000000}, //
// 8
{0b00111100, // ██████
0b01100110, // ██ ██
0b01100110, // ██ ██
0b00111100, // ██████
0b01100110, // ██ ██
0b01100110, // ██ ██
0b00111100, // ██████
0b00000000}, //
// 9
{0b00111100, // ██████
0b01100110, // ██ ██
0b01100110, // ██ ██
0b00111110, // ██████
0b00000110, // ██
0b00001100, // ██
0b00111000, // ████
0b00000000}, //
// A
{0b00011000, // ██
0b00111100, // ████
0b01100110, // ██ ██
0b01100110, // ██ ██
0b01111110, // ██████
0b01100110, // ██ ██
0b01100110, // ██ ██
0b00000000}, //
// B
{0b01111100, // █████
0b01100110, // ██ ██
0b01100110, // ██ ██
0b01111100, // █████
0b01100110, // ██ ██
0b01100110, // ██ ██
0b01111100, // █████
0b00000000}, //
// C
{0b00111100, // ██████
0b01100110, // ██ ██
0b01100000, // ██
0b01100000, // ██
0b01100000, // ██
0b01100110, // ██ ██
0b00111100, // ██████
0b00000000}, //
// D
{0b01111000, // █████
0b01101100, // ██ ██
0b01100110, // ██ ██
0b01100110, // ██ ██
0b01100110, // ██ ██
0b01101100, // ██ ██
0b01111000, // █████
0b00000000}, //
// E
{0b01111110, // ████████
0b01100000, // ██
0b01100000, // ██
0b01111100, // ██████
0b01100000, // ██
0b01100000, // ██
0b01111110, // ████████
0b00000000}, //
// F
{0b01111110, // ████████
0b01100000, // ██
0b01100000, // ██
0b01111100, // ██████
0b01100000, // ██
0b01100000, // ██
0b01100000, // ██
0b00000000}, //
};
// PC値を取得する関数
static inline uint32_t get_pc(void) {
uint32_t pc_value;
__asm__ __volatile__ (
"mov %0, pc\n"
: "=r" (pc_value)
);
return pc_value;
}
static inline void putpixel(int x, int y, uint16_t c) {
VRAM[y * 240 + x] = c;
}
void draw_hex(int x, int y, int v, uint16_t color) {
for (int row = 0; row < 8; row++) {
uint8_t bits = font[v][row];
for (int col = 0; col < 8; col++) {
if (bits & (1 << (7 - col))) {
putpixel(x + col, y + row, color);
}
}
}
}
// 16進数表示用の関数
void draw_hex_number(int x, int y, uint32_t value, uint16_t color) {
for (int i = 0; i < 8; i++) {
int digit = (value >> (28 - i * 4)) & 0xF;
draw_hex(x + i * 9, y, digit, color);
}
}
int main(void) {
REG_DISPCNT = MODE3 | BG2_ENABLE;
for (int i = 0; i < 240 * 160; i++)
VRAM[i] = 0;
// PC値を取得
uint32_t pc_value = get_pc();
draw_hex_number(10,30, (uint32_t)&main, 0x07E0); // MAINの読み込み位置
while (1);
}