Lapis & Lazuli

ゆきれいむぅのにっき

ポケモンエメラルドの技の物理/特殊の区別をタイプ依存から技依存に変えたかった話

こんにちは。令和になってもまだ改造ポケモンで遊んでいる私です。

 

かつては「メイプルストーリー」という、これまた化石みたいなゲームで狂ったように遊んでいたわけですが、どうも私にはレトロゲーに分類される類のゲームの方が性に合っているようです。新しいゲームなんかを買ってもだいたいは数日で飽きてしまっていて、なんだか10代の頃に遊んでいたようなゲーム(東方, ポケモン, FF, etc. )が恋しくなってついつい手を伸ばしてしまう、そんな生活を送っています。

 

さてさて、話を改造ポケモンに戻しましょうか。

改造ポケモンというのは、オリジナルのポケモンシリーズのROMデータを解析&改造して、ポケモン・技・トレーナー・マップなどなど様々な要素を変更/調整した改造ロム、いわゆるハックロムのことをいいます。「改造」と言われるとPARなどの改造コードを思い浮かべる人もいるかもしれませんが、ハックロムとは原理的に異なるものです。

あ、ロムハックの法的な話についてはここではあえて語りません。この記事の目的はそこにはありませんので。嫌だと思う方はブラウザバック推奨ですよ。

改造ポケモンといえば、有名どころとして「東方人形劇」や「ポケットモンスター あるタイル・シリウス/ベガ」、「萌えっ娘もんすたぁ」などがありますね。私も高校生ぐらいの時期によく遊んでいた記憶があります。2011年前後に流行していた気がします。

 

去年くらいだったかな?久しぶりに「東方人形劇」を遊んでいたのですが、ある程度歳をとってから遊んでみると視点が変わって、ハックロムの原理 ― "何をどう改造したらこうなるのか" ― が気になるようになりました。

まあ、ある程度原理は知っていたんです。ROMには機械語、プログラミングでいうところのコンパイル済みのコードが書き込まれているわけで、コンパイラのルールに従って機械語を読んでいけば、処理の内容は分からなくもないということです。ただし、機械語はCPUが処理しやすいように書かれているのであって、決して人間の脳が処理しやすいようには書かれていないので、今まで手を出したいとは思うことはなかったんですよね。ROM内の機械語を逆アセンブラにかけアセンブリ言語に変換したものをなんとか解読することになるのですが、これがなかなか難しく...

幸い、ポケモン改造に関する情報やツールはWeb上に多く残っているので、学習のとっかかりは掴みやすかったです。表面上の要素の変更(例:ポケモンの特性追加、トレーナー出すポケモンの種類とレベルの変更、出現ポケモンの変更などなど)であれば、「pokemon_Synthesis」などのツールを使うだけで簡単にできますが、その差分をバイナリエディタで見たりするだけでも学べるものは多かったです。

話が長くなってしまいましたが、そんな感じでここ最近は本当に少しずつポケモン改造の勉強をしています。ポケモンで一番好きなシリーズがエメラルドなので、エメラルドを自分にとってもっと楽しく遊べるようにするために、少しずつ色々なことに挑戦しています。今回はそんな挑戦のうちの一つを備忘録的に残せたら、という気持ちで記事を書いてみました。

 

第3世代までのポケモンの技の仕様

かなり有名な話かもしれませんが、第3世代(RSE)までのポケモンシリーズは攻撃技の物理/特殊の区別がタイプごとに設定されていました。ノーマル・かくとう・どく・じめん・ひこう・むし・いわ・ゴースト・はがねわざが物理技に分類されて、残りが特殊技に分類されています。

これが今になってみるとなかなか嫌な仕様で、例えばゲンガーを強く使おうと思うと、タイプ一致のシャドーボールを覚えさせたくなるものですが、当時のゴーストタイプの技は物理で計算されるので、ゲンガーの特殊種族値の高さを活かせなくなります(特攻130<->攻撃65)。タイプ一致技で考えたときに、そのタイプの物理/特殊の区別と種族値配分がチグハグなポケモンはかなり多いです。有名どころを挙げると、キングラーギャラドス、3色パンチ(笑)を使い分けるエビワラー、唯一王ブースター、唯一神エンテイなどなど......

第4世代以降では技ごとに物理/特殊の区別が設定されるようになったため、これらの不遇ポケモンたちの多くが救われました。一部のポケモンは覚える技の関係で弱体化してしまったかもしれませんが、その後の世代で少しずつ調整を受けていった印象です。

