2013年5月7日火曜日

ファミコン用の自作ソフトを作って遊ぼう

昨年、初めてニューファミコンというゲーム機を入手したのですが、MSXで育ったせいか遊び方を知りません。本体やコントローラの改造ばかりして遊んでいたのですが、どうもこの遊び方は普通とは違うようです。

というわけで今回は、本体やコントローラじゃなくてカートリッジで遊んでみることにします。
通常は固定データであるカートリッジ内のEPROMを、何度も書き換えが可能なFlashROMで置き換えて自作ソフトを動かすことができる、いわゆるFlashROMカートリッジを作ってみました。

(FlashROMの書き込みについてあまりネットに情報がなさげなので、仕様のメモ代わりにもなっています。適当に読み飛ばしてください)。

FlashROMの入手

秋月にて安価に購入可能な、256kBのPLCC FlashROM(EN29F002T)を選びました。256kBもあれば大抵のものは動かせるでしょう。

PLCC→DIP変換基板はaitendoのものを入手しました。
このaitendoのPLCC→DIP変換基板なのですが、届いてみたら曲者で、ピンの並びが全然違いました。最近傍のピンに繋げているようで、PLCCの1番ピンがDIPの32番ピンに繋がっていたりします…。混乱するので、変換表を作りました(誰得データなので省略)。

FlashROMの制御信号の種類

下記の一連の信号ピンで構成されています。
  • VCC/GND → 電源
  • A0〜A17 → アドレス情報
  • D0〜D7 → データ情報
  • /RESET(Chip Reset) → LOWのとき、FlashROMの状態をリセットします。基本的に常にHIGHにします。
  • /CE(Chip Enable) → LOWのとき、FlashROMの機能が有効になります。基本的に常にLOWにします。
  • /OE(Output Enable) → LOWのとき、データがD0〜D7に出力されます。
  • /WE(Write Enable) → LOWのとき、FlashROM内のコントローラに情報が書き込みされます。
データを読み取りしたいときは、以下のようになります。
  1. /OEと/WEをHIGHにします。
  2. A0〜A17にアドレスを指定します。
  3. /OEをLOWに指定します。
  4. D0〜D7にデータが出力されています。
  5. /OEをHIGHに指定します。

FlashROMの書き込み手順

全消去→書き込み→読み込んでCRC32チェック、という流れです。消去すると全領域が「0xFF」になるので、データが0xFFなアドレスには書き込まなくても良いです。
消去と書き込みには独特のシーケンスが必要です。このシーケンスはJEDECという方式のようです。

コマンド1コ分のシーケンスは以下の通りです。/CEと/OEは基本的にHIGHのままです。
  1. /WEをHIGHに設定します。
  2. アドレスピンの値を設定します。
  3. /WEをLOWに設定します。このタイミングでアドレス情報が設定されます。
  4. データピンの値を設定します。
  5. /WEをHIGHに設定します。このタイミングでデータ情報が設定されます。
全消去の場合、以下のような流れでコマンドを発行していきます。
  1. アドレス: 0x5555 データ: 0xAA
  2. アドレス: 0x2AAA データ: 0x55
  3. アドレス: 0x5555 データ: 0x80
  4. アドレス: 0x5555 データ: 0xAA
  5. アドレス: 0x2AAA データ: 0x55
  6. アドレス: 0x5555 データ: 0x10
  7. この状態でデータを読み取り続けて(前述のデータ読み取り手順の3〜5)、データが「0xFF(もしくは、最上位ビットが1)」になれば完了です。
データ書き込みの場合、以下のような流れでコマンドを発行していきます。
  1. アドレス: 0x5555 データ: 0xAA
  2. アドレス: 0x2AAA データ: 0x55
  3. アドレス: 0x5555 データ: 0xA0
  4. アドレス: 目的のアドレス データ: 目的のデータ
  5. この状態でデータを読み取り続けて(前述のデータ読み取り手順の3〜5)、目的のデータになれば完了です。
