上に戻る
2.理屈抜きにとりあえずやってみる
概要
 とりあえず、バイナリエディタを使って、私の作ったROMを弄くってみようという感じで進行。
 『なぜある場所を変えるとどうなる』とか言う、理屈は抜きで。
 理屈も何も、自分で作ったんだから内情を全て知っているわけですが……
 しかもその内情は、一般に成り立つとは限らないわけですが……(いや、かつてプロの書いたコードと同レベルなものが自分に書けるわけないし……)まぁ、雰囲気はつかめるでしょ……
μBlock
 旧サイトの企画で、μBlockというファミコンのROMを作っていました。
 想像を絶するクソゲーなのですが、まぁ説明のために持ち出してこようと思います。
 ここからDLできます
 うーん……へぼすぎるせめてサウンドがついていれば……変わらんか。
 以下で、こいつをいじくりまわしながら、なんとなく改造の雰囲気をつかんでいこうという進行です。
タイトル画面を弄ってみる
 おいおい、プログラム改造じゃなかったのかよ……って突っ込まれそうですが。
 MB.nesをバイナリエディタで開き、アドレス900hを表示してください。なぜ900hなのかは理屈抜きです^^
 μB アドレス900当たり
 表示できたら、この当たりをおもむろに、80h〜99hまでの値でテキトーに埋めてみてください。
 『書込み禁止になっていないか』『上書きモードになっているか』が大事です。
 こんな感じで書き換えてみた
 こんな風に埋めてみた。これを保存したら、起動してみます。
 びふぉぁ → あふたー
 タイトル画面の『M I C R O』の部分がなにやら書き換わりました。
 どうも、1バイトに1文字が対応しているらしいことがわかります。(わかりますも何も、そういう風に作ったんだけどさ……元から)
 レトロなゲームではだいたい8ドット×8ドットのタイル状のグラフィックを並べることで背景を描きます。細かいことは端折りまして、μブロックでは、以下の256種類のタイルから選び、横に32個、縦に22個並べ、背景を作り上げます。
 この画像作るのけっこう大変だったんだぁ……
 あるタイルの、左の数値と上の数値を足したものがそのタイルの番号です。もちろん16進数です。例えば、Kは8Ahです。
 先ほどの書き換えでは80h〜を置いてみましたが、その部分ではアルファベットが対応していることがわかります。先ほど書き換えたデータは、このタイルの番号をそのまま指定しているということになります。(そういう風に作っ(略))
 試しに、10hに書き換えてみると、×の箱が表示されるはずです。
 さて、μブロックでは、画面の情報がベタに32×22個並べて保存してありましたが、通常のゲームソフトではそんな効率の悪いことはあまりしないと思います。何しろ容量にひっ迫していた時代ですので、圧縮ルーチンを書いたほうがデータ量が縮まるならそうするかもしれません。スーパーマリオブラザーズでもタイトル画面は圧縮されているそうです。
ステージを弄ってみる
 またまた理屈ぬきに、バイナリエディタでアドレスD00hの当たりをみてください。
D00 : FF FF FF FF FF FF FF FF FF FF 10 10 FF FF FF FF
 と、なっています。この辺を、00h〜08hまでにテキトーに埋めていってください。
 こんくらいラクにいろんなソフトが書き換えられたらいいのに
 1面のブロック配置が変わりました。
 これも、1バイト=1タイルで、タイル番号そのまま対応して置かれているようです。(そういう風(略))
 タイトル画面のところでも書きましたが、通常のゲームソフトではこんな格納方法はありえないと思います。
 マップは広大であることが多いので、明らかに圧縮したほうがいいですからね。
 マリオなんて、ものすごい圧縮がかかっているようです……割と多いのが、縦横いくつかタイルを並べたものを単位として、それを改めて並べていく……という圧縮のしかたです。
ちょっとプログラム改造してみる
 理屈は抜きです^^アドレス4F5h付近をみてください。
4F0 : AD 40 00 18 69 04 C9 C0 B0 08 A2 01 8E 41 00 4C
 4F5hは、04hです。これを、08hとしてみてください。そして保存して実行してみてください。
 ……下のバー(正式名称なに?)の、右に動くときのスピードが上がりました。
 これは、立派にプログラム改造です……たぶん^^

 何もかもを省略しまくって大雑把に言いますと実は、04hの前の、69hは、ファミコンのCPUでは足し算の命令です。
 バーのX座標に4を足すことで、右に動いていた……ということです。これを8足す……と書き換えることにより、バーのスピードが上がったのです。
 69hの次の、04hが、『足す数』……ということです。

 では、なぜ、69hが足し算の命令なのか。知りません(爆)
 たぶん、CPUがそうなるように設計されているのでしょう。このように、特定の仕事を割り当てられたある番号を、『オペコード』と言うような気がします
 一方で、『オペコード』に対し、その動作を決めるような続く値……この足し算命令においては『足す数』のことを『オペランド』と言うと思います。
 主語はCPU、述語が『オペコード』、目的語……ではなく、修飾語が『オペランド』……とでも言えますかね。

 ファミコンのCPUでは、『オペコード』は、全て1バイトですが、   ゲームボーイのCPUでは、2バイトの『オペコード』があるように思えます。(あんま知らない^^)
 ちなみに、現行(?)Intel互換のCPUでは、1〜3バイトの『オペコード』と書いてありました。(オペコードの前にさらに何かつけたりするらしい……)

 一方で、『オペランド』は『オペコード』によって、何バイト取るかが異なります。
 例の足し算の命令では、『いくつ足すのか』という1バイトを『オペランド』として取りました。
 しかし、例えばCLCやRTSという命令では、『オペランド』は取りません。
 ファミコンのCPUでは、2バイトまでの『オペランド』を取る『オペコード』が存在するようです。
 ちなみに、スーファミのCPUでは、CPUの状態によって取る『オペランド』の数が変わったりして、目が回ります^^

 とんでもなく大雑把に4F5h付近で何をしているのかを書いてみます。上の通り、
4F0 : AD 40 00 18 69 04 C9 C0 B0 08 A2 01 8E 41 00 4C
 となっているのですが、先頭から……
   AD 40 00……aという場所に、メモリ0040hからデータを読み出します。(いろいろマズイが割愛)
   18    ……キャリーフラグっていうのをクリアします。
   69 04  ……aという場所のものに、04hを足します。
   C9 C0  ……aとC0hを比較します(実は右に行き過ぎないようにするための処理)
   B0 08  ……もしC0hより先に行ってしまったら、処理アドレスを08h進める(ジャンプする)
   (以下略)
 何がなんだか訳がわからんと思いますが、とりあえず、一見して何の意味もないような数字の列には、このような意味のある一連のプログラムが秘められていたのです……

 こんな感じで、ファミコンのROM中にはこういった『プログラム』や、前半で書き換えたような『データ』それに、『グラフィックデータ』それと先頭に『ヘッダ』が存在しています。
(『プログラム』と『データ』はこの列挙では区別すべきではないと思うが)
 やりたいことに応じて、どの部分が対象のものなのかを調べ、どのように書き換えていくかが改造をするということなのだと思います。
オチ?
 バイナリエディタについてはもういいですね。
 後半の話は、バイナリエディタで見れる、一見無秩序に並んでいるように思える値の、その多くは意味のあるものだということです。意味ない部分も結構あったりしますが^^
 目的のデータがどこにあり、どのように書き換えればいいのかを探し出すのが、改造の醍醐味(?)なんだと思います……たぶん。
(6)2006年12月24日 プレさ兵衛
inserted by FC2 system