Doc.4 GBAの仕様について(メモリエリア)

メモリエリア

GBAのメモリエリアは次のようになっています。詳しいことはGBATEKを参照してください。

エリア開始位置終了位置大きさ
System ROM0000:0000h0000:3fffh16kb
EWRAM0200:0000h0203:ffffh256kb
IWRAM0300:0000h0300:7fffh32kb
IO RAM0400:0000h0401:03ffh1kb
PAL RAM0500:0000h0500:03ffh1kb
VRAM0600:0000h0601:7fffh96kb
OAM0700:0000h0700:03ffh1kb
PAK ROM0800:0000h--
Cart RAM0e00:0000h--

System ROM

別名BIOSと言われていて、00h〜2Ahまでのシステムコールを呼び出すこともできます。
頻繁に使用される関数はここに用意されているので自作しなくて大丈夫です。
ただ速度の面で自作した方が速い場合もあります。

電源ONした時に一番最初に表示されるタイトルロゴやコードもこの中に含まれます。

EWRAM

External work RAMの略で、ゲーム上で使用される画像やコードを置いたりします。
もしカードリッジを挿さない状態でマルチブートケーブルを使用した場合、
転送されたデータはEWRAM領域に配置されます。

IWRAM

GBAの中でもっとも高速な領域です。
スピードを求められる処理はIWRAMに置くことをお奨めします。
ただし大きさが32kbしかないため、何を置くか慎重に選ぶ必要があります。

IO RAM

GBAのグラフィックやサウンド、ボタンなどをコントロールしています。
アクセス方法は変数を読む込んだり、書き込んだりする方法と同じです。
ヘッダファイルにメモリの位置をdefineしてアクセスします。

  • gba_input.h(抜粋)
    #define REG_KEYINPUT	*(vu16*)(REG_BASE + 0x130)  // Key Input
    #define REG_KEYCNT	*(vu16*)(REG_BASE + 0x132)  // Key Control

PAL RAM

BG(画面)とスプライトのパレットを設定する領域です。

VRAM

ここのメモリ配置と画面は反映像みたいなもので、
書き換えることで画面に変化をつけることができます。
画面更新の期間(垂直帰線期間)を無視して書き換えを行った場合、
画面がチラついてしまうので注意が必要です。

OAM

スプライトの設定をする領域です。

PAK ROM

カードリッジの領域です。

Cart RAM

ゲームのセーブデータ等に使用されます。
ただ、Cart RAMには様々な種類があってSRAM、EEPROM、Flash ROMなどがあります。
homebrewではアクセス方法の手軽なSRAMが人気のようです。

メモリのアクセス

以下にGBATEKの抜粋を記載します。

Address Bus Width and CPU Read/Write Access Widths
Shows the Bus-Width, supported read and write widths,
and the clock cycles for 8/16/32bit accesses.

Region        Bus   Read      Write     Cycles
BIOS ROM      32    8/16/32   -         1/1/1
Work RAM 32K  32    8/16/32   8/16/32   1/1/1
I/O           32    8/16/32   8/16/32   1/1/1
OAM           32    8/16/32   16/32     1/1/1 *
Work RAM 256K 16    8/16/32   8/16/32   3/3/6 **
Palette RAM   16    8/16/32   16/32     1/1/2 *
VRAM          16    8/16/32   16/32     1/1/2 *
GamePak ROM   16    8/16/32   -         5/5/8 **/***
GamePak Flash 16    8/16/32   16/32     5/5/8 **/***
GamePak SRAM  8     8         8         5     **

Timing Notes:

*   Plus 1 cycle if GBA accesses video memory at the same time.
**  Default waitstate settings, see System Control chapter.
*** Separate timings for sequential, and non-sequential accesses.
One cycle equals approx. 59.59ns (ie. 16.78MHz clock).

All memory (except GamePak SRAM) can be accessed by 16bit and 32bit DMA.

この表のRead, Writeは、そのメモリにアクセスできるビット単位を表しています。

よくみるとVRAMでは8bitでは書き込めないことがわかります。
また、CyclesはIWRAMが1/1/1に対して、GamePak ROMは5/5/8なので、
アクセスのスピードだけでも5倍違うことが分かります。
この辺りの制約は知っていて損はないので覚えておいてください。

指定したいメモリ位置にコードを置く方法

自分の書いたコードを指定したメモリ位置に置く為にはマクロを使うのがいいと思います。
使い方は次のとおりです。

#define IWRAM_CODE		__attribute__((section(".iwram"), long_call))
#define EWRAM_CODE		__attribute__((section(".ewram"), long_call))
#define IWRAM_DATA		__attribute__((section(".iwram")))
#define EWRAM_DATA		__attribute__((section(".ewram")))
#define EWRAM_BSS		__attribute__((section(".sbss")))
#define ROM_DATA		__attribute__((section(".roda")))
// IWRAM領域
IWRAM_CODE void SpriteInit(void)
{
    //
}
// EWRAM領域
EWRAM_CODE void SpriteInit(void)
{
    //
}
// ROM領域(指定なし)
void SpriteInit(void)
{
    //
}

プロトタイプ宣言にも同じように指定して上げることを忘れないでください。
また、1つのソースファイル(.c)に複数の関数を書くとき、領域指定は1つに統一します。
バラバラに指定してコンパイルすることも可能ですが、後々混乱しない為に
ファイルは分けて置いたほうが無難でしょう。

一方、変数の定義は次のように指定することができます。
指定なしの場合、IWRAMになるので注意してください。

u16 test1 EWRAM_BSS;  // EWRAM領域
u16 test2 IWRAM_DATA; // IWRAM領域
u16 test3;            // IWRAM領域(指定なし)

定義の場所は「C:\devkitPro\libgba\include\gba_base.h」の
99行目あたりにあります。

 

正しくメモリ上に置かれているか確認する方法については、
コンパイル後に生成されたマップファイル(.map)で確認可能です。
一度、マップファイルの全体を読んでみるのもいいかと思います。

履歴

  • 2014/10/29
  • 2007/09/11

Last-modified: 2014-10-31 (金) 19:44:07 (2646d)