当前位置: 首页 > 工具软件 > zelda > 使用案例 >

[转]DS汉化破解技术之 Zelda DS PH NFTR字库扩容 by Crystal

姬高澹
2023-12-01

注:这个是Crystal(白总)写的教程。

 

 

Crystal破解技术:
可以破解Zelda首先少不了的NO$GBA Debugger
这里先感谢某人提供此调试器(至于是谁,对方要求保密,这里就不说出来了)
这里先说声谢谢orz。

由于NFTR字库是放在内存的,所以无法直接扩大
她的CGLP段,否则在游戏载入字库到内存时,
会导致内存溢出,结果当然是黑屏的啦。
所以就要跟踪看看游戏到底怎么处理这个字库的。
小白就以 zeldaDS_15.nftr 文件为例子
扩容到了3xxx多字,够用的了,而且没降低字模位数、大小。

1。中断首地址(用来计算字库的字模偏移量)
这个字库的大小是14x16 4色 2BPP的,字库的结构下面会说明
和GBA一样,要中断当然要字库的首地址了,她的首地址就是
字库的CGLP段+0x10就是rom0x00A1303C
(rom地址以rom开始,以便和内存地址区分)
这个地址是无法直接中断的,以为她是被复制到内存的
所以要先跟踪游戏载入NFTR字库的过程,看看她载入到了哪个
内存地址里面,首先下地毯式内存中断(小白的常用方法)
r0=0x00A13000,r1=0x00A13000,r2=0x00A13000,r3=0x00A13000
一般下r0-r3这四个通用寄存器就可以了,中断失败才尝试其他的寄存器
结构在02040608中断,分析发现是载入FAT表
一般第一次中断到的都会是载入FAT(文件分配表的地址可以无视)
按下F9继续跟踪,结果中断在02007BCC处,但是发现还是不是载入代码
一般要中断在ASM处理B7aaaaaaaa000000设置文件地址时才是载入过程
继续中断吧。改为中断[40001a8]=0xb7,结果中断在02040374里面
按几下F7,发现[40001a8]=B7 00 A1 30 00 00 00 00(嘿嘿,字库地址)
出来后在02040608里面就开始复制到内存023C9540
记住了,字库在内存的首地址呀,可以按几下F7,会发现数据不断复制到内存
载入完毕后,首地址和ROM地址一样+CGLP+0x10定位到真正的首地址
就是023C957C,到了这里首地址的工作就结束了
2。 字模在内存字库的偏移量
首先先计算某字模在rom的偏移量,至于是哪个字模,当然是游戏要显示的那个了
如ファイル的フ这个字在模拟器里面一般都是第一次出现的了
用ct2在字库CGLP段查看字模在rom0x00A1778C,注意这个是rom的地址
不能直接中断(汝想中断也不可能-v-),首先计算她在rom首地址的偏差
rom0x00A1778C(フ)-rom0x00A1303C(首地址)=0x4750
将这个值和内存的首地址相加自然就是内存字库里面的字模(フ)偏移量了
简单的数学运算:0x023C957C+0x4750-0x38(字模大小)=0x23CDC94
中断这个要显示的文字吧。r0=0x23CDC94,r1=0x23CDC94,r2=0x23CDC94,r3=0x23CDC94
结果在02029738>mla r1,r4,r1,r2 中断
r4=字模索引,r2=字模大小,r2=内存首地址,就是 r1=r4 X r1 + r2
3。破解上面的偏移计算ASM
首先在rom里面查找这些代码,以便在rom里面修改她,发现怎么也找不到(-_,-~~~)
复位游戏,中断[02029738]!,结果发现这些代码是SDK集:rom0x4B87(ARM9.bin)
![SDK+NINTENDO:BACKUP],不了解这个部分。
不行,改为在ARM9.bin搜索单条指令 94 21 21 E0,结果知道rom0x1F8E0。
试试修改她,重新载入游戏,发现指令改变了,可惜只有一条指令-_,-~~~
这怎么破解嘛~,打算放弃的了,后来想到字库的CGLP段是载入内存的
而且要扩容原本的字库肯定不够大的了,要开辟新的字库空间,她放着也是没用
而且是在内存里面的;想到这里就突然灵光一闪(嘿嘿)
由于Rom地址是不可执行的,小白就将代码写在CGLP+0x10就是首地址里面
反正这个字库是不能扩大的(导致内存溢出),干脆用来做ASM看见好了
嘎嘎,这样就有大量的asm空间了不用怕找不到地方放asm代码了
(PS:同志们在找不到内存ASm时就用小白这个办法吧)

