2016年12月23日 | ブログ記事

ファミコンに自作ゲームを移植しよう。その1

gotoh

gotohです。

僕が個人制作した花びら切りをファミコンに移植してみます。

2012年くらいに僕が制作したミニゲームです。操作は単純かつ難易度は高いハマる人はハマりそうなクソゲーとして僕の中で有名です。

DLはこちら(Windowsのみ)→http://www.freem.ne.jp/win/game/8801

ファミコンに移植するとファミコンエミュレータが動くデバイスで動かせるので実質的にマルチデバイスとなります。あと古き良きファミコンのグラフィックやサウンドの雰囲気が出せます。サウンド弄ったこと無いですが。

僕が花びら切りをファミコンに移植する際に行った手順をまとめました。まあ記事公開までに移植が完了するかわかんないんですけど。

1. 開発環境の準備

MacBook Airを買ったばかりで調子に乗っているのでMacでの開発環境を構築します。

windowsの環境構築方法はこちら→https://trap.jp/post/32/

うわ誰だろうこんなクソみたいなWindows用のブログ記事書いたの……。

Macではまずhomebrewをインストールします。

ここに従ってインストールして下さい→http://brew.sh/index_ja.html

次に6502用コンパイラをインストールします。ターミナルを開き、brew install cc65と入力します。

インストールが終わったら続いてファミコンエミュレータをインストールします。こちらもhomebrewでインストールします。brew install Caskroom/cask/nestopiaと入力して下さい。

続きまして画像編集のためのアプリをインストール……したいのですがMacにはキャラクタロムを編集するソフトがありません(あったら教えてください)

しかしWindowsにはいいソフトがあります。YY-CHRです。Wineを入れて使いましょう。

EasyWine:https://matome.naver.jp/odai/2140238022377155001

YY-CHR:http://www.geocities.jp/yy_6502/

最後にファミコン用HelloWorldプログラムを引っ張ってきます。

NES研究室:http://hp.vector.co.jp/authors/VA042397/nes/index.html

上記のサイトのサンプルプログラムより、1. HELLO WORLD!をダウンロードしましょう。C Versionは甘えです。というか読んで無いので解説できません。

解凍したらそのフォルダに移動してmakeしましょう。コンパイルできたら完璧です。あなたはもうナーシャ・ジベリ。

2. 画面構成の考案

ファミコンはBGとスプライトの2つのレイヤーに分けて画像を描画しています。

BGは主に背景、スプライトは主人公や敵キャラなどのキャラクターの描画に使われています。

ですがここで問題があります。ファミコンは8×8ドットのスプライトを最大64までしか表示できません。今回移植しようとしている花びら切りは主人公がとても大きく、スプライトでは描画できないのです。

そこで主人公は背景扱いにし、花びらや葉っぱをスプライトで描画しようと思います。これはファミコン時代のゲームの大きなボスキャラや、大量のキャラクターを表示させるときにも使われていたテクニックです。

絵はYY-CHR上で直接描いてもいいのですが、移植なので元々あるリソースを適当に加工して使います。花びら切りの主人公は大きめのキャラクターなので1から描き直すのはめんどくさいです。

YY-CHRにはビットマップ画像を取り込む機能が付いています。これを使いましょう。

ファミコンが使えるパレットの色数は4色までです。最初にたくさんの色を使って絵を描くと、あとで色数を落とすのが大変です。最初から4色で描きましょう。4色より多い色数で絵を描く場合は属性テーブルをうまく使って表現することになりますが、その属性テーブルの仕様上、色は16*16ドットでひとまとまりなのでそこを意識して描きましょう。今回はめんどくさいので4色のみ用いて主人公を描きます。

拡大するとこんな感じ。

袴の色は黒一色に、刀も黒に変えました。短くしましたがループで伸ばせるので大丈夫です。

問題はボタンを押したときに変更するBGの量が比較的多いため、VBlank中に描画が間に合わなくなってしまうのではないかということですが、そのへんは後で考えましょう。明日の自分がやればいい。明日の自分が困ればいい。

これをYY-CHRに取り込みます。NES研究室からダウンロードしたHelloWorldのcharacter.chrを開き、

一番下までスクロールした後、メニューを開き、スナップショットを開く(P)を選んで描いた画像を取り込みましょう。

色が変ですね。でも大丈夫です。色は右下にあるこのパレットを変更すればおかしな色は解消されます。

