68系の旅もついに原点の6800へ。
ということで、今回は6800です。
以下のマニュアルを見ながら書きました。

http://www.bitsavers.org/components/motorola/6800/Motorola_M6800_Programming_Reference_Manual_M68PRM(D)_Nov76.pdf

いつもはクロスコンパイラで軽くデバッグしてからエミュレータに載せていたのですが、今回はまずソースが公開されていてmacOSで動くエミュレータがあるかどうかから調べました。
というのも、CMOCやcc65のように現在もアクティブに開発されているクロスコンパイラがなく、うまく動かないときにコンパイラのバグも疑わしく作業量が増えるからです。

そんなわけで検索したところ、ベーシックマスターJr.のエミュレータを見つけました。

http://ver0.sakura.ne.jp/pc/#bm2

ありがたいことに、#includeを追加するだけでIntelでもApple Siliconでも走りました。
早速CompareProcess.hと、以前書いた(6800と類似性が高い)6502エミュレータをリネームして組み込み、6800になるように書き換えていきます。
難なくプロンプトまでたどり着いたのですが、なぜかテープが読めません。無限ループになっているようです。
トレースするとNOPを連ねてタイミングを取っている辺りで失敗しているようで、エミュレータのソースを見るとテープの再生個所をクロック数に応じて厳密に決めていることが判明。
とりあえずロジックが合っていればいいだろうとクロック数を全命令同じにしていたため、タイミングが取れていませんでした。
クロック数をちゃんと実装するとテープを読めるようになりました。

CC6303によるクロス開発

コンパイラは、前もって探したときに見つけたCC6303を使います。

https://github.com/EtchedPixels/CC6303

6303というのは、6800のバイナリ上位互換MPUだと知りました。
6800のバイナリを吐くように指定して試してみると、コンパイラのバグを踏まないように書くのは結構大変でした。

仕方がないので内包するアセンブラas68を使ってサンプルを作りました。
お題はMMLプレイヤー。"ceg"と書くとドミソと音を出す、8ビットPCの頃よくあったやつです。
アセンブラでMMLの解釈をするのは面倒なのでホストで演奏用バイナリを生成することにしました。
play()により単音でメロディーを奏でることができます。

ところで、ベーシックマスターJr.のサウンド出力は5ビットのDACになっています。
ということは、和音やエンベロープに対応できるんです。
実機相当の速度では単音が精一杯ですが、エミュレータなのでクロックを上げればいいということで作ってみました。
play3()で3和音を奏でることができます。playnoise()でノイズも出せます。

https://github.com/kwhr0/bm2-mml-demo

makeするとバイナリa.binができます。
~/.bm2configに
load_bin /path/to/a.bin
のように書くと起動時にバイナリを読み込みます。モニタのGコマンドで実行できます。
さらに、rom_dirをコメントアウトするなどしてROMを読まないようにすると自動実行します。
実行すると単音のデモがループします。

MakefileのPOLY = 0を1に変更し、make cleanしたあとmakeすると和音のデモになります。
このとき、~/.bm2configに
clock 3000
を追加してください。

CC6303の改善

まともに走るようになると、やっぱりCで書きたくなります。
ソースを書いてコンパイル、動かないとトレースダンプを見ていつの間にかコンパイラのデバッグをしていました。
直ったものをプルリクエストで(Linux界隈では有名な人なのでちょっと恐る恐る)投げると、取り込んでくれました。
調子に乗ってさらにいくつかのバグを修正して送りました。

(2025/03/02更新)
最新版にはバグがあるので、以下のものを使ってください。
https://github.com/kwhr0/CC6303


そして、まあまあ実用的なレベルになったのでベアメタルライブラリのデモを作りました。

https://github.com/kwhr0/bm2-baremetal-demo

文字表示とグラフィック表示(line/box/boxfill/circle)のデモです。
main.cの#if 1を0にするとキー入力のデモになります。
Nキーロールオーバー対応で、過渡的に複数キーを押下しても入力できます。

(2025/04/20更新)
chibicc(6800版)に対応しました。

https://github.com/zu2/chibicc-6800-v1

上記をインストールし、Makefileの先頭部分を
CC = chibicc
#CC = cc68
に変更してビルドします。

(2025/05/04更新)
fccに対応しました。

https://github.com/kwhr0/Fuzix-Compiler-Kit

上記をインストールし、Makefileの先頭部分を
#CC = chibicc
CC = fcc
#CC = cc68
に変更してビルドします。

6800のクロスコンパイラは、この記事初出の頃はCC6303がかろうじて使える状態でしたが、最近は選択肢が増えてきました。


ところで、6303って6800とどう違うんだろう。
以下のマニュアルを見ると、多少の追加で6303になることがわかり、最終的に6303エミュレータになりました。

https://www.jaapsch.net/psion/pdffiles/hd6301-3_handbook.pdf

# MMLのデモが3MHzなのは、6303で実際に走るかも、と思ったからです
そして、CC6303は6303のバイナリを指定するとかなりまともに使えることがわかりました。
ただ、やっぱり6800のコードっていうのが味があるんですよねぇ。

エミュレータの変更点

エンコーディングをUTF8に
コメントなどを、現時点で扱いやすいUTF8に変更しました。また、改行をLFだけにしました。

サウンドの待ち合わせ
サウンドの生成と消費は別スレッドで、オリジナルではタイミングの誤差によりプチプチとノイズが乗っていました。
これを、セマフォを使って待ち合わせをすることで解消しました。

ROMなしで実行できるように
.bm2configのload_binにより、クロス開発したものを読んで実行できるようにしました。
デフォルトの読み込みアドレスは0x4000ですが、load_bin_adrで変更できます(16進表記)。
また、バイナリを更新してウィンドウをアクティブにするとリロード&リセットします。

https://github.com/kwhr0/bm2


(2025/04/27更新)
xevious8001を、chibicc-6800-v1を使って6800に移植してみました。

https://github.com/kwhr0/bm2-chibicc-demo
https://github.com/kwhr0/bm2-xevious

binutilsは、長いラベル名に対応した以下のものをインストールしたあとでchibicc-6800-v1をビルドしてください。

https://github.com/kwhr0/Fuzix-Bintools

6800は、Z80に比べるとバイナリが大きくなってしまうため、背景が入りませんでした。
なので地上物がよくわからない状態になってしまいましたが、雰囲気だけでも。

.bm2configは、以下のように設定します。
rom_dir      コメントアウトする
ram_size     64kにする
clock        10000以上にする
load_bin     ビルドしたa.binの場所を指定する
load_bin_adr 2100にする
グラフィックは容量などの関係でシングルバッファなので、クロックが遅いほどチラつきます。
十分大きな値にしてください。タイマー割り込みで律速しているので、重くはなりません。

sp.cの#define NOHITを0にすると、衝突で自機が減るようになります。全部無くなると停止します。
キー操作はEXSDで上下左右、Jがザッパー、Kがブラスターです。


(2025/05/11更新)
fccも試したかったのですが、fccにはchibiccには無い制限があります。

(1) 変数定義はブロックの先頭のみ
 これはC99以前の仕様ですね
(2) 16文字目まで同じ名前は同一とみなす
 長い名前を使うと重複エラーになります

これらを修正し、fccでもコンパイルできるようになりました。
2つほど不具合を報告して修正していただき、まともに動くようになりました。
fccが吐くバイナリは小さく、背景を入れることができました。
Makefileの先頭でfccを指定します。
fccではMPUに6303を選択することもできます。