什么是金手指

金手指是 GameBoy 和 NDS 系列游戏的修改工具,可直接修改游戏数据。主流GBA模拟器基本都支持金手指,目前金手指有Raw CodeGame SharkCode Breaker三种格式,其中Raw Code是原始代码格式,其代码就是真实地址和数据,后面两种都是原始代码加密后的形式。

  • Raw Code 原始代码,格式一般为:变量地址:变量取值。由冒号分开,变量地址是8位的十六进制数,而变量取值可以是2位、4位或者8位十六进制数任意一种。

  • Game Shark(V3) 是基于原始代码(Raw Code)和某些规则,并采用算法加密生成的代码,可简化代码量,格式为:8位十六进制数 8位十六进制数,是由单个空格分隔的两个8位十六进制数。

  • Code Breaker 也是基于原始代码(Raw Code)和某些规则生成的代码,也被称为代码断路器,格式为:8位十六进制数 4位十六进制数这种类型的金手指用的很少。

金手指格式转换

Raw Code <–> Game Shark V3

转换方式

表格基本概念

  • 中间代码的类型 中间代码以行为单位,每行中间代码的格式和V3码相同,都是由单个空格隔开的两个8位十六进制数,中间代码最左边的2位表示中间代码的类型,具体参考表格类型给出的范例。如(02024EA4 -> 00 224EA4)对应Type 00(02024EA4 -> 02 224EA4)对应Type 01

  • 转换规则 类型不同,转换规则也不一样。如表格里Type 00的(02024EA4 -> 00224EA4),括号内是其地址的转换规则,下面的是数据处理规则。

基本转换思路

Raw Code <–> 中间代码 根据功能(每行前2位)寻找合适的中间代码类型,然后根据类型转换规则转换

中间代码 <–> Game Shark V3 使用 gba-ar-crypt 一键转换

升级全国图鉴(B+Select)【GS】

1
2
0CE31DF7 6D3FC225
922CCA11 DE549709

转换为中间代码如下:

1
2
0A400130 000003F9(Type 05,如果04000130一半地址出现03F9就执行下一条代码)
04300E48 081F9EFC(Type 02,在地址03000E48写入081F9EFC)

穿墙(可开关,L开R关)【GS】

1
2
3
4
5
6
7
E8A2266F 4ABC1FE6
94215FE5 80EB4180
0128E239 8B1570A9
B58391F5 1E83E6D2
8E883EFF 92E9660D
6A7D8822 F44AFDAB
C17E0105 7EA5840F

转换为中间代码如下:

1
2
3
4
5
6
7
0A4C0130 000001FF(Type 05,如果04000130一半地址出现01FF就执行下一条代码)
002E4000 00000001(Type 00,用字节 01 将从 020E4000 到 020E4000 的地址区域填满)
482E4000 00000001(Type 24,如果020E4000地址出现01就执行下两条代码)
00000000 18045788(Type 00,用字节 88 将从 02000000 到 02180457 的地址区域填满)
00002000 00000000(Type 00,用字节 00 将从 02002000 到 02002000 的地址区域填满)
0A4C0130 000002FF(Type 05,如果04000130一半地址出现02FF就执行下一条代码)
002E4000 00000000(Type 00,用字节 00 将从 020E4000 到 020E4000 的地址区域填满)

参考Game Shark V3格式码的原理

Raw Code <–> Code Breaker

CB码和V3格式码类似,不同之处在于CB码没有中间代码,且不需要加密,转换规则如下

Type 3:写入一个字节的数据 02024540 64(原始代码) <–> 32024540 0064(CB码)

Type 8:写入两个字节的数据 0202450C 02B0(原始代码) <–> 8202450C 02B0(CB码) 也就是网上传的苹果delta模拟器使用原始代码教程

