DOORmk2/(4)マシン語の切り出し のバックアップ(No.2)



マシン語ファイルを切り出す

  • テープの構成やデータのメモリ配置は何とか把握できたのだが、これを切り出す作業にかかるところで頭を抱えることになる。
  • テープのマシン語が大きすぎて、一度に本体メモリーでは扱えない、さて、どうしよう??
  • つまり、料理する魚が大きすぎて、まな板におけない。いや、ギリギリでのっかるのだが、裁いたり、切り身を置く余裕がない。いや、包丁を置く場所がないというべきか(^^;)

ディスク化へのハードル

  • 通常のディスク化作業といえば、オリジナルのIPLを動作させ、テープを全部読み込んでメモリー上に落とした後に、Basicに復帰してマシン語ファイルとして保存していく、いわば「On Memory」処理とでも言うべきものである。
  • ところが、今回のマシン語ファイルは、64KBのRAM領域をほぼ食いつぶしてしまう程に莫大であり、テープから読み込んでデータをメモリー上に展開してしまうと、もうBasicに戻れない。つまり、手も足も出なくなるわけだ。
  • 実際に何度かオンメモリーでの切り出しもトライしてみた。といっても、そもそもマシン語ローダが起動した瞬間からBasicを完全に無視して動いているのであり、リセットする以外にない。リセットすれば、Basic制御は可能となるが、当然メモリー上のデータを完全に残すことはできなくなるというジレンマだ。

まずは、テープ自体を分割して扱えるように!

  • そこで、テープのマシン語全体を一気にロードすることはあきらめる。前後に大きく2分割して読み込むことにする。そして、IPL-Mainの解析で把握した全体構成に沿ってマシン語データを要素ごとに分離保存していくことにした。
    1. 前半:タイトルデータ部 (一部キャラデータが混在)まで
    2. 後半:キャラクタ・面データやプログラム本体など残り全部
  • 前半部の切り出しは、テープ上のデータを頭から読み取って、そのままフリーエリアのメモリ上にベタッとセットすればよい。切れ目に印はないが、テープカウンタを手がかりに、少し長めに流して止めれば何とかなる。
  • 使ったのはP6用コピーツール『SCP2』で、これはテープから読んだプログラムやデータをすべてメモリー上に配置してから、テープに保存し直すもので、ダブルカセットでダビングするより完全なディジタルコピーが取れた。
  • データは、メモリー0000hから順に置かれるので、5000hまでをBSAVE保存しておけば、ひとまず仕込みは終わる。
  • 問題は後半部だ。途中から読み込みを開始するのは、コピーツールにはない機能だ。 このため、他のマシン語IPL等を参考にして、独自の「読み飛ばしLoader」なるものをマシン語でを作ってみる。コピーツールと同様に、5001hバイト目からメモリー0000h~に順番に配置するようにした。 &ref(): File not found: "11tape_reader.txt" at page "DOORmk2/(4)マシン語の切り出し";
  • これで、後半部(5000hバイト目から)がベタ読みでき、残りの仕込が完了した。いよいよ、2つのブツ切りを少しずつ裁いていくことになる。
  • 読み飛ばしツールを作った後に気が付いたのだが、これはドアドアテープの「万能」切出しナイフみたいなものだ。テープの構成さえ分かっていれば、任意の範囲だけをメモリーに取り出せるのだ。必要ならアドレス降順に並べる指定も可能だし。我ながら、感心してしまった(^^;)
  • また余談になるが、この自作ツールでオリジナルテープを読むと、かなりの頻度でTR(読み取り)エラーが発生して切り出しが頓挫した。これにはさんざん悩んでしまった、自分の作ったマシン語の出来がよくないのかと。原因は、たぶん、テープ制御にBIOS-ROMルーチンを使っているためだと思う。独自読み取りルーチンとの微妙な相性の違いみたいなものではなかろうか。その証拠に、コピーツール「SCP2」でダビングしたテープを使ったところ、一発で読み取りに成功するようになった。
  • さて、実際の作業手順を整理しておくと、
    1. コピーツールや自作の「読み飛ばし(切り出し)」ツールを使って、テープ上のデータの必要な部分を読み取って、フリーエリアのメモリ上にベタッとセットする。この段階でフロッピーに仮保存してしまえば、テープ操作はもう不要になる。手間もかからず、後の調整作業は楽になる。
    2. 本来のメモリーアドレスに配置し直す。
    3. BSAVEでフロッピーに保存する。これが、目的のファイルだ!
  • ただ、Basic上では実アドレスに配置できないものもあるし、まぜこぜのデータもあるので、そのへんの小骨の処理が、なかなか頭の痛いところではある。
  • 続いては、そうした工夫の始まりである。

