JR-300エミュレータの開発その2

JR-300エミュレータのお話、第2弾!(^-^)

その1でも書いた通り、開発中の記録が手元にあるのでブログ書くのも早いよ!

 

前回のブログでもうBASICが起動してて、あれ?その後ってやることあるの?とか思うことなかれ。まだまだ解決しないといけない事柄がたーくさんあるのですよ…(-_-;;

 

前回、あっさりとZ80エミュレータを起動している事に驚かれた方も多いかと思うけれど、自前で開発したZ80モジュールがあるのだ。

これとZ80のプログラムコードを合体させれば、ワリと簡単な作業でZ80エミュレーション環境が出来てしまう(^^)

 

2022/11/12(土)

先日までの作業で、内部的な話であるけれどBASICインタプリタが起動できた。

単に起動画面が出ただけだと思うなかれ!(^-^)

BASICが起動してキー入力待ちになるという事は、それまでに必要な初期化などがすべて終了したって事なのだ。

 

全く動かないものを修正していくよりも、仮であっても動いてるものを修正していく方が気持ち的にも良い…というのは分かってもらえるだろう(^-^)

 

でもJR-300のハードウェアは何も理解出来ていないけれど…(^^;;

サブCPUを制御するためのハンドリングについては先日の解析で実装した。正解かどうかは分からないけれども、動いてる!←動けば正解の精神w

 

次はキー入力系を調べ始める。

 キー入力はサブCPU側の仕事かもしれない
 キーが押されるとメインCPU(Z80)に割り込みが発生する

 キー情報はメインメモリのバッファに格納されていく

という感じの想像をしているけれど、実際にはどうなのか…。

 

キー入力割り込みの処理を捉えることが出来れば、プログラムでキー入力を発生させてテストを繰り返す事が出来る。

この流れが出来れば、ホスト(エミュレータを実行している)マシンからのキー情報をエミュレータへ流し込む事も簡単だ!(^-^)

 

割り込み(RST)?は3種類のエントリがあるっぽい。

 

 RST20      0xD883
 RST30/38   0xD7C7
 RST28      0xD7D1

 

想像出来るのはキー入力、タイマー、シリアルなどだろうか。

これらの割り込みがどのようなタイミングで入ってくるのかは不明。

割り込みエントリを1つずつ解析していって、バッファにデータを貯めるようなコードを探せば…それがキー入力でした~……とか簡単に見つからないだろうか…(^^;

 

何でも良いけど誕生日になにやってんだ私は…orz

 

2022/11/13(日)
RST20を解析していったところ、おそらくキー入力と思われるコードが見つかった。
やはりキー入力は別のCPU側が管理していたか…。

サブCPU側の機能面から見ても、コントローラでなくてCPUがいると仮定した方が良さそうだ。

 

以下の手順で、Z80側にキー入力割り込みを発生させられる。

・キー情報を0xFC2Eに書き込む(アスキーコード or 制御コード)
・0xFC02のbit1(0x02)を立てる(これが割り込み要因となる)
Z80に割り込みを掛ける

 

キー入力バッファは0xDD12からの32バイトとなっている。
32バイトを越えたキー情報は捨てられてしまうので、エミュレータのプログラムでキー情報を発生させる場合にはバッファ溢れの配慮が必要。

 

returnキーのコードは0x0Aまたは0x0Dのどちらでも良いらしい。
もしかしたらフルキーのreturnと、テンキーのreturnでコードが違うとか??

 

外部割り込みでRST20が入る事から、Z80の割り込みはモード0が使われている。

 

問題発生!!

キー情報が入れられるようになったことで気を良くしていたら、なんとBASICのコマンドが実行出来ない。
RUN[return]としても、なーんにも起こらない…。
10 REM[return] としても入力された感じがしない。

 

こういう……それっぽく動いちゃうバグが、エミュレータを作ってて最も面倒くさい。
原因を探って行こうにも取っ掛かりがないのだ(T-T)

 

根気よくコードを追ってみると、メモリ0x0300にある「00で埋まっている場所」と「何か」を比較しているようなコードがあった。
この00が埋まってるところが怪しい…。

この領域を初期化しているプログラムコードが見つからないのだ。

ということは、サブCPU側から送られてくる何か

 

…なんて事を考えていたら、そうか、今から実行しようとしているコマンドの文字列が、Z80側には情報が無いのか…と気がついた。

 

キー入力があると1文字ずつ表示はしているけれど、あくまでも表示をしてるだけ。

JR-300はメインCPU(Z80)側にテキストバッファを持っていない。


カーソル位置の左側に何の文字があるのかは、サブCPU側にあるテキストバッファを知る必要があり、そのためにはサブCPUへお伺いを立てる必要があるのだ。


そのためのサブCPUコマンドがあるはずなんだけど……。

こうなってくるとコードを追いかけるというよりは「おそらくこういう構造になっているはず。そのためのプログラムを探す」という感じになってくる(^^;;

そんな感じに探していたら、こんなコマンドが引っかかってきた。

 

SUBCPU  DE:A4AF (06 0E 05  [ 0B 00 09 00 03 ])

 

サブCPUコマンド0x0E、パラメータは5つ。
このパラメータ自体はサブCPUが解釈するものなので詳細は分からない。

わからないけど予想するしかない!

 

実験の結果、おそらくこうだろうというのが予想出来た。

1バイト スクリーン情報からコピーするバイト数
1バイト コピー開始するスクリーンX座標
1バイト コピー開始するスクリーンY座標
2バイト コピー先アドレス(サブCPU側のオフセットアドレスっぽい)

 

ここで実行時にちょっと変な動作があった。
コピー先アドレスが、なぜか0300hから0100hに変わってサブCPUに渡ってしまう。
ん?これは??バグ??バグなのか???
ここでもサブCPU側の動作を予想する。

 

おそらく…これまでの流れで見ると、サブCPU側は(Z80側の)0xFC00からアクセス出来るっぽい。
その0xFC00からのオフセット0x0100で、0xFD00からデータを書き込め…という指定ではないかと考えた。


そして0xFD00に書かれたデータを、Z80側の0x0300へコピーするコードがどこかに有るはずだ。
実験的に0xFD00へテストデータを置いて試してみると、0x0300からテストデータがコマンドが入る事が分かった!

 

この実験結果に基づいて、サブCPU側の処理を追加してみた。

これでZ80側に実行するべきコマンドの文字列が渡り、実行できる…はず!

おおお、無事にプログラムが実行できた!!!(^o^)/

 

試してはいないが、1行の長さはコマンドパラメータならびにバッファサイズの関係から256バイトに制限されている気がする。

 

FOR I=20の値を200とかにすると、プログラム終了時に表示されるReadyの位置がずれてしまう。
おそらくまだ正しく解釈出来ていないサブCPUコマンドのせいだろうな…。

 

この先はBASICの命令を解析しつつ、サブCPU側の実装を進めていく流れとなる。
同時にBASICもマニュアルも書けるといいなぁ…。

 

2022/11/14(月)
JR-300にはあまり見覚えのないBASIC命令がいくつか存在している。

BASICインタプリタ内にあるコマンドを可視化してみた。

 

AUTO AUX ABS AND ASC ATN
BEEP BOOT 
CONSOLE CONT COS COM COLOR CIRCLE CHR$ CHR CSRLIN CLOSE CLEAR CALL CDBL CINT CLR CLS CSNG
DELETE DIM DEF DATA DATE$ DAY$
END ELSE ERASE ERROR EOF EQV ERL ERR EXP 
FIND FOR FIX FRE FN
GOTO GOSUB GCURSOR GCOLOR GET
HEX$ HCOPY 
INPUT INTERVAL INKEY$ INITP INSTR INP INT IMP IF
KEY
LIST LLIST LAYER LOCATE LPRINT LOAD LINE LEFT$ LFIND LPOS LEN LOG LOC LTRON LET
MON MERGE MLOAD MSAVE MAT MID$ MOD
NEXT NOT NEW
ON OFF OPEN OUT OR
PRINT PAINT PALET POKE PRESET PUT PSET PRTY PEEK PLAY PLOT POINT POS
RETURN RENUM RESTORE RESUME READ RANDOMIZE RIGHT$ RUN REM RND
SCREEN SAVE STOP STEP SOUND SYMBOL STRING$ STICK STR$ SPC( SQR SIN SGN SET
THEN TERM TAB( TAN TIME$ TROFF TRON TVMD TVCH TVPW TVOL TO
USING USR
VIEW VERIFY VARPTR VAL
WIDTH WINDOW WAIT
XOR

 

BOOT、INITP、OFF辺りはタイマーによる電源制御系かな…。
TVxxはテレビコントロールな気配がする。
PRTYは表示のプライオリティ??
LAYER……レイヤーとは?
PALETはパレット機能??あるんだっけ?
PSETとPLOTは別命令?
COMとAUXの関係は??
MATとは?
…ぱっと見ただけでもそれなりに不思議な命令が揃ってる。

でもMON(マシン語モニタ)があるのは素直に嬉しいw


今後の方針を簡単に決めてみた。

・ここまでのプログラムをいちど整理したいw
・BASICコマンドの解析
 ・テキスト周り
 ・グラフィック周り(ここで表示をWindow対応する)
サウンド解析
・デモンストレーション解析

こんな感じ?

まだまだ先が長いぞコレは…orz

 

キー入力が完成した事によりBASICのコマンドを実験できる環境が整ったので、せっかくなのでテキスト文字に色をつけてみたい!
ということで、COLOR命令を試してみる。
試した結果、COLOR命令はJR-200と同じオプションらしい。

 

  COLOR 文字色[,背景色[,オプション]]

 

文字色と背景色だけを指定すると、サブCPUコマンド0x04が呼び出される。
何故か色フォーマットは上位下位の4ビットずつではなく、00bbbfffと律儀な3ビット形式。

 

そして3つめの引数であるオプション指定が様々な問題を引き起こす…。
オプションは0〜3の値を取り、それぞれに以下の意味らしい(JR-200)。

 

0 ... ユーザー定義モードの解除
1 ... ユーザー定義図形の表示
2 ... 文字色と背景色を反転
3 ... 背景色を式2の指定色に一括変更

 

0と1はPCGの事で、これがJR-300に存在する命令なのかどうか現時点では不明。


2を指定した場合は、サブCPUコマンドの色情報が上下ひっくり返って渡される。

 

そして3を指定すると…サブCPUコマンド0x12,0x13,0x1Fの3つが呼び出され、それぞれの意味は解析出来ていない。

そもそも一括変換ってどんな動作するの??


うーん、未解析なサブCPUコマンドがどんどん増えていく恐怖よ…orz

 

ちなみにCOLOR命令単体(引数なし)で実行するとSyntax errorとなる。
Illegal function callじゃないのか…汗


WIDTH(横の文字数)の実験してて気がついた。
どうやらリセット後の横文字数はWIDTH 40が標準らしい。

 

どーにも我慢しきれなくて、先にウィンドウ表示させてしまった!(TT)

エミュレータを開発してる時は、可能な限り画面表示は後回しにして、テキストベースでデバッグするのが好みなんだけど、色とか使い始めたら見てみたいワケで(^^)

 

SDL2というライブラリを使用して表示するようにしておけば、WindowsでもMacでもLinuxでもソース共通で動く。

 

SDL2に対応した記念?に、適当にも適当なるキー入力を実装してみた。

実行しているエミュレータ上でキー入力することが出来るようになった!

これで好きなコマンドを入れることが出来るようになったよ!(^-^)

特にデバッグの役に立つわけではないけれども、すごーく出来てきた気分になれるw

 

ではまた次回!(^-^)ノ