ゲームボーイで画像を表示した話

昨日の続きでゲームボーイ(以下GB)のお話。

画像を表示したい(BG編)

GBにも任天堂ハードの例によってBGとOBJ(加えてGBにはウインドウ)があります。ざっくり言えばOBJはスプライト(プレイヤーや敵キャラみたいな動き回るやつ)でBGは背景(タイル状に敷き詰められてオフセットスクロールのみ)です。ウインドウはまだ詳しく調べてないけど、BGとは別に(=オフセットスクロールに依存しない)サブ画面を持たせるためのやつらしい。ファミコンよりゲーム用の機能を充実させた感じ。
今回は任意の画像をGBのBG画面に表示させたいと思います。ところで「GBのBG画面」ってややこしいな。

まずGBDKのコンパイラのインクルードファイルを眺めます。/opt/gbdk/include 以下がそれですね。
gb/hardware.h とか gb/gb.h あたりにいい感じの定義とか関数がたくさんまとめられてるっぽい。gb/gb.hを見てみましょう。

(略)
/** Turns on the background layer.
    Sets bit 0 of the LCDC register to 1.
*/
#define SHOW_BKG \
  LCDC_REG|=0x01U
(略)

LCDC_REG はBGコントロールレジスタへのポインタっぽいです。SHOW_BKG;でBGを有効化できるみたいですね。

続けて下の方も見てみましょう。

(略)
/** Sets the tile patterns in the Background Tile Pattern table.
    Starting with the tile pattern x and carrying on for n number of
    tile patterns.Taking the values starting from the pointer
    data. Note that patterns 128-255 overlap with patterns 128-255
    of the sprite Tile Pattern table.  

    GBC: Depending on the VBK_REG this determines which bank of
    Background tile patterns are written to. VBK_REG=0 indicates the
    first bank, and VBK_REG=1 indicates the second.

    @param first_tile   Range 0 - 255
    @param nb_tiles Range 0 - 255
*/
void
set_bkg_data(UINT8 first_tile,
         UINT8 nb_tiles,
         unsigned char *data) NONBANKED;
(略)

void set_bkg_data() はタイルの画像データを配列 *data で受け取ってVRAMに設定してくれそうな感じがします。

(略)
/** Sets the tiles in the background tile table.
    Starting at position x,y in tiles and writing across for w tiles
    and down for h tiles. Taking the values starting from the pointer
    data.

    For the GBC, also see the pan/k00Pa section on VBK_REG.

    @param x        Range 0 - 31
    @param y        Range 0 - 31
    @param w        Range 0 - 31
    @param h        Range 0 - 31
    @param data     Pointer to an unsigned char. Usually the 
                first element in an array.
*/
void
set_bkg_tiles(UINT8 x,
          UINT8 y,
          UINT8 w,
          UINT8 h,
          unsigned char *tiles) NONBANKED;
(略)

こっちの void set_bkg_tiles() はタイルのパターン(配置)を配列 *tiles で受け取ってVRAMに設定してくれそうな感じがします。

ここで昨日紹介したGBTDG(GAMEBOY Tile Data Generator) を見ると、ちょうど画像から画像データとそのタイルパターンの配列を出力してくれる(しかも同じタイルを最適化してくれる、神)じゃないですか!
ゲームボーイの解像度は160x144、色数はモノクロ4階調なので、それに合わせて画像を作成して、GBTDGに投げて出力を保存します(ここではshumatsu.cとしましょう)。

上のgb/gb.hを参考に、昨日のHello Worldのmygame.cを以下の内容に書き換えます。

#include <gb/gb.h>
#include "shumatsu.c"

void main() {
    set_bkg_data(0, 255, shumatsu_tile_data);
    set_bkg_tiles(0, 0, shumatsu_tile_map_width, shumatsu_tile_map_height, shumatsu_map_data);

    SHOW_BKG;
}

