ゲームボーイのカートリッジを自分で作って遊んでいます。いままでカートリッジ側のROM・RAM・MBCをすべてマイコンに実装したものを作って遊んでいましたが、カートリッジの外からRAMにデータを書き込む方法が見つからず難儀していました。
マイコン側CPUの処理を使うとゲームボーイが止まる
このカートリッジでは、ゲームボーイに対するROMデータの出力をマイコンのCPUがまかなっています。
- ゲームボーイ側がカートリッジにアドレスを渡す。
- マイコンがアドレスを受け取る。
- Read/Writeのどちらか、バンク設定があるのかを判断して、返すべきデータを決める。
- マイコンがデータを出力する。
1バイトとはいえ、どのデータを返すかが決まるまでにいくつかの条件分岐が入ります。なので、外部通信等で他の処理がCPUを使用すると、このデータを返す処理が間に合わずゲームボーイ側がハングアップします。
外部通信の受信をDMAに任せたらどうか
今回、受信したデータをそのままカートリッジRAMの領域に直接書き込む形にしたら問題が解決しました。DMAのサンプルコードをみると、受信したあとそのデータを確かめるためのコールバック関数があったりしますが、その部分が動くとCPUを使ってしまうため、その部分は絶対に使わないようにします。ゲームボーイのソフト側は、DMAの書き込み先に合わせた特定のアドレスだけを読むようにすれば、カートリッジRAMに書き込んだデータをゲームボーイ内で扱うことができます。
実装例
ゲームボーイのカートリッジRAMにMIDIデータを書き込み、MIDIノートオンのときにゲームボーイ側で音を鳴らす仕組みです。
やったー
— niccolli (@niccolli) November 8, 2019
鍵盤からゲームボーイの音を鳴らせるようになったよ pic.twitter.com/FaVdR5hRL9
MIDIは、フォトカプラで受信後はbaudrateが31250のUARTとしてそのまま扱えるので、マイコンのDMAで直接RAMに書き込むことができます。書き込まれる予定のアドレスをゲームボーイ側は常時監視し続け、MIDIノートオンのメッセージを受信したら、ノート番号に合わせた音程で音を鳴らすという仕組みになっています。
0 件のコメント:
コメントを投稿