GBAには電源を切ってもデータが残る領域としてCart RAMがあります。カードリッジを分解して覗いてみると本体チップの横にある小さなチップがそれに当たります。もちろんセーブ機能がないゲームだった場合は入っていないので注意してください。折角の機会ですから型番を検索して仕様を調べてみるのもいいかもしれません。この部分のメモリにはSRAM(32KB)、EEPROM(512B or 8KB)、Flash ROM(64KB)などの種類があります。特に扱いやすいのはSRAMで、自作ゲームを作られている方はだいたい使用しています。ここではSRAMの使い方のみを説明します。
SRAMは32KBのサイズを持っていてアドレスは0E00:0000h~E007:FFFhまでとなっています。読み書きにはポインタを使い、レジスタの設定などの前準備はまったく不要です。ただし実機でテストしたい場合、マジコンの種類によってはCart RAMの形式を指定する必要があるかもしれません。以下にマクロと関数を用意しましたので、参考にしていただければと思います。
#include "lib/gba.h" #define ADR_SRAM (u8*)0xe000000 //--------------------------------------------------------------------------- u8 SRAMRead8(u32 offset) { u8* sram = (u8*)ADR_SRAM + offset; return (u8)sram[0]; } //--------------------------------------------------------------------------- u16 SRAMRead16(u32 offset) { u16 ret; ret = SRAMRead8(offset++); ret |= SRAMRead8(offset) << 8; return ret; } //--------------------------------------------------------------------------- u32 SRAMRead32(u32 offset) { u32 ret; ret = SRAMRead8(offset++); ret |= SRAMRead8(offset++) << 8; ret |= SRAMRead8(offset++) << 16; ret |= SRAMRead8(offset) << 24; return ret; } //--------------------------------------------------------------------------- void SRAMWrite8(u32 offset, u8 data) { u8* sram = (u8*)ADR_SRAM + offset; *sram = (u8)(data & 0xff); } //--------------------------------------------------------------------------- void SRAMWrite16(u32 offset, u16 data) { SRAMWrite8(offset++, (u8)((data ) & 0xff)); SRAMWrite8(offset++, (u8)((data>>8) & 0xff)); } //--------------------------------------------------------------------------- void SRAMWrite32(u32 offset, u32 data) { SRAMWrite8(offset++, (u8)((data ) & 0xff)); SRAMWrite8(offset++, (u8)((data>>8 ) & 0xff)); SRAMWrite8(offset++, (u8)((data>>16) & 0xff)); SRAMWrite8(offset++, (u8)((data>>24) & 0xff)); } //--------------------------------------------------------------------------- u8* SRAMGetPointer() { return ADR_SRAM; } //--------------------------------------------------------------------------- void WaitForVsync(void) { while (*(volatile u16*)0x4000006 >= 160) {}; while (*(volatile u16*)0x4000006 < 160) {}; } //--------------------------------------------------------------------------- int main(void) { // エミュレータのTools->Memory viewerで書き込まれた値を確認してください // SRAMのアドレス:E000000 SRAMWrite8(0x00, 1); SRAMWrite16(0x04, 2); SRAMWrite32(0x08, 0xdeadbeef); // エミュレータのTools->Loggingで読み込まれた値を確認してください TRACE("0x%x\n", SRAMRead8(0x00)); TRACE("0x%x\n", SRAMRead16(0x04)); TRACE("0x%x\n", SRAMRead32(0x08)); for(;;) { WaitForVsync(); } }
関数にも記載されていますが、SRAMは8bitづつしかアクセスできないのでそのことは忘れないでください。