#navi(DOORmk2)
* ディスク版ローダの詳細 [#ude1e101]
- 残るは、Loaderとしての組立て方の話になるのだが、実は試行錯誤と手直しの連続でもあり、あまり詳しく書いても退屈なだけだ。(もう。十分に退屈な話だったと思うが ^^;)
- 結論から話を進めることにしよう。できあがったDisk版Loader ”ドアドア.503”の解説である。
#contents
** Disk版ローダのBasicプログラム [#q3c4b952]
- 基本的にBasicで書いてある。自作のマシン語Loaderは5つのモジュールに分かれているが、いずれもDATA文による埋込みである。
- プログラムリストは長いので、PDF版を添付する。(開いた場合は、ブラウザの「戻る」ボタンで復帰してください。)&ref(16door503.pdf,,50%,ドアドア_503);
&br;
- これをフローにすると、大体の流れが少し分かりやすくなるかも。&br;
&ref(17diskloader_fc.jpg,,40%,ディスク版ローダ);&br;
- さらに、メモリーマップの変化を参照してもらうと、マシン語Loaderの動作内容に納得してもえるかもしれない。Basicシステムや、用の済んだマシン語Loaderを破壊しながら、データが埋め尽くされて行く様が。&br;
&ref(18diskloader_map.jpg,,60%,ディスク版メモリーマップ);&br;
- 以下は蛇足的に、ディスク版ローダの動作概要とポイントを記録した。さらに、マシン語部分のリストや処理の詳細については、付録を参照。
** 隠しメニューの無敵化処理について [#x3436700]
- 通常は230行のオリジナルの面選択(前半/後半)画面だけであるが、本来の "1" か "2" 以外の "d" のキー入力を受け付けるようになっている。
230 LOCATE 0,5:PRINT"Which game do you want to play,1 or 2?"
- 実際の処理は、800行以降にJUMPして、パッチデータを作成する
。&br;
320 IF A$="d" THEN 800
800 REM ---- secret menu -------
810 CLS:LOCATE1,4:COLOR10:PRINT" << SECRET SELECTION ONLY FOR YOU!! >>"
&ref(19secret.jpg,,60%,隠しメニュー);&br;
- 最終的には本体のメインプログラム”DoorM3.PRG"にパッチを当てるのだが、この段階ではまだBLOADされていない。フロー等にも書いてあるが、start3の機能がパッチ処理であり、これは最初にBasic実行の最初の段階でメモリセットされている。この中にあらかじめパッチデータを埋め込んでおき、ファイルロードが完了してゲーム開始直前の段階になって、メインプログラムにパッチを当てる仕掛けである。
*** 無敵化の設定 [#k74b156a]
- 無敵の場合:主人公「CHUN」がモンスターに接触するとアウトになるのだが、その場合でも「CHUN」の数が減らないようにするもので、メインプログラムの(5798h~)あたりが、その処理個所である。
5798 3A365F LD A,(5F36H)
579B 3D DEC A ★
579C 32365F LD (5F36H),A
- (5F36h)が「CHUN」の現在数を記録しているデータエリアだが、それをregAに読み込んで、★減算処理(DECrement)して、また元のアドレスに格納している。この減算処理をキャンセルしてそのままの値を戻せばよい。NOPでもいいようなものだが、ちょいと格好をつけて、☆AND処理にしてみた。これで値は変化しない。
579B A7 AND A ☆
- この書き換え(3Dh→A7h)用のデータをメモリ上の【start3】のデータ部に仕込んでおけば、start3実行時に、メインプログラムの減算処理部(579Bh)がパッチされる。
- 蛇足ながら、(5F36h)に直接パッチを当てて、CHUNの数を一気に256(FFh)くらいに増やしてしまう手も思いつくのだが、実は、これはうまく行かなかった。どうも、メインプログラムの起動時に初期化している様子なのだが、その処理部がどこにあるのか分からずお手上げ。
*** ゲーム開始面の任意指定を可能にする [#w7639f05]
- プレイ中の面数を記録しているデータエリアは(5F35h)であることがつかめた。しかし、ここにパッチをあてておいても、CHUN数の場合と同じく、メインプログラムが起動する時に初期化してしまうので意味がない。
- メインプログラムの5752h以降にゲーム面の判定ルーチンらしきものがあるのを見つけた。この判定ルーチンは、クリアした後の処理なのだが、まずは、「次の面」が35面か50面になるかどうかをチェックしている。合致した場合、何か別のサブルーチンを呼び出した後に、データエリアに次の面の値を戻している。(これに、どういう意味があるのか、よく分からないのだが ^^;)
- このあたりにパッチをあて、データエリアに戻す時の値を強制的に変更してしまえば、何とかなるのではないかということだ。ただ、この面判定ルーチン自体は、とにかくクリアした後に働くので、ゲーム開始時には有効ではない。
930 POKE&hE021,1
950 POKE&hE031,N-1
- 930行は、判定ルーチンを1面クリア時に必ず実行させるためのパッチ。デフォルト値は23hで、35面かどうかのチェックなのだが、この比較値を01hにしておけば必ず処理が始まることになる。実際に35面クリア時には働かないことになるが、まぁゲーム自体の大勢には影響ないと思われる。(たぶん、「CHUN」数をおまけするとか、その程度だと思うのだが。。。)
- 950行は、現在面数のデータエリアに値を戻す時に、指定面数に変更してしまうためのパッチである。デフォルトは 23hで、同じ値を戻しているだけだが、この値を希望の面数に変更しておけば、それがデータエリアに上書き保存される形になる。なお、パッチの値がN-1となっているが、データエリアに格納されている値が「現在の面数」のためである。
- 従って、 ゲーム開始時は必ず1面から始まる。この1面目クリア後の判定ルーチンで、データエリアを指定の値に変更する処理が働くから、次からは希望の面にジャンプする形になる。
- そのものずばりのパッチ箇所でないのは悔しいが、メインが複雑過ぎて解析がかなわず、この辺で手を打つことに(^^)
- 従って、 ゲーム開始時は必ず1面から始まる。面倒でも、この1面は必ずプレイ&クリアする必要がある。そして、クリア後の判定ルーチンで、データエリアを指定の値に変更する処理が働くので、次は2面ではなく希望の面にジャンプする形になる。
- そのものずばりのパッチ箇所でないのは悔しいが、メインプログラムが複雑で解析がかなわず、この辺で手を打つことに(^^)
** タイトル表示ルーチン [#f4ef2a3c]
- ディスク版のタイトルファイルはテープ版で表示完了したものをファイル化したものである。これを、テープ版のように上下から縞状に表示させるのが目的である。
- ディスクから直接1バイトずつ読み込みながら、GV-RAMメモリー上の分散セットするなんて芸当はできないから、あらかじめ裏画面にロードし終えたものを、表画面に1バイトずつ転送する方法をとった。
- この処理で苦労した点は2つある。ひとつはスタック処理、もうひとつはスピードである。
- データ転送は、最初深く考えずに、regAを介して1バイトずつ裏→表へ転送するループを作成した。転送元と転送先のアドレスをregHLに格納しながらカウンター値を加算したのだが、そのスタックメモリー不足でデータ自体が破壊してしまった。
- 分かりやすく作っただけだったのだが、少しはアルゴリズムのことも考えろという天の声か。つまり、4つの基点アドレスの管理(格納)とシフト処理の仕方が甘かったというわけ。
- 対策というほどのものではないが、アドレス値を管理するために専用のデータエリアを作った。といっても、ルーチン内に転送元と転送先のアドレス値を格納するためのエリアを16バイト(=2バイト×2×4)確保しただけ。そこを経由して4つの基点アドレスのシフトと値保存するだけで解決した。
- 逆に、速くなりすぎて、あっという間に終わってしまった。BGMを楽しむ暇がほとんどないというわけで、急遽スピード調整ルーチンを挿入した。4基点の画像データ転送毎に、200h回分のregデータの減算処理ループを加えた。
** マシン語によるBLAOD [#xf8e24d2]
- 410行からのタイトル画像の表示に続いて、440行で面データ(B$)のBLOAD処理が終わる
410 BLOAD"DoorM4.TI",&H4000
420 SCREEN 3,3,3:EXEC&HC000
430 BLOAD"DoorM1.CHR"
440 BLOAD B$
- ここまではタイトル画面(Page3)を表示のままだが、その後450行でPage2をテキスト画面に変更している。これは、"DoorM3.PRG"をロードするとPage1が破壊されてしまうため、あらかじめPage2のモード変更と切替える準備を行っているものである。GOSUB710でstart4のセットが完了する。
450 SCREEN 1,2,3:CLS:CONSOLE,,0,0:GOSUB710
460 COLOR 12:LOCATE9,15:PRINT "モウ"
462 COLOR 4:LOCATE12,15:PRINT"シバラク オマチクダサイ。
- 470行のEXEC&HE0A0でBasic文は実質最後で、いよいよマシン語【start1-3】が動作を開始する形になる。とはいえ、実は、まだ【satart1】(E0A0h~)の部分は、実質的にBasicROM内ルーチンを使用したBLOAD処理である。
470 EXEC&HE0A0:REM bload & JP start
480 END
- この前後で画面の切替処理(CALL 13EDh)を頻繁に行っている。少し分かりにくいので簡単に説明しておく。まず、”DoorM3.PRG"のBLOAD時は、Page3を表示したままだ。"DoorM0.CHR"をBLOAD先はPage3のエリアなので、直前にPage2に表示画面を切り替える。
- M3とM0のBLOAD処理までは、まだ、実質的にBasicシステムの中で動作している。
** いよいよゲームスタート[#w34738dd]
- マシン語ファイルのBLOADがすべて終わった。いよいよ最後のStepにかかる。
- 【start2】が起動して、以降はBGM停止、ALL-RAMで動作し、BasicROMとはおさばらだ。【start3】の無敵化パッチと続いて、【start4】で”M0”を正規アドレスにブロック転送して、遂にゲームスタート!!
&br;
** 終わった(^^) [#s8748ade]
- 長かった作業も終わった! その記録も完成した! ビバ!! わがP6青春!!
#navi(DOORmk2)