MC6800 SDFS/68を作る その1 ~ROMから第2段DOSを起動する~

前回までのROMモニタ本編では、K68-VDGや2nd ACIAキーボード、ビルド構成軸の整理まで進めていました。
ここまで来ると、次に気になってくるのは「ROMにどこまで入れるのか」です。
最初は、ROMモニタにSD/FAT32の DIR や LF filename を入れて、SDカードからS-RecordやIntel HEXをロードできるようにしていました。これはこれでかなり便利です。PCからシリアルで流し込まなくても、SDカードにファイルを置いておけばロードできます。
ただ、ROMは最大8KBとして扱っています。モニタ本体、MIKBUG互換入口、ブレークポイント、逆アセンブル、SD初期化、FAT32、VDG、キーボード……と足していくと、だんだん無理があります。
そこで考えたのが、SDFS/68です。
ROMには最低限の BOOT だけを残し、FAT32を読む処理やDOS的な操作はSDカード上の第2段へ逃がす、という方向です。
SDFS/68は別シリーズにする
今回から、Blogも少し分けることにしました。
これまでの「MC6800 ROMモニタ自作」は、ROMの中に小さなモニタを作っていく話でした。ところがSDFS/68は、ROMの外、つまりSDカードからRAMへロードして動く第2段です。
もちろんROMモニタから起動しますし、同じプロジェクトの中の機能です。でも、主題としては「ROMモニタを拡張する」よりも「小さいDOSを作る」に近くなってきました。
なので、ここからは別シリーズとして「MC6800 SDFS/68を作る」にしてみます。
最初に考えていた案と、やめた案
最初は、ROMがFAT32 root directoryから SDFS.BIN を直接探してロードする案を考えていました。
PCから見ると普通のFAT32カードで、rootに SDFS.BIN を置けば起動する。これは分かりやすいです。
でも、ROM側にFAT32 mount、root directory検索、FAT chain読み込みを残すことになります。つまり、ROM容量を減らしたいのに、いちばん重いところがROMに残ります。
そこで方針を変えました。
ROMは固定LBAからstage1 loaderを読むだけにします。stage1 loaderをRAMに置き、そのstage1がFAT32を読んでrootの SDFS.BIN を探す。こうするとROM側はかなり単純になります。
今の起動の流れはこうです。
SDFS/68 v1 起動フロー
`] BOOT
ROM monitor が fixed LBA 16 から stage1 を読む
stage1 が FAT32 root から SDFS.BIN を読む
SDFS/68 が起動する
SDFS> `
ROMはFATを見ません。FATを読むのはstage1です。
fixed LBAに置くのはSDFS.BINではない
途中で少しややこしかったのは、fixed LBAに何を置くかです。
一時期は、fixed LBAに SDFS.BIN 本体を置く案も考えました。ROMから見ると単純で、決まったsectorを順に読んでRAMへ置けばよいです。
でも、それだとFAT rootに置いた SDFS.BIN とfixed LBA側の内容を同期する必要があります。しかも、SDFS/68本体をロードしたあと、fixed LBA loaderは使い捨てになります。
最終的には、fixed LBAにはstage1 loaderを置くことにしました。
stage1はRAMに常駐し、S1API68 というheaderとjump tableを持ちます。SDFS/68起動後も、SD sector readやFAT32 mountなどのboot servicesとして使えます。
これはなかなかよい落としどころでした。
メモリ配置
SDFS/68まわりのRAM配置は、profileごとに少し違います。
stage1 / SDFS/68 メモリ配置
sbcio_vdg では、SBC-IOの拡張RAM $C000-$DFFF を使います。
$C000-$C1FF: sector buffer$C200-$C3FF: monitor / stage1 work$C400-$CFFF: stage1$D000-$DEFF: SDFS/68本体$DF00-$DFFF: stack余白
k6802_vdg では同じ構造を $A000-$BFFF 側に置きます。
v1のSDFS/68本体は、まだかなり小さいです。とはいえ、ここに今後 DIR、TYPE、RUN などを足していくことになるので、最初の2KB枠では苦しく、stage1側は3KB枠へ広げました。
システムSDイメージを作る
専用のSDイメージを作るために、tools/mk_sdfs_image.py も用意しました。
このツールは、実SDカードへ直接書き込むのではなく、FAT32のイメージファイルを作ります。直接デバイスへ書くと、Mac、Windows、Linuxで権限やデバイス名が違いますし、指定ミスで別ディスクを壊す危険もあります。
なので、まずは安全に「イメージファイルを作る」ところまでです。
SDFS/68 システムSDイメージ
基本形はこんな感じです。
`python3 tools/mk_sdfs_image.py \
--stage1 build/stage1-sbcio-vdg.bin \
--sdfs build/SDFS-sbcio-vdg.BIN \
--output sdfs.img \
HELLO.S HELLO.HEX`
生成されるイメージは、ざっくりこうなります。
- physical LBA 16以降: stage1 loader
- physical LBA 32以降: FAT32 partition
- FAT root:
SDFS.BIN、HELLO.S、HELLO.HEXなど
実SDカードへは、Mac/Linuxなら dd、Windowsなら既存のイメージライタで書く想定です。
v1でできること
SDFS/68 v1は、まだDOS完成ではありません。
できることは、かなり絞っています。
`SDFS> L HELLO.S
OK
SDFS> L HELLO.HEX
OK
SDFS> D0200
0200 86`
L filename で、FAT rootにある8.3名のS-RecordまたはIntel HEXをロードします。Dhhhh はロード確認用の最小dumpです。
存在しないファイルや壊れたHEX、終端recordなしのファイルでは、? や ?S5 / ?I5 のようなエラーを出してプロンプトへ戻ります。
つまり、v1は「SDFS/68という名前の最小ローダ環境」です。まだ DIR も TYPE もありません。
ROM側のDIR/LFはどうなったか
ROM側には、互換用として sbcio profileだけ DIR / LF を残しています。
一方で、sbcio_vdg や k6802_vdg のような本線profileでは、ROM側FATは外しました。ROMからは BOOT でSDFS/68を起動し、SDFS/68側でロードする構成です。
この整理はPR #135で入れました。
いきなりROM側FATを全削除しなかったのは、互換や実機確認の逃げ道を残すためです。SDFS/68が育つまでは、sbcio profileのROM常駐FATは実験用としてまだ価値があります。
関連IssueとPR
このあたりの作業は、かなり細かいIssueに分けて進めました。
主なところだけ挙げると、こんな感じです。
- Issue #82 / PR #106: SDFS/68 第2段ブート設計
- Issue #103 / PR #112:
mk-sdfsSDイメージ生成ツール - Issue #101 / PR #127: ROM固定LBA stage1
BOOT - Issue #111 / PR #132: stage1 loader完成
- Issue #102 / PR #133: SDFS/68最小本体
- Issue #130 / PR #134: SDFS/68側HEX/S-record loader
- Issue #128 / PR #135: ROM常駐FAT
DIR/LFの整理
次にやること
SDFS/68 v1で「起動して、SD上のファイルをロードする」ところまでは来ました。
次は、SDFS/68を小さいDOSとして育てる話です。
最初は LOAD を中心に考えていたのですが、DOSっぽくするなら、やっぱり「ロードしてからモニタに戻ってG」では少し変です。DIR でファイルを見て、RUN で実行する方が自然です。
その話は次回にします。
関連リンク
- Issue #82: https://github.com/kuninet/mc6800-rom-monitor/issues/82
- Issue #101: https://github.com/kuninet/mc6800-rom-monitor/issues/101
- Issue #102: https://github.com/kuninet/mc6800-rom-monitor/issues/102
- Issue #103: https://github.com/kuninet/mc6800-rom-monitor/issues/103
- Issue #111: https://github.com/kuninet/mc6800-rom-monitor/issues/111
- Issue #128: https://github.com/kuninet/mc6800-rom-monitor/issues/128
- Issue #130: https://github.com/kuninet/mc6800-rom-monitor/issues/130
- PR #106: https://github.com/kuninet/mc6800-rom-monitor/pull/106
- PR #112: https://github.com/kuninet/mc6800-rom-monitor/pull/112
- PR #127: https://github.com/kuninet/mc6800-rom-monitor/pull/127
- PR #132: https://github.com/kuninet/mc6800-rom-monitor/pull/132
- PR #133: https://github.com/kuninet/mc6800-rom-monitor/pull/133
- PR #134: https://github.com/kuninet/mc6800-rom-monitor/pull/134
- PR #135: https://github.com/kuninet/mc6800-rom-monitor/pull/135