コンパイルされたmygame.gbをエミュレータで開いて、あらかじめ作成した画像が表示されれば成功です。やったぜ。

f:id:yaplus:20180603180412p:plain
終わるまでは終わらないよ

set_bkg_tilesし忘れるとこうなります。(追記:この形状的に起動直後のNintendoロゴの残骸っぽいと思うんだけどよくわからん。VRAM見れるエミュレータが必要だな…。)

f:id:yaplus:20180603180445p:plain
石でも食ってろ

こんなんサルでもできるやろがい

f:id:yaplus:20180603180556p:plain
エーケイザー・エケリ

GBAの時は参考書籍を参考にドライバを自作したので、インクルードひとつでこれだけの機能が扱えるあたり、先哲の知恵は偉大ですね。
まあ実際には貧弱なリファレンスとインターネットの怪情報を片手にGBDKにどういう機能が用意されているのか調べる必要があるし、コンパクトなソースにしたいのであれば自分で実装した方が早いというのもあるかもれないですけども、今回は車輪の再発明をしないという方向でやっていきたいと思います。英語を読む勉強にもなるし。

色々と気になったことがあったので以下は備忘録です。

ROMの拡張(バンク切り替え)ってどのくらいの規模になると必要になるの?

こんなもの見つけました。GBのソフトとその容量およびカセット内部の構成をまとめたものです。
とりあえず思いつくゲームタイトルで検索してみると、なんとGBのローンチタイトルであるスーパーマリオランドですらいきなりMBC1によるバンク切り替え(64KB)を行なっているようです(!)。ファミコンでのノウハウから最初からバンク切り替えを前提に設計されたと思っていいでしょう。実際MBC1にはMMCに似たところがあるようです(未確認)。
一方でテトリス(無印)やドクターマリオヨッシーのたまごあたりの初期のパズルゲームタイトルはバンク切り替えなし(32KB)です。ハードは異なりますが、以前自作したガヴドロアドバンスの容量は90KBくらいで、しかもGBAは複数BG分タイルデータが大きいにも関わらずこの程度で済んでるので、自作ソフトでどれだけ作り込むかにもよりますが、案外ミニゲーム程度であれば32KBでもなんとかなるんじゃないかと思えてきました。

万一容量がオーバーするような場合にはGBDKは手動でのバンク切り替えをライブラリでサポートしてくれるみたいですGBDKのドキュメントは色々お役立ち情報があるみたいですがたまに書きかけで雑に放置されてたりするので過信は禁物。

OBJ(スプライト)のパレットってどうなってるの?透明色の設定は?

GBはファミコンと同じく1つのOBJに対して3色+透明色1色を設定できます。扱える色は4色なので、4色のうち1色が透明色という扱いになるみたい。
具体的には

OBP0_REG = 0xE1;

みたいに設定します。
GBでは2ビット(4色)が11が黒、10が濃いグレー、01が薄いグレー、00が白と設定されています。
0xE1 = 0b11100001であり、OBP0_REGの2ビットずつがパレットであり、最下位2ビットが透明色に設定されるということらしいです。この場合は01(薄いグレー)が透明色になります。

当面の目標

OBJ(スプライト)の表示

キー入力の受け付け

これがないとゲームにならないでしょ。
やることとしては当面GBA開発のときと同じ手順でやっていくつもり。

感想

うるせ〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜!!!!!!!
しらね〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜〜!!!!!!!!

魔界塔士Sa・
Ga

ゲームボーイの開発環境を整えた話

某ポルノアニメ氏を見てたら何かしらレトロゲームぽいやつを作りたい熱が再燃してきたので、ゲームボーイの開発環境を整えた。
前にゲームボーイアドバンスの開発環境を整えたことがあったが、GBとGBAアーキテクチャが全く異なるように開発環境も違うっぽい(ちなみにDSの開発はdevkitProで済む)。以下メモ。

環境は以下の通りです(2018年6月2日現在最新)。