将上面的02029738>mla r1,r4,r1,r2 改为 blx r2
就是pc跳到内存的字库首地址里面执行,我们只要将破解指令放在那里就可以了。
下面粘贴小白的破解代码(代码使用goldroad ARM编译):
将她编译后放到字库CGLP段+0x10的首地址上。

上面的代码将会计算到的字模偏移量对应于rom的地址数据载入到指定内存
这里将计算到的数据也是载入到这个可以让大家发挥的鸡肋字库里面(汝不会用完整个字库吧?)
然后将这个地址放到r1返回,这样游戏画字时就从r1读取了。
4。NFTR字库文件结构
之前小白破解了字库CGLP段,但是这种字库时通过CMAP段将字符编码转换成索引号的
就是字模在字库的第几个Tile上。字库扩容了,这个索引表也要同时扩大。
由于NFTR字库文件的大小不能变大。所以CMAP段也是和上面一样,将CGLP这个废弃的段
分一部分给CMAP用(CWDH段也是如此,这个是字符的属性值,如字符宽度等等)
CMAP结构

地址    大小    作用
00000000  4     标记 “PAMC”
00000004  4     结构大小
00000008  2     开始编码(0000)
0000000A  2     结束编码(FFFF)
0000000C  2     CMAP类型
0000000E  2     未知
00000010  4     指向下一个CMAP的 00000008(开始编码(0000)),地址相对字库文件
00000014  2     当类型是 2 时 此处是编码(索引)项目数量
00000016  2     第一个字符编码
00000018  2     第一个字符编码对应字库的索引号
nnnnnnnn  2     第n个字符编码
nnnnnnnn  2     第n个字符编码对应字库的索引号
当类型段为 0 时计算字模索引号的方法:
字符编码-开始编码(0x00000008)+wCount(0x00000014)=字模索引号
当类型段为 2 时 0x00000016 开始为 字符编码、字符索引号的数组表
字符编码(0x00000016)是从小到大排序的,用来 /2 快速查找
如果汝新添加的CMAP数据没排序,就有可能无法显示(找不到编码对应的索引号)
上面是在跟踪Zelda时发现的

CWDH段:

地址    大小    作用
00000000  4     标记 “HDWC”
00000004  4     结构大小
00000008  2     开始编码(0000)
0000000A  2     结束编码(FFFF)
0000000C  4     未知
00000010  1     第一个字符属性 未知
00000011  1     第一个字符属性 未知
00000012  1     第一个字符属性 宽度
nnnnnnnn  1     第n个字符属性 未知
nnnnnnnn  1     第n个字符属性 未知
nnnnnnnn  1     第n个字符属性 宽度
这个段很简单就是通过字模索引号找到字符对应的字模属性
字模索引号X3+0x00000010就是指定字模的属性位置

FINF段:这个段很重要,汝在调整上面的段时整理的指针也要改,不然游戏无法找到上面的段

地址    大小    作用
00000000  4     标记 “FNIF”
00000004  4     结构大小
00000008  4     未知
0000000C  4     未知
00000010  4     未知
00000014  4     指向CWDH段
00000018  4     指向第一个CMAP段的 开始编码(0x00000008)处
小白在开始改这个NFTR字库时就是因为没改FINF指向的第一个CMAP、CMAP执行的下一个CMAP
数据段,导致显示不正常,这个也是在跟踪时发现的。

NFTR文件头:

地址    大小    作用
00000000  4     标记 “RTFN”
00000004  4     未知
00000008  4     文件大小
0000000C  2     本结构大小
0000001E  2     附加段的数量(CWDH、CMAP。。。)
00000010  n     FINF结构

 类似资料: