スプライトがらみの作業が終わったのでまた無限回廊フロアを追加する作業に戻っているのですが、大体の理屈はわかったものの、その理屈に則って実装しても動作してくれません。まだ何か見逃している部分があると思うのですが見つからず。座標系のアドレスってあまり解明されてないので解析するのが結構苦痛。
DQ3はシリーズ中で珍しく獲得経験値を山分けするようになっています。その兼ね合いでモンスターに設定されている経験値は通常の4倍になっているわけですが、このため一人当たり獲得できる経験値の最大は65535/4=16384です。クリア後のダンジョンが経験値稼ぎの場になっておらず、結局補給の問題もあり、リムルダールが稼ぎやすい場なのはつまらないなーということで、クリア後のダンジョンにメタルキングを導入することにしました。メタルキングの経験値はお約束の一人当たり30000ちょい、トータル120000なのですが、当然ながらモンスター情報に設定できる経験値の上限(65535)を超えてしまいます。というわけで、メタルキングに限っては、モンスター情報には一人当たりの経験値をセットしておき、戦闘中の経験値加算時にモンスターIDをみてメタルキングならば4倍する、という処理を加えることにします。まあいわば特例です。同様に、獲得ゴールドが同じのおどるほうせき、ゴールドマンに対してすごろく中の不均衡を是正するため(数が多く出現でき逃げにくいおどるほうせきと戦った方が多くゴールドを獲得できるという問題)、おどるほうせきの獲得ゴールドを700Gに落とし、逆にゴールドマンは2046Gに変更します(変更前は両方共1023G)。おどるほうせきに関してはただ単にデータ中の値を変えるだけで問題ないのですが、ゴールドマンについては、モンスター情報の獲得ゴールドは10ビットで最大1023なので、メタルキング同様モンスターIDをみてゴールド加算時に2倍する、という処理を追加します。処理対象が局所的なので変更自体は気楽に行えます(多分)。ところで、初めてFC版DQ3をやったとき、「ゴールドマンが出る」と聞いたときには、あのゴーレムタイプのやつが出るのかとわくわくしたんですが、結局ようがんまじんの色違いということでがっかりしたのを覚えてます。可能ならDQ7から輸入したいですね。
(5/20米欄の指摘により大幅変更)
- SR: $02B1DC 獲得経験値・ゴールド加算
略 | |||
---|---|---|---|
02B216 | JSR $E7A9 | SR: $02E7A9 | 戦闘中経験値計算(メタルキングなら経験値4倍) |
02B219 | NOP | ||
02B21A | NOP | ||
02B21B | CLC | c=off | |
02B21C | LDA $23DC | A=$23DC | |
02B21F | ADC $00 | A+=(DP($00)+c) | |
02B221 | STA $23DC | $23DC=A | |
02B224 | LDA $23DE | A=$23DE | |
02B227 | ADC $02 | A+=(DP($02)+c) | |
02B229 | STA $23DE | $23DE=A | |
略 | |||
02B247 | JSR $E983 | SR: $02E983 | 戦闘中ゴールド加算(ゴールドマンは設定値の2倍) |
02B24A-E | NOP |
- SR: $02E7A9 戦闘中経験値計算(メタルキングなら経験値4倍)(新SR)
02E7A9 | JSL $C2CC69 | SR: $02CC69 引数:1#$0003 | モンスター情報から経験値を取得 |
---|---|---|---|
02E7AF | STZ $02 | DP($02)=#$00 | |
02E7B1 | CPX #$00BB | X==#$00BB? | モンスターIDがメタルキングか |
02E7B4 | BNE #$06 | if(z==off) goto $02E7BC | |
02E7B6 | ASL | A<<1 | |
02E7B7 | ROL $02 | DP($02)<<1 | |
02E7B9 | ASL | A<<1 | |
02E7BA | ROL $02 | DP($02)<<1 | |
02E7BC | STA $00 | DP($00)=A | |
02E7BE | RTS | return |
- SR: $02E983 戦闘中ゴールド加算(ゴールドマンは設定値の2倍)(新SR)
02E983 | JSL $C2CC8B | SR: $02CC8B 引数:1#$0005 引数:2#$03FF | モンスター情報からゴールドを取得 |
---|---|---|---|
02E98B | CPX #$0072 | X==#$0072? | モンスターIDがゴールドマンか |
02E98E | BNE #$01 | if(z==off) goto $02E991 | |
02E990 | ASL | A<<1 | |
02E991 | RTS | return |
ゴールドの場合はゴールドマンでも2バイトを超えないので扱いが楽ですが、経験値の場合は扱う値が3バイトにまたがるので、処理を明確に分けるためにSRの頭で特例かどうかを判断しているので若干冗長になっています。もうちょっとすっきり書こうとしたらできるかもしれません。
コメント
SEP #$20 : LDA $23DE : ADC $02 : STA $23DE : REP #$20
はAの上位バイトの値が残るのでちょっと危険な気がします
($00-$03[$00199A-$00199D?]が変更可能であれば)以下のような
感じでどうでしょうか
org $C2B216
JSR $E7A9
NOP
NOP
CLC
LDA $23DC
ADC $00
STA $23DC
LDA $23DE
ADC $02
org $C2E7A9
JSL $C2CC69 : dw $0003
STZ $02
CPX #$00BB
BNE $06
ASL
ROL $02
ASL
ROL $02
STA $00
RTS
ご指摘ありがとうございます。確かにAレジスタにゴミがある場合に$02B22C以降の処理で経験値が膨大($FFFFFF)になる可能性がありますね。示してもらった実装のほうがシンプルですっきりしてるのでそのまま使わせていただきます。