ラズパイアドバンス拡張ボード

エミュレータも良いけれど実機プレイもしてみたい。そんなあなたにオススメなのはCUBIC STYLEさんの同人ハードウェア3点セットです。必要なレシピは以下のとおり。

9.png

https://cubic-style.booth.pm/

電子工作取扱店にて入手

50分ぐらいでサクっと環境は整いますので以下に手順を説明します。

rapberry piのインストール

sudo apt update
sudo apt upgrade -y
sudo apt dist-upgrade -y
sudo apt autoremove -y
sudo apt autoclean
sudo reboot

開発環境のインストール

8.png

「3 Interface Options」を選択。「I4 SPI」を選択。「Would you like the SPI interface to be enabled?」と表示されるので「Yes」を選択。「The SPI interface is enabled」と表示されます。「 OK 」を押したらメニュー画面に戻されるのでTabキーを使って「Finish」を選択。raspi-configを終了させます。

各オプション

以下、説明書などからの抜粋です。

カートリッジを読み込む(吸い出す)

$ sudo rpa -r game.gba

カートリッジに書き込む

$ sudo rpa -w game.gba

フラッシュカートリッジは書き込む前に、Flashを消して空の状態にする必要があります。フラッシュカートリッジの消去は-E オプションです。

バックアップメモリからセーブデータを読み込む

カートリッジのバックアップメモリの読み書きは-sオプションを指定します。-s -rオプションで、バックアップメモリに保存されたセーブデータを保存します。-wオプションでセーブデータを書き込めます。

$ sudo rpa -s -r game.sav

バックアップメモリの初期化

$ sudo rpa -s -E

0xffで初期化されます。

先頭アドレスのdump確認

$ sudo rpa -d
$ sudo rpa -s -d

ROMとFLASHの内容を確認できます。

通信ポートでマルチブート

両コネクタの端子が全結線されている通信ケーブルで本体と接続する必要があります。GBポケット用通信ケーブルを用いると、そのままのケーブルでマルチブートが可能です。GBA専用通信ケーブルは対応していません。

$ git clone https://github.com/cubicstyle/multiboot.git
$ sudo multiboot mb.gba

raspberry piの電源の切り方

$ sudo shutdown -h now

