こんなもんで息抜きするのもどうかと思うが、今回のターゲットは闘人魔境伝ヘラクレスの栄光。 かるーく武具の耐久力減らない、でも探してみるかと。 まず例によってゼロページをぼーっと眺めながら戦闘をしてみると、78~7C番地に、 武器1、武器2、武器3、盾、鎧の順に耐久力が格納されているようなので、 そのまま78~7C番地に"on write"でブレイクポイントを仕掛け、敵を攻撃してみる。 E83E sec E83F lda $78 B841 beq $E85B E843 sbc $0C E845 bcs $E849 E847 lda #$00 E849 sta $78 E84B bne $E85B というところでブレイク。色々処理がされているようですが、用は書き込まなきゃいいんだけれど、 この場合、一撃で耐久力を上回る消耗をしてしまった場合、まずいことになると思われるので、 念には念を入れて確実にE84B番地から分岐するように、E849番地を"sta $78"(85 78)から"lda #$78"(A9 78)に書き換えます。 …見事攻撃しても武器の耐久力が減らなくなりました。 続いてブレイクポイントはそのままでダメージを食らってみると、 E9D3 sta $0C E9D5 lda $7B E9D7 beq $E9ED E9D9 sec E9DA sbc $0C E9DC bcc $E9E0 E9DE bne $E9ED E9E0 lda $82 E9E2 sta $98 E9E4 lda #$62 E9E6 jsr $D95A E9E9 lda #$00 E9EB sta $82 E9ED sta $7B E9EF rts という部分に突き当たり、また直後に7C番地をロードする、非常に似通ったルーチンでもブレイクする。 ここは、他のアドレスにも同様の数値が書き込まれているため、出来れば減算を潰したい。 迷っている最中に、ステップ実行でサブルーチンの呼び出し元にリターンしてみると、 E9A8 lda #$01 E9AA jsr $E9D3 …どうもこの即値代入されている0x01が減算される値のようである(1を引くならDEC命令を使った方が良さそうなものだが…) なのでここを"lda #$01"(A9 01)から"lda #$00"(A9 00)に書き換える。 7C番地をロードするルーチンに関しても、呼び出し部分が、 E9C1 lda #$01 E9C3 jsr $E9F0 と形が同じなので同じように書き換える。 結果見事成功。 コード化すると次のようになります。 耐久力減らない A6150A3C<武器 FCE18524<盾 FCE184D6<鎧 -- 以下6月15日追加 -- さて前回のコードは正直あまり役に立たないので、 思い切ってアタシの得意技の一つ、ランダムエンカウント無視を探してみましょうか。 まず、敵の種類がストアされているアドレスを探します。 相変わらずぼーっとゼロページを眺めてみると、97番地が 55=ラビ 58=プノトン 5B=ほこうじゅ A6=歩行時 と変化していたので、ここに"on write"でブレイクポイントを仕掛けて歩いてみる。 と、一歩歩くごとにE7AA番地で7回ほどブレイクがかかるが、当然無視する。 いちいち一歩ごとに7回ずつプログラムを再実行しながら歩いていると、ついに E4D4 ldy #$00 E4D6 lda ($08),y E4D8 sta $97 E4DA beq $E4EE という箇所でブレイク。だが、ここを通過した時点で敵の出現は確定してしまっているので、 ここを飛び越すように分岐させなければならない。で、プログラムをかなりさかのぼると、 E475 lda $23 E477 bne $E4F0 E479 lda #$F0 E47B jsr $E8EB E47E cmp $6B E480 bcs $E4EE という所(実はサブルーチンの頭)にたどり着いた。 ここでコンペアされている6B番地は、フレームごとに1ずつ増加しており、乱数の代わりのようである。 またその2行上でaレジスタにセットされている0xF0はしきい値で、 サブルーチンの飛び先では、条件によってそれに0x10が減算されている(つまりエンカウント率は1/8or1/16) よってE480番地のジャンプ命令を常に分岐させればよい。 …ように見えるが、実はトラップがある。 さらに上で参照されている23番地は海上かどうかのフラグ判定なのだが、 ここで分岐してしまうと海上専用のエンカウントチェック(ルーチンそのものはほぼ同じ)に行ってしまうのだ。 そのため、そちらの方でも分岐をいじらなければならず、プロアクションロッキーの仕様上それは避けたい。 そのためさらにさかのぼり、このサブルーチンを呼び出している箇所を見てみると、 E2DE jsr $E475 E2E1 bcs $E2E4 E2E3 rts となっている。つまりキャリーフラグがoffの状態でサブルーチンから戻ればよいわけだ。 ここで、さっきから散々分岐先として出て来ているE4EE番地の命令を見てみると、 E4EE clc E4EF rts と見事にキャリーフラグをoffにした後リターンしている。なのでここに直接飛ばすように、 E2DE番地のコールを"jsr $E475"(20 75 E4)から"jsr $E4EE"(20 EE E4)にすれば良いわけだ。 暗号化するとこちら 雑魚敵出ない 9146FEA6 -- 以下6月16日追加 -- さてさて、上記のコードを使ってしまうと、onにしたままではレベルアップが出来ず、 かといってFCの構造上、コードをon・offするのは怖いというわけで、いわゆるバランス崩壊コードの最右翼、 「戦闘終了後経験値最大」を調べてみます。 まず経験値のアドレスですが普通に見ていれば76-77番地がすぐ目に付きますので、即座に"on read"でブレイクを仕掛けます。 そして敵を倒してみると… E7F9 clc E7FA lda $76 E7FC adc $0498 E7FF sta $76 E801 lda $77 E803 adc #$00 E805 sta $77 E807 bcc $E811 E809 lad #$FF E80B sta $76 E80D sta $77 E80F sta $78 E811 jsr $E908 あまりにも分かり易すぎます。 E807番地の分岐命令を潰すだけで76-78番地にFFが書き込まれ、経験値が16777216に…ってちょっとまて。 このゲーム経験値最大65535だろ。しかもよくよく考えたら78番地って装備中の武器の耐久力じゃないのさ…。 しかしこうもはっきり記述されているということは「経験値が65535を超えると武器耐久力が255になる」という仕様なのでしょう。 そういうことにしておいて、遠慮無くE807番地"bcc $E811"(90 08)を"bcc $E809"(90 00)に書き換えますと、 見事一回の戦闘でレベル30にアップ、武器耐久力も255になりました。 ついでなので所持金もいっときましょう。 アドレスは7D-7E番地なのでここに"on read"でブレイクを仕掛けて、また敵を倒します。 DC7D clc DC7E lda $7D DC80 adc $0484 DC83 sta $7D DC85 lda $7E DC87 adc $0485 DC8A sta $7E DC8C bcc $DC94 DC8E lad #$FF DC90 sta $7D DC92 sta $7E DC94 lda #$01 DC96 jmp $BC48 はい。素直ですね。DC8C番地の"bcc $DC94"(90 06)を"bcc $DC8E"(90 00)に書き換えればOKです。 暗号化するとこちら 戦闘勝利後経験値最大 FCBCFE00 戦闘勝利後所持金最大 FC2B9108 さらに悪乗りしてみます。 このゲーム、地下迷宮にはいると画面がマスクされ、用意された「ろうそく」や「ランプ」といったアイテムを使っても、 見える範囲がかなり狭くなってしまいます。そこで、これを解除してみます。 まず地下迷宮に入り、真っ暗>ろうそく>ランプ、と順に使って数値の変化を見てみると、26番地が 1=真っ暗 2=ろうそく 3=ランプ と変化していました。ここで地上に出てみると、数値が0x00になります。 もしやと思い、迷宮内でここに0x00を代入してみると… あれ、変化しない。 と思ったら、歩いてみると画面全体が表示されていきます。どうやら当たりのようです。 今回は、直接代入値をいじれば良さそうなので"on write"でブレイクポイントをセット。 地下迷宮に入ると、 D00F lda ($3C),y D011 beq $D017 D013 ldy $26 D015 bne $D019 D017 sta $26 というところでブレイクする。このルーチンがなかなかややこしく、 まずD00F番地でロードされるのがマップのマスク判定なのだが、その次のldy命令で現在のマスク状態をロードし、 0x00以外、つまりマスクがかかっている場合、その直後のsta命令が実行されないのだ。 そのため何とかして、D013番地で書き込みを行いたい。 そこでこの時の各レジスタの値を調べてみると、うまい具合にXレジスタが常に0となっているため、 これを利用してD013番地"ldy $26"(A4 26)を"stx $26"(86 26)に書き換える。 これで見事地下迷宮のマスクが取れた…のだが、なんとBGMが民家のものになってしまった。 つまり、26番地は建物の種類も表していたということになる。 あまり気分は良くないが、これを解消しようとすると、行数が増えてしまうため、これで妥協する。 暗号化すると ダンジョンマスク解除 E267A1D2 となる。