GBFS

GBAにはLinuxのようなOSがない為、当たり前に使っているような恩恵を受けることもできません。その1つはファイル管理システムの存在です。C言語にはfopenやfseekなどの関数を使用すると中身のバイナリにアクセスするわけですけれどGBAはそうはいきません。その為、自分でプロジェクトに結び付けることをすると1つ1つポインタでやりとりして管理が面倒になります。そこでお奨めなのはGBFSです。ツールはdevkitProに標準装備されています。

原理

仕組みはとても簡単です。.gbaファイルの終端にファイルを繋げて読み込ませてしまおうというものです。例として.gbaファイルが0x1000のサイズだった場合、起動したときのアドレスは0800:0000h~0800:0FFFhになります。.gbaファイルの後ろにデータを追加したとき、その内容は0800:1000h以降に配置されるわけです。もちろんこのアドレスはROM領域に配置される為、リードオンリーであることは忘れないでください。

#define ADR_ROM_END  (u8*)&__rom_end__
extern u8 __rom_end__;

__rom_end__はC:\devkitPro\devkitARM\arm-none-eabi\lib\gba_cart.ld(github)に定義されています。このアドレスを利用して次のような関数と使います。

// ExtendTinyFileSystem

u8* EtfsReadu8(u32 offset)
{
	u8* p = ADR_ROM_END + offset;
	return *p;
}

u16* EtfsReadu16(u32 offset)
{
	u16* p = (u16*)ADR_ROM_END + offset;
	return *p;
}

u32* EtfsReadu32(u32 offset)
{
	u32* p = (u32*)ADR_ROM_END + offset;
	return *p;
}

u8* EtfsGetPointer(void)
{
	return ADR_ROM_END;
}

改良

GBFSは、上記の原理を拡張して複数のファイルを参照可能にし、さらに詳細なファイル情報を追加したものです。仮に以下のようなファイルがあったとします。

1.txt
2.png
3.bmp

これらをGBFSファイルにアーカイブ化するには以下のコマンドを入力します。

gbfs.exe test.gbfs *.txt *.png *.bmp

test.gbfsのファイル構造は次のとおりです。

// ヘッダ(32バイト)
typedef struct {
	char sig[16];			// シグネチャ "PinEightGBFS" + 0x0d + 0x0a + 0x1a + 0x0a
	u32  size;			// アーカイブの大きさ
	u16  dirOff;			// ファイル一覧のオフセット(ROM終端からの相対)
	u16  fileCnt;			// ファイルの登録数
	u8   noUse[8];			// 空き領域
};
// ファイル情報(32*3バイト)(今回の例では3つ分存在します)
typedef struct {
	char fname[24];			// ファイル名
	u32  size;			// サイズ
	u32  dataOff;			// ファイルのオフセット(ROM終端からの相対)
};
// 1.txtのバイナリデータ
// 2.pngのバイナリデータ
// 3.bmpのバイナリデータ

さらに次のコマンドで.gbaファイルと連結します。

padbin.exe 256 x.gba
copy /b x.gba + x.gbfs x2.gba

padbinコマンドは256バイト境界に合わせて連結させる為の処理です。この処理を忘れるとアドレスが誤って奇数位置で連結してしまう可能性があります。データがうまく取り出せない場合はpadbinをしてないことを疑ってください。

GBFSとMode3の画像表示

公式にあるソースコードはモジュール化に失敗しておりユーザ側にGBFS情報を持つ必要があります。その為、ここでは自作したものを使用しました。

ファイルのポインタを取り出す関数には2種類あり、Safe付かどうかがあります。自分で自前に用意する場合は100%存在するのでNULLの返却を許さず、Safeなしはユーザが用意し、NULLでも許容するというコードになっています。

動作画面

履歴


トップ   一覧 検索 最終更新   ヘルプ   最終更新のRSS