コマンド入力後、緑のLEDランプが点灯しなくなるまで待ちます(30秒ぐらい。あとは電源ケーブルを抜いてください。

ファイル転送

ロムファイルを転送するにはTera Termウィンドウにドラッグ&ドロップします。OKボタンを押すとホームディレクトリに転送されます。他の方法としてはsambaを使うのもいいかもしれません。

10.png

CUBIC STYLE Flashの書き込みテスト

おまけでカードリッジのセーブ、ロードをテストしてみました。

#include "flash.h"
#include "bg.h"

//---------------------------------------------------------------------------
EWRAM_CODE void FlashInit(void)
{
	BgDrawPrintf(0, 0, "MemoryBackup Cubic Test");
}
//---------------------------------------------------------------------------
EWRAM_CODE void FlashExec(void)
{
	if(FlashIsExist() == FALSE)
	{
		BgDrawPrintf(0, 2, "Flash not found");
		for(;;){}
	}

	BgDrawPrintf(2, 1, "Type : Flash");
	BgDrawPrintf(2, 2, "Id   : %x", FlashGetId());

	BgDrawPrintf(2, 4, "Erase 0, 1, 2");
	FlashEraseSector(0);
	FlashEraseSector(1);
	FlashEraseSector(2);

	FlashByte(0x0000, 1);
	FlashByte(0x0001, 2);
	FlashByte(0x0002, 3);

	FlashByte(0x1000, 4);
	FlashByte(0x1001, 5);
	FlashByte(0x1002, 6);

	FlashByte(0x2000, 7);
	FlashByte(0x2001, 8);
	FlashByte(0x2002, 9);

	BgDrawPrintf(3,  5, "%x %x %x", FlashRead(0x0000), FlashRead(0x0001), FlashRead(0x0002));
	BgDrawPrintf(3,  6, "%x %x %x", FlashRead(0x1000), FlashRead(0x1001), FlashRead(0x1002));
	BgDrawPrintf(3,  7, "%x %x %x", FlashRead(0x2000), FlashRead(0x2001), FlashRead(0x2002));

	BgDrawPrintf(2,  8, "Erase 1");
	FlashEraseSector(1);

	BgDrawPrintf(3,  9, "%x %x %x", FlashRead(0x0000), FlashRead(0x0001), FlashRead(0x0002));
	BgDrawPrintf(3, 10, "%x %x %x", FlashRead(0x1000), FlashRead(0x1001), FlashRead(0x1002));
	BgDrawPrintf(3, 11, "%x %x %x", FlashRead(0x2000), FlashRead(0x2001), FlashRead(0x2002));

	BgDrawPrintf(2, 12, "Erase Chip");
	FlashEraseChip();

	BgDrawPrintf(3, 13, "%x %x %x", FlashRead(0x0000), FlashRead(0x0001), FlashRead(0x0002));
	BgDrawPrintf(3, 14, "%x %x %x", FlashRead(0x1000), FlashRead(0x1001), FlashRead(0x1002));
	BgDrawPrintf(3, 15, "%x %x %x", FlashRead(0x2000), FlashRead(0x2001), FlashRead(0x2002));

	BgDrawPrintf(2, 16, "Done");
}
//---------------------------------------------------------------------------
EWRAM_CODE void FlashByte(u16 adr, u8 dat)
{
	// Byte-Program
	FlashWrite(0x5555, 0xAA);
	FlashWrite(0x2AAA, 0x55);
	FlashWrite(0x5555, 0xA0);
	FlashWrite(adr, dat);

	// 20us
	FlashWait(400);
}
//---------------------------------------------------------------------------
EWRAM_CODE u8 FlashRead(u16 adr)
{
	u8* p = (u8*)SRAM + adr;

	u8 ret = *p;

	return ret;
}
//---------------------------------------------------------------------------
EWRAM_CODE void FlashWrite(u16 adr, u8 cmd)
{
	u8* p = (u8*)SRAM + adr;

	*p = cmd;

	__asm("NOP");
}
//---------------------------------------------------------------------------
EWRAM_CODE void FlashEraseChip(void)
{
	// Chip-Erase
	FlashWrite(0x5555, 0xAA);
	FlashWrite(0x2AAA, 0x55);
	FlashWrite(0x5555, 0x80);
	FlashWrite(0x5555, 0xAA);
	FlashWrite(0x2AAA, 0x55);
	FlashWrite(0x5555, 0x10);

	// 100ms
	FlashWait2(10);
}
//---------------------------------------------------------------------------
EWRAM_CODE void FlashEraseSector(u16 sec)
{
	_ASSERT(sec < 0x10);


	// Sector-Erase
	FlashWrite(0x5555, 0xAA);
	FlashWrite(0x2AAA, 0x55);
	FlashWrite(0x5555, 0x80);
	FlashWrite(0x5555, 0xAA);
	FlashWrite(0x2AAA, 0x55);
	FlashWrite(sec * 0x1000, 0x30);

	// 25ms
	FlashWait2(3);
}
//---------------------------------------------------------------------------
EWRAM_CODE void FlashWait(u32 cnt)
{
	for(vu32 i=0; i<cnt; i++)
	{
		// 1週 0.0625us(大雑把に)
		__asm("NOP");
	}
}
//---------------------------------------------------------------------------
EWRAM_CODE void FlashWait2(u32 cnt)
{
	for(vu32 i=0; i<cnt; i++)
	{
		// 1週 16.743ms
		while(REG_VCOUNT >= 160) {};
		while(REG_VCOUNT <  160) {};
	}
}
//---------------------------------------------------------------------------
// SST39VF010 : 0xD5BF
// SST39VF020 : 0xD6BF
// SST39VF040 : 0xD7BF
EWRAM_CODE u16 FlashGetId(void)
{
	// ID Entry
	FlashWrite(0x5555, 0xAA);
	FlashWrite(0x2AAA, 0x55);
	FlashWrite(0x5555, 0x90);

	// Read ID
	u8 id0 = FlashRead(0x0000);
	u8 id1 = FlashRead(0x0001);

	// ID Exit
	FlashWrite(0x5555, 0xAA);
	FlashWrite(0x2AAA, 0x55);
	FlashWrite(0x5555, 0xF0);

	return id0 | (id1 << 8);
}
//---------------------------------------------------------------------------
EWRAM_CODE bool FlashIsExist(void)
{
	// 読み込み、書き込みテスト
	u8 t1 = FlashRead(0x7FFF);
	u8 t2 = ~t1;

	FlashWrite(0x7FFF, t2);

	if(FlashRead(0x7FFF) != t2)
	{
		FlashWrite(0x7FFF, t1);

		return TRUE;
	}

	return FALSE;
}

動作画面

11.png

履歴


添付ファイル: file9.png 30件 [詳細] file11.png 32件 [詳細] file5.png 28件 [詳細] file10.png 25件 [詳細] file8.png 31件 [詳細] file7.png 27件 [詳細] file6.png 22件 [詳細] file4.png 26件 [詳細] file3.png 28件 [詳細] file1.png 33件 [詳細] file2.png 24件 [詳細]

トップ   差分 履歴 リロード   一覧 検索 最終更新   ヘルプ   最終更新のRSS
Last-modified: 2023-09-29 (金) 08:35:02