JavaScriptを有効にすると、ここにメニューを表示します。
富士通FM-7実機用ディスクBIOSリダイレクタ
ディスクドライブの無いFM-7実機でRS232C経由でディスク版ソフトを実行

ysflight.com

時には昔の実機を

時には昔の実機を使おう。このプログラムは富士通FM-7シリーズ実機とRS232Cカードがある状態(あるいはFM77AV20/40以降だとRS232Cカードはオンボード)で、Disk BIOSをRS232CにリダイレクトしてWindows上のD77サーバープログラムからセクタデータを送り込むことでディスクが無くても実機でディスク版ソフトを実行してしまうという大技です。(まさか成功するとは思ってなかった。)これにより、素のFM-7でもRS232Cカードとサーバー用Windows PCと忍耐力さえあればディスク版ソフトを実行できます。

また、ディスクドライブが既に動作不能になっているFM-77以降の機種でもRS232Cさえあればある程度ディスクベースのプログラムを実行できます。

ただし、実行できるのはディスクの読み書きにBIOSを使っているものだけです。Disk BASICベースのものであれば多分大半動作すると思います。また、サーバープログラムはセクタデータをFM-7に送信する前にBIOSコールをリダイレクタ呼び出しに書き換えて送信するので、複雑な暗号化がかかっているものは対応できません。

なお、FM-7のソフトがフロッピーディスクにアクセスするには大雑把に二通りの方法があり、ひとつはBIOSを使う方法、もうひとつはDisk I/Oを直接制御する方法です。このリダイレクタで対応できるのはBIOSを使ってディスクにアクセスしているソフトだけなのでDisk I/Oを直接制御しているものは対応できません。そのような場合は、ソフトのコードを読んでDisk I/Oを使わないように書き換えることができれば実行できると思います。ここではどう書き換えればいいのかは書けませんので、どうしても実行したい昔のFM-7ソフトがある人は自力でがんばってください。

Disk I/Oを使わないようにプログラムを書き換えるというのは結果的にコピープロテクトを解除してしまうことになるかもしれませんが、必ずしもコピープロテクト解除と同一ではありません。例えばF7セクタをチェックするコピープロテクトを、代わりに01セクタの存在をチェックするように書き換えるとコピープロテクトは解除できますが、まだDisk I/Oを使っているかもしれません。それだとこのリダイレクタでは動作しません。逆にコピープロテクトがかかっていないタイトルでもディスクBIOSを使っていないものは、ディスク読み出し部分をBIOSを使用するように書き換えることでこのリダイレクタによる実行を可能にできるかもしれませんが、その場合はコピープロテクトの解除とはぜんぜん関係ありません。

読み込み速度を計測したら大体1トラック4096バイトを2秒で読んでいたので、1秒あたり2048バイト。RS232Cは1バイト送るごとにストップビットを送るはずなので9x2048=18432bps。大体19200bpsのほぼフルスピードが出ているようです。そんなに悪くありません。

ダウンロード

他のFM-7シリーズ実機再稼働ユーティリティと一緒なので、ここから

ソースコード

https://github.com/captainys/FM/tree/master/7/util

(* ソースコードのURLが変わりました)

使い方

このプログラムはFM-7シリーズ実機とWindowsのコマンドラインから実行するサーバーのペアで使います。FM-7実機とWindows PCの間はRS232Cクロスケーブルで接続して、FM-7実機上のRS232Cカードは最高速に設定しておく必要があります。

FM-7上では短いプログラムを打ち込む必要があります。

10 OPEN "I",#1,"COM0:(F8N1)"
20 LINE INPUT #1,A$
30 CLOSE
40 EXEC VARPTR(A$)

そして、RUNして待ち状態にしてください。次にWindowsのコマンドプロンプトまたはPower Shellに入ってサーバーを起動します。

RS232CDiskBios.exe diskimage.d77 1

のようにタイプしてください。なお、RS232CDiskBios.exeにパスが通っていない場合は相対あるいは絶対パスで指定してください。とくに、Power Shell上ではカレントディレクトリに置いてある場合でも ./ をつけないと実行してくれません。1というのはCOMポート番号なので環境に応じて適当な番号を指定してください。サーバーが起動したら、サーバープロンプト上で、

IL

とタイプしてください。FM-7が再起動してサーバー起動時に指定したイメージから起動します。どのセクタを読み書きしているかはコマンドプロンプト上に出るので、動作してるのはわかります。