GBDKのインストール

ゆとり世代だからアセンブリなんか書きたくない!
GB用のCコンパイラや色々便利なライブラリがセットになったGBDKをインストールします。
さくさんさんの記事を参考にしました。

macOS用パッチ付きのGBDKをcloneしてきてビルドします。

$ git clone https://github.com/CH3COOH/gbdk.git
$ cd gbdk
$ patch -p0 < macosx.patch
$ mkdir -p sdcc/bin
$ make

次からが重要で、ビルドが終わったら (作業ディレクトリ)/gbdk/build/ppc-unknown-linux2.2/ 以下の gbdk/ ディレクトリを /opt 以下にコピーしてあげましょう(シンボリックリンクにしようとしたけどうまく動かんかった)。
/opt がなければ作ってください。

$ sudo mkdir /opt
$ cp -r ./build/ppc-unknown-linux2.2/gbdk/ /opt

終わったらサンプルをビルドしてみましょう。

$ cd /opt/gbdk/examples/gb 
$ make
../../bin/lcc -Wa-l -Wl-m -Wl-j -c -o galaxy.o galaxy.c
../../bin/lcc -Wa-l -Wl-m -Wl-j -o galaxy.gb galaxy.o
../../bin/lcc -Wa-l -Wl-m -Wl-j -c -o space.o space.s
../../bin/lcc -Wa-l -Wl-m -Wl-j -o space.gb space.o
../../bin/lcc -Wa-l -Wl-m -Wl-j -c -o paint.o paint.c
../../bin/lcc -Wa-l -Wl-m -Wl-j -o paint.gb paint.o
../../bin/lcc -Wa-l -Wl-m -Wl-j -c -o rpn.o rpn.c
../../bin/lcc -Wa-l -Wl-m -Wl-j -o rpn.gb rpn.o
../../bin/lcc -Wa-l -Wl-m -Wl-j -c -o rand.o rand.c
../../bin/lcc -Wa-l -Wl-m -Wl-j -o rand.gb rand.o
../../bin/lcc -Wa-l -Wl-m -Wl-j -c -o comm.o comm.c
../../bin/lcc -Wa-l -Wl-m -Wl-j -o comm.gb comm.o
../../bin/lcc -Wa-l -Wl-m -Wl-j -c -o irq.o irq.c
../../bin/lcc -Wa-l -Wl-m -Wl-j -o irq.gb irq.o
../../bin/lcc -Wa-l -Wl-m -Wl-j -c -o filltest.o filltest.c
../../bin/lcc -Wa-l -Wl-m -Wl-j -o filltest.gb filltest.o
../../bin/lcc -Wa-l -Wl-m -Wl-j -c -o ram_fn.o ram_fn.c
../../bin/lcc -Wa-l -Wl-m -Wl-j -Wl-g_inc_ram=0xD000 -Wl-g_inc_hiram=0xFFA0 -o ram_fn.gb ram_fn.o
../../bin/lcc -Wa-l -Wl-m -Wl-j -c -o fonts.o fonts.c
../../bin/lcc -Wa-l -Wl-m -Wl-j -o fonts.gb fonts.o
../../bin/lcc -Wa-l -Wl-m -Wl-j -c -o samptest.o samptest.c
../../bin/lcc -Wa-l -Wl-m -Wl-j -o samptest.gb samptest.o
../../bin/lcc -Wa-l -Wl-m -Wl-j -c -o banks.o banks.c
../../bin/lcc -Wa-l -Wl-m -Wl-j -Wf-ba0 -c -o bank_0.o bank_0.c
../../bin/lcc -Wa-l -Wl-m -Wl-j -Wf-bo1 -Wf-ba1 -c -o bank_1.o bank_1.c
../../bin/lcc -Wa-l -Wl-m -Wl-j -Wf-bo2 -Wf-ba2 -c -o bank_2.o bank_2.c
../../bin/lcc -Wa-l -Wl-m -Wl-j -Wf-bo3 -Wf-ba3 -c -o bank_3.o bank_3.c
../../bin/lcc -Wa-l -Wl-m -Wl-j -Wl-yt2 -Wl-yo4 -Wl-ya4 -o banks.gb banks.o bank_0.o bank_1.o bank_2.o bank_3.o
rm filltest.o comm.o rand.o rpn.o samptest.o paint.o space.o fonts.o irq.o galaxy.o

