MC6800 ROMモニタ自作 その21 ~profileから構成軸へ、ビルドを解きほぐす~

MC6800 ROMモニタMC6800 ROMモニタ自作 その21 ~profileから構成軸へ、ビルドを解きほぐす~

前回までで、K68-VDGとか2nd ACIAキーボードとかを実機でつなげる流れができてきました。そのたびに MONITOR_PROFILE が増えていきまして、basesbciosbcio_vdgk6802_vdg の4つになっていました。それぞれちゃんと意味はあるのですが、今後さらに「SBC-IOは挿してるけどVDGは無し」「VDGは挿してるけど別のVRAM配置」「I2Cも入れたい」みたいな組み合わせを足しはじめると、profile名がどんどん長くなりそうな気配がありました。

このまま増やし続けるのはちょっと無理がありそうだったので、profile名で全部を抱えるのをやめて、設計判断を構成軸の組み合わせで表現するように整理してみました。これが今回のIssue #96です。

今回やったこと

  • ビルド構成を MEMORY_CONFIG / BOARD_IO / FEATURE_SD / FEATURE_VDG / FEATURE_KEYBOARD / FEATURE_I2C の構成軸に分けた。
  • MONITOR_PROFILE は捨てずに残し、軸の既定値を展開する「完成品プリセット」として使う。
  • 軸を直接指定するビルドも入口として正式に追加した。
  • profileから生成した build/monitor_config.inc をasl側でincludeして、機能ごとに条件アセンブルする。
  • FEATURE_X=0 のときは、コマンド本体・内部ルーチン・関連文字列をROMから落とす。
  • HMAP の表示もこれに連動させる。

設計の話はPR #94、実装はPR #95です。ビルドを構成する軸を絵にするとこんな感じです。

依存関係としては、FEATURE_SDFEATURE_KEYBOARDFEATURE_I2CBOARD_IO=sbcio がないと使えないようにしてあります。SBC-IOに乗ってるACIAやPIA前提なので、ここはMake時に弾かれます。FEATURE_VDG だけは別の外部装備なので、SBC-IOがなくても独立して使えるかたちです。

既存profileを軸に展開すると

既存の4つのprofileを、新しい軸で書き直すとこうなります。

こうやって並べてみると、profileの違いが「メモリ配置はどこか」「外部I/Oは何か」「機能フラグはどれを上げてるか」だけで説明できることがわかります。これまでは profile名 (sbcio_vdg_vdg の部分) でしか表現できなかったので、SBC-IO + VDGなし + メモリ配置だけ違う、みたいな細かい組み合わせを名前で表現するのが苦しかったのが解消されたと思います。

ビルドの流れ

具体的なビルドの流れもひとつにまとめておきました。

入口は make bin MONITOR_PROFILE=... でも make bin MEMORY_CONFIG=... BOARD_IO=... FEATURE_*=... でもよくて、Makefile側で軸の既定値を展開したり、コマンドラインで上書きされた軸を反映したりします。値の検証と依存関係チェックもここで行います。

そのあと tools/generate_monitor_config.pybuild/monitor_config.inc を作って、asl が src/main.asm をアセンブルするときにそれをincludeします。アセンブラの条件指示 if MONITOR_FEATURE_* を使って、機能ごとにコードを出し入れする仕組みです。

最終的には *.bin / *.srec / *.hex ができて、ROMライタ用には make rombin ROM_KIND=27C64 のように容量合わせ済みのバイナリも作れます。書き込みは make program ROM_KIND=... で、minipro 経由で焼きます。profile経由でも軸を直接指定しても、generate_monitor_config.py から先のレールは同じ、というのが今回のキモです。

直接指定ビルドと、profile化までの導線

新しい組み合わせを試したいときは、軸を直接指定して make bin するのが一番手っ取り早いです。たとえば、k6802_vdg profileに相当する構成を直接指定で作るとこうなります。

make bin \
    MEMORY_CONFIG=ram64_a000_work \
    BOARD_IO=sbcio \
    FEATURE_SD=1 \
    FEATURE_VDG=1 \
    FEATURE_KEYBOARD=1 \
    VDG_VRAM_CONFIG=c000 \
    BUILD_CONFIG_NAME=axis-k6802

出力は build/mc6800-monitor-axis-k6802.bin になります。BUILD_CONFIG_NAME を付けると、出力名のsuffixを自分でつけられます。付けない場合は、軸の値をぜんぶ連結した長いsuffixが自動生成されます。読みにくいですが、何のROMかは一目でわかります。

不正な組み合わせはMake時に弾かれます。たとえば BOARD_IO=none のままで FEATURE_SD=1 にすると、FEATURE_SD=1 requires BOARD_IO=sbcio でエラーになります。ハードウェア的に成立しない組み合わせを早めに止められるので、これは便利でした。

