5かいでオーキドせんせいと戦う

トレーナーの手持ちバリエーションを制御する方法が分かったので念願のオーキドせんせいとご対面。

原理

D036に数値を書き込むと対応したポケモン・トレーナーとの勝負になることはよく知られていますが、 トレーナーは事前にD03Aに数値を入れておくことで同じ見た目の複数バリエーションと戦うことができます。 通常はボスでないむしとりなどの手持ちの種類を選ぶためのものですが、サカキやライバル、オーキドせんせいは複数種類の手持ちがあるのでD03Aで選択することができます。 逆に、D03Aが正しく設定されていないとアネ゛デパミ゛を出してきたりします。

コーディング

愚直に書く

要はD036にE2、D039に00以外(BGM変更のため。optional)、D03Aに01から03までのどれかを書けばよいので、


3e 01; ld a, 01
ea 3a d0; ld (d03a), a
ea 39 d0; ld (d039), a
3e e2 ; ld a, e2
ea 36 d0 ;ld (d036), a

が実行できれば問題ありません。これを文字列に起こすと

ぼイ゛ゥばみゥの゛みぼょゥに゛み

となり、だいぶ無理があります。

イ゛ をつぶす

簡単なところからつぶしていきます。最初のld a,01は01を入れられれば良いので、次のように置き換えてみます。


3e 06; ld  a,06
d6 05; sub a,05
ea 3a d0; ld (d03a), a
ea 39 d0; ld (d039), a
3e e2 ; ld a, e2
ea 36 d0 ;ld (d036), a

文字列として見ると

ぼギよガゥばみゥの゛みぼょゥに゛み
ちょっと伸びましたがイ゛をつぶすことができました。

ゥをつぶす

dest addrを即値指定するldはゥとなり使えないということが分かったので、レジスタ指定を考えます。候補は

の三択ですが、この中で文字として入力可能なのは0x12(デ)のみです。よって自動的にアドレスを格納するレジスタはdeになります。

3e 06; ld  a,06
d6 05; sub a,05
16 d0; ld d, d0
1e 3a; ld e, 3a
12 ; ld (de), a
1d ; dec e
12 ; ld (de), a
1e 36; ld e, 36
3e e2 ; ld a, e2
12 ; ld (de), a

文字列に起こすと

ぼギよガヌ゛みミ゛ばデマ゛デミ゛に゛ぼょデ

・・・悪化したぞ・・・

なんとかしてdeに値を入れる

dやeに対する即値ldは総じて使えないということが分かりました。また、ld d,b(50)とかld e,b(58)とかの類もちょうど制御文字にぶつかるため基本的に使えません。さてどうしよう。 ここでx86でいろいろなshell codeを眺めていた時のカンが働きます。 「いったんスタックに積めばいいんじゃね?」


3e 06; ld  a,06
d6 05; sub a,05
06 d0; ld b, d0
0e 3a; ld c, 3a
c5; push bc
d1; pop de
12 ; ld (de), a
1d ; dec e
12 ; ld (de), a
1d ; dec e
1d ; dec e
1d ; dec e
3e e2 ; ld a, e2
12 ; ld (de), a

ぼギよガギみゾばなむデマ゛デマ゛マ゛マ゛ぼょデ
いいせんいってる。

decをcでやってみる

しょうがないのでcをdecして毎回pushとpopをやります。


3e 06; ld  a,06
d6 05; sub a,05
06 d0; ld b, d0
0e 3a; ld c, 3a
c5; push bc
d1; pop de
12; ld (de), a
0d; dec c
c5; push bc
d1; pop de
12; ld (de), a
0d; dec c
0d; dec c
0d; dec c
c5; push bc
d1; pop de
3e e2; ld a, e2
12; ld (de), a

ぼギよガギみゾばなむデゼなむデゼゼゼなむぼょデ
・・・ょ

名前にすると0x50が入るよね

ょをつぶす方針はイ゛同様にsubとかaddとかでなんとかすることにしますが、その際についでに0x50を巻き込んで処分したいです。 ということで、影響がないように0x50を挟みます。駄目そうなときはコードに影響がない範囲でうまく順番を入れ替えます。


06 d0; ld b, d0
0e 3a; ld c, 3a
c5; push bc
50; ld d, b

d1; pop de
3e 06; ld a, 06
0d; dec c // もうpopしたからこっちは先に変えちゃってok
06 50; ld b,50 // dを守る必要があるのでbを壊した・・・けど実は生の0x50でも問題なかった

d6 05; sub a, 05
06 d0; ld b, d0 // 壊したbを戻す
c5; push bc // 先にd039をpushしてもいいよね
50; ld d, b // bもdもd0だから入れちゃっても影響ないよね

12; ld (de), a // ようやくd03aに01を代入できた
d1; pop de // d039をdeにpop
12; ld (de), a // d039に01を代入
0d; dec c
0d; dec c
50; ld d,b // bもdもd0

0d; dec c
06 d0; ld b,d0 //いらなかった
c5; push bc
3e 50; ld a,50 // aに0x50を入れつつ終端文字を処分

d1; pop de
c6 92; add a,92
12; ld (de), a
c9; ret
50;

これを文字に起こすと
ギみゾばな[EOM] むぼギゼギ[EOM] よガギみな[EOM] デむデゼゼ[EOM] ゼギみなぼ[EOM] むにテデの[EOM]
となり、きれいに収まりました。36byteに収まった瞬間、「やっぱり わたしは てんさいだ!」と思ったのですが、まだ最適化の余地がありますね・・・

完成形

5匹30byteに収めました。たぶん最短だとおもうのですが、さらに最適化できたら教えてください。pushとpopが近くなってかなり可読性も上がってます。


06 d0; ld b, d0
0e 3a; ld c, 3a
c5; push bc
50; ld d, b

d1; pop de
3e 06; ld a, 06
d6 05; sub a, 05
50; ld d, b

12; ld (de), a
0d; dec c
c5; push bc
d1; pop de
12; ld (de), a
50; ld d, b

0d; dec c
0d; dec c
0d; dec c
c5; push bc
d1; pop de
50; ld d,b

3e 12; ld a,12 
80; add b // bはd0
12; ld (de), a
c9; ret
50;

ギみゾばな[EOM] むぼギよガ[EOM] デゼなむデ[EOM] ゼゼゼなむ[EOM] ぼデアデの[EOM]

エントリポイントを書く

通常の5かいバグでは道具欄に相対ジャンプするのを前提としていますが、今回は名前欄で実行させます。 パソコンは遠いので絶対ジャンプでメノクラゲのPPから一気に飛ばすことにしました。


D174 c3 64 de ; jp DE64 (メノクラゲ技1: PU3, PP3 / 技2: PU1, PP36 / 技3: PU3, PP30)

実験

動画でお楽しみください。

評価

既存手法と比べて何度でも戦え、かなり安定している点で優れていますが、手持ちの2枠が制限される点、 ボックスの頭から並べる必要があるため全ボックス使用中だと面倒である点がデメリット。


戻る
connecting: riko.2rnd.msmrrneda.net