- 5.25"FDの2DをDMA転送で使用
- BIOSワークの未公開フラグを使用してFDC-GVRAM間を直接転送
- BIOSワークに展開されたR/Wルーチンの書き換え
- BIOSの変な所を呼び出している
HuBASIC, turbo CP/MでSCSIが使えるようになってからも、全く動作せずハングアップしたり謎のエラーが出たりするソフトがひとつだけ存在していて、使わないソフトだったのでずっと放置していました。
その動作しなかったシャープ純正ソフトは"ユーザー辞書確保.Uty"です。
大した事をしてなさそうで、いろいろ際どい事をやっているソフトだったわけです。
調べたところ、動かない原因は次の2つ。
- BIOSの変な所を呼び出している
- BIOSワークに展開されたR/Wルーチンの書き換え
まともなエントリではない所を呼び出されてもいいように、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 件のコメント:
コメントを投稿