[心得] FC中文化經驗談(二)—擴充ROM容量—
【前言】
即便是文字不多的動作遊戲,也很常會遇到刻好的中文字無法全部塞進去的窘境,
這時就得將遊戲占用容量擴大,並且遊戲程式碼還要認識擴大後的區域,
這就是擴容。
【正文】
本篇以光神話歐美版為例來說明如何擴充容量
==========================================================================
一、查詢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://www.ptt.cc/bbs/Emulator/M.1731944999.A.615.html
留言