galaxy.gbが /opt/gbdk/examples/gb にできていればオッケーです。

動作確認用エミュレータのインストール

以前インストールしたmGBAゲームボーイ(カラー)も動作するって書いてあったのに動作しなかった。よくわからん。
色々探してたら上記の記事でも紹介されているGambatteのCocoaアプリ版であるGambattyeがあったのでとりあえずこれを導入。Macネイティブでアプリのアイコンもかっこいい(重要)し。

しかしGambattyeにはRAM/VRAMビューワが付いてないっぽい。うーん…デバッグの時困りそう。いい感じの動作確認用エミュレータがあればコメントやTwitterとかで教えてください。助かります。

Hello Worldをビルドする

まだGBDKについてよくわかってないんですが、この辺を参考に以下の感じでHello Worldできたんでまあいいかってなってます。

適当なディレクトリにmygame.cとMakefileを作る。

mygame.c

#include <stdio.h>

void main() {
    printf("Hello World.\nYappy Dayo.");
}

Makefile

GBDK = /opt/gbdk
CC   = ${GBDK}/bin/lcc -Wa-l -Wl-m -Wl-j
BIN  = mygame.gb

all:    $(BIN)

%.o:    %.c
    $(CC) -c -o $@ $<

%.s:   %.c
    $(CC) -S -o $@ $<

%.o:    %.s
    $(CC) -c -o $@ $<

%.gb:    %.o
    $(CC) -o $@ $<

clean:
    rm -f *.o *.lst *.map *.gb *~ *.rel *.cdb *.ihx *.lnk *.sym *.asm

makeすればmygame.gbっていうファイルができてると思います。やったね!

f:id:yaplus:20180602202551p:plain
こんにちわ〜

ハードウェアの仕様とか調べつついい感じにやっていきたい。ゆうてGBAと似たことすればなんとかなるっしょくらいに思ってる。ゆとり世代だし。

便利そうなやつ見つけた

GAMEBOY Tile Data Generator

GBA開発で言うところのgrit的なやつ(と思われる)。
画像をGB用にモノクロ4色に減色してC(またはZ80アセンブリ)コードに落とし込んでくれるだけなんだけど、GBAでの経験的にこれがあるだけでだいぶ助かると思う。タイルデータさえできればあとは汎用マップエディタでマップデータ作ればいいしね。

感想

2018になって29年前のゲームボーイソフト開発?って思うかもしれないけど、逆にせいぜい17年くらいのGBAよりも風情があってよくない?

精神的に向上心のない者はばかだ。 - K (夏目漱石「こころ」)

精神的に向上心のない太郎なので今日はここまで。

iPad Proを買った

タイトル通りiPad Proを買いました。

 

 

10.5インチ/スペースグレイ/64GB/Wi-Fiモデル ミニマム構成です。

続きを読む

ゲームボーイアドバンス開発メモ その1

大学の主専攻実験の1つでゲームボーイアドバンス(以下GBA)上で動作するプログラムの作成を行うことになったため、以下の環境で開発環境を構築した際の(雑な)備忘録です。

2017年にもなって自分からGBA開発する人がどれだけいるかわからないですが、来年の後輩とか興味を持った人の参考程度になるといいです。

devkitProのインストール

GBA用のプログラムのコンパイルにはARM7に対応したコンパイラが必要なので、コンパイラ一式とモジュールやツール類がセットになったdevkitProをインストールします。