さて、そんな仕様がある第3世代ですが、エメラルドをもっと楽しく遊べるようにするために、バトルフロンティアでもっと色々なポケモンを活躍させて遊べるように、この技の仕様をなんとか変えたい!というのがエメラルドの改造をするにあたっての一番最初の大きな目標になりました。

具体的には第4世代以降の技の仕様に変更したいわけで......

はてさて、何から手を付ければよいか......

 

パッチを探そう!

ポケモン改造の多くはファイアレッド(FR)のROMを対象にして行われてきた歴史があります。「東方人形劇」や「萌えっ娘もんすたぁ」もベースはFRです。そんな背景もあって、改造に関する資料やパッチはFR用の物が多いです。

ポケットモンスター アルタイル・シリウス」など、エメラルド(EM)をベースにしたものもあるにはあるのですが、その数は少なく、研究も進んでいない印象を受けます。

何が言いたいかというと、EM用のパッチがなかなか落ちていないんですよね。

それでも前述の技の仕様に関してはさすがに先行研究があったようで、「東方人形劇まとめwiki」の非公式パッチの中から該当するものを見つけることができました。

  • SkillSystem Of BW(EM): 技の仕様をEMのものからBWのものへ変更
    • ここからきっと見つけられます...

技システムをBWに変化させるという趣旨のパッチのようで、技の物理/特殊のタイプ依存を脱却するだけでなく、「すなあらし中の岩タイプの特防1.5倍」など第5世代(BW)までに変更された様々な対戦仕様をEMに再現することに挑戦したパッチのようです。実はそれより前にSkillSystemOfDPという第4世代版のパッチも既に開発されていたみたいで、そちらを踏襲しているようです。今回はEM用のパッチが用意されているBWの方を採用させていただきました。

ついでに、技の物理/特殊の属性を表示させることのできるパッチを見つけました。こっちも後で一緒に入れちゃいましょう。

  • 物理特殊表示パッチ (EM)

パッチも見つけられたのでこれで勝つる!と思って喜んでいたのですが、その後かなり沼ってしまったのが今回の本題にもなります。

 

パッチを当てよう!

パッチを当てるのは簡単です。いつも通りWinipsなどを仕様して素ROMに対してパッチファイルを当てるだけです。今回は SkillSystemOfBW(EM).ips パッチを当てます。

ちなみに、改造ポケモンの文脈でいうところのこのパッチファイル、中身がどうなっているのか気になったことがありませんか?実は結構簡単な作りをしていて、バイナリエディタなんかでipsファイルを開いて観察すると見えてくるんですが、6バイト目以降から「どのアドレスを」「何バイト分書き換えるか」「書き変えるデータの中身」の順番に差分の箇所だけ書かれています。最初の5バイトはIPSのシグネチャのようで "PATCH" の5バイトになります。以下の記事が大変参考になると思います。

 

技ごとのタイプ(物理・特殊・変化)を設定をしよう!

さて、パッチさえ当てれば物理/特殊がタイプ依存から技依存になっている!と期待していましたが、ゲームを起動して遊んでいてすぐに違和感を覚えました。

「全部物理になってる・・・」

検証用のデータで使用していたラグラージなみのりも、サーナイトサイコキネシスも、どちらも攻撃の値でダメージ計算されていそうな予感。

試しに、チートコードを使用して攻撃999&特攻1にしたポケモンAと、攻撃1&特攻999にしたポケモンBであらゆる技を使用して比較みました。結果、「本来物理であるはずの技」も「本来特殊であるはずの技」も、ポケモンAの方の攻撃は一撃必殺級の威力、ポケモンBの方の攻撃はねこぱんち、どちらも物理で計算されていることがわかりました。

これはどういうことなのか、原因がさっぱり分かりません。実はSkillSystemOfBWのパッチファイルには、私みたいな未熟者にも分かりやすく書かれたREADMEのような資料が同梱されておらず、何らかの手順が足りていないということにしばらく気づくことができませんでした。

このことでしばらく頭を悩ませていましたが、前述のSkillSystemOfDPの方に同梱されていたREADMEに気になる記述があることに気づきます。

技の仕様をFR(EM)のものからDPのものへ変更します。
SkillSystemOfDP のみでは技の物理・特殊属性は設定されません。
物理・特殊属性を設定して遊ばれる際は、お手数ですがご自分で割り振られるか、SetSkillフォルダ内のファイルを適用してください。

(SkillSystemOfDP Ver.1.05a - README.txt)