Type 2:用给定的值和某个地址处的16位数据(两个字节)进行“逻辑或”运算,将二进制运算结果写入该地址二进制最高位。
比如首宠6V个体值代码02024534 3FFFFFFF(原始代码),这个代码地址二进制数的最高位决定普通特性,次高位决定是否为蛋,而个体值是由该地址后面3-32位二进制数决定的,一个16进制数占用4位二进制宽度,所以仅使用原始代码无法单独修改第1、2位的数据,这时使用CB码的“逻辑或”运算可做到仅改变第1或者第2位的数据,将其和8000(1000 0000 0000 0000)做逻辑或运算22024536 8000(CB码),可以不改变其它位数据,仅将首位二进制数置为1,也就是仅改变普通特性

Type 6:“逻辑与”,和“逻辑或”类似,一般和7FFF(0111 1111 1111 1111)搭配使用 62024536 7FFF,将地址首位二进制数置为0

Type 4:批量写入,格式:4aaaaaaa yyyyzzzzxxxx iiii 含义是从地址aaaaaaa开始,每相隔iiii的长度写入一次yyyy数据,每次写入之后内容再加上zzzz,共写入xxxx次。
举个例子,V3格式码的“全图鉴发现”金手指,它对应的中间代码是:

1
2
3
00225F60 000000FE
00225F61 00006EFF
00225FD0 00000007

根据这3行中间代码可以很方便地转换成CB码:

1
2
3
4
82025F60 FFFE
42025F62 FFFF
00000037 0002
82025FD0 0007

这里看一下CB码的中间两行,含义是从02025F62开始,每隔2个字节(0002)写入一次FFFF,共写入55(0037)次,由于每次写入的都是FFFF,不需要变化,因此Type 4类型的第二行左侧高四位是0000。
由于每次写入的字节数固定为2个(这是CB码格式规定的,空格的右边是4位十六进制数,也就是2个字节),所以使用Type 4的CB码进行连续地批量写入时,一般来说第二行的右半边都是0002,也就是每隔2个字节写入2个字节,让写入的内容连续起来。

Type 7:条件判断
Type 7类型最常用的地方是按键触发类的金手指,比如V3格式码的“随身回复”金手指,它的对应的中间代码是:

1
2
0A400130 000003F9 // 当04000130处的变量取值为03F9时,执行下一条代码
04300E48 081FC01A // 将“对话程序”对应的变量修改为和精灵中心护士对话的程序

这两行代码对应的CB码是:

1
2
3
4
74000130 03F9
83000E48 C01A
74000130 03F9
83000E4A 081F

由于CB码一次最多只能写入2个字节,而对话程序的地址都是4个字节,所以需要用两次条件判断,分两次写入2个字节,这也是CB码相对于V3格式码麻烦一点的地方。

参考:CB码/code breaker/代码断路器介绍——科普向,什么是金手指(十一)

金手指制作

金手指制作是最难的一步,任天堂的游戏是闭源的,只能逆向修改游戏,这需要一定的计算机基础,至少要知道数据地址和代码调试的概念

金手指本质就是游戏数据,学会查看这些数据已经成功一半了,一般使用GBA模拟器查看

  • mGBA 一个GBA模拟器,可以方便地查看内存与修改数据,偏游戏

  • visualboyadvance-m 一个GBA模拟器,可以方便地查看内存与修改数据,偏开发

  • No$GBA 一个GBA即时断点调试模拟器,通过断点不仅可以找到游戏当前状态数据,还可以通过数据地址反查XSE脚本,找到XSE脚本就能改很多东西了

No$GBA的断点调试类似于编程里的代码调试,不过面对的是16进制数据,更难看懂了,使用起来有一定门槛,下面是简略的打断点教程
语法[地址][参数]或者[内存区域][参数]
参数详解
? 在任何读取(从指定地址/区域)时断点
!? 在任何读取或改变写入时断点
!!? 在任何读取或任何写入时断点
! 在改变写入时断点
!! 在任何写入时断点
示例

1
2
[3007ffc]! 当地址为3007ffc的数据被修改时中断
[6000000..6003fff]? 当此内存区域被读取时中断

菜单中选择“Debug-Define Watchpoint”直接输入变量地址可在左下方查看实时变量数据

可能用得上的数据
04000130 03FF 按键地址及默认取值
按键映射表

组合键取值计算方法(以Select+上为例):(0040 or 0004) xor 03FF = 03BB

03000e48 对话程序的变量地址