上に戻る
3.nesasmでデータ改造 前編
概要
 nesasmでデータ改造をするにはどうしたら良いかというのを実例を通して解説します。
実例?
 そうです実例です。つまり実際に、何かのソフトを改造しながら解説することになります。ここで一つ問題が有り、その対象のソフトはメジャーなほど解説として相応しい事になります。例えば、SMBなら、誰も文句をつけないほどの知名度を誇り、ここで題材として使うのに適切です。
 ……しかしながら、私がSMBについて殆ど知らないことと、私自身の現在の興味の問題も有り、ここでは、ロックマン2を題材にします。このゲームソフトを知らない人にとっては、妥当ではない流れになってしまうと思いますが、よし、じゃあ、この機会にロックマン2の改造に手を出してみては(ry
 ま、まあ、別のソフトでも利用できそうな作りを心がけたいです。まあ無理だったんだけど。実例を眺めるだけではなく、是非、ご自分で同じ事をやりながら読んで頂けるとわかりやすいと思います。
解析はしない
 ここで実例として、特定のアドレスにあるデータを変更することで改造を行います。実際には、その、「どこにあるか」を調べるまでが大変であると思いますが、このコンテンツはあくまでアセンブラの使い方に焦点を当てているので、そこの解説はしません。資料を見ながらその通りに弄るような流れとなります。
アセンブラで改造するための下準備
 通常、実際に完成したROMをベースにアセンブラを利用し始めるということは稀でしょう。むしろ、ソースファイルをアセンブルした結果が完成したROMなのです。ある意味ではこれからやろうとしていることは、その流れに逆行していることになります。しかしそれでもアセンブラは非常に効果的に利用することができます。
 用意するものは以下のとおりです

(1)NESASM.EXE
(2)バッチファイル(.bat)
(3)アセンブリファイル(.asm) 実は別に.asmという拡張子でなくても良い
(4)ベースのROMを加工した物
 順番に用意していきましょう。準備した物は適当に作ったフォルダにまとめて入れておきます。
 (1)これは適当に入手して下さい。
 (2)これは自分で作ります。テキストエディタにおいて、以下の内容のテキストをコピペして、do.batという名前で出力して下さい。

del DataHack.nes
nesasm.exe DataHack.asm >out.txt
type out.txt
pause
コメント:
ここで注意すべき点があります。テキストエディタによっては、do.bat.txtといった名前で保存してしまうかもしれません。もしそうなったら自分で拡張子を削るなりして対処して下さい。
 さらにこの際、Windowsの表示設定次第で、「.txt」が表示されておらず、確かに「do.bat」なのに動かないといったトラブルも考えられます。正直そこまで解説する気はないのでご自分でどうにかして下さい。
 (3)ですが、これがかなり厄介です。以下のようなテキストファイルを作り、ここではDataHack.asmという名前で保存して下さい。

    inesprg $10 ;プログラムバンク数
    ineschr $00 ;キャラクタバンク数
    inesmap 1   ;マッパー番号
    inesmir 0   ;ミラーリング0:Horizontal 1:Vertical

    bank 0
    org $0000
    incbin "Original.prg"
;以下アセンブリを打ち込む
 以上はロックマン2の場合の例です。上の4行は、対象のソフトによって書き換える必要があります。
 対象のソフトをバイナリエディタで開いた時の、オフセット4,5の2バイトが、上2つの値となっています。また「ミラーリング」や「マッパー番号」という物も正しく指定する必要があります。FCEUXというエミュレータを使えば確認することができます。対象のソフトを起動した後、メニューにある「Help」→「Message Log」で開くウインドウにおいて、「Mapper #」の後の値と、Mirroringの値を見て適当に設定して下さい。
コメント:
実はロックマン2の場合、「ミラーリング」は0でも1でも動いたりします。上のasmではinesmirを0にしましたが、1でも構いません。
 最後の(4)ですが、対象のソフトのROMの先頭10hバイトを切り落としたものを、ここではOriginal.prgという名前にして準備して下さい。
 大変だったかもしれませんが、これで準備が整いました。
まずは何もせずにアセンブル
 ここまで準備が整ったら、do.batをダブルクリックして、何も書き換えていない状態での出力を確認してみましょう。エラーが起こらなければ、DataHack.nesという名前の結果が出力されます。もし何かエラーが起きた場合は、「out.txt」を見れば解決の糸口が掴めるかもしれません。
 こうして出力されたDataHack.nesが、元のソフトと完全に一致している必要があります。もし、ファイルの最初の当たり(0-F)だけが違うなら、「DataHack.asm」で指定した値が間違っている可能性があります。また、もし最初だけではなく盛大に異なるようなら、色々間違っていると思うので、もう一度「Original.prg」を作りなおすのがいいかもしれません。
 もし対象ソフトと完全に一致するファイルが出力されたなら、それでようやくスタート地点にたったことになります。「DataHack.asm」の後ろの方にコードを追加して書き換えていきましょう。
 ここまでの例が、ここの[3-10]の2ファイルです。(NESASM.EXEとOriginal.prgは各自ご用意下さい)
ボスの特殊武器に対する耐性の書き換え
 それでは「ロックマン2」のデータ改造をしてみます。このゲームに出てくるボスは、こちらが使う武器によりダメージが異なります。そのダメージのリストをアセンブラで書き換えてみましょう。
コメント:
 ↑のサブタイトルを見て「え?そんなのバイナリエディタでやればいいじゃん!」と思った方が居るかもしれません。しかしここでは一見して無駄に見えるそれを敢えてアセンブラで行なってみます。アセンブラの実用性が見えてくるかもしれません。
 作業としては「DataHack.asm」の後方にコードを足していきます……が、まずは以下のコードを何も考えずに、DataHack.asmの後方に書いて下さい。

ROMADDR .macro
    bank ((\1-$10)/$2000)
    org (((\1-$10)&$1FFF)|$8000)
    .endm
 ……ま、まあ、プログラミング言語において、とりあえずおまじないのように書いておけ!ってのは良くあることですよね!
 上の4行を追加したら、続けて、ロックマンの武器に対するダメージを書き換えるためのコードを書いて行きましょう。ここでは「ヒートマン」の武器耐性を調整します。以下のコードをさらに下に足して下さい。

    ROMADDR $2E933+0
    db   3 ;ロックバスター
    ROMADDR $2E941+0
    db $FF ;ヒートフルチャージ
    ROMADDR $2E94F+0
    db   4 ;エアー
    ROMADDR $2E95D+0
    db   4 ;リーフ
    ROMADDR $2E96B+0
    db  13 ;バブル
    ROMADDR $2E979+0
    db   4 ;クイック
    ROMADDR $2E987+0
    db   4 ;クラッシュ
    ROMADDR $2E995+0
    db   4 ;メタル
    ROMADDR $2E9A3+0
    db $07 ;相手の体当たりダメージ
コメント:
いきなり長えよ、こんなんならバイナリエディタでやったほうがよほど早ぇわ!と思ったかもしれませんが、まあ正解ですねw 確かに「これだけを」やりたいならバイナリエディタのほうがよほど早いでしょう。
 このコードを追加したら、再びdo.batをダブルクリックし、アセンブルした後で、DataHack.nesをプレイしてみましょう。ちょっとボスが遠くてステージも難しくて大変ですが、「ヒートマン」に与えられるダメージが変わっているはずです。
コメント:
ありがちなミスとして、次のようなものがあります。テキストエディタ上では更新したつもりだが「保存」しておらず、そのままdo.batを叩いてしまい、「あれ?変わってないぞ???」となる事です。変更した時は、きちんと上書き保存を行なってから、do.batを実行するようにしましょう。
 さて、このコードにどのような意味があるでしょうか。以下の2行を取り出して見てみましょう。

    ROMADDR $2E933+0
    db   3 ;ロックバスター
 まず1行目の

    ROMADDR $2E933+0
ですが、これはROM上のどこを書き換えるかを指定しています。nesasmは、常時ROM上の何処かを指しています。比喩としては、キャンバスのどこに筆を向けているか、といったところです。「$」は続く値が16進数であることを表します。
 2E933は、「ヒートマン」の「ロックバスター」に対するダメージを格納しています。これにより、今まさに書き換えたい場所が指し示されたことになります。(「+0」は気にしないでください)
 そして2行目

    db   3 ;ロックバスター
 dbというコマンド(ディレクティブ)は、「現在書き換えている場所に1バイトデータを書き込め」という命令です。ここでは値「3」が指定されているので、これで「ヒートマン」に「ロックバスター」を当てると3ダメージ与えられることになります。
 尚「;」より後ろは注釈であり、アセンブラは無視します。こういったように注釈を付けられるのもアセンブラの一つの大きな魅力です。
 この命令が終わると、「書き換える箇所」は書き換えた分進みます。キャンバスに色を塗った分、筆が一つ横に動いたのです。この「書き換える箇所」には恐らく一定の名前があると思うのですが、とりあえず「PC位置」(PC=プログラムカウンタ)(the location of the program counter/Usage.txtより)と呼んでおくことにします。
 例えば、以下のように、連続してdbディレクティブを使うと、次々とPC位置を進めながらデータを1バイトずつ入力できます。

 db  2
 db  3
 db  4
 db  5
 ……
 尚、こういう指定をしたい場合、dbは以下のように「カンマ区切り」で書くことができます。

 db 2,3,4,5
 「ヒートマンへのロックバスターでのダメージ」の後方には、他のボスへのダメージがあるので、もし仮にこういったコードを書いたら、他のボスに対するダメージを書き換える事になります。ここではヒートマンのそれのみを書き換えることにします。
 今入力したコードは、行こそは多いですが、実は説明した2行の繰り返しです。2行につき1つ、ダメージを指定しています。最後の一つは、相手から食らうダメージを設定しています。
 ここまで正しくasmファイルが作れているなら以下のようになっているはずです。

    inesprg $10 ;プログラムバンク数
    ineschr $00 ;キャラクタバンク数
    inesmap 1   ;マッパー番号
    inesmir 0   ;ミラーリング0:Horizontal 1:Vertical

    bank 0
    org $0000
    incbin "Original.prg"
;以下アセンブリを打ち込む

ROMADDR .macro
    bank ((\1-$10)/$2000)
    org (((\1-$10)&$1FFF)|$8000)
    .endm

    ROMADDR $2E933+0
    db   3 ;ロックバスター
    ROMADDR $2E941+0
    db $FF ;ヒートフルチャージ
    ROMADDR $2E94F+0
    db   4 ;エアー
    ROMADDR $2E95D+0
    db   4 ;リーフ
    ROMADDR $2E96B+0
    db  13 ;バブル
    ROMADDR $2E979+0
    db   4 ;クイック
    ROMADDR $2E987+0
    db   4 ;クラッシュ
    ROMADDR $2E995+0
    db   4 ;メタル
    ROMADDR $2E9A3+0
    db $07 ;相手の体当たりダメージ
 ところで、先ほどキャンバスの比喩を出しましたが、通常キャンバスはまっさらな状態からはじめ、多くのデータをアセンブラによって詰め込むことで「絵」つまり実際のROMとして完成させます。しかし、改造においては、まず完成した絵をキャンバスに準備する必要があります。
 その為に、「DataHack.asm」にある以下の3行

    bank 0
    org $0000
    incbin "Original.prg"
で、いきなり完成したROMを、アセンブラにロードしてしまいます。そしてその完成した状態から、絵筆を好きな場所に当ててガリガリ書き換えていくわけです。
雑魚の特殊武器耐性も書き換える
 ボスをやったら次は雑魚です。「そんなのボスと同じだろ解説する必要ないだろ」と思った人も居るかもしれません。それは正解です……が、この節でアセンブラの魅力が見えてくると思います。
 今回ダメージを書き換える対象は、エビの形をしたザコ「シュリンク」です。こいつは内部での処理番号が00なのです。コードは以下のようになります。先ほどのコードの下に追加してみましょう。(今後文にはしませんが、追加したら保存してアセンブルしてプレイして変わっているかを検証すると良いです)

    ;00 シュリンク
    ROMADDR $3E986+$00
    db   3 ;ロックバスター
    ROMADDR $3EA02+$00
    db  20 ;ヒートフルチャージ
    ROMADDR $3EA7A+$00
    db  10 ;エアー
    ROMADDR $3EAF2+$00
    db  20 ;リーフ
    ROMADDR $3EB6A+$00
    db   5 ;バブル
    ROMADDR $3EBE2+$00
    db   4 ;クイック
    ROMADDR $3EC5A+$00
    db  20 ;クラッシュ
    ROMADDR $3ECD2+$00
    db   4 ;メタル
    ROMADDR $3ED4A+$00
    db   1 ;相手の体当たりダメージ
 解説はボスと同じなのでしません。データの与え方を見た感じ、ダメージは低くなったが、耐久力が総じて上昇しており、うざったいザコに改造されたといったところです。
 さて、この節で語りたいのはそこではありません……もしロックマン2のザコ耐性を書き換えたことの有る方なら、この書き換え方を見て、「おおっ?」と思っているかもしれません。実際にやってみればわかるのですが、これをバイナリエディタで書き換えようとすると、アドレスが飛び飛びになっているので、目的の箇所を見つけ出すのがなかなか大変です。一方、こうしてアセンブラを使うと、非常に見通しがよく全部の武器に対する耐性を指定することができます。
 ……しかしそれだけではありません。続けて、処理番号0Cの大きなカエルのザコ「ケロッグ」の耐性も同じように書き換えてみましょう。以下のコードを追加します。

    ;0C ケロッグ
    ROMADDR $3E986+$0C
    db   3 ;ロックバスター
    ROMADDR $3EA02+$0C
    db  20 ;ヒートフルチャージ
    ROMADDR $3EA7A+$0C
    db   7 ;エアー
    ROMADDR $3EAF2+$0C
    db  20 ;リーフ
    ROMADDR $3EB6A+$0C
    db   5 ;バブル
    ROMADDR $3EBE2+$0C
    db   4 ;クイック
    ROMADDR $3EC5A+$0C
    db  20 ;クラッシュ
    ROMADDR $3ECD2+$0C
    db   4 ;メタル
    ROMADDR $3ED4A+$0C
    db  10 ;相手の体当たりダメージ
 一見してこれだけタイプするのは面倒に見えます……が、実は、先ほどの「シュリンク」のコードをコピペした後、後ろの「+$00」を「+$0C」に書き換えただけで準備が完了します。そして、実際にダメージを書き込んで作業終了です。
 他のザコの耐性を書き換えるのも、全く同様にコードをコピペしてサクッと終わらせることができます。
 この様に、大量のデータを打ち込む時の作業能率が大きく上がるのがアセンブラの特徴です。そして、後から見返しての修正するという時も、うっかり隣のバイトを弄ったりしてしまう危険性を大いに減らすことができます。
 ここまでのasmファイルはここの[3-20]の様になっているはずです
ところでROMADDRって……
 先程から当たり前のように使っているROMADDRですが、これはnesasmのコマンドではありません。自分で登録したマクロです。マクロというのは定型文のようなもので、よく使うお決まりのコードを登録しておいて利用したり、あるいは、後ろに与えた「引数」により、類似した処理のマイナーチェンジ版を作りながら利用したりすることができます。
 書き換え始める時に真っ先に書いた、これ。

ROMADDR .macro
    bank ((\1-$10)/$2000)
    org (((\1-$10)&$1FFF)|$8000)
    .endm
 これが「マクロ」の定義です。これの内容はともかくとし、とりあえずこうしておくと、ROMのアドレスを指定しただけで、「PC位置」を指定できます。
 マクロの詳細はnesasm同梱のusage.txtに書いてあります。あとは……慣れて下さい。
オチ
 バイナリエディタで1バイトずつ書き換えるように、アセンブラを使って書き換えることが出来るようになりました。ここまで理解して頂ければ、「それなら別にアセンブラなんて要らなくね?」とは思わないはずです。少なくとも、データの視認性を高めるのに役に立っています。
 次回は、もう少し色々なデータ改造を施してみましょう。
(244)2013年5月25日 プレさ兵衛
inserted by FC2 system