FM77AV20/40以降の機種で使うには(FM77AV1/2以前でRS232Cカード使用の場合は不要)、上の手順の前にまずRS232CをEnableする必要があります。F-BASICのプロンプトから、

POKE &HFD0C,5
POKE &HFD0B,16
EXEC -512

と打ち込んで、30秒ぐらい待つとRS232Cが使えるようになって再起動します。なお、FM-7実機で実行すると、POKE &HFD0B,16とした瞬間にF-BASICが固まります。実はFM-7実機では$FD0Bに書き込むのが$FD0Fに書き込むのと同じ効果があります。なので、上のコマンドはFM77AV20/40以降で使う場合のみタイプしてください。

高度な使い方

デフォルトではリダイレクタはFM-7の$FC00~$FC63に常駐します。しかし、実行したいプログラムがこの領域を使っていたら当然実行できません。その状態を回避するために、オプションで常駐アドレスを変更することができます。例えば、

RS232CDiskBios.exe diskimage.d77 1 -install $6F80

のようにタイプすると常駐先を$6F80に変更します。また、Disk BASICベースのプログラムの場合、エラーさえ起らなければエラーメッセージはいらないので、エラーメッセージが格納してある$7F25~に常駐させることができます。が、そのためにはIPLがDisk BASICを読み込んでいる間は別の場所に常駐している必要があるので、違うオプションを使います。

RS232CDiskBios.exe diskimage.d77 1 -install2 $7F25

こうするとIPLがDisk BASICを読み込んでいる間はリダイレクタは$FC80に隠れて、読み込み後$7F25に常駐します。この手を使うことでDisk BASICから起動するプログラムは多分大半実行できると思います。

サーバーコマンドオプション

[基本]

RS232CDiskBios.exe diskimage.d77 portNumber

指定のディスクイメージをFM-7実機にRS232C経由で送信できる状態になる。マルチディスクイメージの場合、最初のディスクがドライブ0、二番目のディスクがドライブ1にあるものとする。BIOSリダイレクタはFC80~に常駐する。

イメージファイル名には.D77に続けて#を書くことでオプションを指定できる。オプションについては、下のイメージファイル名オプションを参照。

[常駐先指定 (-install)]

RS232CDiskBios.exe diskimage.d77 portNumber -install 7F90

上の例だとBIOSリダイレクタを$7F90~に常駐する。アドレスには先頭に何もつけない($とか0xとか&Hとかつけない)で16進数で指定。起動したいFM-7用プログラムが$FC80~を使ってしまう場合、このオプションでリダイレクタの常駐アドレスを変更できる。ただし、F-BASICのDisk BASIC上での常駐先を指定するには、次の -install2 を使う。

[Disk BASIC用常駐先指定 (-install2)]

RS232CDiskBios.exe diskimage.d77 portNumber -install 7F25

F-BASICのDisk BASICを使う場合の常駐アドレスを指定する。上の例では$7F25(Disk BASICのエラーメッセージエリア)に常駐するようになる。

[ドライブ1のディスクイメージ指定(-1)]

RS232CDiskBios.exe diskimage.d77 portNumber -1 drive1.d77

ドライブ1のイメージを指定する。ドライブ0用のディスクイメージファイルがマルチディスクイメージで、イメージ1以外をマウントしたい場合は、ファイル名の代わりに #DSK0#3 のように書くとドライブ0用ディスクイメージのディスク番号3をマウントする。

ドライブ0と同じイメージファイルを使いたいとき、あらためて同じファイル名を書いた場合は動作保証無し。

