LoginSignup
1
1

More than 3 years have passed since last update.

EK-RE01 256KBでGBエミュレータを動かしてみた

Posted at

RE01にGBエミュレータを移植してみた話

EK-RE01 256KBにはMIP-LCD基板が付属しています。
MIP-LCD基板を接続するとRE01 256KB内蔵のSPIを使用して画像や文字を表示できます。
今回はRE01にGitHub上で公開されているGBエミュレータを移植してみます。
そして、GBエミュレータの描画結果をMIP-LCDに表示させてみることにします。

GitHub上で公開されているGBエミュレータ

GitHub上で公開されているCで記述されたGBエミュレータを探してみました。
結果、koenkさんが公開しているGBCが良さそうなので、これを使用させていただきます。
(koenkさんGBCをGitHub上に公開していただきありがとうございました!)

ソースコードの内容を確認するとファイルシステムが使われているみたいです。
なので、インターネット上でChaNさんが公開しているFatFsをRE01 256KBに移植してみました。
しかし、RE01 256KBにはRAMが128KBしか実装されていません。
内蔵RAMだけでファイルシステムを使うためにはこの容量は十分とは言えません。

なので方針を変更しました。
ファイルシステムを使わずにRAM使用量を削減できるようにソースコードを変更します。

RAM使用量を削減するためにしたこと

カートリッジROMはRAMにコピーせずにROMに配置したまま使用

GBCでは、エミュレータを動かす際に使用するカートリッジROM等はRAMにコピーします。
このままだとRAM使用量を圧迫してしまうので、ROMに配置したまま使用します。
state.cのstate_new_from_rom関数の内容を以下のように変更しました。

state.c
s->mem_ROM = rom;
s->mem_WRAM = malloc(WRAM_BANKSIZE * s->mem_num_banks_wram);
if (s->mem_num_banks_extram)
    s->mem_EXTRAM = malloc(EXTRAM_BANKSIZE * s->mem_num_banks_extram);
s->mem_VRAM = malloc(VRAM_BANKSIZE * s->mem_num_banks_vram);

また、state.cのstate_add_biosの内容も以下のように変更しました。

state.c
void state_add_bios(struct gb_state *s, u8 *bios, size_t bios_size) {
    assert(bios_size == 256);
    s->mem_BIOS = bios;
    s->in_bios = 1;
    s->pc = 0;
}

RAMにコピーする関数の削減

CMSIS Driverの各ドライバ関数の一部はプログラムをRAMに展開する仕様になっています。
今回はRAMに展開したプログラムで動作させる必要はありません。
なので、RAMに展開しないようにコンフィグ設定ファイルを変更しました。

r_adc_cfg.h
#define S14AD_CFG_R_ADC_OPEN            (SYSTEM_SECTION_CODE)     ///<R_ADC_Open() section
#define S14AD_CFG_R_ADC_SCAN_SET        (SYSTEM_SECTION_CODE)     ///<R_ADC_ScanSet() section
#define S14AD_CFG_R_ADC_START           (SYSTEM_SECTION_CODE)     ///<R_ADC_Start() section
#define S14AD_CFG_R_ADC_STOP            (SYSTEM_SECTION_CODE)     ///<R_ADC_Stop() section

MIP-LCDで表示させるためのコードの追加

これはRAM使用量削減とは関係ないですが、MIP-LCDで表示させるためにコードを追加しました。
GBエミュレータの表示処理はsdl.cにあります。
ここにMIP-LCDに画像データを送信する処理を追加しました。

uint8_t disp_copy[(GB_LCD_WIDTH / 8) + 1];
uint8_t display_img[(SMIP_CFG_KYOCERA_DISP_LINE * SMIP_CFG_KYOCERA_DISP_WIDTH) / 8]    = {0};

memset(&disp_copy, 0x00, sizeof(disp_copy));
for (int x = 0; x < lcd_width; x++)
{
    int idx = x + y * lcd_width;
    pixels[idx] = palette[pixbuf[idx]];
    if ((0xffffffff == pixels[idx]) || (0xaaaaaaaa == pixels[idx]))
    {
        disp_copy[x / 8] = disp_copy[x /8] | (1 << (7 - (x % 8)));
    }
}

memcpy(
    &display_img[((y * 256) / 8)
            + (((SMIP_CFG_KYOCERA_DISP_WIDTH - GB_LCD_WIDTH) / 2)
                / 8)
            + (((SMIP_CFG_KYOCERA_DISP_LINE - GB_LCD_HEIGHT) / 2)
                    (SMIP_CFG_KYOCERA_DISP_WIDTH / 8))],
    &disp_copy, sizeof(disp_copy));

result = R_SMIP_Send(((SMIP_CFG_KYOCERA_DISP_LINE - GB_LCD_HEIGHT) / 2 ), GB_LCD_HEIGHT, &display_img[0]);

プログラムの実行

作成したGBエミュレータを実行してみます。
今回はフリーで公開されている20Y (GB Demo)をカートリッジとして使用させて頂きました。
メモリー使用量を見るとRAM使用量は94%程度でギリギリ収まっているようです。
プログラムを実行すると20Y (GB Demo)が起動しました。
ただし、FPSは著しく悪いです…これはSPIの通信速度が原因かなと思っています。

PXL_20210216_172526291.jpg
PXL_20210216_172630366.jpg

最後に

今回はRE01 256KBにGBエミュレータを移植して動作させてみました。
最近、RX72N Envision Kitを購入したので、今度はRXファミリに移植して動作させてみたいと思います。

1
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
1