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

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

前回までのROMモニタ本編では、K68-VDGや2nd ACIAキーボード、ビルド構成軸の整理まで進めていました。

ここまで来ると、次に気になってくるのは「ROMにどこまで入れるのか」です。

最初は、ROMモニタにSD/FAT32の DIRLF 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本体は、まだかなり小さいです。とはいえ、ここに今後 DIRTYPERUN などを足していくことになるので、最初の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.BINHELLO.SHELLO.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という名前の最小ローダ環境」です。まだ DIRTYPE もありません。

ROM側のDIR/LFはどうなったか

ROM側には、互換用として sbcio profileだけ DIR / LF を残しています。

一方で、sbcio_vdgk6802_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-sdfs SDイメージ生成ツール
  • 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 で実行する方が自然です。

その話は次回にします。

関連リンク

SDFS/68