借り初めのひみつきち

仮ブログです。移転先募集中

BASIC-DOS

さいきん変な OS が発表されたっぽいです。

basicdos.com

2020 年になって DOS !!!

ぼくはこういうソフトを見つけた時に、普通の人とはちょっと視点で見てしまいます。

このソフト、ぼくの自作エミュレータで動くのかな?

バイナリないナリ

ということで、まずは公式サイトからダウンロードしてみましょう。

残念ながら、バイナリイメージを見つけることができませんでした。

ソースを GITHUB.COM からダウンロードして中身をのぞいてみます。

2020 年なのに開発環境も DOS !!!

そもそも、ブラウザで動かす前提なので通常のディスクイメージは提供してないようです。

幸いにして COM 形式のバイナリは git に含まれているようなので、そこからディスクイメージを錬成します。

とりあえず作った最初のイメージはブートエラーでした。

起動できるまで

IPL のソースを見てみます。

DOS の基本ブートシーケンスは IPL が IO.SYS と MSDOS.SYS を探して読み込もうとします。 PC-DOS の場合は IBMBIO.COM と IBMDOS.COM という名前になる以外は基本的に同じです。 この OS ではそれに加えて CONFIG.SYS も読み込もうとするようです。いくつか CONFIG.SYS のサンプルがあったのでそれも組み込むようにしました。

また、当初 2HD でイメージを作りましたが BPB の内容が 160KB だったので 160KB で作り直しました。 IPL にうまくパッチを当てれば 2HD でも起動できそうですがそちらは試していません。

なんとか起動してコマンドプロンプトまで進みました。

古の開発環境再来

なんとか起動しましたが、キー入力の応答が悪く、カーソルの描画も変な感じでした。

コンソールドライバのソースを調査して原因の予想がついたので自作エミュレータ側を改修する必要がありますが、 なんと開発機をリプレースしたときに開発環境がなくなってしまっていたのでした。

ということで、開発環境を再構築しようとしましたが、必要なツールのひとつが darwin-arm64 なんか知らん!とエラーになってしまいました・・・。

これのためだけに x86 環境整えるのもなんだかめんどくさいなったので、古い Mac 君に頑張ってもらうことにしました。 久々に触った Intel Mac はとても重みを感じます。

修正

f:id:neriring16:20201226161804p:plain

カーソルの描画がおかしい問題は、おそらくエミュレータ側の座標計算が間違ってるだろうということですぐに解決しました。

問題はキー入力です。

通常、自作エミュレーターのキー入力は以下のようなフローで動きます。

ブラウザでキーを押す
 ↓
ホストOSのキーイベントが発生
 ↓
JS のキーイベント発生
 ↓
PS/2 ドライバがスキャンコードに変換して FIFO に書き込み、 IRQ 発火
 ↓
BIOS が PS/2 ポート(60)から FIFO の値を読み出してキーバッファに書き込む
 ↓
キーボード BIOS がキーバッファからキーデータを読み込む

一方、この OS のキーボードドライバを入れるとこうなります。

ブラウザでキーを押す
 ↓
ホストOSのキーイベントが発生
 ↓
JS のキーイベント発生
 ↓
PS/2 ドライバがスキャンコードに変換して FIFO に書き込み、 IRQ 発火
 ↓
OS のドライバが PS/2 ポートの FIFO の値を盗み見してホットキーの処理をし、 
BIOS の IRQ ハンドラを呼び出す
 ↓
BIOS が PS/2 ポート(60)から FIFO の値を読み出す→この時 FIFO がすでに空
 ↓
キーボード BIOS がキーバッファからキーデータを読み込む→空

OS のドライバが先に FIFO の値を読み込んでしまうので、その後 BIOS がキーデータを読み出す時には FIFO が空になってしまいます。

これを対策するために PS/2 のキーデータを FIFO ではなく上書き方式にすると、キー入力自体はできるようになりました。

しかし、IRQ の発火回数とデータの読み取り回数が一致しなくなるので、短期間に連続でデータが来た時のデータを保証することができなくなって取りこぼしや重複する問題が発生します。 この変更によって今まで動いていたソフトにも影響が出てしまう可能性があるので対策を考えています。

突然の UNDEFINED INSTRUCTION

とりあえず起動して操作できるようになったので、いくつか付属のアプリの動きを検証してみます。

f:id:neriring16:20201226163821p:plain

_人人人人人人人人人人人人人人人人_ > 突然の UNDEFINED INSTRUCTION <  ̄YYYYYYYYYYYYYYYY^ ̄

エミュレーターのバグの可能性もあるので色々調査したところ、普通に直接呼び出していました。

f:id:neriring16:20201226164024p:plain

FFBF:04D0 をリニアアドレスにすると 0x1000C0 になり、さらに A20 をマスクすると 0x000C0 になります。 INT 0x30 の割り込みベクタと一致します。

CALL 5 って CP/M 互換システムコールで使われているのですが、なんでこんな変なアドレスなんでしょうか? よくわかりませんでした。

いかがでしたか

謎 OS を自作エミュレーターに対応させるのは楽しいですが、時には謎挙動に頭を悩ませることもあります。

それと開発環境はちゃんと残しておきましょう。