DOORmk2/(7)付録
Last-modified: 2010-06-16 (水) 15:19:32 (5276d)
付録というか蛇足 †
- ディスク版ローダの自作マシン語部分の解説は、内容的には重複する上に、枝葉の話で本筋から離れてもいけないので、ここにまとめて記載した。あとで思いついたP6関連のTipsも書き留めていきたいと思う。
- 基本的には、【disp_title】【start1】【start2】【start3】【start4】の5つである。
- なお、逆アセンブルリストには NOP(00h) が多くて見苦しいが、これはハンド・ドアセンブルしているためで、後で修正や追加したりする時のダミーと言うことでご了解を。また、ラベルも付いていないので見にくいが、まぁ、よしなにご判読を(^^;)
【disp_Title】の解説 †
============================ 【Disp_Title】 ・グラフィックタイトル表示処理 &hC000-&hC079:メインルーチン &hC080-&hC08F:ワークエリア ============================= C000 010020 LD BC,2000h C003 0000000000 NOP C008 2A80C0 LD HL,(C080h) C00B CD8DFE CALL FE8Dh C00E 23 INC HL C00F 23 INC HL C010 2280C0 LD (C080h),HL C013 00 NOP C014 2A82C0 LD HL,(C082h) C017 77 LD (HL),A C018 23 INC HL C019 23 INC HL C01A 2282C0 LD (C082h),HL C01D 000000 NOP C020 2A84C0 LD HL,(C084h) C023 CD8DFE CALL FE8Dh C026 23 INC HL C027 23 INC HL C028 2284C0 LD (C084h),HL C02B 00 NOP C02C 2A86C0 LD HL,(C086h) C02F 77 LD (HL),A C030 23 INC HL C031 23 INC HL C032 2286C0 LD (C086h),HL C035 000000 NOP C038 2A88C0 LD HL,(C088h) C03B CD8DFE CALL FE8Dh C03E 2B DEC HL C03F 2B DEC HL C040 2288C0 LD (C088h),HL C043 00 NOP C044 2A8AC0 LD HL,(C08Ah) C047 77 LD (HL),A C048 2B DEC HL C049 2B DEC HL C04A 228AC0 LD (C08Ah),HL C04D 000000 NOP C050 2A8CC0 LD HL,(C08Ch) C053 CD8DFE CALL FE8Dh C056 2B DEC HL C057 2B DEC HL C058 228CC0 LD (C08Ch),HL C05B 00 NOP C05C 2A8EC0 LD HL,(C08Eh) C05F 77 LD (HL),A C060 2B DEC HL C061 2B DEC HL C062 228EC0 LD (C08Eh),HL C065 000000 NOP C068 110002 LD DE,0200h C06B 1B DEC DE C06C 7A LD A,D C06D B3 OR E C06E C26BC0 JP NZ,C06Bh C071 00 NOP C072 0B DEC BC C073 0B DEC BC C074 78 LD A,B C075 B1 OR C C076 C208C0 JP NZ,C008h C079 C9 RET ------------------- C080 0040000000600020 C088 FF5FFF1FFF7FFF3F
- これは、グラフィックタイトルを描画するルーチンである。いったんPage2(4000h-7FFFh)にロードしたデータを1バイトずつPage3(0000h~3FFFFh)に分散転送するもの。
- regBCはカウンターとして使用している。初期値として2000h を格納。処理の最後に 減算処理を2回するので、実質1,000h回のループ処理であるが、4基点のデータ転送だから、トータル 4,000hバイトの処理となり、V-RAM容量と勘定が合うはず。
- [C080h-C08Fh]は、転送元と転送先のGV-RAMアドレス値を管理するデータエリアとして使用
C080h-C08Fh 16バイト分 (2バイト×4基点×元先) C080 0040:転送元基点① 4000h C082 0000:転送先基点① 0000h C084 0060:転送元基点② 6000h C086 2000:転送先基点② 2000h ------------------ C088 FF5F:転送元基点③ 5FFFh C08A FF1F:転送先基点③ 1FFFh C08C FF7F:転送元基点④ 7FFFh C08E FF3F:転送先基点④ 3FFFh
- [CALL FE8Dh] は、RAMで LD A,(HL) を行うBasicROM内サブルーチンである。Page2-3のアドレス領域(0000h-7FFFh)は、BasicROMとの重複するエリアであり、このエリアのメモリーデータを読み取る場合はRAM側であることを指示する必要がある。その指定を簡単に行うためにBasicルーチンを利用している。逆に、書き込む際は、無条件にRAM側になるため、処理は不要である。
- 転送元アドレスの値をregAに読み込み、転送先アドレスに書き込んで、それぞれのアドレスアイアイを2バイトずつ加算(もしくは減算)して格納する。
- [C068h~C079h]は描画スピードの調整するための処理である。4バイト分転送(描画)する度に、200回の減算処理ループをまわしている。ところで、これは何妙程度の時間稼ぎになっているのだろう?
【start1】の解説 †
- 【start1】では、BasicROMを直接CALLする形で、BLOADと画面の切替処理を行っている。
============================ 【start1】 ・BasicROMを直接CALLして、BLOAD処理と画面の切替 &hE0A0-&hE0BA:メインルーチン &hE0D0-&hE0EF:文字列(ファイル名データ格納エリア) ============================ E0A0 21D0E0 LD HL,E0D0h E0A3 CDC0E0 CALL E0C0h E0A6 0000 NOP E0A8 3E01 LD A,01h E0AA CDED13 CALL 13EDh E0AD 21E0E0 LD HL,E0E0h E0B0 CDC0E0 CALL E0C0h E0B3 3E02 LD A,02h E0B5 CDED13 CALL 13EDh E0B8 C380E0 JP E080h E0BB 0000000000 NOP E0C0 CD3A51 CALL 513Ah E0C3 DD360300 LD (IX+3),00h E0C7 DD361901 LD (IX+25),01h E0CB CD465F CALL 5F46h E0CE C9 RET ------------------- E0D0 22446F6F724D33505247220000000000 :"DoorM3PRG" E0E0 22446F6F724D30434852000000000000 :"DoorM0CHR
- それぞれの詳細を説明する
BLOADのROM内ルーチン利用方法 †
- BLOAD処理は、E090h~にサブルーチンとしてまとめてある。CALLするBasicROMは2つ。
- [CALL 513Ah]はディスクのファイル名のセット。 regHLにファイル名文字列の先頭文字( " ダブルコーテーションマーク)のアドレスをセットしてCALLするだけ。ファイル名の拡張子区切り「.」や最後の「”」は不要
- [CALL 5F46h]がBLOAD処理。主なパラメータは、
(IX+3):BLOADフラグ 00h:Rオプションなし (IX+25):BLOADフラグ 01h:アドレス指定なし
表示画面の切替にROM内ルーチン利用 †
- [CALL 13EDh]でSCREEN第3パラメータ値を設定するもので、regA に設定値(パラメータ値-1)をセットして、CALLする。
- すなわち、"DoorM0.PRG"のBLOAD中は、そのままPage3(グラフィック画面)を表示し、 "DoorM0.CHR"のBLOAD直前に、表示画面をPage2(テキスト)に切替えている。
- 2つのファイルをBLOADするが、後者はGV-RAM領域のロードされるので、その前にPage2(テキスト画面)に切り替えている。実は、ロード後に再度Page3に切替えている。この時の表示画面は一部崩れているのだが、ほぼ瞬時にメインプログラム起動まで進むので、見た目は全く問題ない。
【start2】の解説 †
============================ 【start2】&hE080-&hE09C ・BasicROMを直接CALLして、BGM停止 ============================ E080 CD90E0 CALL E090h E083 CDB31B CALL 1BB3h E086 0000 NOP E088 C300E0 JP E000h E08B 0000000000 NOP E090 F3 DI E091 3E74 LD A,74h E093 3206FA LD (FA06h),A E096 3E0F LD A,0Fh E098 3207FA LD (FA07h),A E09B FB EI E09C C9 RET
- [FA00h-FA17h]はシステムのワークエリアで、割込み用テーブルがある。個々を直接操作しているが、実際はBasicROMのルーチンにリンクしている。
- [FA06h:DEFW 0F74h]は、2msecタイマ割込みで、TIMEのカウントやカーソル点滅、PLAYの発生処理とあるが、詳細は不明。同じく[FA07h:DEFW] も?
- [1BB3h]は、PLAY用のバッファをクリアし、PSGの音を止める
- BGMを止めるための処理を記述したものだが、たぶん、オリジナルのIPLの処理をパクッたものだと思われる。
【start3】の解説 †
============================ 【start3】&hE000-&hE041 ・無敵化等のパッチ処理 ============================ E000 F3 DI E001 3EDD LD A,DDh E003 D3F0 OUT (F0h),A E005 D3F1 OUT (F1h),A E007 3E55 LD A,55h E009 D3F2 OUT (F2h),A E00B 3EFF LD A,FFh E00D ED47 LD I,A E00F 310000 LD SP,0000h E012 000000000000 NOP E018 3E3D LD A,3Dh :無敵化 E01A 329B57 LD (579Bh),A E01D 000000 NOP E020 3E23 LD A,23h :開始面数の変更① E022 325757 LD (5757h),A E025 000000 NOP E028 3E09 LD A,09h E02A 325957 LD (5759h),A E02D 000000 NOP E030 3E23 LD A,23h :開始面数の変更② E032 326257 LD (5762h),A E035 000000 NOP E038 3E27 LD A,27h E03A 326F57 LD (576Fh),A E03D 000000 NOP E040 C3004F JP 4F00h
- 例によって、NOP(00h)が多いが、まず前半はポート操作によるメモリーブロックの指定。このあたりから、いよいよBasicROMとはおさらばだ。
- [ポートF0h,F1h]は、メモリリード時のメモリブロック指定である。
F0h 下位4bit 0000h-3FFFhを指定 上位4bit 4000h-7FFFhを指定 F1h 下位4bit 8000h-BFFFhを指定 上位4bit C000h-FFFFhを指定 値はすべて0Dhなので、RAM1(内部RAM)の指定となる - [ポートF2h]は、メモリライト時のメモリブロック指定 2bitごとにメモリ範囲を指定(0000h/4000h/8000h/C000h) 指定値は55h=01/01/01/01 すべてRAM1(内部RAM) つまり、READ&WRITEとも、ALL RAMで動作する形になる。
- 後半は、無敵化等のパッチデータ処理である。メインプログラム("DooRM3.PRG")を全部で5箇所書き換えるようになっているが、Basicと対照してみれば分かるとおり、実際に変更しているのはコメントのある3個所だけ。(残り2個所は結果的に不必要だったのだが、消さずに残っただけ ^^;)
【無敵化】メインプログラム(579Bh)の値を 3Dh(DEC A)→A7h(AND A)変更 850 IF K$="Y" OR K$="y" THEN POKE&HE019,&HA7 --- E018 3E3D LD A,3Dh :無敵化 E01A 329B57 LD (579Bh),A 【開始面数の変更①】メインプログラム(5757h)の値を23h→01hに変更 930 POKE&hE021,1 --- E020 3E23 LD A,23h E022 325757 LD (5757h),A 【開始面数の変更②】メインプログラム(5757h)の値を23h→(N-1)に変更 950 POKE&hE031,N-1 --- E030 3E23 LD A,23h E032 326257 LD (5762h),A
- ここに、セットされているデータ、はデフォルト値(非無敵化)だが、最初のBasicの隠しメニュー画面の入力に対応してデータが書き換えられている。
- 最後に、JP 4F00h でゲームスタートへの最終処理となる
【start4】の解説 †
============================ 【start4】&h4F00-&h4F16 ・"DoorM0.CHR"のデータをブロック転送 ・画面モードの変更と割込み禁止処理 ============================ 4F00 F3 DI 4F01 21003C LD HL,2000h 4F04 110078 LD DE,E000h 4F07 010030 LD BC,1F00h 4F0A EDB0 LDIR 4F0C 3E08 LD A,08h 4F0E D3C1 OUT (C1h),A 4F10 3EC7 LD A,C7h 4F12 D3F3 OUT (F3h),A 4F14 C39D2A JP 559Dh
- まず、GV-RAMの2000h~に仮にロードしておいた”DoorM0.CHR"を、本来のアドレスE000h~に転送する。もう、BGMは停止したし、Basicシステムにも依存していない環境なので、ワークエリアはつぶれるが問題はない。
- [ポート C1h]は、CRTコントローラモードの設定で、08hで15色グラフィックモードを指定している。
- [ポート F3h]は、割り込み処理の設定で、C7hで完全に割込み禁止となる。ゲームが始まったら最後、本体をリセットするしかなく手はなくなる。
- ゲーム本体のスタートアドレス[559Dh]にジャンプして、ディスク版ローダはその任務を終了する。