2018/03/12

SCSIに非対応なソフトへの対応

BIOSを普通に呼び出しているソフトであれば従来のもの(SASI)と同様にほぼ動作するわけですが、中には特殊なソフトウェアもあり、特にシャープ純正にそういった曲者が多くあります。
  • 5.25"FDの2DをDMA転送で使用
  • BIOSワークの未公開フラグを使用してFDC-GVRAM間を直接転送
  • BIOSワークに展開されたR/Wルーチンの書き換え
  • BIOSの変な所を呼び出している
など、公然の裏技というか、メーカーならではのやりたい放題(上の二つは有名ですね

HuBASIC, turbo CP/MでSCSIが使えるようになってからも、全く動作せずハングアップしたり謎のエラーが出たりするソフトがひとつだけ存在していて、使わないソフトだったのでずっと放置していました。

その動作しなかったシャープ純正ソフトは"ユーザー辞書確保.Uty"です。
大した事をしてなさそうで、いろいろ際どい事をやっているソフトだったわけです。

調べたところ、動かない原因は次の2つ。
  1. BIOSの変な所を呼び出している
  2. BIOSワークに展開されたR/Wルーチンの書き換え
BIOSの変な所を呼び出している 」への対応
まともなエントリではない所を呼び出されてもいいように、SCSI BIOS内のアドレスをSASIと同じ配置にする事で対応しました。動かないソフトの方を書き換えてもいいのですが、こういったソフトが他にもある可能性を考えて。

BIOSワークに展開されたR/Wルーチンの書き換え」への対応
書き換えている事は分かっていたのですが、なぜ書き込み処理が終わった後のチェック処理で書き込み失敗と判定されるのか当時分からず、このため放置する事に…

書き換えが行われる、BIOSワークに展開されたSASIのR/Wルーチンは次のようになっています。
F929  06 1E     HDDMAS: LD      B,1EH
F92B  ED 41             OUT     (C),B
F92D  F3                DI
F92E  3E 87             LD      A,87H
F930  01 1F80           LD      BC,1F80H
F933  ED 79             OUT     (C),A
F935  1E 10             LD      E,10H
F937  21 0000           LD      HL,0
F93A  01 0FD1           LD      BC,0FD1H
F93D  ED 78     LF93D:  IN      A,(C)
F93F  E6 1F             AND     1FH
F941  FE 0F             CP      0FH
F943  28 09             JR      Z,LF94E
F945  2B                DEC     HL
F946  7C                LD      A,H
F947  B5                OR      L
F948  20 F3             JR      NZ,LF93D
F94A  1D                DEC     E
F94B  20 F0             JR      NZ,LF93D
F94D  37                SCF
F94E  06 1D     LF94E:  LD      B,1DH
F950  ED 41             OUT     (C),B
F952  FB                EI
F953  C9                RET
ここが、次の内容に書き換えられます。
F929  06 1E     HDDMAS: LD      B,1EH
F92B  ED 41             OUT     (C),B
F92D  F3                DI
F92E  00                NOP
F92F  00                NOP
F930  CD DFD0           CALL    LDFD0
F933  00                NOP
F934  00                NOP
F935  1E 10             LD      E,10H
F937  21 0000           LD      HL,0
F93A  01 0FD1           LD      BC,0FD1H
F93D  ED 78     LF93D:  IN      A,(C)
この書き換えられたところから、次のDMA設定処理が呼び出されます。
DFD0  01 1F80   LDFD0:  LD      BC,1F80H
DFD3  3E 34             LD      A,34H
DFD5  ED 79             OUT     (C),A
DFD7  3E 87             LD      A,87H
DFD9  ED 79             OUT     (C),A
DFDB  C9                RET
BASICプログラム中のでは、次のリストです。
2270 POKE &HDF10,&H28,&H79:MEM$(&HDFD0,12)=HEXCHR$("01801F3E34ED793E87ED79C9")
2280 STOP OFF
2290 MEM$(&HF92E,7)=HEXCHR$("0000CDD0DF0000")
書き換えられた部分から呼び出される DFD0H~では、DMA転送のソースとなるメインメモリ(ポートA)側をアドレス固定に再設定しています。こうすることで、同じデータを大量に書き込む際でも、1バイトのメモリだけ設定すれば済むようになります。

初めはSCSI BIOSに何らかの見落としでレジスタ値の齟齬でもあるのかと考えていたのですが、ようやく「ソース側をアドレス固定」という小細工と、SCSI BIOSで256バイト以外のセクタサイズに対応させた事と、ひじょーに相性が悪い事に気付きました。

なぜ、チェック処理で書き込み失敗と判定されるのかと言うと、SCSI BIOSではセクタサイズ256バイト以外にも対応するために、内部的に1セクタごとの処理に分割し、1セクタ分(256バイト)転送したらメモリ側アドレスに256加算という処理を、指定回数だけ繰り返します。この「内部的にメモリ側のアドレスに256加算」で、256バイト先の全く別のデータを参照してしこれを書き込んでいたため、チェック処理で引っ掛かっていたわけです。

問題となる処理は次のようになっています。
2300 FOR I3=0 TO KAISU
2310 IF SL>=256 THEN SECL=255:SL=SL-SECL ELSE SECL=SL
2320 POKE &HDFFD,SECL,FNX2(REC11),FNX1(REC11)
2330 CALL FDWR
2340 REC11=REC11+SECL
2350 NEXT I3
"KAISU"回のループ中で、"SECL"に処理するセクタ数、"REC11"に開始セクタ番号、そして"CALL FDWR"で書き込み。なので、"CALL FDWR"で1セクタだけ書き込むように変更し、これをSECL"回呼び出すようにします。
2330 FOR A=0 TO SECL-1:POKE &HDFFD,1,FNX2(REC11+A),FNX1(REC11+A):CALL FDWR:NEXT
これで動くようになったわけではありますが、いまさらユーザー辞書とか使わないわけで…音訓変換で十分過ぎる気がします。

0 件のコメント:

コメントを投稿