[LD? #$FE0?もリダイレクト]

RS232CDiskBios.exe diskimage.d77 portNumber -ldxFExx
RS232CDiskBios.exe diskimage.d77 portNumber -ldyFExx
RS232CDiskBios.exe diskimage.d77 portNumber -lduFExx

プログラムによっては、BIOS呼び出しを LDY #$FE08 JSR ,Y のように書いているものがあるので、それに対応する。

[エンコーダー]

RS232CDiskBios.exe diskimage.d77 portNumber -encoder XOR xx
RS232CDiskBios.exe diskimage.d77 portNumber -encoder NEG
RS232CDiskBios.exe diskimage.d77 portNumber -encoder COM

プログラムによっては、実行ファイルを読み込んでから一定の値とXORを取ったり、マイナスにしたり、ビット反転するようなものがあるので、それに対応する。xxは2文字で16進数。 

[38400 bps通信]

RS232CDiskBios.exe diskimage.d77 portNumber -38400bps

通信速度38400bpsを使用。このオプションを使うにはRS232Cカードが38400bpsに対応していてそのように設定されている必要があります。

イメージファイル名オプション

D77イメージファイルを指定するとき、.D77に続けてスペースを空けずに#を書くことでオプションを指定することができる。続けて複数のオプションを指定することも可能。

[新規作成 (#NEW)]

diskimage.d77#NEW

標準F-BASICフォーマットのディスクイメージを作ってマウント。ただし、同名のファイルが既に存在する場合はエラーになる。

[強制新規作成 (#FNEW)]

diskimage.d77#FNEW

標準F-BASICフォーマットのディスクイメージを作ってマウント。既に同名のファイルが存在する場合は、最初にFM-7からなんらかの書き込みがあったときに上書きする。

[ディスク番号指定 (#0)(#1)(#2)(#3)...]

diskimage.d77#3

マルチディスクイメージの場合、何番目(0が最初)のイメージをマウントするか指定できる。

[書き込み禁止 (#WP)]

diskimage.d77#WP

D77イメージファイルのライトプロテクトフラグが無くてもライトプロテクト状態でマウントする。

サーバープロンプト用コマンド

[BIOSリダイレクタローダー送信 (IL)]

IL

FM-7をF-BASICで待ち状態にして、サーバー上でILコマンドをタイプすると0x7Eバイトのリダイレクタローダーを送信する。ローダーはその後サーバーと交信してリダイレクタインストーラを0x6000からに展開してジャンプする。

ILコマンド用待ちプログラムは次の通り。IAコマンドより速い。

10 OPEN "I",#1,"COM0:(F8N1)"
20 LINE INPUT #1,A$
30 CLOSE
40 EXEC VARPTR(A$)

[BIOSリダイレクタインストーラ送信 (IA)]

IA

FM-7をF-BASICで待ち状態にして、サーバー上でIAコマンドをタイプすると256バイトのリダイレクタインストーラを送信する。デフォルトの例では$6000からに書き込むことにしてるけどインストーラはリロケータブル。

[Verboseモード On/Off (V)]

V

VコマンドでVerboseモードをトグルできる。Verbose Mode=Onでは受信バイトを全部表示する。

動作確認

[ ]は確認した機種

できれば素のFM-7で動作確認したいが権力が無いため大学の自分の机に常にFM-7を置いておけるだけのスペースが無くてとりあえずいつも使える状態にしているFM77AV40で確認しているけど順次FM-7でも動作確認次第追加していく予定。

コマンド例の"2"というのはポート番号なので環境に応じて書き換える。

(非公式対応)というのはDisk I/Oを直接アクセスしないように書き換えることで起動可能。

F-BASIC 3.0 (富士通) [実機AV40]

起動確認。

なお、F-BASIC 3.0のディスクでうまく動作しないものは、オプションに、

-install2 7F25

をつけてやるとDisk BASICのエラーメッセージ領域に常駐するので動作するかもしれない。
エラーが出るとクラッシュするかもしれない。

F-BASICから起動確認したのは、

URADOS (I/O掲載) [実機AV40]

起動確認。ただし$7F9Fまでしか使えない。なお、インストールアドレスを指定しなかったらサーバーはURADOSを自動判別してインストールアドレスを7F80に変更する。URADOSはFC00~を使ってしまうのでデフォルトの位置にはリダイレクタをインストールできない。

R-DOS (I/O掲載) [実機AV40]

DOSモードで起動してくるものなので、サーバーオプション

-dosmode

が必要。DOSモードというのは、単に$8000~$FBFFがRAMモードで、IPLが$0300からにロードされるというものなので、インストーラがそのような状態にしてIPLにジャンプすることで対応。

(非公式対応)Thexder (ゲームアーツ) [実機AV40]

FC00~FCFFはThexderが使うので、インストール先を変更する必要あり。

コマンド例:

RS232CDiskBios thexder.d77 2 -install 0040

(非公式対応)MAGUS (ソフトプロ) [実機AV40]

FC00~FCFFはMAGUSがスタックとして使うのでインストール先を変更する必要あり。

コマンド例:

RS232CDiskBios magus.d77 2 -install 0040

(非公式対応)A列車で行こう (アートディンク) [実機AV40]

起動中にメインCPUのRAMをほぼ全域使ってしまうので、Disk BAISCのエラーメッセージ領域をつぶしてBIOSフックをインストールしなくてはならないが、IPLがDisk BASICを読み込み中はBIOSフックは別の場所に無いと起動しないので、IPL中とIPL後で別のアドレスにBIOSフックをインストールすることで起動できる。
コマンド例:

RS232CDiskBios magus.d77 2 -install2 7F25

(非公式対応)大戦略FM (システムソフト) [実機AV40]

普通にそのまま起動した。パラメータ不要。

(非公式対応)信長の野望・全国版 (光栄) [実機AV40]

戦争モード突入・終了もできたから多分最後まで行けると思う。

コマンド例:

RS232CDiskBios.exe nobuzen.d77 2 -install DE40 -encoder XOR 1 -ldyFExx -dosmode

技術情報

FM-7のBIOSはフロッピーディスクアクセスのために、RESTORE($08), DWRITE($09), DREAD($0A)の三種類の機能を提供する。F-BASIC 3.0はすべてこの機能を使ってディスクにアクセスする。この3種類の機能をリダイレクトして代わりにRS232C経由でサーバー間でデータの読み書きするように書き換えてやれば、物理的なディスクがなくてもディスクイメージから実機でディスク版プログラムを起動・実行することができる。F-BASICを使わない市販品のプログラムであっても、BIOSを使っているものであればある程度対応できる。

 ただし、リダイレクトプログラムをFM-7のメモリに常駐させたとしても、ディスク上のプログラムが直接BIOSを呼んでしまったのでは意味がないので、セクタデータを送り込むサーバー側はBIOSコールしていると思われる部分を見つけるとリダイレクトプログラムを呼ぶように書き換えてから送信する必要がある。なお、サーバーがバイナリを書き換えて送信するので、LOADMして同じものをSAVEMしてしまうと、このリダイレクタが同じアドレスに常駐しているときしか実行できないプログラムに変化してしまう可能性があるのでそれはしない方がいい。

具体的には、以下のインストラクションを探して変更する。

JSR [$FBFA]
JMP [$FBFA]
JSR $F17D
JMP $F17D

また、BIOSが内部で使っているRESTORE, DWRITE, DREADのアドレスも公開されているので、以下のインストラクションも変更する必要がある。

JSR $FE02
JMP $FE02
JSR $FE05
JMP $FE05
JSR $FE08
JMP $FE08

LBSR $FExx、LBxx $FExxとしてコールしている場合、そのセクタがメモリ上のどこに読み込まれるのかわからないと変更することができない。URADOSが LBEQ $FE08 を使っていたが、これはURADOSであることを判定して適当に書き換えることで対応している。また、IPLセクタ(Track 0, Side 0, Sector 1)であれば$0100から読み込まれると仮定するとFExxへの差分が計算できるので、これも対応している。

また、プログラムの中には、

LDY #$FE08
JSR ,Y

として呼び出しているものがある。ほとんどの場合はLDY #$FE0x, LDX #$FE0x, LDU #$FE0x (x=02,05,08)をすべて書き換えてしまっても良いが、念のためこの書きかえはサーバーの起動時のオプションでオン・オフを可能にしている。

また、F-BASICは、次のベクター

00DE 7EF17D JMP $F17D

を経由してBIOSを呼ぶので、[$00DF,$00E0]の値もリダイレクト先に変更する。これは、リダイレクタのインストーラから実行する。

もうひとつ問題は、F-BASICの初期化がせっかくインストールしたリダイレクタをクリアしてしまう点。だからF-BASICを起動するときは、最初のIPLとDisk BASIC読み込みのためにリダイレクタをインストールして、その後もう一度F-BASICの初期化後にリダイレクタをインストールする必要がある。これは、サーバーがIPLセクタを送信するときDisk BASICの初期化のコールバックアドレスを変更することで実現できる。F-BASICのIPLは、Disk BASICを読み込み後

0170 8E 6E 00 LDX #$6E00
0173 43 COMA
0174 6E 9F FB FE JMP [$FBFE]

このように、XにDisk BASIC初期化ルーチンのコールバックアドレスをセット、Carry Flagを1にセットしてベクター[$FBFE]にジャンプする。F-BASICはその後基本的な初期化の後、コールバックアドレスにジャンプする。このとき、コールバックアドレス以前のコンベンショナルメモリは初期化されてしまう。インストーラが$00DFにリダイレクタアドレスを書いていたとしてもF-BASICの初期化でリセットされてしまう。

そこで、サーバーはF-BASICのIPLを識別して (LDX #$6E00とJMP [$FBFE]の存在で確認)、LDX #$6E00をリダイレクタインストーラのアドレスに書き換える。当然インストーラは最初のインストール時はTrack 0 Side 0 Sector 1を読み込んでスタックを適当な位置にセットして$0100にジャンプすれば良かったが、2度目のインストールでは$0100にジャンプするとリセット無限ループになってしまう。これを防止するために、リダイレクタのインストーラは最初のインストール時に自身を書き換えて、2度目のインストール後は、Disk BASICの初期化のコールバックにジャンプするように仕掛ける。また、URADOSなども同じ枠組みを使っているが、URADOSの初期化は$4D00、リダイレクタのインストーラは原則$6000で、IPLの最後にLDX #$6000とするとF-BASICの初期化中にURADOSの初期化コードが消えてしまうので、これを防止するために、リダイレクタのインストーラは最初のインストール時に自身を$2000~と$4000~にコピーしておく。コピー先もサーバーから指定してもよかったけど2か所もあれば多分十分。

これによりDisk BASIC、URADOSの起動は可能になった。次の問題はリダイレクタの常駐アドレス。デフォルトでは$FC00~$FC63に常駐するが、プログラムによってはこの領域を使ってしまう。実行したいプログラムが使う領域を避けるため、リダイレクタは好きな場所にインストールできるようになっている。Disk BASICのプログラムなどでは、エラーが出ない限りエラーメッセージは必要ないので、$7F25~に常駐させる方法で、事実上普通のDisk BASICと同じだけもメモリを利用することができる。

しかし、$7F25に常駐させると、Disk BASICのIPLがDisk BASIC本体を読み込み途中にリダイレクタが破壊されてしまう。悪いことにリダイレクタ実行中に破壊されてしまうのでこれでは復活の余地がない。そこで、リダイレクタのインストーラは初回インストール先と二度目インストール先を変更できるようにした。サーバーがインストーラを送り込むとき初回インストール先と二度目インストール先を書き換えて送ることで対応している。二度目のインストール先は -install2 7F25 のようにオプションで指定できる。

ILオプションによるプログラム転送について。F-BASICの文字列は、例えばA$という変数は、

[VARPTR(A$)]   1バイト 文字数
[VARPTR(A$)+1] 2バイト 文字列の最初の文字の格納アドレス

として記録されている。仮にバイナリプログラムを文字列としてFM-7に送り込んだ場合、ちょうど0x7Eバイト (126バイト)の文字列にしておくと、0x7Eは6809のJMP命令なので、EXEC VARPTR(A$) でプログラムにジャンプさせることができる。

問題は、F-BASICのINPUT #, LINE INPUT #命令はどちらも0x0Dが文字列の終端と解釈するし、それ以外の0x20未満のバイトはすべて無視してしまう。そこで、サーバーは0x20をエスケープとして、0x20以下のバイトxは、0x20, COM(x)として2バイトにして送り出す。0x7Eバイトに足りない分は'0'で埋める。送り込むプログラムの先頭部分にデコーダを書いて、デコーダ部分はすべて符号なしで0x20より大きな値のインストラクションだけで書く。これはちょっとトリックが必要だった。例えば、LDA #2と書くと0x86 0x02というコードが発生するので、2バイト目を文字として送信できない。そこで、CLRA INCA INCA または LDA #2 NEGA とする。また、LEAX LOADER_START,PCRとすると、オフセット部分で0x20以下が発生するので、LEAX LOADER_START+$2F2F,PCRとして、後から LEAX -$2F2F,Xとしてつじつまを合わせる。BNE NO_ESCAPEでオフセット2バイトのジャンプが発生したのでその部分は仮に別の箇所にBNEとしておいてあとからオフセットに2を書き込むなど。

この方法で、サーバーからILコマンドをタイプするとLINE INPUT #で待っているFM-7に文字列としてプログラムを送信。FM-7側ではEXEC VARPTR(A$)でプログラムにジャンプ、その先頭部分で後半部分をデコード、デコードされた後半部分はサーバーにバイナリインストーラ送信要求コマンド"YAMAKAWA"を送信する。それを受けたサーバーはバイナリで256バイトのリダイレクタインストーラをFM-7に送信。FM-7はそれを0x6000からに展開して、インストーラにジャンプ。インストーラから再起動する。

Comments are welcome.  Send E-Mail to: 

Back to http://www.ysflight.com