アイテムの拡張はセーブデータをオリジナルと非互換にして拡張する必要と思われるので正直あまり気が進まず、とりあえず今作業ができているところまででテストプレイをちんたらやっているところです。自分の作ったインターフェース改良パッチを当てたいところですが、単体で問題がないことを確認することも兼ねてグッと我慢してオリジナルのままやっていますが、まあ使いづらい。アイテムを渡しても装備してくれないし、いちいちアイテムを使うとウィンドウは閉じちゃうし、ふくろからアイテムを直接実行できないし、全ウィンドウクローズもないのでステータスを見ている途中でウィンドウを閉じれないし。このへんはDQ6 Extendedベースならいくらでもいじれるので(領域もあるし、ウィンドウも新規定義可能なのでやりたい放題)、ゲーム性を変えるパッチを作る暁にはDQ6 IFIMPをベースにDQ3レベルまで持って行きたいなと思うところです(DQ6 IFIMPも細かいところで使い勝手はDQ3オリジナルには及びません)。とはいえ、DQ6はもともと使っているROMの容量がDQ3よりかなり多いので、空き領域はそれほど多くないです。今回いろいろ調子に乗って各固定長のレコードサイズを増やしましたが、残りは可変長のデータ(スプライトグラフィックやらマップ実データ)やプログラムのためにある程度空けておく必要があります。
今回一つの山だと思っていたのは「移動中メッセージをハフマン圧縮を解凍した状態でROMに書き戻し、さらにROM中の移動中メッセージのデコードプログラムも合わせて変更する」点でしたが、意外とあっさり終わってしまいした。ハフマン圧縮を解凍するのはSFCGENEditorのDQ6プラグインですでにできていたので、解凍した状態の文字列をバイナリ変換して本体、インデックスをバイナリファイルに書き出すという作業を行い、ROMの適当な場所に埋め込みます。次にメッセージデコードSRを変更し、ハフマン木を参照せずにそのままデコードするように変えます。この辺はDQ3 Extendedの該当部分を参照し、真似しただけです。メッセージインデックスは$122300-に、メッセージ本体は$123200-に移動してあります。
- SR: $002B69 メッセージインデックスから開始アドレスを取得
002B69 | LDA $5998 | A=$5998 | |
---|---|---|---|
002B6C | AND #$0007 | A&=#$0007 | インデックスは8毎なのでターゲットのメッセージの頭出しの回数を取得 |
002B6F | STA $5A1E | $5A1E=A | |
002B72 | LDA $5998 | A=$5998 | |
002B75 | LSR | A>>1 | |
002B76 | LSR | A>>1 | |
002B77 | LSR | A>>1 | |
002B78 | PHA | Push A | |
002B79 | ASL | A< <1 | |
002B7A | ADC $01,S | A+=(Stack($01)+c) | |
002B7C | TAX | X=A | インデックスの該当位置を決定 |
002B7D | PLA | Pull A | |
002B7E | LDA $D22300,X | A=$122300+X | インデックスの指す開始アドレスを取得 |
002B82 | STA $A0 | DP($A0)=A | |
002B84 | LDA $D22302,X | A=$122302+X | |
002B88 | AND #$00FF | A&=#$00FF | |
002B8B | STA $A2 | DP($A2)=A | |
002B8D | LDA $A0 | A=DP($A0) | |
002B8F | CLC | c=off | |
002B90 | ADC #$3200 | A+=(#$3200+c) | インデックスのアドレスから本体のアドレスを取得 |
002B93 | STA $A0 | DP($A0)=A | |
002B95 | LDA $A2 | A=DP($A2) | |
002B97 | ADC #$00D2 | A+=(#$00D2+c) | |
002B9A | STA $A2 | DP($A2)=A | |
002B9C | LDA $5A1E | A=$5A1E | |
002B9F | BEQ #$12 | if(z==on) goto $002BB3 | |
002BA1 | JSR $2BD4 | SR: $002BD4 | メッセージ1文字読み出し? |
002BA4 | CMP #$00AC | A==#$00AC? | |
002BA7 | BEQ #$05 | if(z==on) goto $002BAE | |
002BA9 | CMP #$00AE | A==#$00AE? | |
002BAC | BNE #$F3 | if(z==off) goto $002BA1 | |
002BAE | DEC $5A1E | $5A1E– | |
002BB1 | BRA #$E9 | goto $002B9C | |
002BB3 | RTS | return |
メッセージのインデックスは8個ごとに設定されているので、ターゲットのメッセージの開始位置を特定するには、8で割った商の位置にあるアドレス(これが直近の8で割り切れるメッセージの開始位置)を取得してから8で割った余りの分だけデコードを繰り返し、区切り文字が出てきたら1カウントするようにしてターゲットのメッセージの位置を特定します。これにより、頭出しのためのデコードにかかる手間は最大6?メッセージ分ということになり、メッセージ表示にかかる時間をある程度の範囲内に収められるということになるようです。
- SR: $002BD4 メッセージ1文字読み出し?
002BD4 | LDA $59AE | A=$59AE | |
---|---|---|---|
002BD7 | CMP #$0001 | A==#$0001? | |
002BDA | BNE #$0F | if(z==off) goto $002BEB | |
002BDC | LDX $59B4 | X=$59B4 | |
002BDF | LDA $59B8,X | A=$59B8+X | |
002BE2 | INX | X++ | |
002BE3 | INX | X++ | |
002BE4 | STX $59B4 | $59B4=X | |
002BE7 | JSR $2C28 | SR: $002C28 | |
002BEA | RTS | return | |
002BEB | LDA $A0 | A=DP($A0) | |
002BED | STA $5BDC | $5BDC=A | |
002BF0 | LDA $A2 | A=DP($A2) | |
002BF2 | STA $5BDE | $5BDE=A | |
002BF5 | LDA $A0 | A=$(DP[$A0]) | |
002BF7 | INC $A0 | DP($A0)++ | |
002BF9 | BNE #$02 | if(z==off) goto $002BFD | |
002BFB | INC $A2 | DP($A2)++ | |
002BFD | INC $A0 | DP($A0)++ | |
002BFF | BNE #$02 | if(z==off) goto $002C03 | |
002C01 | INC $A2 | DP($A2)++ | |
002C03 | RTS | return |
このSRは現在アドレスをインクリメントしながらメッセージを1文字ずつ読みだして返しているようです。このSRをコールしているSRで頭出しの判断をしているようです。ハフマン木の参照がなくなった分シンプルになっています。正直これだけの変更でなんで未圧縮のデータが読めているのかいまいち不明ですが、オリジナルのDQ3とDQ3 Extendedの関連部分を比較する限り、他に変更している箇所は見当たりません。気持ち悪いですが、とりあえず解析は後回しにします。
コメント