前半部:タイトルデータ等の分離

  • 前半部のメインはタイトルデータだが、フローチャートで解説にも書いたように、グラフィックタイトルは、テープを読み込みながら画面上下から縦帯状に表示する複雑な処理を行っている。さらに驚きは、それ以外にもキャラクタデータとおぼしきものが混在していることだ。
  • データを5バイト単位で、以下のアドレスに順次振り分けているのだ。
     ①FEFFh→EF00h(サイズ 1000h)
     ②0000h(→1FFFhに向かって、2バイト毎に) (サイズ 1000h)
     ③1FFFh(→0000hに向かって、2バイト毎に) (サイズ 1000h)
     ④2000h(→3FFFhに向かって、2バイト毎に) (サイズ 1000h)
     ⑤3FFFFh(→2000hに向かって、2バイト毎に) (サイズ 1000h)
  • ②~⑤がグラフィックデータだが、内訳として②③はアトリビュートデータで、④⑤が実データである。これが、1バイトずつV-RAMにロードされていく。しかも、セットアドレスは2バイト毎シフトするという複雑さ!
  • 実際の表示としては、画面の左下と右上からスキャンするようにタイトル画像が現れてくる。ただ、V-RAMアドレスは2バイト毎なので、縦じまの隙間が空いていく形になるがが、最後は双方から互いに埋め合う形で全画面が完成する。
  • さらに、その合間に①が1バイトずつロードされているわけだ。つまり、5バイト単位で、セットアドレス①~⑤に順次振り分けているのだ。
  • この分離用のプログラムをBasicで書いてみたが、難なく成功。元の構成が分かっていれば何とかなるものだ。  &ref(): File not found: "12titledata_cutter.txt" at page "DOORmk2/(4)マシン語の切り出し";
  • タイトル読み込み完了後のフルスクリーン表示状態では 0000h~3FFFFh のV-RAM領域に配置される。そのままBsaveすれば、②~⑤がまるまるタイトルデータファイルとして取り出せる。
  • 問題は ①混在するキャラクタデータ(FEFFh~)の方だ。実アドレスに配置すると、ここはそもそもBasicの管理エリアだから、システムは暴走してしまう。このため、いったん安全なフリーエリアに落として保存しておく必要がある。仮のSetAddとしては、取りあえずは分かりやすくDF00h~EEFFhなどとしてファイル化しておく。Loadするときは、実行直前に実アドレスへ転送する形をとることにしておこう。このファイルの置き場所については最後まで悩まされることになるのだが、その話はまた。

後半部:面データ等とメインプログラムの分離

  • 後半部も同じように、頭から一つずつ処理していくことにする。が、やはりでかすぎるのである。ダンプファイルを先頭から大きく3枚にブツ切りにしておく。
  • IPL-Mainの中でも進行状況をセットアドレスで何度かチェックしている箇所があるので、そのアドレス値を切れ目にしてファイルを分割し、その後、個々に実アドレスへの再配置や分離作業を行うことにする。ここで、さっきの自作「読み飛ばしツール」が大活躍する。

キャラクタデータ

  • まずは、先頭のキャラクタデータから。アドレスEEFFh~B220Hhにセットされる部分。これは実アドレスに読み込む際に、テープとは逆順に高位アドレスから配置するだけの問題であり、特に難点はない。「読み飛ばしツール」のパラメータを変更して「範囲指定切出し&逆配置ツール」と使うだけで一発だ。
  • EEFFhから降順でメモリーにセットしてBSAVEするだけ。

面データの分離

  • 続く面データは面倒だ。テープ上のデータ並びがいかにも複雑。なんと、前半(1-50)面と後半(51-100)面の各面が交互に1バイトずつ格納されているのだ。
  • 実際のゲーム時はメニューで初心者向けの前50面か上級者向けの後50面を選ぶようになっており、指定の50面分だけをメモリー上にロード(セットアドレス A220h~B21Fh)する。本来のサイズは1000hなのだが、テープ上のサイズは2倍の2000hとなっているのである。
  • このため、例の「切り出しナイフ」でテープから読み込む際のセットアドレスを9220h~B21Fhとしてまとめてベタ読み込みして、あとで分離プログラムを作って前半と後半の50面ずつに分けて保存することにする。これもBasicで何とか処理できた。  &ref(): File not found: "13mendata_cutter.txt" at page "DOORmk2/(4)マシン語の切り出し";

Main Program

  • これも、同じ理屈で、逆順に実アドレスに並べ替えるだけ。自作「範囲指定切出し&逆配置ツール」のセットアドレス等を少し直すだけで、簡単にいく。
  • これをそのまま実アドレスでBSAVEすれば、メインプログラム部のバイナリーファイルが取れることになる。

BGMルーチンの切り出し

  • 話は前後するが、マシン語のLoading中に、凝ったタイトルを表示しながら、かなり長いBGMが流れている。
  • BASIC-IPLの解析でも書いたが、このBGMデータとサウンドルーチンは、Basic一体型で読み込まれるマシン語IPLに含まれており、裏RAM(5100h~635Fh)に転送され、最初のマシン語ファイルであるタイトルデータの読み込み処理に先立ってCALL(Entry_Add:55B3h)されている。
  • ディスク化にあたって、このBGMルーチンは何とか残して使いたいのだが、実はいろいろと問題がある。つまり、オリジナルは裏RAM上で動作するもので、Basicとは共存できない。Disk用のLoaderをBasicで作る予定なので、データをロードしている間は動かせない=BGMにならないということ。
  • 何とか表RAMでも動作するようにしたいのだが、それにはBGMルーチンがリロケート可能かどうかが鍵となる。まぁ、その辺はあらためて検討することにして、ひとまずそのままのアドレスでファイル保存しておく。

分離したマシン語ファイルの構成

  • 分離したファイルを整理すると次の表のようになる。  Tape_Files
    1. 実行時のメインファイルは全部で5種6個になる。
    2. Load時のBGMプログラムも抽出しておいた(1個)
  • 以上で、まずはテープからのファイル抽出作業が完了した。

トップ   一覧 単語検索 最終更新   ヘルプ   最終更新のRSS   リンク元