直接指定で何回か試して「これは何度も使うな」と思った組み合わせは、Makefile の MONITOR_PROFILE 分岐に追加してプリセット化します。やりかたは docs/usage/build_commands.md の「独自profileを追加する手順」にまとめました。

外部機器用ルーチンの組み合わせの変え方

FEATURE_* の軸は、ROMに何の外部機器を相手にするコードを積むかを決める軸です。FEATURE_X=0 にすると、src/main.asmif MONITOR_FEATURE_X ガード(全体で30箇所くらいあります)が else 側になって、コマンド本体・内部ルーチン・関連文字列がROMから丸ごと落ちます。使わない機能は条件アセンブリで落としちゃえばROMの容量が節約できるという寸法です。

絵にするとこんな感じです。

例えば「base ROM」ではSD/FAT、VDG、KEYTESTのコードがそもそもROMに入っていません。プロンプトで DIR とか LF とか VDGTEST とか KEYTEST とか叩いても、未定義コマンド扱いで ? を返すだけです。逆に「sbcio_vdg ROM」だと、SD/FATもVDGもKEYTESTも全部入っています。H の表示も連動していて、有効な機能だけがヘルプに出ます。

このおかげで、base の8KB ROMでもギリギリ入る、というのも保てています。SD/FATのコードはそれなりに大きいので、base で同じ条件アセンブルなしに全部入れたらおそらく入りません。

ちょっと面白かったのは、4つめの例「自作: SDなし VDGだけ」みたいな組み合わせも、今後profile名を増やさずに直接指定で作れる、ということです。「SBC-IOは挿してるけど今日はSDなしでVDGの実験だけしたい」みたいなときに、いきなりprofileを足さなくてもよくなりました。

割り切ったところ・残しているところ

  • MONITOR_PROFILE_*MONITOR_FEATURE_* の既存シンボルは、今のところ monitor_config.inc に生成し続けています。アセンブラ側のソースが既存シンボル名で if しているので、段階的移行のために残しました。
  • FEATURE_I2C は軸と依存関係チェックだけ入れて、本実装はまだです。PIA経由のI2Cドライバを書くのは次以降のIssueです。
  • MAP の見出しは MAP SBCIO VDG のように profile名互換のままにしました。設計文書では、将来 MEM / IO / FEAT 形式へ広げる余地を残してあります。

ちょっと中途半端な気もしますが、profile名を根拠に機能を推測する設計には戻したくないので、当面はこの形でやってみます。

テスト結果

  • make bin (= base 既定) と、MONITOR_PROFILE=sbcio / sbcio_vdg / k6802_vdg でそれぞれ test_smoke.pytest_sd_fixture.py がパス。
  • 軸を直接指定した axis-base / axis-sbcio / axis-sbcio-vdg / axis-k6802 でも、ROMをビルドして test_smoke.py がパス。
  • make bin MEMORY_CONFIG=base8k BOARD_IO=none FEATURE_SD=1FEATURE_SD=1 requires BOARD_IO=sbcio で正しく失敗。
  • MONITOR_PROFILE=k6802_vdg make rombin ROM_KIND=W27C512 で容量合わせ済みのバイナリができることも確認。
  • listingのsymbol tableを見て、base ではSD/FAT/VDG/KEYTEST関連のラベルが出てこないこと、sbcio ではVDG関連が出てこないこと、を目視確認。

エミュレータでのsmoke testは今までと同じ条件で通せたので、profile名でビルドしてる人にとっては「何も変わってない」のが理想だと思います。実際、過去のメモを見ながら MONITOR_PROFILE=sbcio_vdg make bin を叩いても、出力ファイル名 (mc6800-monitor-sbcio-vdg.bin) も変わらないようにしてあります。

次にやること

今回でビルドの土台が一段整理できたので、次は中身を増やしていくフェーズです。

  • K68-VDGを OUTCH 側に組み込んで、ROMモニタのプロンプトを画面に出す簡易コンソール化。
  • 2nd ACIAキーボードを入力側に組み込み、VDG + KBD でPCコンソールがなくても動かせる構成へ。
  • FEATURE_I2C の中身として、PIA経由のI2Cドライバ(RTCあたり)を入れる。

このあたりがそろってくると、FEATURE_VDG=1 FEATURE_KEYBOARD=1 FEATURE_I2C=1 の組み合わせで、いよいよスタンドアロン機っぽい構成になってくるはずです。ビルドが「複雑になった」というよりは、「組み合わせを明示できるようになった」感じです。たぶん今後 profile を新しく増やすのは、本当に頻出する組み合わせだけになる、と思っています。

MC6800 ROMモニタSBC6800