ははーん。

なるほど、それもそのはず。東方人形劇のような改造ポケモンでは、そもそも技自体のテーブルが本家より大きく変更されていることがほとんどで、オリジナルの技が追加されていたり、技の仕様が変わっていたり、技の数自体増えていたり......。そんな条件下で技ごとの物理/特殊の設定を勝手に書き換えられたら困ってしまいますね。最悪ROMが起動しなくなることも考えられます。

そのまま読み進めてみると、こんな記述も見つかります。

■属性の設定法

 技の情報における変数10~12はFRにおいて未使用であるため、11に属性を設定しています。

すなわちPSを用いたときのアタックエディターにおける最下部の6つの変数のうち、下段中央に技の属性を記述しています。以下、数値と属性の対応関係。

  • 0 → 物理
  • 1 → 特殊
  • 2 → 変化 (物理技、特殊技、のろい以外の全ての技)
  • 3 → のろい(「???」タイプのみ個別処理が行われていたため)

(SkillSystemOfDP Ver.1.05a - README.txt)

PSというのは、恐らく「pokemon_Synthesis」のことを意味しています。さっそく、PSで技のデータを覗いてみましょう。

この赤枠で囲った部分の値が技の変数11に該当するようです。こちらの値を技ごとに設定していくことで、特殊技も特攻で計算されるようになることが期待されます。この変数の初期値はすべての技で0になっていますから、パッチを当てた直後はすべての攻撃技が物理技として計算されていたという理屈になります。

では、すべての技の属性を設定していくわけですが、結論としてここでは以下のように設定するようにしてください。(後述する物理特殊表示パッチ (EM) も正常に動作させるための設定になります。)

  • 0 → 物理
  • 3 → 特殊
  • 4 → 変化
  • 8 → のろい

SkillSystemOfBW(EM) ではこの設定で期待通り動作するようになりました。変化技およびのろいについては、この値に設定しておくと物理特殊表示パッチ (EM) も正常に動作します。

この時代、ポケモンの技は全部で354個あります。根気強く属性を設定していきましょう...!ここは人力になります。暇な誰かがここの差分でパッチファイルを作成しない限りは...... 技のデータは以下のページが参考になります。データ内に格納されている順番に技の情報が書かれています(=技コードの順)。

この作業を終われば、技の変数11を「0」に設定した攻撃技は物理技として攻撃のステータスを使用して、技の変数11を「3」に設定した攻撃技は特殊技として特攻のステータスを使用して、ダメージ計算がされるようになるはずです!

 

技の属性を表示させよう!

物理特殊表示パッチ (EM)というのもあったので、こちらもせっかくなのであててみましょう。

タイミングとしてはSkillSystemOfBW(EM)のパッチを当てた直後の方が良いと思いますが、技の変数11を書き換えた後に実施しても問題ありません。チョットコワイダケ

私がこのパッチを導入した当時はパッチにバグがありまして、それがアセンブリ言語を学び始めたきっかけだったりします。今は有志の方が修正版を上げてくれていますね。(まだポケモン改造勢生きてるんだ...)

導入に成功すれば、技の変数11に設定した値に応じて技の属性がPPの文字の下に表示されるようになります!

 

なんで特殊技が「3」なの?

ここからは余談になります。

上記手順では、特殊技にしたい技の変数11には「3」を入力するように、と書かせていただきました。では、何故「3」なのか?当然気になってきますよね、私も気になります。

実は私、最初はここの値を「2」にしていたんです。そうしたところ、確かに攻撃技を使用した際には、物理技は攻撃のステータスを参照するように、特殊技は特攻のステータスを参照するようにはなっていたのですが、どうも防御側のダメージ計算がおかしかったんです。「技の変数11の秘密を暴いた俺天才じゃね?」と優越感に浸りながら遊んでいたのも束の間、旅パのラルトスイワークにねんりきを使用した際に再び違和感を持ちます。「固くね?」と。

イワークの攻撃種族値がポッポと同等であることは大変有名ですが、イワークの特防種族値はネイティらと同じ「45」です。紙です、紙。ラルトスのねんりき、タイプ相性は普通ですが、本来はもっとダメージが通るはずなんです。ダメージカリキュレーターにぽちぽち情報を入力して計算しても、やはりどこかおかしいことが分かります。

結論から言うと、今度は防御側の計算がすべて防御の値を使用して計算されていたんです。もうお手上げです。どうなってんねんこれ、バグやんけ!と。

 