上の17と書いてあるところをクリックし、

下の21に当たるところをクリックすると色が変更され、

服の色が直りました。同様にして他の色も直していきます。

いい感じですね。

次に降ってくる花びらと葉っぱを描きます。これはYY-CHR上で描いたほうが楽ですね。

      

この時パレットは下段を編集するようにして下さい。スプライト用になります。

パレットはそれぞれ分けて作ります。上段左端4つが侍用、下段左端4つが花びら用、そのとなりの4つが葉っぱ用です。

このパレットを保存しましょう。パレット(P)→パレット定義を保存を押して保存します。

これで画像の準備が大体できました。背景は暇があったら描きます。

3. アセンブリプログラミング

さていよいよアセンブリプログラミングです。一から解説したいところですが、時間もあまりないので飛ばし飛ばし行きます。

わからないところがあったらNES研究室を見るかギコ猫でもわかるファミコンプログラミングを見て下さい。NES研究室は命令表やメモリマップ、IOポート一覧もあるので行き詰まったらここを見ると結構解決します。

それでもわからなければコメントに書いていただければ回答できるかもしれません。如何せん私もほとんど初心者なので回答できないかもしれません。

sample1.asmを開きましょう。HEADERセグメントはカセットの情報が入ります。今回は多分このままでいいでしょう。

ファミコンのプログラムはSTARTUPセグメントから始まります。ここから書いていきましょう。

最初にパレットテーブルをPPUに送ってますが、BG用のみ送っているそうなのでスプライトも送るように変更しましょう。

まずパレットデータを読み込みます。75行目のパレットテーブルが定義されているところを、YY-CHRで出力したパレット定義ファイルを読み込むようにします。


palettes:
.incbin "palette.dat"

読み込んだら次にスプライト用のパレットテーブルも送るようにしましょう。


; パレットテーブルへ転送(BG用のみ転送)
lda#$3f
sta$2006
lda#$00
sta$2006
ldx#$00
ldy#$20;ここを変更
copypal:
...

途中で他の色を使いたくなった場合はPPUのパレットテーブルに違う値を入れれば変更できます。

次の、ネームテーブルへ転送とコメントが書いてあるところは、HELLO WORLDという文字をネームテーブルに送っているところです。

本当はここで侍の絵を転送したいのですが、あまりにも大量のデータを送っているとVBlank割り込みが来て死にます。これくらいならもしかしたら大丈夫かもしれないですが、以前やらかしてしまい少し怖いので、ファミコンによくある1ラインずつ描画する演出によって描画処理の高速化を図ります。こんかいはここでは描画しないことにします。描画処理を消しちゃいましょう。

ついでにスクロールレジスタへの書き込みもまだ必要ないので消しちゃいます。

BG用キャラクタテーブルベースとスプライト用キャラクタテーブルベースの位置を変更するため、PPU制御レジスタ1(0x2000)に送るデータを#$08から#$10に変更します。


; スクリーンオン
lda #$10 ; ここを10に変更
sta $2000
lda #$1e
sta $2001

これで前処理は終了です。

メインの処理は花びらを動かしたり、キー入力を受け取って刀を振るかどうか決めたりするなどの処理です。

描画処理はVBlank中に呼び出したいので、ベクタテーブルに描画処理用のサブルーチンを設定します。

まず描画用サブルーチンであるDrawmain(名前はなんでも構いません)を作っておきます。


.segment "CODE"
.proc Drawmain
.endproc

そうしたら下の方にあるVECINFOの一番目の$0000となっているところをdrawmainに変えます。


.segment "VECINFO"
.word Drawmain ; ここを変える
.word Reset
.word $0000

悲しいことに23日以内に完成しなかったので、その2に続きます。数日お待ち下さい。

この記事を書いた人
gotoh

Hello

この記事をシェア

このエントリーをはてなブックマークに追加

関連する記事

2016年12月24日
わくわくGBAプログラミング
kriw
2016年12月23日
UnityでtiteQuest(のようなもの)を作ってみる
satoriku
2016年12月20日
状態遷移と状態の排除
phi16
2016年12月14日
Re:ゼロから始めるTwitter API
CulMen
2016年12月10日
javaからkotlinに乗り換えよう
takashi_trap
2016年12月7日
Clojure, Elixir でプロセス間通信 〜TCP通信でBF & UDS通信でなんでも掲示板〜
Double_oxygeN

活動の紹介

カテゴリ

タグ