|
[ここに書いてる内容は、FM TOWNSの技術情報を残すことを目的に書いてるので、どんどん転載しちゃってください。]
YSSCSICD.SYSを使うことで、内蔵CD-ROMドライブが故障して動作しなくなったFM TOWNSで、起動フロッピーディスクあるいはハードディスクに起動パーティションを作ることである程度のCD-ROMソフトウェアを動作させることができる。
富士通FM TOWNSは日本のコンピュータの歴史に明らかに大きなインパクトを与えた機種だった。残念ながら今では動作する機体は日を追うごとに減ってきていると思う。しかし、歴史的意義の高いコンピュータを動態保存することにはそれなりの意味があると思う。富士通FM-7, FM77AV, FM TOWNSを渡り歩き、プログラミングを学んだ自分としては、FMシリーズの動態保存に自分なりの貢献をしたいと思う。
FM TOWNSが与えた最大のインパクトは世界で初めてCD-ROMを標準装備として搭載したこと、PharLap 386 DOS Extenderの標準採用することで80386の32ビットモードをすべてのユーザに提供したこの2点だった。しかし、FM TOWNSのCD-ROMドライブは採用時期が早すぎてSCSIやIDEの仕様が決まる前だった影響でプロトコルが標準規格と全く違うらしい。少なくともピンアウトはまったく違う。そのため、いったん内蔵CD-ROMドライブが故障してしまうともはや交換部品の入手はほとんど不可能になった。しかも悪いことにCD-ROMドライブを標準搭載していたため、CD-ROMドライブの存在を前提としたソフトが大半を占める。このため、いったん内蔵CD-ROMドライブが故障してしまうと、これまではFM TOWNSは事実上使用不可能になってしまった。
この問題に対応するために、奇跡的にCDSD.SYS, CDISC2.SYSというデバイスドライバが存在した。このふたつのドライバを組み合わせることで、外付けSCSI CD-ROMドライブを内蔵CD-ROMドライブの代替とすることができ、ある程度のCD-ROMソフトウェアを実行することができた。しかし、CDSD.SYSは、事実上バイナリの入手が不可能という問題があった。作者はバイナリを製品として販売する意図があったらしい。そのため、ソースコードは再配布可能または改変なども自由というライセンス条項があり、バイナリを再配布できない。CDISC2.SYSにしても、いくつかの問題があり、起動できないソフトウェアが多かった。
その問題を解決するために、今回YSSCSICD.SYSを開発した。これ一本でCDSD.SYS, CDISC2.SYS同等以上の機能を実現できる。CDSD.SYS, CDISC2.SYS両ドライバのバグやエミュレーションが不完全だった部分を改善してあるので、既に以前は外付けSCSI CD-ROMドライブから実行できなかったいくつかのタイトルも実行できるようになったことを確認した。
また、フロッピーディスクからCD-ROM上のTownsOSを起動する上で問題だったのが起動ドライブキャッシュだった。フロッピーディスクのAUTOEXEC.BAT内でカレントドライブをQにしてTMENU.EXPを実行したとしても、頻繁にAドライブのファイルを探しに行ってしまう。どこに起動ドライブが記録してあるのか。それもついに究明できた。そこで、AUTOEXEC.BATの先頭で起動ドライブを変更できるように、ユーティリティSYSDRV.EXEも開発した。これもGitHubからダウンロードできる。と、思ったら実はTowns OS V1.1はTowns OS V2.1と違う方法でシステムドライブを検出していることがわかったが、SYSDRV.EXEが対応したので、TownsOS V1.1にも対応できるようになった。
YSSCSICD.SYSの開発にあたっては両ドライバのソースコードをかなり隅々まで読んだので、ソースコードを開示していただいたことを開発者の方にとても感謝している。
INT 93H AX=01C0HがドライブモードをDLに返してなかったので修正。多分Ms. Detective #1はSCSI CD-ROMドライブから使えると思う。
INT 93H AX=05C0H CH=0FFH (物理アドレスへの直接読み込み)時、Unrealモードを使っていたのをやめて、DMAを直接攻撃するようにした。バッファがいらなくなったんでファイルサイズが一気に7KB程度に縮小。
ReadTOC (AH=54H)が返すCDの長さを修正。前のバージョンだとSCSIが返す値から2秒引いた値を返してたけど、その影響でOperation Wolfが正規のCDではないと識別して起動しなかった。この修正でOperation Wolfも起動可能になった。
80386のUnreal-modeを利用して、INT 93H, AH=05H/15H, CH=0FFH (下位4GBの物理メモリ空間にセクタ内容の読み込み)をエミュレートした。これによりV1.1L30の起動ディスクでRAYXANBERが起動可能になった。
Wing CommanderのBGM再生に成功。これは難しかった。一大デバッグ作戦だった。何が起きていたかというと、Wing Commanderは独自のハードウェアIRQハンドラを設定していた。そのハンドラがDOS Extenderの32-bitモードと16-bitモード間のデータ交換バッファを使用していた。YSSCSICD.SYSがCDDA再生コマンドを受け取ると、まず最初にCD-ROMドライブの状態をチェックした。が、この状態チェックがIRQを発生させていたらしく、Wing CommanderのIRQハンドラに処理が移って、データ交換バッファを破壊してしまった。YSSCSICD.SYSがCDDA再生の開始時間と終了時間をデータ交換バッファから読む段階では既に内容が破壊されていた。解決は簡単で、ドライブ状態チェックの前に開始時間と終了時間をキャッシュするだけで問題解消。なお、Towns OS V1.1起動フロッピーディスクから直接Wing CommanderのCD-ROM上のTowns OSを起動して、そこからWing Commanderを起動するか、あるいはV2.1から実行するのであれば、コマンドから次のように実行する。(+mオプションでBGM有効)
Q: A:RUN386.EXE WC.EXP savepath=a: +m kanji
英語版で起動するには kanji オプションを削除する。
ところで、DOSの"Default Drive"って、起動したドライブのことだと思ったら、ただのカレントドライブなのか。わざわざSYSDRVコマンド作る必要無かったな :-P
SYSDRV.EXEとSYSINIW.EXEをYSSCSICD.SYSに統合。CONFIG.SYSに
DEVICE=\YSSCSICD.SYS /D:Q
と書くことで、システムドライブをQに変更できる。また、
DEVICE=\YSSCSICD.SYS /M
と書くことで、SIDEWORK.EXEとSYSINIT.EXEがメッセージを表示するようになる。
統合したんだけどやっぱりTownsOS V1.1を起動するためにSYSDRV.EXEは必要になった。
CD-ROM BIOSの57H, 58HをただNo Errorを返すよりは少し良くエミュレートするようにしたつもり。SYSDRV.EXEとSYSINIW.EXEを追加。
/RオプションでRS232Cデバッグをenableすると、RS232Cポートに更新可能なデバイスがつながってないと起動中にハングしてしまうので、オプションでデバッグを指定するのをやめた。代わりに、コマンドラインからEnable/Disableできるようにした。
RS232CデバッグEnable
ECHO R > CPTYS_CD
RS232CデバッグDisable
ECHO r > CPTYS_CD
ConsoleデバッグEnable
ECHO V > CPTYS_CD
ConsoleデバッグDisable
ECHO v > CPTYS_CD
成功!初公開!
ゲームはエンディングまではテストしてないけどゲーム開始まで確認できたもの。一部、専用起動フロッピーが必要。(VINGBIOSが必要なものとか)
(*1) マウスが必須なので486DXの高速モードで使うにはV1.1起動ディスクにV2.1 L20のTBIOS.SYS, TBIOS.BINをコピーしておく。
(*2) コピープロテクトの影響でV1.1起動ディスクをBドライブ、オーガスタのユーザ/プログラムディスクをAドライブに入れてBドライブから起動。プロテクトの解除方法がわかる人は、プログラムディスクの全ファイルをV1.1起動ディスクに書いておけばディスク1枚で起動可。
(*3) V1.1起動ディスクでV1.1のTBIOSが必要。そうでないとMOS_startが失敗する模様。486DX機では互換モードで起動する必要あり。Bドライブから起動するか、タイトル画面まで出たらでAドライブにユーザディスクを入れる。起動ディスクにユーザディスクのファイルをコピーしても大丈夫の模様。
バイナリも含めて→ https://github.com/captainys/FM/tree/master/TOWNS/YSSCSICD
なんとかがんばってこのディスクイメージをフロッピーディスクに焼く。この手が使えるかもしれない。
(このディスクイメージだとTowns OS V1.1 + V2.1L20 TBIOS。)
CONFIG.SYS
SHELL=C:\COMMAND.COM C:\ /P DEVICE=\SYS\CTL.SYS DEVICE=\TBIOS.SYS /TBIOS.BIN /D DEVICE=\TOWNS.SYS DEVICE=\SYS\OAK0.SYS DEVICE=\SYS\OAK1.SYS /S0 /H1 /K0 /R0 /M3 /B1 DEVICE=\YSSCSICD.SYS /M /D:Q BUFFERS=8 FILES=20
AUTOEXEC.BAT
C:MSCDEX /D:TOWNS_CD /M:8 /L:Q Q: AUTOEXEC.BAT
なんとかがんばってこのディスクイメージをフロッピーディスクに焼く。この手が使えるといいんだけど。
V2.1 L20が起動できるのに、V1.1 L30の起動ディスクをあえて作ろうということは、Wing Commanderがプレイしたいのね。滅茶苦茶気持ちわかる。
この場合は、ちょっと手順がややこしい。まずV1.1 L30のIO.SYSがインストールされた起動フロッピーディスクを作らなくてはならない。それから、起動ドライブの指定を多分CONFIG.SYSが終わってからやらなくてはならないから、SYSDRV.EXEを使う。
どうやるかというと、
CONFIG.SYS
SHELL=C:\COMMAND.COM C:\ /P DEVICE=TBIOS.SYS /TBIOS.BIN DEVICE=YSSCSICD.SYS /D:Q BUFFERS=8 FILES=20
AUTOEXEC.BAT
SYSDRV.EXE C:MSCDEX /D:TOWNS_CD /M:8 /L:Q Q: AUTOEXEC.BAT
Towns OS V1.1 L30のディスクの初期化で「CD演奏」をインストールしたフロッピーディスクを作成。以後ケース(B)の手順7にジャンプ。
(1) 上の手順で作成したフロッピーディスクをドライブ0に入れる。
(2) FM TOWNSに接続した外付けSCSI CD-ROMドライブに対応するバージョンのTowns OSのCD-ROMを入れる。
(3) Fキーと0キーを押した状態で電源投入。0キーはフルキー側。テンキー側は不可。フロッピーディスクから起動が始まるまでキーを押し続ける。さっき思い出したんだけどジョイパッドのAを押しながら起動でもできる。
FM TOWNSの内蔵CD-ROMを外付けSCSI CD-ROMドライブで置き換えるだけならば、FM TOWNSのCD-ROM BIOSだけ置き換えればいい。しかし、なぜCDISC2.SYSはわざわざ入手困難で、しかもバグがあってTOWNS OSで動作しない(どうやらMS-DOS for FM TOWNSでは動作したらしい。僕がバグ取った) CDSD.SYSに依存したのか?おそらくその理由は二点あったと思う。いや、三点かな。
内蔵CD-ROMドライブが健全でリダイレクタを使わない状態で、内蔵CD-ROMドライブのファイルをアクセスするときの流れは以下のようになる。
MSCDEX -> TOWNS_CD -> CD-ROM BIOS -> Internal CD-ROM Drive
このCD-ROM BIOSを挿げ替えてTOWNS_CDからのコマンドをSCSI CD-ROM Driveにリダイレクトすれば原理的にはSCSI CD-ROMドライブ上のファイルにアクセスできるようになる。しかし、CD-ROM BIOSを解析した結果、未公開機能 AH=0FCH, 0FDH, 0CH, 0EH, 0FH, 10H, 11H, 56H, 57H, 60H, 61Hの存在が明らかになった。このうち、0FCH, 0EH, 0FH, 061Hは実際にTOWNS_CDから呼び出される。011Hも呼び出されるがこれは電源切断時、リセット時なのでこの機能は無視してもほぼ問題がなさそうだ。おそらくCDISC2.SYSの作者も最初はこの方法を考えたのではないか。しかし、実際に実装してみたところ隠し機能の存在が判明したのでこの方法を断念したのではないか。
また、FM-R/TOWNSでSCSI CD-ROMにアクセスする方法が公開されていなかった。CDSD.SYSはFM-Rの隠し機能INT 93H, AH=0FDHを使っていた。そうでなければ、I/Oポートを直接攻撃しなくてはならない。富士通FM-Rシリーズ徹底解析マニュアル,増補改訂版,インターブログ編にはこの機能は載っていない。CDSD.SYS作者がその情報をどこから入手したのかはわからない。INT 93H, AH=0FDHの機能を自力で調べるよりはすでに存在するCD-ROMドライバ、CDSD.SYSを使う方が合理的と考えたのかもしれない。
もうひとつの問題は、DOSのDevice DriverだけではどうしてもエミュレートできないCD-ROM BIOSの機能がふたつある点だった。INT 93H, AH=05Hまたは15H, CH=0FFHだった場合、CD-ROM BIOSは下位1MBを超える上位メモリに直接データを書き込まなくてはならない。リアルモードで動作するCD-ROM BIOSになぜそれが可能だったのか。それはDMAを使ったから可能だった。DMAはx86の命令セットに関係なく物理メモリのどこにでも値を書き込むことができた。しかし、同等の機能を80186の命令セットで実現しようとしてもそれは不可能。MSCDEXから命令を受けるTOWNS_CDがそのふたつの機能を使うとは考えにくいが、もしも使っていたら詰んでしまう。ちなみに、実験の結果本当に使ってなかった。だが、そのリスクを避けるためにあえてCD-ROM BIOSだけでなくそのひとつ上位にあるTOWNS_CDまで置き換えてしまおうと考えたのかもしれない。
いずれにせよ、CDISC2.SYSは非常に複雑な処理をすることになった。大雑把に言うとCDISC2.SYSはふたつの処理をする。
したがって大半のファイルアクセスは、
MSCDEX -> CDISC.SYS -> CDSD.SYS -> SCSI CD-ROM Drive
という流れで処理される。この流れの場合、CD-ROM BIOS呼び出しは一切かかわらないので、絶対にハイメモリに直接アクセスが発生することはない。
また、TOWNS OSのアプリケーションからCDDAの演奏を実現するためにCD-ROM BIOSの機能もMSCDEXコマンドのリダイレクトとは別にSCSIコマンドにリダイレクトするようにできている。
しかし、残念ながらCDSD.SYSには多くのバグがあった。そもそもTOWNS OSに対応していなかった。また、FM-R/TOWNSのSCSI BIOSの隠し機能はエラーコードをAHとCHに返すが、CHをチェックしていないため、エラーを取りこぼすバグもあるようだった。そもそも、どちらのバグも取ったのだが、ライセンス条項にソースコードは再配布してもかまわないがバイナリは再配布禁止とあるため僕にできるのはビルドインストラクションとソースコードをアップロードするだけで、現実的に今FM TOWNSを動態保存している人が使える状態で配布できなかった。
また、CDISC2.SYSにも問題があり、INT 93H, AH=52H, CH=0FFHに対応していなくてエラーを返してしまう。この機能はSCSI2のコマンドにも存在しないが、単純に無視することでアプリケーションを続行させることができるのだが、エラーを返してしまうため動作しないソフトがいくつもあった。
今回開発したYSSCSICD.SYSはCDISC2.SYSのアプローチと違って単純にFM TOWNSのCD-ROM BIOSを置き換える。必要最低限の隠し機能、0EH, 0FHはCD-ROM BIOSを逆アセンブルして動作をおおよそ解明して実装した。TOWNS_OSドライバがハイメモリにデータを読み込むような指令を出すとは思えなかったが、一応、同じ機能でたまたまアドレシングが下位メモリを指していた場合は動作するように書いた。これまでのところハイメモリにデータを書き込むようなコマンドが発行された様子は無い。
Comments are welcome. Send E-Mail to: |