たま日記

たまに書く

MAMEのTX81Zに手を入れた(1)

ここしばらくMAMEソースコードを読んでいた。まだまだTX81Zのエミュレーションは不完全であることが分かった。Youtubeでも確認できる。

もちろんYM2414の実装であるymfm_opz.cpp, ymfm_opz.hが未完成であることが原因なのだが、どうもTX81Zの実装であるymtx81z.cpp、そのCPUであるHD6303の実装m6801.cppにも起因するようだ。IRQや内部タイマからの割込みに対応できていない。

興味が出てきたので、これらの動作を改善してみることにした。MAMEでTX81Zがうまく動けば、TX81ZやYM2414の解析にも役立つかもしれない。というわけでC++とHD6303アセンブラの勉強をしていたのが、ここ一月ほどの作業。とりあえず割込み関連から手を付けた。

参考資料

それから、https://www.rutles.net/products/detail.php?product_id=794 。当時?の空気を感じたり、CPUの設計思想を理解するのによい資料。文体も楽しい。

YM2414のIRQ

MAMEのデバッガについてる逆アセンブラでTX81ZのROMを読んでみた。$8FF6から始まるIRQの割り込みハンドラの中で、YM2414の発音に必要なレジスタ書き込み($08+ch)が行われている。しかしながら、この割込みハンドラはMAMEでは実行されていない。YM2414はIRQをどうやって出すのだろう?

TX81Z実機で観察したレジスタ書き込み内容をYM2414に流し込んで発音させる、という実験を前回おこなった。YM2414のIRQ出力をロジアナで観察すると、普段はHのIRQ出力が発音時に一瞬だけLに落ちていた。書き込みシーケンスのどこかでIRQが変化するようだ。

ROMを読んだり動作を観察したりした結果、どうもこういうことらしい。TX81Zは音を出すときにYM2414のレジスタ$20+ch(0~7)にbit6=1の書き込みを行う。bit6はYM2151では未定義の機能で、この書き込みを行うとYM2414は次の動作を行う。

  1. IRQをLにして、CPUに割込み要求を行う
  2. 読み出し専用レジスタのbit5を1にする
  3. 読み出し専用レジスタのbit4,3,2にch番号をセットする

YM2151では読み出し専用レジスタはbit7,1,0しか使わないのに対し、仕様が変わっているみたい。前回作成したESP32+YM2414の回路を使って観察した。レジスタ読み出しのために3.3V<->5V双方向のレベル変換を追加した。


Timer2の割込み

TX81Zは1秒間に96回ほど、YM2414に書き込みを行っていることを以前観察した。LFO Delayやポルタメント、ピッチベンド?をソフトウェアで実現するためのようだが、この書き込みをMAMEはしていない。

ROMを眺めていたら、$8F1Fから始まるTimer2 Counter Matchの割込みハンドラの中で行っていることが分かった。

現在の状況

m6801.cpp・ymtx81z.cppを変更し、上記2つの割込みハンドラを実行するようにしてみた。出音の内容は変わってないが、より実機に近いエミュレーションができるようになったはず。

例えば、PLAY/PERFORMボタン上のLEDの動作が改善された。音を出したときON→OFFのまま再度点灯しなかったのが、実機のように再度ONになるようになった。Timer2の割り込みハンドラ内に再点灯のコードがあった。

次は?

$8F8Bから始まるTimer1の割り込みハンドラが何をしているのかよく分からない。これを少しつついたあと、ymfm_opz.cppに手を付ける。Nuked-OPMベースだがOPZのエミュレーションはできているので何とかなりそう。

以前から何らかのエミュレータを作ってみたいなーと思っていたので、作業はとても楽しい。HD6303のアセンブラ解析も暗号解読のようで面白い。C++は難しい…

2023/07/09追記
$8F8Bから始まるTimer1の割込みハンドラはDelay処理だった。MIDIノートオンを受け取った時、MIDIノートオフを受け取った時、Delayする音色の音を出している時(ディレイ音が出ている間)に呼び出されるようだ。