|
●単純書き込み(RAM)
0aaaaaaa 000000dd
1aaaaaaa 0000dddd
2aaaaaaa dddddddd
aで示すアドレスにdで示すデータを書き込みます。上からそれぞれbyte/halfword/word単位での書き込みです。
●複数アドレスへの同一データ連続書き込み
3000nnnn dddddddd aaaaaaaa×(n-1)
(n-1)回のaで示すアドレス群にdで示すデータをまとめて書き込みます。単位はword。
※・・だけだったら良いんですが、d自体をもアドレスとみなして一度余計に書いてしまっています。
●指定アドレスの値加減算
301000nn aaaaaaaa
302000nn aaaaaaaa
3030nnnn aaaaaaaa
3040nnnn aaaaaaaa
3050xxxx aaaaaaaa nnnnnnnn 00000000
3060xxxx aaaaaaaa nnnnnnnn 00000000
aで示すアドレス内のデータにnの値を、3文字目が奇数なら加算、偶数なら減算し続けます。
加減算値の単位は3種ありますが、対象データの単位はword固定です。
※nまたはxの値は、0にすると入力時にハングアップしてしまうようです。
●単純書き込み(ROM)
6aaaaaaa 0000dddd
aで示す値×2のアドレスにdで示すデータを書き込みます。単位はhalfword。
08000000h以降のROMエリアを変更する場合に使用します。
●スイッチ書き込み
8a1aaaaa 000000dd
8a2aaaaa 0000dddd
8a4aaaaa dddddddd
PARスイッチが押された時に、アドレス0a0aaaaaにdで示すデータを書き込みます。
上からそれぞれbyte/halfword/word単位での書き込みです。
●スローモーション
80F00000 0000xxxx
PARスイッチを押すことによってゲームがスローモーションになります。
xの値で速度を調整します。FFFFが最低速。再度押すと元に戻ります。
●条件比較(1)
Daaaaaaa 0000dddd
Daaaaaaa 0010dddd
Daaaaaaa 0020dddd
Daaaaaaa 0030dddd
aで示すアドレスのデータと、dで示すデータを比較し、条件に合致する場合のみ次のコードを実行します。単位はhalfword。
条件は上からそれぞれ、=、≠、d≧(a)、(a)≧dです。
●条件比較(2)
E0nndddd 0aaaaaaa
E0nndddd 1aaaaaaa
E0nndddd 2aaaaaaa
E0nndddd 3aaaaaaa
(1)と同様ですが、一致しない場合は以下、nで示す数のコード群を一気にスキップします。
●不明
DEADFACE yyyyyyyy
●マスターコード
Faaaaaaa 0000010b
cccccccc 001DC0DE
ゲーム内からcheatを有効にするために必要なコードです。
カラットがコードを発表している場合はそれを使えば良い訳ですが、ない場合はツールで検索する、あるいは自前で作成する必要があります。
aで示す値は、PARがフックすると思われる、頻繁に実行されるアドレスです。PS2PARの形式4と同様、キー入力ポート(04000130h)を読み出している辺りのアドレスが指定されている場合が多い感じです(後述)。
bの値は、フックの種類かと思われますが、詳細は不明。ほとんどが1ですが、ごく一部で3がありました。
cで示す値は、カートリッジに記載されているコード"AGB-XXXX-JPN"のXXXXの部分をASCII文字列で前後逆に表したもので、例えば"ABCD" ならば 44434241 となります。
他、固定値で書いた0000010及び001DC0DEについては、いくつか調べたコードが全てこの形でしたので、今の所固定とします。
※マスターコードのアドレスの求め方の例
1.ROMを吸い出す。
5〜6が複数見つかる場合は、見つかった順に試します。
(例)FE-封印の剣-の場合
1〜4/略
5.に該当するのは
2.ここから disarm (arm/thumb用逆アセンブラ)を入手。
3.全部逆アセンブルはデカすぎると思いますので、バイナリエディタでROMの先頭から適当に40000Hバイト程を抽出、仮にX.BINとする。
4.DOS窓から > DISARM -s08000000 -t X.BIN > X.SRC と入力。(Thumb命令として逆アセンブル)
5.X.SRCをテキストエディタで開き、"(SPACE)0130(SPACE)"を検索し、次の行が 0400 となっている事を確認。
ワイルドカード等が使えるなら、"(SPACE)0130(SPACE)*\n*(SPACE)0400(SPACE)"とかで検索でもOK。
6.発見したアドレスに対して、ldr命令で読み出している箇所を検索。
7.見つかったらその後の、SP/LR/PCレジスタに関らない命令(movやmvn等)が2つ続けて存在するアドレスが該当。
8.マスターコードを入力して試してみる。テストにはスローモーションコード(78960794 27667199)が便利。
確実性を上げるなら、VBA-SDLのデバッガで7のアドレスにBreakPointを置いてみる(bt命令)などして、頻繁に通っている事を確認すると良いでしょう。08001930 0130 lsl r0, r6, #4
08001932 0400 lsl r0, r0, #16
6.に該当するのは
08001910 4807 ldr r0, [pc, #28] ($08001930)
7.に該当するのは$08001912〜$08001920までならどこでも。例として
08001914 43c8 mvn r0, r1
08001916 1c01 mov r1, r0
8.カートリッジのコードは"AGB-AFEJ-JPN"なので、マスターコードは
F8001914 00000101
4A454641 001DC0DE
暗号化すると
2490A08C D22C5D79
42490754 CF825CD7
となります。
bitの配列をシャッフルした後、XORをいろんなパターンで6回程掛けています。良くある乱数生成ルーチンのseed値に固定値を入力することによって、出て来る数値が一定の値になることを利用しているようです。その固定値を決定するのにマスターコード1行目の値が様々な形で利用されています。
変換用ツール:ツールのお部屋のGBACODE(DOS汎用)/暗号/復号部ソース(386)
・コードの機能
●単純書き込み
3aaaaaaa 00dd:1バイト書き込み
8aaaaaaa dddd:2バイト書き込み
●演算書き込み
2aaaaaaa dddd:or書き込み
6aaaaaaa dddd:and書き込み
Eaaaaaaa dddd:加算書き込み
(a)のデータにdの値をorまたはandまたは加算して(a)に書き込みます。
●連続書き込み
4aaaaaaa dddd aaaabbbb cccc
a:データ加算値、b:繰り返し回数、c:アドレス加算値として繰り返し書き込みます。
5aaaaaaa dddd xxxxxxxx xxxx・・・
d:バイト数×2として以下のデータをそのまま書き込みます。
●条件比較
7aaaaaaa dddd:=
Aaaaaaaa dddd:≠
Baaaaaaa dddd:<
Caaaaaaa dddd:>
Faaaaaaa dddd:and
d=(a)、d≠(a)、d<(a)、d>(a)の場合、またはd and (a)が0でない場合次のコードを実行します。
●キー入力判定
D0000010 xxxx:≠
D0000020 xxxx:=
xはBitで******LR ↓↑←→StSeBA、1で押されている状態とし、
不一致または一致した場合次のコードを実行します。
●マスターコード
9:マスターコード1行目。
0:マスターコード2行目。
1:マスターコード3行目。
1行目は先頭9で以下は暗号/復号用の値。(省略可らしい)
2行目は先頭0でアドレス部はROM先頭64KBのCRC値[計算ツール/計算部ソース]。この値はXTA起動時LRABを押しておくと解るらしい。ツール作った意味なし(泣)。データ部は通常000A。
3行目は先頭1でアドレス部はフックポイントか?PAR用マスターコード検索ツールで出たアドレス付近を指定(ただし2文字目の8は0にする)して動く事がある。ADVTermがあれば"]w f l filename"と入力すると解るらしい。データ部は通常0007。
試しに公表されているコードの1行目を900000000000として、2、3行目をそれ用に暗号化し直した物を入れても動いちゃいました(偶然かもしれませんが)。ゲームによって1行目が全然違う値になっているのが最大の謎(?)です。特に頭から2バイト目などは、暗号処理にすら使われていません。
VisualBoyAdvanceでは、先頭値0,3,4,7,8,A,Dについてのみ処理を行っています。
また、ねこかぶさんのサイトにも解説がありますので、そちらも参照してみて下さい。