作者ADHI ()
看板Emulator
标题[心得] FC中文化经验谈(二)—扩充ROM容量—
时间Mon Nov 18 23:49:43 2024
【前言】
即便是文字不多的动作游戏,也很常会遇到刻好的中文字无法全部塞进去的窘境,
这时就得将游戏占用容量扩大,并且游戏程式码还要认识扩大後的区域,
这就是扩容。
【正文】
本篇以光神话欧美版为例来说明如何扩充容量
==========================================================================
一、查询ROM的规格
最主要是要知道ROM的Mapper和PRG、CHR的大小,
我们不可能记住Header每个byte的定义,所以使用工具查看才是正确方式
图中可知光神话是Mapper1,PRG-ROM有128KB,没有CHR-ROM
https://meee.com.tw/sirFyzT
==========================================================================
二、查询该规格的规格书
推荐到下列网站查询
https://www.nesdev.org/wiki/Mapper
https://problemkaputt.de/everynes.htm#cartridgesandmappers
光神话使用MMC1这个晶片做辅助,
之所以叫Mapper1是做出nes格式的模拟器作者所做的编号,
他将MMC1编号成1号,其他常见的还有MMC3(Mapper4)
https://meee.com.tw/f6hFWvT
图中为nesdev查到的Mapper1规格,PRG-ROM最大到512KB,
这代表只使用128KB的光神话还可以扩容,
如果遇到原游戏已经使用到该Mapper的上限,
要嘛看看程式中是否有空白区段,
要嘛看有没有其他可以相容的Mapper,
要嘛放弃 XD
==========================================================================
三、扩大ROM前的注意事项
1.区块编号
每一区块的PRG或CHR都会有编号,依序由前到後从编号0开始递增
2.预设映射的PRG区块
每个ROM在执行前就会有固定某一段PRG由卡带中被映射到主机里,
依照每个Mapper规范,会预设的区块不一定是哪一块,
但我看到的基本上都是最後一个PRG会被预映射。
3.编号不可异动
增大档案後,除预映射(最後的区块)外不可导致原本区块编号有所更动,
也就是区块顺序须不变
4.异动後的PRG/CHR总大小各自都得是2的某次方KB
例如原ROM是PRG(32KB)+CHR(16KB),两种区块都想增大,
那最後ROM得要是PRG(64KB)+CHR(32KB),
即使中文化的需要量没那麽多也得扩充这麽大,
PRG没照这规则应该会不能跑,
CHR没照这规则可能会影响实机或部分模拟器不能跑。
==========================================================================
四、实作
以光神话所属的Mapper1来说,PRG一个区块16KB,
光神话PRG有128KB,故光神话共有编号0~7共8个区块的PRG,
又Mapper1固定是最後一个区块(编号7)在开机时会被映射到0xC000~0xFFFF,
依照规则,
原编号0~6须保持在0~6不可变,
原编号7也须保持是最後一个区块,
所以我们要安插的地方就落在6、7之间,
这样可以保持0~6还在原位且原本的7还是最後一块;
要插入的大小则须是128KB(总大小256KB,是2的8次方),
这样一来就多了编号7~14(0xE)的区块可用了。
喔,对了,
之前有提到模拟器要辨识ROM size是透过Header,
所以要记得修改Header中size的定义,
否则会发现此时ROM无法执行,
Mesen有提供Header Edit,很方便;
该功能位於Debug -> Edit iNES Header
https://meee.com.tw/dWW9ExP
改成256KB後,模拟器就能正常执行了
==========================================================================
五、程式中如何使用扩充的区段(需6502组合语言)
要使用新增的区块,就得将其映射进CPU,
这牵涉到各Mapper的定义,依照Mapper1的定义,
是将要切换的编号写入到$E000~$FFFF(这区段任意挑一个即可),
图为nesdev查到的Mapper1切RPG ROM的位置定义
https://meee.com.tw/BnBjvXW
图为Mapper1切换的程式码范例
https://meee.com.tw/1WVdppw
可以看到写入的方法不是很直觉,需连续写五次,且每次写完後需做bit shift,
感觉很麻烦,但照抄即可 XD
举例说明,如果要将编号12映射到CPU RAM,程式码如下
LDA #$C (0xC(16进位) = 12(10进位))
STA $E123
LSR
STA $E123
LSR
STA $E123
LSR
STA $E123
LSR
STA $E123
------------(语法说明,看看就好,有用到再查)-------------
LDA(Load to A) 是将数值放入累加器(或者说是A暂存器)
STA(Store from A) 是将累加器里的数值写到某位置(例如$E123)
LSR(Logical Shift Right)是将累加器里的数值往右做一次bit shift
==========================================================================
六、扩充CHR
刚好举的案例是无CHR-ROM的,所以没提到,
基本上扩充CHR没有预设映射问题,
故只要在档案最尾巴依照2的次方大小增加并修改Header即可,
切换则是透过$A000-$BFFF & $C000-$DFFF这两组位置,
方法和上一节一样。
举例:将编号4的CHR映射到PPU RAM的$1000~$1FFF
LDA #$4
STA $D321
LSR
STA $D321
LSR
STA $D321
LSR
STA $D321
LSR
STA $D321
值得注意的是,原本没有CHR-ROM代表所使用的图形是1byte 1byte写进PPU的,
我们加上CHR-ROM後,在Mapper1会导致原本写入PPU的程式失效,
故还需将原程式由写PPU的模式改为切换映射的模式;
似乎是有Mapper是同时支援CHR-RAM与CHR-ROM的,我不是很确定 XD
以上。
--
※ 发信站: 批踢踢实业坊(ptt.cc), 来自: 123.192.217.145 (台湾)
※ 文章网址: https://webptt.com/cn.aspx?n=bbs/Emulator/M.1731944999.A.615.html
1F:推 if4: 推 11/19 00:34
2F:推 kenu1018: 太专业了 纯推看不懂... 11/19 01:55
3F:推 Jay915: 推 11/19 07:56
4F:推 kashin: 推推 11/19 08:26
5F:推 protect6090: 顶个 11/19 09:27
6F:推 bgworld: 推,谢谢 11/19 15:55
7F:→ djboy: 推 11/20 00:37
8F:推 picefun: 必须推 11/20 01:53
9F:→ samyes: 推推~ 11/20 15:54
10F:推 ijwbg: 推 11/20 22:22
11F:推 aoirx: 大推 11/21 09:38
12F:推 sdbsy14242: 推好文,感谢分享 11/21 09:40
13F:推 articlebear: 好强 11/21 20:49
14F:推 tinyfan: 看不懂,但还是要大推 11/22 11:48
15F:推 kf0916: 不明觉厉 11/23 16:03
16F:推 tonybin: 推 这些都是计算机的硬功夫 组合语言 11/24 00:37
17F:→ ksntw: 推 11/24 08:16