●AVI2ISDがエミュ上で動くようになるまで

━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
 ISDファイルの作り方を覚えて、データを作り始めたある日のこと。

 無圧縮なAVIファイルを実機に持っていくのは時間がかかる事から、
 当初からエミュレータ(EX68)を使っていました。

 ところが AVI2ISD で変換しようとしても「AVIファイルじゃない」と
 怒られてしまう事があるのです。実機にファイルを移してみると問題
 なく動くのに・・・です。

 最初はファイル形式が違うとか、エミュレータ上での問題だろうと、
 深く考えてなかったのですが、ある日、windrv.sys 経由でホストの
 ディスクを使った場合にのみ、この現象が起きるとわかりました。

 不思議なのは、全てのドライブで発生するのではないことです。

 たまたま、ディスク容量が足りなくて他のドライブに移した際に
 ドライブ依存である事に気づいたというわけです。

 しかし、自作のソフトでは別に windrv.sys 経由であろうと何で
 あろうと特に問題は起きないんですよね。そこで、AVI2ISD.x を
 調べてみることにしました。

 泥臭い方法ですが、こんな感じです。

   * AVI2ISD.X を dis.x にかけてソースファイル化
   * 「AVIファイルではありません。」から追ってみる
   * やはりファイルの読み込みに問題がありそうなので、_read 周辺を見る
   * Windows上の成功ドライブ(h:)、失敗ドライブ(k:)に test.avi を用意
   * EX68 を起動し、成功例を DB.X で追っていく
  C>DB.X AVI2ISD.X h:test.avi h:test.isd
 ps _read      --- _read のアドレスを調べる
 $000FAB5E:_read
 b1 fab5e      --- ブレークポイントの設定
 g             --- _read の位置まで実行
 l             --- この位置からリスト表示
 b2 xxxxx      --- read から戻る位置にブレークポイント設定
 d xxxxx       --- SP位置からダンプして、スタックに詰まれた引数を得る
 d yyyyy       --- 引数の読み込み領域のアドレスからダンプ
 g             --- _read から戻る位置まで実行
 d yyyyy       --- 何が読み込まれたかを確認
 ...           --- 繰り返し

   * 同様に、失敗例を DB.X で追っていく
 C>DB.X AVI2ISD.X h:test.avi h:test.isd
 ps _read
 $000FAB5E:_read
 b1 fab5e
 ... 
   * 両者を比較したところ、読み込み結果が異なる事がわかった。
   * 再度、失敗例で _read の位置からステップ実行して見ていく。
   * 結果、fab7e の tst.l $0c(a0,d0.l) が 0 なら正常, 1 なら異常と確認
   * これは __fddb 内 だということで…あれ、これ isatty() の判定フラグ?
   * ファイルオープン時点で問題がありそうなので、__open 周りを調べる
 C>DB.X AVI2ISD.X h:test.avi h:test.isd
 ps _open      --- __open のアドレスを調べる
 $000FA958:__open
 b1 fa958      --- ブレークポイントの設定
 g             --- __open の位置まで実行
 l             --- この位置からリスト表示
 ...
   * 順に見ていくと…ドライブのデバイス情報が怪しい…
 $000FA984  move.w  d3,-(a7)
 $000FA986  clr.w   -(a7)
 $000FA988  DOS     __IOCTRL
 $000FA98A  addq.w  #4,a7
 $000FA98C  move.l  d0,($0010,a3)
 
   (中略)
 
 $000FA9CC  moveq.l #$00,d1
 
 $000FA9CE  move.l  ($0010,a3),d0
 $000FA9D2  and.l   #$00008004,d0  <-- chk1: bit15 と bit2 が落ちてるか?
 $000FA9D8  beq	    $000FA9E4
 
 $000FA9DA  moveq.l  #$03,d0
 $000FA9DC  and.l  ($0010,a3),d0   <-- chk2: bit0,1 が落ちてるか?
 $000FA9E0  beq     $000FA9E4
 
 $000FA9E2  moveq.l  #$01,d1

 $000FA9E4  move.l   d1,($000c,a3)   <-- ここで値を書き込んでいる

   * $FA98C にブレークポイントを設定し、d0 の値を調べると…
 b fa98c    (止まる度に d0の値 をチェック)
        NG例    OK例    内蔵HDD
 1回目  80c1    80c1    80c1
 2回目  80c2    80c2    80c2
 3回目  80c2    80c2    80c2
 4回目  c0c0    c0c0    c0c0
 5回目  80c0    80c0    80c0
 6回目  2027    202a    0002   <--- NG例では、chk1,2 共に流れる値が返ってる
 7回目    -     206a    0042

   * 肝心のデバイス属性の意味(ぷにぐらま〜ずマニュアルより)
 bit15   0:ブロックデバイス  1:キャラクタデバイス
 bit14   0:IOCTRL 不可       1:可能
 bit11   0:特殊 IOCTRL 不可  1:可能
 bit 5   0:COOKED MODE       1:RAW MODE
 bit 3   1:CLOCK   デバイス
 bit 2   1:NUL     デバイス
 bit 1   1:標準出力デバイス
 bit 0   1:標準入力デバイス
 
 (bit0〜5 は bit15 が 1 の場合のみ有効)
 結局のところ、どうも、ドライブのデバイス情報を得た時に、間違って
 キャラクタデバイスと誤認されてしまう事が問題ではないかと思えます。

 細かいことを言えば、bit0〜5は bit15 が 1 の時のみ有効というもので、
 bit15 を見るのはいいですが、bit2 は見なくてもいいんじゃないかなと
 考え、$000FA9D2 のand.l #$00008004,d0 を and.l #$00008000,d0 に
 書き換えてみることにした。

   * 実際のファイルの書き換え

 ジャンプする命令じゃないので、そのまま C0BC 0000 8004 を検索して、
 C0BC 0000 8000 に書き換えてあげます。DB 使って書き換えてみました。
 C>db
 X68k Debugger version 3.00 Copyright 1987-1993 SHARP/Hudson
 Micro Processor Unit:16bit MC68000
 Floating Poing Co Processor:Software emulation.
 -p
 Micro Processor Unit:16bit MC68000
 Floating Poing Co Processor:Software emulation.
 debug program from $000B7A40
 user  program from $000EE4B0
 -r AVI2ISD.X,$100000
 -p
 Micro Processor Unit:16bit MC68000
 Floating Poing Co Processor:Software emulation.
 debug program from $000B7A40
 user  program from $000F0110
               end  $0010D96E
               exec $00100000
 symbol table  from $000EE3C0
 -msw 00100000 0010D96E C0BC 0000 8004 
 0010A902
 -d 0010a902
 -l 0010a902
 -mew 10a906
 0010A906     8004 :8000
 0010A908     670A :.
 -w avi2isdK.x,$100000 $10D96D
 -q
 
 C>fc /b AVI2ISD.X avi2isdK.x
 0000A907: 04 00
 C>
 さて、こうして 1byte 書き換えた avi2isdK.x で、先の NG例 のドライブの
 AVIファイルを試してみたところ・・・Wow! AVIファイルじゃない!なんて
 言われずにちゃんと走ってくれました(^^)

 まぁ、戻ってくるデバイス属性値が変だから仕方ないところではありますが、
 何はともあれ、これでエミュレータ上で、びしばしISD変換できるようになり
 幸せになったのでした。

(EOF)