[心得] FC中文化经验谈(三)—找到目标—

楼主: ADHI   2024-12-03 11:56:14
【前言】
要修改自然得找到想修改的目标,
例如要制作生命不减的ROM至少得知道储放生命值的内存在哪,
故找到目标便是首要作业;
仔细想想,这讲完好像就没了 XD
【正文】
我们要找到的目标大致有两个,一个是字库,一个是文本,
这两个在画面显示时,肯定都在PPU里,
其中字库在显示当下会放在PPU的0x0000~0x1FFF
(不只字库,包含背景、人物图像都会在此),
而文本则会放在PPU的0x2000~0x3FFF
(不只文本,包含背景、人物组成以及调色盘都会在此)。
一、字库
说是字库,其实也就是图形长得像文字,和其他包括背景或人物图形没什么差别;
由于画面上所有东西肯定都在PPU里,使用PPUViewer(或检视PPU Memory)可以找到;
不过大部分的案例直接开启tlp工具通常就找的到。
1. 透过tlp或YYCHR之类的工具找
由于红白机的ROM,通常未压缩,或者说未编码过,
所以使用工具直接开启ROM档,即可直接看到图形部分。
图为光神话,红框的数字即是图形在档案中的起始位置
https://meee.com.tw/b2tmFpR
2. 透过PPU Viewer找到
开启Mesen的PPU Viewer,切到CHR Viewer页签,
此页签显示的即是PPU的0x0000~0x1FFF的内容,
很直观可以看到0~9、A~z等等文字,
我们可以在0上面按右键→Edit in Memory Viewer,
这样模拟器会自动帮我们开启Memory Tools,并且定位到0这个字的位置,
其中位于0x1000~0x100F这16Bytes
(38 4C C6 C6 C6 64 38 00 00 00 00 00 00 00 00 00)便是0的pixel data,
此时使用任意16进位编辑器(UltraEdit之类的软件)开启ROM,
并且搜寻38 4C C6 C6 C6 64 38 00 00 00 00 00 00 00 00 00
高机率可以找到0在ROM里的位置,
实际搜寻可以发现位置在ROM的0x1010,和第1点的方式显示的位置一致。
(图为PPU Viewer)
https://meee.com.tw/Hf5aWZq
(图为PPU Viewer的右键选单,选择使用Edit in Memory Viewer)
https://meee.com.tw/mqTGueL
(图为Memory Tools for PPU,已定位到字库位置)
https://meee.com.tw/yCiZlc4
(图为搜寻到字库在ROM档里的位置)
https://meee.com.tw/wIMO6I7
3. 如果以上方法找不到,那代表图形有压缩或是编码过,在红白机很少见,
这代表图像肯定是1 byte 1byte写进PPU的,得要追踪程式。
4. 找到后就可以建立所谓的码表,
其实就是每一单位(红白机叫做Tile,一Tile为8x8像素,实际占用16bytes)
的图片编号表,依前面找到的可以建立出这样的编号表
00 = 0
01 = 1

0F = -

2F = Z

==========================================================================
二、文字
1. 文字的找寻方式大致可参考前述第一项第2点,
一样是开启PPU Viewer,透过PPU Viewer快速跳到Memory Tools,
就可以看到显示在画面上的文字实际的的编码
图为指标选中PUSH START的P时的资讯,
其中可以看到P的编码是0x31,位置(PPU Addr)在0x21E7
https://meee.com.tw/NiYS6hx
图为Memory Tools显示PPU,
https://meee.com.tw/rJduFxz
其中
0x31 = P
0x5D = U
0xC0 = S
0x64 = H
....
2. 找到文字的编码后,一样可以在ROM档里搜寻到
https://meee.com.tw/vP2uH0q
==========================================================================
三、如果前面方法找不到,如何分析
0. 首先稍微说明一下CPU如何读写PPU
CPU是透过两个Port来读写PPU,
0x2006: 决定要写入的PPU位置
0x2007: 要写入的值
也就是如果CPU想要将0x31写到PPU的0x21E7这个位置时,
首先得先透过0x2006将欲读写的位置指定成0x21E7,
然后再往0x2007这个位置写入0x31即可;
实际程式码会是,
LDA #$21
STA $2006
LDA #$E7
STA $2006
LDA #$31
STA $2007
可以看到2006被写两次,肇因于红白机能读写的数值是1byte,
但PPU位置是2Bytes,
所以红白机分两次写入(先写高byte再写低byte)来达到目的。
1. 首先使用debugger针对PPU做写入侦测的中断点
图为如何设定中断点
https://meee.com.tw/C3scTqY
2. 让程式回到文字显示之前重跑
此处案例为开头画面,故只要reset即可,
其他时候会在显示文字前先即时存盘来方便重跑,
如果中断点设定正确,程式会在对应的位置中断;
图为程式中断
https://meee.com.tw/bjWV8u6
此处案例可以看到如下程式码,
写入值是0x31也符合我们已知道的文字P的编码,故可确认此找到的程式正确
…..
LDA ($43),Y @ $A2E8 = $31
STA PpuData 2007 = $00
INY
…..
并且会停在在STA PpuData 2007这行,这就是前面说的CPU正透过$2007写入PPU,
写入值是0x31也符合我们已知道的文字P的编码,故可确认此找到的程式正确
3. 检视内存
前面找到的程式码,
其中LDA ($43),Y @ $A2E8 = $31是资料来源,
意思是读取0xA2E8位置的值放进暂存器A,
所以P(0x31)来自0xA2E8这个位置,
此时可以打开Memory Tools,并跳到0xA2E8这个位置
图为0xA2E8的内存内容
https://meee.com.tw/XPmLRuF
4. 依样画葫芦便能在ROM中找到位置
图为在ROM中搜寻31 5D C0 64 12 C0 C3 A7,并确实找到
https://meee.com.tw/r7pHSGY
以上,字库跟文本都找到了,只要异动这两个地方,
就可以达到在画面上显示自己要的东西,当然也包括中文字。
作者: gfneo (gfneo)   2024-12-03 11:59:00
作者: msun (m桑)   2024-12-03 13:17:00
作者: tinyfan (小风扇)   2024-12-03 13:40:00
看不懂但还是要推
作者: djboy (雞尾酒)   2024-12-03 16:23:00
先推再说
作者: if4 (if)   2024-12-03 16:52:00
谢谢心得 XD
作者: articlebear (政治真的满狗屁的)   2024-12-03 19:21:00
作者: sdbsy14242 (あやめづきの子)   2024-12-04 08:48:00
长知识,感谢分享
作者: picefun (帆)   2024-12-04 11:41:00
这必须推
作者: samyes (不买最赚)   2024-12-04 12:27:00
推~
作者: kf0916 (kf0916)   2024-12-04 13:41:00
不明觉厉
作者: EDGE (選前擾民選後隱形)   2024-12-04 19:43:00
推分享~
作者: bgworld (Solid)   2024-12-04 20:20:00
推,虽然不懂
作者: if4 (if)   2024-12-04 22:39:00
是啊,我也不懂 XD
作者: xxgreen (张比克)   2024-12-05 00:31:00
作者: edaeda (绿色法皇)   2024-12-07 11:52:00
不懂但是推
作者: reiden (雷电,经典的STG(?))   2024-12-08 12:02:00
好像有点懂,但真的大感谢分享
作者: aaaaagw (暱称可以吃吗)   2024-12-11 05:46:00
推,真的辛苦QQ抽屉和上面的标签都得找到才能换

Links booklink

Contact Us: admin [ a t ] ucptt.com