そこでようやくバイナリを見ることに。アセンブリ言語と格闘することを決意します。

SkillSystemOfBWのパッチファイルには、私みたいな未熟者には決して分からない言葉で処理の内容が記述されたドキュメントが同梱されていました。読んでみましょう。

// 物理・特殊(攻撃)分岐
0806972a 4659        mov    r1, fp
0806972c 2901        cmp    r1, #1
0806972e d902        bls    $08069736
08069730 4645        mov    r5, r8
08069732 201c        mov    r0, #1c
08069734 e001        b    $0806973a
08069736 1c3d        mov    r5, r7        (add r5, r7, #0)
08069738 2019        mov    r0, #19

// 物理・特殊(防御)分岐
08069772 4659        mov    r1, fp
08069774 2001        mov    r0, #1
08069776 4008        and    r0, r1
08069778 2800        cmp    r0, #0
0806977a d002        beq    $08069782
0806977c 9b07        ldr    r3, [sp, #1c]
0806977e 201d        mov    r0, #1d
08069780 e001        b    $08069786
08069782 9b06        ldr    r3, [sp, #18]
08069784 201a        mov    r0, #1a

この意味不明な文字の羅列こそがアセンブリ言語になります。

一応、この意味不明な文字の羅列の読み方を簡単に紹介しておきます。例えば「0806972a 4659   mov  r1, fp」という行は「ROM内のアドレス"0806972a"に格納された命令は" 4659"で、これは分かりやすく言うと"mov  r1, fp"ってことやねん。」ということを意味しています。分かりましたか?

私は当時も(今も)アセンブリ言語に関してはド初心者で、はっきりいってチンプンカンプンなわけです。しかし、今は令和の時代。困ったときにはいつも助けてくれる非常に頼もしい味方がいるではありませんか。

そう、ChatGPT先生です。

まずは攻撃側の処理を覗いてみましょう。

1行目の処理はfpの値をr1レジスタに格納しています。「fpってなんやねん!」って感じですが、ここでは技の変数11に設定した値がfpとして入ってくるようです(経験則)。

2,3行目の処理は、プログラミングでいうところのif文による分岐条件に該当しそうです。fpの値がr1レジスタの値(=1)より大きいかどうかで処理が分岐しています。

4行目以降は分岐後の処理の詳細で、r5レジストリに値を代入しているのを見ると、r7には攻撃側のポケモンの攻撃のステータスの値が、r8には攻撃側のポケモンの特攻のステータスの値が格納されていて、r5レジストリにセットされた値を使用して攻撃側のダメージ計算をする、という流れになっていそうですね。

当初、技の変数11には物理技を「0」特殊技を「2」に設定したわけですから、この処理をなぞれば "物理技が攻撃のステータスを参照するように、特殊技が特攻のステータスを参照するようになった" ことに説明がつきますね。条件の分岐は「1より大きいかどうか」です。実は技の変数11は「1」より大きい値であれば何でも良かったのです。私はたまたま「2」を入れたらうまくいったから「2」に設定したに過ぎませんでしたが、ここで根拠の裏付けを取ることができました。

 

では問題の防御側の処理を覗いてみましょう。

今度はちょっと難しいです。

1行目から4行目の処理では、r1(= fp)の最下位ビットの値を確認して、その値をr0レジスタにセットしているようです。その値が以降の処理の分岐に使用されているようですね。

それ以降の行には分岐後の処理が記されています。恐らくは、どちらかが防御側のポケモンの防御のステータスを使用するための処理、どちらかが防御側のポケモンの特防のステータスを使用するための処理になっているのでしょう。

問題は「fpの最下位ビットの値を分岐条件に使用している」という点です。fpは技の変数11の値のことでしたから、物理技を「0」特殊技を「2」と設定していた場合、ここではどちらも最下位ビットは"0"として計算されてしましますね。どちらも同じブロックに処理が分岐されてしまいます。ここで処理を正しく分岐させるようにするためには、技の変数11に対する特殊技の設定値を奇数にしなければなりません。またイワークでの反省から、技の変数11の値が偶数なら防御でのダメージ計算、奇数なら特防でのダメージ計算に分岐するということもわかりますね。

 

これでなぞはとべてすけました。SkillSystemOfBWにおいて物理技/特殊技のダメージ計算を正しく行うための条件は、

  • 技の変数11の値が、物理技で1以下の正の整数、特殊技で1より大きい整数であること。
  • 技の変数11の値が、物理技で偶数、特殊技で奇数であること。

このようになり、これらの条件を同時に満たす値は、最小で物理技が「0」特殊技が「3」となるわけです。特殊技はもっと大きな奇数の値、変数11は1ビットっぽいので「5」か「7」でも問題なさそうに見えますが、これらの値は物理特殊表示パッチ (EM)との兼ね合いを考えると採用できません。「3」より大きい値だと技の属性表示が「へんか」となるためですね。

 

ちなみに余談の余談ですが、私は一度「2」に設定してしまったすべての技の変数11を「3」に変更するのが非常に面倒だったので、防御側の処理の方を変更しました。

要するに最下位ビットを比較しているのが都合が悪いので、次のビット、2番目に下位のビットを比較してもらうようにしましょう。0 -> 0000, 2 -> 0010 ですから、2番目に下位のビットの偶奇で処理を分岐できるようにできれば嬉しいです。

08069774 2001        mov    r0, #1
08069776 4008        and    r0, r1

これを

08069774 2002        mov    r0, #2
08069776 4008        and    r0, r1

こうすることができれば、その処理が実現できる気がします。(#1, #2などは即値と呼ばれ、#の後ろの数値そのままの値を持ちます。)fpと"2"を比較させます。fpが00(2)なら10(2)とのANDで結果は00(2)、fpが10(2)なら10(2)とのANDで結果は10(2)となりますね。その結果が次の行で比較されて、処理を期待通りに分岐させることができます。

ここまで分かれば、あとはROMを書き換えて処理を無理やり変更して辻褄を合わせるだけです。アドレス"08069774"に格納されている命令を"2001"から"2002"に変更すればよいのです。実際にはリトルエンディアンを意識して"02 20"の順に値を格納します。(リトルエンディアンってなんだよ、しらねーよって感じですか?勉強しなさい。)

これで辻褄を合わせることができました。

皆さんは特殊技に設定したい技の変数11には「3」を入れるようにしてくださいね。決して私のようにならないように。

 

最後に

今回の話、一言で言うなら「良いなと思った商品を購入してみたら説明書がついてなくて組み立てにめちゃくちゃ苦労したけど頑張ったらなんとかなった。」ということになります。その足跡を備忘録的に残したかったという思いから書いてみました。普段仕事ではエンジニアをしているのですが、改めてドキュメント整備の重要性を実感しましたね......

とはいえ、先人たちの研究には感謝しかありません。説明書がなかったとしても、あのパッチファイルがなかったら素人の私には手も足も出すことができませんからね。改めて、ありがとうございました。

 

最近はこんな感じでエメラルドを遊びやすくするための簡単な改造に取り組んでいます。

今回紹介したもの以外にも

  • 出現ポケモンの変更(エメラルド単体で全てのポケモンを入手できるように調整)
  • ゲーム難易度調整(トレーナーの所持ポケモンおよびレベルの変更)
  • ポケモンのステータス調整(技追加、特性追加、メガシンカステータス化など)
  • ショップアイテムの変更(技マシンの無限リソース化+おまけ)
  • 一部ポケモンの進化条件の変更(通信進化を撤廃してなつき進化に)
  • 努力値稼ぎ用のマップの追加
  • 主人公とライバルのグラフィックを変更(東方人形劇から蓮メリいんぽーと)

などいろいろ取り組んでいます。一生バトルフロンティアで遊んでいたい。。

当面の目標はゲーム難易度とステータス調整の良い着地点を見つけることです。やりすぎたら面白くなくなっちゃうからね。多少はね。他にも、バトルフロンティアの出現ポケモンのデータ変更なんかも考えたいですね。(※自己満足作品なので配布等は全く考えておりません。)

もっとスキルを磨くことができればイベント処理の改造とかにも手を付けられるようになるかもしれませんが、まだまだ未熟者ですゆえ、引き続き勉強していく次第であります。

 

暇があればまたこのネタで更新するかもしれません。では!

  • もち

    こんにちは
    素敵な記事をありがとうございます🙏
    自分も最近エメラルドをアレコレして遊ぼうと思っていたところ、
    同じく「パッチ当てたら全部物理になるやん…」状態になりまして
    シンセで0,1,2,3の分類してみても上手く行かなかったので放り投げかけたところ、ここにたどり着きました

    エメラルドの情報はFRに比べて少ないので本当に感謝です
    メガ進化も導入したいなと思っているのですが難しく……
    是非参考にしたいので、今後の記事も見てみたいです!

コメントを書く