ここのdevkitARMupdate.plをダウンロードし、

> perl ~/Downloads/devkitARMupdate.pl

でインストール後、パスを通しておきます。fish(すごいシェル)では以下のように。

# devkitPro (for GBA development)
set -x DEVKITPRO $HOME/.devkitPro
set -x DEVKITARM $DEVKITPRO/devkitARM
set -x fish_user_paths $DEVKITARM/bin $fish_user_paths

以上でdevkitProのインストールは完了です。これで環境構築のほとんどの作業は終わったと思っていいです。

動作確認用エミュレータのインストール

Mac用のGBAエミュレータはいくつかあるみたいですが、比較的最近も更新が行われておりOpenEmuにもコアが内蔵されているmGBAをインストールしました。
デバッグ用のメモリビューアやタイルビューアなども一通り入っておりこれで十分かと思います。
一時期メジャーだったVBA(Visual Boy Advance)のMac移植版のMac Boy Advanceは自分の環境ではなぜかROMの読み込み時に必ずクラッシュしたので確認してません。

実機で動かすためのブートケーブルとソフトウェアの準備

大学の実験ではGBA SPとLinuxから目覚めるぼくらのゲームボーイ!と付属のUSBブートケーブルが貸与され実機で確認できるようになっているので、実機への転送用ソフトウェアもインストールします。
この書籍の著者である西田氏のホームページでoptusbという転送用プログラムが用意されています。

まずoptusbに必要なlibusbをインストールしますが、バージョンが古いために当時のバージョンと互換性のあるlibusb-compatをbrewからインストールします。

> brew install libusb-compat

次に、ここ からダウンロードしてきたソースコードMakefileを以下のよう書き換えます。

optusb: optusb.c usb.h libusb.a
    gcc -I `brew --prefix libusb-compat`/include/usb.h -L `brew --prefix libusb-compat`/lib -lusb -Wall -o optusb optusb.c

clean:
    rm -rf optusb *.o

これをmakeすればoptusbのビルドの完了です。
ここら辺はほとんど大学のOBであるshiftky氏のGistを参考にしました(Makefileはそのままです)。この場を借りて感謝します。問題があれば消します。

サンプルをビルドしてみる

devkitProを通常通りにインストールすると~/.devkitPro以下にサンプルプログラムがたくさん入ってるexamples/gba/があると思うので、この中からtemplate/を適当なディレクトリにコピーしてきます。

> cp -r ~/.devkitPro/examples/gba/template ~/Documents/GBA/
> cd ~/Documents/GBA/template

そのままmakeするとtemplate.gbaというファイルができているはずです。

> make
template.c
arm-none-eabi-gcc -MMD -MP -MF /Users/yaplus/Documents/GBA/template/build/template.d -g -Wall -O3 -mcpu=arm7tdmi -mtune=arm7tdmi -fomit-frame-pointer -ffast-math -mthumb -mthumb-interwork -iquote /Users/yaplus/Documents/GBA/template/include -I/Users/yaplus/.devkitPro/libgba/include -I/Users/yaplus/Documents/GBA/template/build -c /Users/yaplus/Documents/GBA/template/source/template.c -o template.o 
linking cartridge
built ... template.gba
ROM fixed!
> ls
Makefile        source          template.gba    template.sav
build           template.elf    template.pnproj

.gbaファイルがROMファイル(バイナリ)なので先ほどインストールしたエミュレータで動作確認してみてください。

とは言うものの

devkitPro付属のサンプルプログラムはビルドできたものの、これだけではソースコードすら読んでいないし、実際ソースファイルであるtemplate.cではdevkitPro付属であろう未知のライブラリを使っているので、何が何だから全然わからんです。
せっかく組み込みシステムで開発をするのにハードウェアへの理解もないままプログラミングするのは向上心がないので、次のエントリあたりで実際のプログラムについてのメモ書きをしようと思います。