具体的な実装については、ソースコードをgithubに公開しているので、参照してみてください。

書き込み用ハード・ソフトの作成

当初 mbed + ブレッドボードで作っていたのですが、大層ハマってしまい、ハードのバグなのかソフトのバグなのかも分からなくなったので、一旦保留しました…。
多数のGPIOを持つ必要があるならArduino MEGAでも良いじゃないか、というわけで、気分転換でArduino MEGAに挿せる変換基板を作って、ソフトも実装してみました。githubにて公開していますので、ご自由にお使いください。

ライター動作中の様子

mbedへの移植は、近日中に行う予定です。
今回の書き込み用ソフト作成にあたって、unagiフラッシュメモリ EN29F002T ライタのソースコードが参考になりました。

ベースとなるカートリッジの選定と購入

今回は「バッテリーバックアップ付きのMMC1」をターゲットにしています。ハードオフのジャンクコーナーで、裏に「バッテリーバックアップについての注意書き」があるカートリッジをいくつかピックアップしてきました。有名なタイトルでなければ、一個あたり数百円で手に入ります。

てきとーに選んで「ベースボールスター(SKROM)」にしました。

ファミコン・カートリッジの仕様

EPROMとしては、プログラムROM(PRG-ROM)とキャラクタROM(CHR-ROM)の二つが搭載されています。この他にメモリコントローラとバックアップ用SRAMがあります。
今回はPRG-ROMとCHR-ROMをFlashROMに載せ替えます。

FlashROMの配線とテスト

  • カートリッジを殻割りして、基板を取り出します。殻割りの方法はニコ動の「ファミコンカセットを簡単に殻割りする裏技」という動画が参考になります…が、古いカートリッジはプラスチックが脆くなっているので、ある程度の確率で爪が折れるでしょう。
  • 基板に付いている32ピン・28ピンのEPROMを、はんだ吸い取り線などを用いて取り外します。フラックスで汚れるので、アルコールなどで洗っておきましょう。
  • ROMの居たところに、32ピンのICソケットを取り付けます。
  • 32ピンの基板接続ピンヘッダと、PLCC→DIP変換基板をユニバーサル基板に取り付けます。サンハヤトのICB-504を半分にしたものが、丁度よい大きさでした。
  • ピンヘッダと変換基板の対応するピンを接続していきます。ファミコンカートリッジ側のEPROMのピンアサインは、nesdevのドキュメントに記載があります。
  • 今回、ROMは外して書き込みできるので、特別な配線はしません。A0〜A17、D0〜D7、VCC/GND をそれぞれ接続します。/CEと/OEはGNDに接続、/RESETと/WEはVCCに接続します。
  • インターネット上で合法に公開されている、HomeBrewなROMデータ(NTRQとか、激おこプンプン丸とか)をFlashROMに書き込み、動作テストをします。
PRGROM側だけ配線が終わって、実機で動かしている様子

ソフトの開発

ソフトの開発にはCC65というコンパイラを使います。Cコンパイラですが、基本的にアセンブラが推奨されています。ファミコンで使えるCの機能は限定的なので、「Cで書ける」以外の利点はあまりないかもしれません。

コンパイルしてはFlashROMに書いてデバッグ…とするのはすごく時間が掛かるので、主な開発・動作テストはエミュレーター上で行います。都合のいいことに、ファミコンのエミュレータはいっぱいあります。

とりあえず、「Hello World」と表示するだけのプログラムを書いて動かしてみました。と言っても「NES Game Programming Part 1」というドキュメントにあるコード、ほぼそのままですが。
キー操作やキャラクタ描画、音の再生などなど、まだ全然分かっていないのでこれから勉強していきます。

1 件のコメント:

  1. フラッシュROMの書き込みについて調べていたところヒットして読ませていただいてます。
    「/CEと/OEは基本的にHIGHのまま」だとCEが有効にならないのでコマンドを受け付けてくれないのではないでしょうか?

    返信削除