目次
バイナリ編集概要
CDイメージをバイナリエディタで編集することで、ゲームデータの改変が可能。
改造コードでは実現が難しい、セーブデータだけでは保持されないデータの改造はもちろん、
大規模編集によるオリジナルデータの作成なども可能となる。
基本的な考えは
改造コードと同じであり、
ファイルの位置、データの位置、値の役割を把握した上で、そこのデータを書き換えれば望みの結果を得られる。
しかし改造範囲が大規模になると、CD-ROM形式の特有のデータの並び方など、いくつか把握しておくべき論点が生じる。
セクタ構造
CDイメージをマウントし、エキスプローラ等で開くと、中の「実データ」を閲覧・抽出することができる。
この時のファイルAのデータ列の状態を以下とする。
しかし、CDイメージそのものをバイナリエディタで開き、データAの部分に移動すると、
このように、データAが一定単位ごとに別の「仕切りデータ」で分割されていることが分かる。
この時、A1、A2、A3・・・を結合していくとファイルAと一致する。
仕切りデータのサイズは304(130h)バイト
+仕切られた実データの分割単位は2048(800h)バイト
=これがセットで1セクタ、計2352(930h)バイトとなる。
以下は304バイトの仕切りデータの見本。実際にはセクタ毎のヘッダー、エラー訂正符号などの役割を担う。
XXにはランダムなデータが入るが、先頭と末尾に特徴的な00とFFの並びが現れるため、慣れれば見分けることができる。
XX XX XX XX 00 00 00 00 00 00 00 00 XX XX XX XX
XX XX XX XX XX XX XX XX XX XX XX XX XX XX XX XX
XX XX XX XX XX XX XX XX XX XX XX XX XX XX XX XX
XX XX XX XX XX XX XX XX XX XX XX XX XX XX XX XX
XX XX XX XX XX XX XX XX XX XX XX XX XX XX XX XX
XX XX XX XX XX XX XX XX XX XX XX XX XX XX XX XX
XX XX XX XX XX XX XX XX XX XX XX XX XX XX XX XX
XX XX XX XX XX XX XX XX XX XX XX XX XX XX XX XX
XX XX XX XX XX XX XX XX XX XX XX XX XX XX XX XX
XX XX XX XX XX XX XX XX XX XX XX XX XX XX XX XX
XX XX XX XX XX XX XX XX XX XX XX XX XX XX XX XX
XX XX XX XX XX XX XX XX XX XX XX XX XX XX XX XX
XX XX XX XX XX XX XX XX XX XX XX XX XX XX XX XX
XX XX XX XX XX XX XX XX XX XX XX XX XX XX XX XX
XX XX XX XX XX XX XX XX XX XX XX XX XX XX XX XX
XX XX XX XX XX XX XX XX XX XX XX XX XX XX XX XX
XX XX XX XX XX XX XX XX XX XX XX XX XX XX XX XX
XX XX XX XX XX XX XX XX XX XX XX XX XX XX XX XX
XX FF FF FF FF FF FF FF FF FF FF XX XX XX XX XX
仕切りデータそのものは全く解析できていないが、する必要も恐らくない。
少なくともこれまでの試行では、仕切りデータを弄ることなく改造データは上手く動いている。
巨大なデータの差し替えは困難
差し替えやデータ移動の量が多くなる場合は面倒な事になる。例えばファイルAを改造したファイルA'をAの位置に組み込む場合、
A'を2048バイトずつのA'1、A'2、A'3・・・に分割しつつ、A1、A2、A3の位置に正確にコピペしていく作業が必要だ。
例えばBGMデータも上記原理で理論上は差し替え可能だが、ファイルサイズが巨大で数千セクタにも及ぶため、
手動で分割コピペしていくのは非現実的だ。よって改造は小~中規模に抑えるのが無難である。
プログラムで上記処理を行うツールが作れるならそれが一番だが、できない人は苦労することになる。
(ちなみに筆者はキーマクロを利用した自動コピペ法を考えたことがある)
仕切りデータの構造を無視してA'の実データ列を丸ごと貼り付けてしまうことも不可能ではない(SSFが読んでくれた事例もある)が、
少なくともCD-ROMセクタ構造は失われ、Windowsエキスプローラではフォルダごと読めなくなるし、
ゲーム内でも不測のエラーが起こる可能性は十分にあり、あまり推奨できる方法ではない。
セクタ構造2
以上のようにファイルの差し替えにあたっては面倒な方式だが、利点もある。
ファイルの先頭データは必ずセクタの先頭に来るという特徴がある。
つまり、仕切りデータに着目するとファイルの開始位置が特定しやすい。
よってセクタで区切られた空間(実ファイルデータに使える空間)は2048バイトの倍数になる。
実際のファイルサイズが2048の倍数に満たない場合、余りの領域は00で満たされる。
よって00の羅列に着目するとファイルの終端位置を見積もれる場合もある。
・・・ |
An-1 |
仕切 |
An(終端) |
余り(0000...) |
仕切 |
B1 |
仕切 |
B2 |
・・・ |
次にCDイメージにおける一番初めのセクタの実データ位置だが、
実はアドレス0(冒頭)ではなく、アドレス10h(17バイト目~)である。
以下に鋼鉄のアドレス0~のデータを載せる。
00 FF FF FF FF FF FF FF FF FF FF 00 00 02 00 01
53 45 47 41 20 53 45 47 41 53 41 54 55 52 4E 20
53 45 47 41 20 45 4E 54 45 52 50 52 49 53 45 53
47 53 39 30 32 35 20 20 20 20 56 31 2E 30 30 30
31 39 39 35 30 38 32 34 43 44 2D 31 2F 31 20 20
4A 54 20 20 20 20 20 20 20 20 20 20 20 20 20 20
4A 4D 20 20 20 20 20 20 20 20 20 20 20 20 20 20
57 4F 52 4C 44 20 41 44 56 41 4E 43 45 44 20 44
41 49 53 45 4E 52 59 41 4B 55 20 20 20 20 20 20
20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20
20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20
20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20
20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20
20 20 20 20 20 20 20 20 20 20 20 20 20 20 20 20
00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
~
2行目(アドレス10h)~8行目「53 45 47 41 20 53 45 47 ~ 53 45 4E 52 59 41 4B 55」は
ASCII形式で「SEGA SEGASATURN ~ WORLD ADVANCED DAISENRYAKU」を表すが、
その前の「00 FF FF FF FF FF FF FF FF FF FF 00 00 02 00 01」は先ほどの304バイトの仕切りデータの末尾16バイトに相当する。
つまり304バイトのうち、末尾16バイトは実はセクタのヘッダで、残りの288バイトはフッタということになる。
以上により、ファイルの実データは 10h+n×(2048+304) の位置にあると分かる。
これが次のファイルインデックスの話に繋がる。
ファイルインデックス
アドレスB7D0~に移動すると、CDイメージ内のファイル名などが書かれたデータに遭遇する。
22 00 14 00 00 00 00 00 00 14 00 20 00 00 00 00
20 00 5F 08 18 0F 02 22 14 02 00 00 01 00 00 01
01 00 22 00 14 00 00 00 00 00 00 14 00 20 00 00
00 00 20 00 5F 08 18 0F 02 22 14 02 00 00 01 00
00 01 01 01 2E 00 31 00 00 00 00 00 00 31 14 1A
02 00 00 02 1A 14 5F 08 18 0F 02 22 14 00 00 00
01 00 00 01 0C 30 30 30 30 30 30 30 30 2E 42 49
4E 00 2C 00 23 8E 01 00 00 01 8E 23 00 C0 2F 00
00 2F C0 00 5F 08 18 0F 02 22 14 00 00 00 01 00
~
上記のうち冒頭のデータ(22 00 14 00~)は解説しづらいため、5行目途中の「2E 00 31 00 ~」から解説する。
結論から言えばこの「2E 00 31 00 ~」は「00000000.bin」を示すインデックスである。
- 2E: インデックス1件のデータサイズ。この場合は2Eの箇所から数えて46バイトでひとまとまり。
どうやら必ず2の倍数になっているらしい(後述)
- 00: 不明。多分特に意味のないクッションデータ。
- 31 00 00 00 00 00 00 31: 実データが格納されているセクタ番号。
リトルエンディアン4バイト(31 00 00 00)と、ビッグエンディアン4バイト(00 00 00 31)、
同じ値が両方の形式で格納されている。(エンディアンについては
Wikipediaを参照)
セクタ番号は16進で0から数えるため、31h+1=50番目のセクタを表す。先述の計算式により、
このファイルは 10h+31h×(2048+304)=アドレス1C240 以降にあるということになる。
- 14 1A 02 00 00 02 1A 14: 実データのファイルサイズ。
これもリトルエンディアン4バイトとビッグエンディアン4バイトで格納されている。
つまりこの場合は 21A14=137,748バイト。
- 5F 08 18 0F 02 22: 1バイトごとに年月日時分秒を表す。
作成日時と更新日時の区別はないため、エクスプローラ上では両方この日付時刻が表示される。
これをそのまま10進にすると(19)95/8/24 15:02:34である。
しかし実際は(日本では)これに+4時間した1995/8/24 19:02:34と表示される。
元データの15:02はUTC(世界標準時)でもないので、なぜこうなのかは良く分かっていない。
※ なお、+4時間した結果日付が変わるようであれば繰り上げて表示される。
(例:
作戦ファイル、FILM0000.CPK、日本時1995/8/16 2:46、元データは8/15 22:46)
今のところ不明。ただしファイルでなくフォルダの場合は2バイト目が02に変化することは判明している。
- 0C:次に続くファイル名の文字数(データサイズ)つまり0C=12文字。
- 30 30 30 30 30 30 30 30 2E 42 49 4E:「00000000.bin」←ぴったり12文字
ASCII文字コード形式でファイル名を表す。ただしこのファイルは違うが、末尾になぜか「;1」(3B 31)が付く場合が殆どで、
その場合はファイル文字数も「;1」分までカウントされる(エクスプローラ上では「;1」は表示されない)。
- 00:多分ただのクッションデータ。ここまで46バイト、直後は次のインデックスになる。
なおこの00は無い場合がある。先述の通りインデックス1件のデータは必ず偶数になっている模様だが、
変動要因であるファイル名文字数自体は偶奇どちらもありうる。そこでこの00があるかないかで偶数に調整しているようだ。
改めて冒頭の「22 00 14 00~」を解析すると、
インデックスデータ量22バイト、セクタ番号14h(アドレスB7D0)、ファイルサイズ8,192バイト(4セクタ分)、
時刻(日本時)1995/8/24 19:02:34、続いて14 02 00 00 01 00 00 01(2バイト目が02なのでフォルダ属性を表す)、
ファイル名なし(ファイル名文字数は0ではなく1とされている)
※ 以上がなぜかほぼ2回繰り返されており、その後00000000.binのインデックスへと続く。
アドレスB7D0はこのファイルインデックスの冒頭と一致する。つまりこのCD-ROMの「ルートフォルダ」と推定される。
改造におけるインデックス利用
改造目的でインデックスを使うのであれば、
・セクタ番号: 実データ格納アドレスを計算、あるいは参照セクタそのものを変えてしまう
・ファイルサイズ: 改造対象のファイルサイズを増やしたいときにここの値を変える
などが重要になるだろう。
特にセクタ番号の情報は改造したいファイルの冒頭データをコピー → 検索だけでは限界がある場合に有効だ。
ただしファイルサイズを増やすのには上限がある(2048の倍数を超えると次のファイルのセクタ領域に行ってしまう)
ので、より大規模な改造としては、CDイメージ全体の末尾にある大量の空白セクタを利用して、
ここに新たにファイルを書き込み、それをインデックスから参照させるといったこともできるかもしれない。
(あまり大きいファイルだと当面は困難ではあるが)
最終更新:2023年02月20日 17:05