技データの解析について解説。
技データは「BALANCE/waza_p.bin」に格納されており、各ポケモンの技習得データも一緒にまとめられている。
SIR0形式のファイルで、どこからが技データか、技習得データであるかがポインターで示されている。
SIR0形式については以下の記事を参照。
lainel.hatenablog.com
なお、本記事ではロムハック等を行っていないバニラの状態であることを前提とする。
「waza_p.bin」の構造は以下の通り。
0x00~0x0F | SIR0ヘッダー |
0x10~(不定) | 技習得データ |
(技習得データ)~(不定) | 技データ |
(技データ)~ | SIR0ポインターリスト |
技習得データはSIR0ポインターの展開と同じ仕組みでデータが圧縮されているので、バイナリから値を読むには変換する必要がある。これについては先程のSIR0の記事に書かれているが、本記事でも解説していく。
データ取得
技習得データはフシギダネ(0x001)~闇のディアルガ(0x228)まで順番に格納されており、そこから更に「レベル習得技」、「技マシン習得技」、「タマゴ技」と3つのリストに分かれている。
そして、SIR0ポインターリストが指すポインターは"それぞれ3つの習得技リスト×全ポケモン分"となっている。
ここでは例としてフシギダネのデータを解析してみる。
まずポインターリストの位置を特定する必要がある。
SIR0ヘッダーの0x08を確認する。
ここの値を4バイト取ると「B0 33 01 00」。並べ替えると「000133B0」なので、ポインターリストは0x133B0が開始位置となる。
0x133B0にジャンプしてみると、やたらと0x4が並んでいるがこれはポインターの値が4バイトであるため、4バイト区切りでポインターが存在しているということになる。
このポインターリストは最初の値から順に足していくことでポインターのポインターを把握することができる。ややこしいけど。
最初の0x4はSIR0ヘッダー内の0x4にあるコンテンツポインターを表す。
次は0x4なので先程の0x4に加算して0x8。これは先程確認したSIR0ヘッダーのポインターリストのポインター。
その次の値がやたらとデカいが、これは値が複数のバイトで構成されており、0x80を下回るまで連続で取得する必要がある。
現在の値は0x84。これは0x80を超えている。
その次の値は0xB3。これも0x80を超えている。
更にその次の値は0x34。ここまででようやく0x80未満となるのでここで区切る。
次に以下の式で値を求める。0x80を下回るようにするため0x7FでAND演算を行い、「取得した値の数×7」の分だけ左へシフトした値を足していく。シフト数は値を足すにつれて7ずつ減らしていく。
# 取得した値が4つ 値 = ((1つ目の値 & 0x7F) << 21) + ((2つ目の値 & 0x7F) << 14) + ((3つ目の値 & 0x7F) << 7) + (4つ目の値 & 0x7F) # 取得した値が3つ 値 = ((1つ目の値 & 0x7F) << 14) + ((2つ目の値 & 0x7F) << 7) + (3つ目の値 & 0x7F) # 取得した値が2つ 値 = ((1つ目の値 & 0x7F) << 7) + (2つ目の値 & 0x7F) # 取得した値が1つ 値 = 1つ目の値 & 0x7F
今回の値を当てはめると以下の通り。
値 = ((0x84 & 0x7F) << 14) + ((0xB3 & 0x7F) << 7) + (0x34 & 0x7F)
((0x84 & 0x7F) << 14) = 0x10000
((0xB3 & 0x7F) << 7) = 0x1980
(0x34 & 0x7F) = 0x34
これらを合計すると、0x10000 + 0x1980 + 0x34 = 0x119B4
そして以前までの値である0x8を足すと、0x119B4 + 0x8 = 0x119BC
よって、フシギダネのレベル習得技にあたるポインターリストのポインターは「0x119BC」となる。
以降は技データのポインターまですべて0x4なので、「0x119C0」「0x119C4」「0x119C8」といったように、4バイト区切りでポインターが並んでいることがわかる。
0x119BCにジャンプすると、ここでようやく「フシギダネのレベル習得技データ」そのものへのポインターに辿り着く。
ここの値は「13 00 00 00」なので、「0x13」がフシギダネのレベル習得技データのポインターとなる。
ついでに、次のポインターにあたる0x119C0の値は「0x3C」。これがフシギダネの技マシン習得技データにあたり、その次の0x119C4の値は「0x70」で、これがタマゴ技習得データとなる。
技習得データ
先程求めた0x13にジャンプすると、これまた不規則な数字がやたらと並んでいるように見えるが、これもSIR0のポインターと同じように変換する必要がある。
最初の値は「0x81」で、これは0x80を超えているので続けて値をチェックする。
次の値は「0x1A」で、0x80を下回るのでここで区切る。
今回は2つの値になるので、「((0x81 & 0x7F) << 7) + (0x1A & 0x7F)」で求める。
よって、0x80 + 0x1A = 0x9A。
この値は一旦置いといて、次の値を取る。値は「0x1」で、0x80を下回るので区切る。
技取得データはこの2バイトで構成されている。
最初に取得した「0x9A」は技IDを表し、次に取得した「0x1」は習得レベルを表す。
0x0 | 技ID |
0x1 | 習得レベル |
0x9Aにあたる技は「たいあたり」なので、「フシギダネはレベル1でたいあたりを覚える」ということになる。
技IDに関しては、text_j.strに含まれる技名リストのインデックスとなっているのと同時に、後述の技データのインデックスにもなっている。
技マシン・タマゴ技習得データ
これら2つの習得データにはレベルが存在しないため、すべて技ID単一となる。
フシギダネの技マシンのポインターは0x3Cなので、そこにジャンプ。
0x12は「いあいぎり」、0x18は「いばる」・・・といったように、レベル技と同じように並んでいる。同様に、0x80以上の値は変換する必要がある。
0x0Bは「あまえる」、0x54は「くさぶえ」・・・といったようにこれも同じ構造。
ちなみに、技マシンの習得データには本来技マシンとして存在しない「あまごい」等の天候技や「かげぶんしん」「がんせきふうじ」「よこどり」が含まれていることがある。正真正銘の没データ。
これらの技は技マシンではなくふしぎだまの効果(「あめだま」「ぶんしんだま」等)として存在している。技マシンとふしぎだまには技IDを設定できるパラメータが用意されており、この値が他の道具と被ると何らかの不都合があるため技マシンから削除されたと思われる。
習得データとして登録されているのはおそらく、本家ポケモンから習得データをツールか何かで一括変換した際の名残・・・だと思っている。
技データ
SIR0ヘッダーの0x4であるコンテンツポインター(4バイト)を確認する。
値は「A0 33 01 00」で、アドレス0x133A0を指している。
ここへジャンプすると、2つのポインターが並んでいることが確認できる。
これは0xE0E0、0x119B0から始まるデータがこのファイルのコンテンツとして存在しているということになる。
0xE0E0にジャンプすると0x00が多いスカスカなデータ群が見つかる。これが技データである。
ちなみに0x119B0は先程の習得データのポインターリストのポインターを指している。この位置から数えると0x00のポインターが3つ取得できるが、これは無効な値となる。いわゆるnullである。
ポケモンデータの一番最初は「なにものか」というダミーのポケモンが設定されており、ゲーム内で表示させようとするとスプライトIDが0xFFFFである為フリーズ。更にあらゆる値が0x00である為、終端を0x00で判定している処理ではいろいろ不具合が起きてしまう。
おそらく習得データの個数をポケモンデータの個数と揃える為に入れられたダミーデータと思われる。
技データの構造は以下の通り。長さは26バイト。
アドレス | データ型 | 名称 | 備考 |
---|---|---|---|
0x00 | int16 | 威力 | 技の威力。内部の値であり、ゲーム上では確認できない。主にダメージ計算に使用される。 |
0x02 | int8 | タイプ | 技のタイプ。ポケモンデータと同様。 |
0x03 | int8 | 分類 | 0…物理、1…特殊、2…変化 |
0x04 | int16 | ビット1 | 近距離攻撃に関連するビットフラグ。詳細は不明。 |
0x06 | int16 | ビット2 | 遠距離攻撃に関連するビットフラグ。詳細は不明。 |
0x08 | int8 | PP | 技のPP。 |
0x09 | int8 | ? | 不明。0、8、10、15、20、25、30、70の値。 |
0x0A | int8 | ? | 不明。0、15、20、65、70、75、80、85、88、95、100、125の値。 |
0x0B | int8 | 命中率 | 技の命中率。値が125の技は必中。 |
0x0C | int8 | ? | 不明。0、20、50、75の値。 |
0x0D | int8 | 最大連続攻撃数? | 連続で攻撃する技の最大攻撃回数? 複数回攻撃する技のみ2~5の値が設定されているが、0に設定されている技もある為詳細不明。 |
0x0E | int8 | カテキン使用上限 | カテキンで技を強化できる回数。攻撃技はすべて99、変化技はすべて0。 通常攻撃にあたる「こうげき(0x168)」のみ値が1。 |
0x0F | int8 | 急所率 | 急所に当たる確率。何故か変化技にも設定されているが、殆どの技は8である為これが開発中のデフォルト値だったと思われる。 他にも、連続攻撃技は1~3、「きりさく」等の急所に当たりやすい技は30、ふしぎだまの効果にあたる技や未使用($$$)の技はすべて0、「がまん」「リベンジ」「ゆきなだれ」が解かれた時に出る攻撃技は2に設定されている。 |
0x10 | int8 | ? | 不明。0~1の値。相手に効果がある技のフラグ? |
0x11 | int8 | ? | 不明。0~1の値。自身に効果がある技のフラグ? |
0x12 | int8 | ? | 不明。0~1の値。何らかのフラグ? |
0x13 | int8 | やけど関連の値? | 相手をやけど状態にする技やそれを回復する技のみ0に設定されている。それ以外は1。詳細不明。 |
0x14 | int8 | 攻撃技を示すフラグ? | 攻撃技は1、それ以外は0。 |
0x15 | int8 | ? | 不明。0~31の値。 |
0x16 | int16 | 技ID | 内部で明示的に設定された技のID。 有効な技である0x21Fの技までは連番が振られているが、無効な技となるその次の技からは何故か0x19Eから順に割り当てられる。 |
0x18 | int8 | ? | 不明。0~1の値。何らかのフラグ? |
これを元に技データを構成していく。
先頭である0xE0E0から技データ1つ分である26バイトを取る。
技データの一番最初(ID=0x00)はダミーデータとなっており、技名は「なし」。一応技ではあるのでこれも技データとして取得する必要がある。
この値を上記表に当てはめると、各パラメータが何を表しているかがわかる。ただ、ダミーデータだとわかりづらいのでその次のデータ(ID=0x01)を例とする。
最初の位置から26バイト進んだ0xE0EAから26バイト取得する。
この技は「アイアンテール」。これを表に当てはめていくと以下のようになる。
0x00 | 威力 | 40 (0x0028) |
0x02 | タイプ | はがね (0x11) |
0x03 | 分類 | 物理 (0x00) |
0x04 | ビット1 | 00000000 00000000 (0x00) |
0x06 | ビット2 | 00000000 00000000 (0x00) |
0x08 | PP | 10 (0x0A) |
0x09 | ? | 15 (0x0F) |
0x0A | ? | 125 (0x7D) |
0x0B | 命中率 | 78 (0x4E) |
0x0C | ? | 75 (0x4B) |
0x0D | 最大連続攻撃数? | 1 (0x01) |
0x0E | カテキン使用上限 | 99 (0x63) |
0x0F | 急所率 | 8 (0x08) |
0x10 | ? | 0 (0x00) |
0x11 | ? | 0 (0x00) |
0x12 | ? | 0 (0x00) |
0x13 | やけど関連の値? | 1 (0x01) |
0x14 | 攻撃技を示すフラグ? | 1 (0x01) |
0x15 | ? | 11 (0x0B) |
0x16 | 技ID | 1 (0x0001) |
0x18 | ? | 0 (0x00) |
尚、データ終端はポインターリストまで「0xAA」で埋められているため、プログラムを書く場合はここの値でループを抜ける条件にすると良い。
技名について (text_j.str)
技名はwaza_p.binには含まれておらず、文字列がまとめられた「text_j.str」に格納されている。「MESSAGE」というディレクトリに含まれている。
このファイルの0x2F4A2以降が技名となっている為、ここの文字列を0x00で区切って各技に割り当てることで対応した技名になる。
その他
waza_p.binの他にも、「waza_p2.bin」というファイルが存在している。空のみに存在し、時闇には無い。
構造は全く同じでバイナリの値こそ異なるものの、値を展開するとwaza_p.binと同じ値になる為用途は不明。psy_command氏によるとROMから削除しても一応問題なく動くとのこと。