任地獄MMC5

本文github備份地址

本文編寫以及具體實現中, wiki的MMC5頁面居然進行了修改(主要是針對BANK切換的說明進行了修正).

MMC5的Mapper編號就是005, 還是有不少的遊戲(NesCartDb記錄24款, 有美版日版之分). 不過用到MMC5擴展音源的只有:

  • 光榮聖戰(Just Breed)
  • 金屬之光(Metal Slader Glory)
  • 新四人麻將: 役滿天下(Shin 4 Nin Uchi Mahjong: Yakuman Tengoku)
  • 宇宙警備隊 SDF(Uchuu Keibitai SDF)

其中值得一提的是, 金屬之光被稱為畫面最好的FC遊戲, 畢竟是可視小說(VN)類型. 其ROM大小是1MB, 在那時肯定是巨無霸水平的.

不過雖然只有少數用了擴展音源, 不過不像VRC7, MMC5沒用上的遊戲卡帶還是擁有相應的硬體(至少FC版).

PRG-RAM

MMC5支持切換RAM-BANK, 這對於目前架構來說又是致命的, 只能再想想. 但是這不是最致命的, 最致命的是信息缺失.

例如《大航海時代》, 資料庫中表明其擁有一個電池供電支持的16kb WRAM(SRAM). 一般地, 原始iNES文件頭有:

  • 8: Size of PRG RAM in 8 KB units (Value 0 infers 8 KB for compatibility; see PRG RAM circuit)

亦或者NES 2.0的文件頭:

  • Byte 10 (RAM size)

但是自己手上的大航海時代ROM這兩個位元組均是0. 也就是說ROM信息不夠完整, wiki給出的解決方案是: 假定為64kb大小.

強大的MMC5

MMC5性能非常地強大:

  • 4種RPG-ROM切換模式
  • 4種CHR-ROM切換模式
  • 最高支持到128kb的WRAM, 除了WRAM的$6000-$7FFF, 甚至還能映射到$8000-$DFFF
  • 還有一個8bit-8bit到16bit的乘法器
  • 基於掃描線的IRQ計數器
  • 能夠讓8x16精靈和背景使用不同的CHR-BANK(黑科技啊)
  • "填充模式"的名稱表, 用於場景轉換很有用
  • 1024位元組的on-chip內存, 用途還不少
  • MMC5擴展音源(自然)

BANK 切換

PRG mode 0:

  • CPU $6000-$7FFF: 8 KB switchable PRG RAM bank
  • CPU $8000-$FFFF: 32 KB switchable PRG ROM bank

PRG mode 1:

  • CPU $6000-$7FFF: 8 KB switchable PRG RAM bank
  • CPU $8000-$BFFF: 16 KB switchable PRG ROM/RAM bank
  • CPU $C000-$FFFF: 16 KB switchable PRG ROM bank

PRG mode 2:

  • CPU $6000-$7FFF: 8 KB switchable PRG RAM bank
  • CPU $8000-$BFFF: 16 KB switchable PRG ROM/RAM bank
  • CPU $C000-$DFFF: 8 KB switchable PRG ROM/RAM bank
  • CPU $E000-$FFFF: 8 KB switchable PRG ROM bank

PRG mode 3:

  • CPU $6000-$7FFF: 8 KB switchable PRG RAM bank
  • CPU $8000-$9FFF: 8 KB switchable PRG ROM/RAM bank
  • CPU $A000-$BFFF: 8 KB switchable PRG ROM/RAM bank
  • CPU $C000-$DFFF: 8 KB switchable PRG ROM/RAM bank
  • CPU $E000-$FFFF: 8 KB switchable PRG ROM bank

PRG-BANK 最後一個8kb BANK一定是ROM.

CHR mode 0:

  • PPU $0000-$1FFF: 8 KB switchable CHR bank

CHR mode 1:

  • PPU $0000-$0FFF: 4 KB switchable CHR bank
  • PPU $1000-$1FFF: 4 KB switchable CHR bank

CHR mode 2:

  • PPU $0000-$07FF: 2 KB switchable CHR bank
  • PPU $0800-$0FFF: 2 KB switchable CHR bank
  • PPU $1000-$17FF: 2 KB switchable CHR bank
  • PPU $1800-$1FFF: 2 KB switchable CHR bank

CHR mode 3:

  • PPU $0000-$03FF: 1 KB switchable CHR bank
  • PPU $0400-$07FF: 1 KB switchable CHR bank
  • PPU $0800-$0BFF: 1 KB switchable CHR bank
  • PPU $0C00-$0FFF: 1 KB switchable CHR bank
  • PPU $1000-$13FF: 1 KB switchable CHR bank
  • PPU $1400-$17FF: 1 KB switchable CHR bank
  • PPU $1800-$1BFF: 1 KB switchable CHR bank
  • PPU $1C00-$1FFF: 1 KB switchable CHR bank

CHR-BANK這裡倒是沒有什麼.

PRG mode ($5100)

7 bit 0
---- ----
xxxx xxPP
||
++- Select PRG banking mode

大部分遊戲使用的是模式3(除了惡魔城3-美版, 用了模式2). 暗榮的遊戲從來不寫入該寄存器, 可知默認是模式3.

CHR mode ($5101)

7 bit 0
---- ----
xxxx xxCC
||
++- Select CHR banking mode

金屬之光使用的是模式1, 其他的使用的是模式3

PRG RAM Protect 1 ($5102)

7 bit 0
---- ----
xxxx xxWW
||
++- RAM protect 1

D1D0位必須是10(2)才能正常寫入. 需要結合$5103.

PRG RAM Protect 2 ($5103)

7 bit 0
---- ----
xxxx xxWW
||
++- RAM protect 2

D1D0位必須是01(1)才能正常寫入. 同樣需要結合$5102.

Extended RAM mode ($5104)

7 bit 0
---- ----
xxxx xxXX
||
++- Specify extended RAM usage

  • 0 -Split模式, 作為額外的名稱表使用
  • 1 -Split+ExGrafix模式, 作為擴展用屬性表(自然也能用於名稱表)
  • 2 -ExRAM模式, 作為一般的RAM
  • 3 -ExRAM模式, 作為一般的RAM, 寫入保護

ExRAM@$000-$3BF:

  • ExGrafix模式: 用於強化背景顯示
  • Split模式: 待補充
  • ExRAM模式: 擴展用

ExRAM@$3C0-$3FF:

  • ExGrafix模式: 未使用
  • Split模式: 待補充
  • ExRAM模式: 擴展用

Nametable mapping ($5105)

7 bit 0
---- ----
DDCC BBAA
|||| ||||
|||| ||++- Select nametable at PPU $2000-$23FF
|||| ++--- Select nametable at PPU $2400-$27FF
||++------ Select nametable at PPU $2800-$2BFF
++-------- Select nametable at PPU $2C00-$2FFF

  • 0 -自帶的VRAM-前1kb
  • 1 -自帶的VRAM-後1kb
  • 2 -內部擴展RAM, 不過$5104必須是模式00或者01, 否則全部讀取到0
  • 3 -填充模式數據

MMC5內部實現應該是, 例如模式3, 就根據地址返回填充數據就行. 作為模擬器的話, 可以實現為:

for (int i = 0; i != 4; ++i) {
uint8_t* ptr = NULL;
switch (value & 3)
{
case 0:
ptr = famicom->video_memory + 1024 * 0;
break;
case 1:
ptr = famicom->video_memory + 1024 * 1;
break;
case 2:
//ptr = (mapper->exram_mode & 2) ? sfc_mmc5_zero_nt(famicom) : sfc_mmc5_exram(famicom);
ptr = sfc_mmc5_exram(famicom);
break;
case 3:
ptr = sfc_mmc5_fill_nt(famicom);
break;
}
value >>= 2;
base[i] = ptr;
}

Fill-mode tile ($5106)

8位均用於填充模式的圖塊編號

Fill-mode color ($5107)

低2位用於填充模式的屬性位, 實際填充的的是:

color = value & 3;
color = color | (color << 2) | (color << 4) | (color << 6);

可以具體平臺使用位運算或者查表.

PRG Bank 0, 1, 2 ($5110-5112)

不在PRG空間內, 無效.

PRG Bank 3, RAM Only ($5113)

7 bit 0
---- ----
xxxx BBBB
||||
++++- PRG RAM bank number at $6000-$7FFF
+--- Select PRG RAM chip

這個就比較複雜了, 這就是前面提到的信息不完整. 就目前而言有以下幾種情況:

  • 0KB: No chips
  • 8KB: 1x 8KB chip
  • 16KB: 2x 8KB chip
  • 32KB: 1x 32KB chip

D2位表示哪個chip. wiki建議始終假設為64kb, 然後根據這4bit(3bit)載入偏移數據, 因為2x8kb模式是寫入100而不是001.

  • 實際上有能力最多支持到128kb, 但是實際上最多搭載了32kb額外RAM.
  • 自己打算使用32kb的實現, 但是將D2與D1做異或運算, 然後使用D1D0進行判斷.
  • 這要求遊戲使用非常標準思路的進行切換, 可能會有BUG(而且不支持64~128kb的額外RAM).
  • 這樣內部本來WRAM有8kb就富餘出來了, 用於MMC5內部其他的RAM.
  • 對, C/C++程序猿就是摳門.

case 0x5104:
// Extended RAM mode ($5104)
#ifndef NDEBUG
printf("[%5d]MMC5: Extended RAM mode ($5104) = %02x
", famicom->frame_counter, value & 3);
#endif
mapper->exram_mode = value & 3;
mapper->exram_write_mask_mmc5 = 0x00;
famicom->ppu.data.ppu_mode = SFC_EZPPU_Normal;
if (mapper->exram_mode == 1) {
mapper->exram_write_mask_mmc5 = 0xff;
famicom->ppu.data.ppu_mode = SFC_EXPPU_ExGrafix;
}
break;

PRG Bank 4, ROM/RAM ($5114)

7 bit 0
---- ----
RBBB BBBB
|||| ||||
|+++-++++- PRG ROM bank number
| ++++- PRG RAM bank number
| +--- Select PRG RAM chip
+--------- RAM/ROM toggle (0: RAM; 1: ROM)

  • 模式 0 - 忽略
  • 模式 1 - 忽略
  • 模式 2 - 忽略
  • 模式 3 - 選擇 8KB PRG bank @ $8000-$9FFF

PRG Bank 5, ROM/RAM ($5115)

7 bit 0
---- ----
RBBB BBBB
|||| ||||
|+++-++++- PRG ROM bank number
| ++++- PRG RAM bank number
| +--- Select PRG RAM chip
+--------- RAM/ROM toggle (0: RAM; 1: ROM)

  • 模式 0 - 忽略
  • 模式 1 - 選擇 16KB PRG bank @ $8000-$BFFF (忽略最低位)
  • 模式 2 - 選擇 16KB PRG bank @ $8000-$BFFF (忽略最低位)
  • 模式 3 - 選擇 8KB PRG bank @ $A000-$BFFF

PRG Bank 6, ROM/RAM ($5116)

7 bit 0
---- ----
RBBB BBBB
|||| ||||
|+++-++++- PRG ROM bank number
| ++++- PRG RAM bank number
| +--- Select PRG RAM chip
+--------- RAM/ROM toggle (0: RAM; 1: ROM)

  • Mode 0 - 忽略
  • Mode 1 - 忽略
  • Mode 2 - 選擇 8KB PRG bank @ $C000-$DFFF
  • Mode 3 - 選擇 8KB PRG bank @ $C000-$DFFF

PRG Bank 7, ROM Only ($5117)

7 bit 0
---- ----
xBBB BBBB
||| ||||
+++-++++- PRG ROM bank number

  • 模式 0 - 選擇32KB PRG-ROM bank @ $8000-$FFFF (忽略低2位)
  • 模式 1 - 選擇 16KB PRG-ROM bank @ $C000-$FFFF (忽略最低1位)
  • 模式 2 - 選擇 8KB PRG-ROM bank @ $E000-$FFFF
  • 模式 3 - 選擇 8KB PRG-ROM bank @ $E000-$FFFF

似乎啟動時是往$5117寫入$FF, 也就是最後8kb RPG-BANK載入最後一個BANK.

CHR Bankswitching ($5120-$5130)

前面提到了MMC5的黑科技——8x16精靈使用的圖樣表允許和背景使用的不同. 8x8模式只會使用$5120-$5127, 而8x16模式下$5120-$5127是針對精靈, $5128-$512B是針對背景.

並且, 最後一次寫入的部分(前8, 後4), 會用於 PPUDATA ($2007)

wiki提到到目前未知還不清楚MMC5是怎麼檢測PPU處於哪種模式的, 真的黑科技.

寫入地址 | 1 KiB | 2 KiB | 4 KiB | 8 KiB
--------|--------|-------|-------|-------
$5120 | BANK0 | - | - | -
$5121 | BANK1 |BANK0-1| - | -
$5122 | BANK2 | - | - | -
$5123 | BANK3 |BANK2-3|BANK0-3| -
$5124 | BANK4 | - | - | -
$5125 | BANK5 |BANK4-5| - | -
$5126 | BANK6 | - | - | -
$5127 | BANK7 |BANK5-7|BANK4-7|BANK0-7
$5128 |BANK0, 4| - | - | -
$5129 |BANK1, 5| 01,45 | - | -
$512A |BANK2, 6| - | - | -
$512B |BANK3, 7| 23,67 |0-4,5-7| 0-7

根據$5130的說法, 比如8kb模式就是選擇的是8kb為窗口的BANK編號.

Upper CHR Bank bits ($5130)

7 bit 0
---- ----
xxxx xxBB
||
++- Upper bits for subsequent CHR bank writes

當使用1kb模式時, 最多隻能訪問256kb的CHR-ROM, 要訪問整個1024kb就需要這兩位了. 不過唯一一個超過256kb CHR-ROM的金屬之光卻使用的是4kb模式. 換句話說就是沒有一個遊戲使用了這個機能(甚至連初始化都沒有).

Expansion RAM ($5C00-$5FFF, read/write)

  • 模式 0/1 - 不可讀, 僅可在PPU渲染時可寫(否則寫入0)
  • 模式 2 - 可讀可寫
  • 模式 3 - 只讀

模式1下( ExGrafix 模式), 就是MMC5實現的一個難點了: 擴展RAM區每個位元組可以用來強化背景顯示.

7 bit 0
---- ----
AACC CCCC
|||| ||||
||++-++++- Select 4 KB CHR bank to use with specified tile
++-------- Select palette to use with specified tile

4*64=256, 為了使用整個1024kb空間, 需要配合$5130的兩位進行使用.

這種模式下基本可以確定使用的是單屏模式下. 舉個栗子, 第一個圖塊$2000. 原本的模式下, 首先確定背景是用的哪個圖樣表, 然後利用[$2000]的數據, 獲取圖樣數據.

現在ExGrafix模式下, 會在ExRAM:$000獲取相應信息, 而本來的圖樣表幾乎完全是為精靈服務的.

高精度的模擬器應該是模擬讀取過程, 不過作為中精度的模擬器可以直接拿渲染開刀.

Split模式相關寄存器

待補充

目前只有宇宙警備隊 SDF使用了該模式, 這個模式目前不想實現(懶), 等待以後實現吧.

IRQ Counter ($5203)

用於指定掃描線id來觸發IRQ, 內部比如寫入$04會在第5條可見掃描線開始時觸發. 寫入0應該是觸發不了IRQ的. 由於是基於掃描線的, 所以應該只會在可見掃描線觸發相關同步操作.

目前的Ez模式下, 本身自己是在每條掃描線最後觸發水平同步的, 所以就是應該寫入多少就在第幾條觸發.

IRQ Status ($5204, write)

7 bit 0
---- ----
Exxx xxxx
|
+--------- IRQ Enable flag (1=IRQs enabled)

寫入僅僅用來啟用/關閉IRQ功能, 即時關閉也能在本來可以觸發IRQ情況將Pending置為1(當然不會觸發IRQ).

IRQ Status ($5204, read)

7 bit 0
---- ----
SVxx xxxx MMC5A default power-on value = $00
||
|+-------- "In Frame" signal
+--------- IRQ Pending flag

In Frame是當MMC5不再檢測到掃描線信號時, 比如最後一根掃描線掃過, 或者說PPU沒有渲染背景/精靈($2001相關位). 也就是說實際上如果中途關閉渲染, 會提前清除In Frame標誌(懶得實現).

Pending標誌會在MMC5的相關IRQ掛起時觸發, 讀取後清除(確認IRQ), 或者在In Frame0->1時也會清除.

Unsigned 8x8 to 16 Multiplier ($5205, $5206 read/write)

這就是那個16位乘法器了, 寫入會進行乘法運算. 讀取時, 低地址讀取地址, 高地址讀取高地址.

其他寄存器

其他還有一些就不介紹了

switch-case

由於地址部分連續, 部分離散, 所以只好直接用case了, 讓編譯器自己優化.

switch (address)
{
case 0x5100:
// ...
case 0x5101:
// ...
case 0x5102:
// ...
// ...
};

新介面

read_low, 讀取[$4020, $6000), 這部分區域會調用該介面. 在正常情況下, 與之前的PRG段快速訪問優化不衝突.

區別ROM RAM

目前是使用的32bit整型保存偏移量, 但是沒有辦法區別BANK是來自ROM還是RAM. 所以現在統一用最高位區別RAM與ROM.

/// <summary>
/// StepFC: 利用指針創建偏移量
/// </summary>
/// <param name="famicom">The famicom.</param>
/// <param name="ptr">The PTR.</param>
/// <returns></returns>
static inline uint32_t sfc_make_offset(sfc_famicom_t* famicom, const uint8_t* ptr) {
const uint8_t* const fc0 = famicom->video_memory;
const uint8_t* const fc1 = (const uint8_t*)(famicom + 1);
// RAM
if (ptr >= fc0 && ptr < fc1) {
const uintptr_t rv = ptr - fc0;
// 256 MiB夠大了
assert(rv < 0x10000000);
return (uint32_t)rv;
}
// ROM
else {
const uintptr_t rv = ptr - famicom->rom_info.data_prgrom;
// 256 MiB夠大了
assert(rv < 0x10000000);
return (uint32_t)rv | (uint32_t)0x80000000;
}
}

/// <summary>
/// StepFC: 利用偏移量創建指針
/// </summary>
/// <param name="famicom">The famicom.</param>
/// <param name="offset">The offset.</param>
/// <returns></returns>
static inline uint8_t* sfc_make_pointer(sfc_famicom_t* famicom, uint32_t offset) {
// ROM
if (offset & 0x80000000) return famicom->rom_info.data_prgrom + (offset & 0x7fffffff);
// RAM
else return famicom->video_memory + offset;
}

之前的文件頭"-StepFC-SRAMWRAM"完全沒有必要, 但是看著文件管理器顯示9kb有點煩, 乾脆去掉了. 完全根據大小信息判斷:

  • 8kb: SRAM
  • 32kb: MMC5 PRG-RAM

模擬大航海時代出現的問題

由於使用了MMC5-ExGrafix模式, 這個背景顯示老是有問題. 以為是ExGrafix模式實現有問題, 結果發現是因為很久沒碰渲染層導致邏輯忘了.

目前的實現每個像素有效位為低5位: [xxxA BCDE], 其中E是判斷是否為全局背景: E = C | D, CD是圖樣的低兩位, AB是屬性位, 自己還以為是[xxxx ABCD]模式.

MMC5 擴展音源

MMC5的擴展音源相對其他來講很簡單——因為實際上已經實現過了: 和2A03的相關聲道幾乎一致. 對比起VRC6來, 沒有鋸齒波也罷了, 方波還沒有什麼特色.

所以在NSF創作者看來, MMC5擴展音源毫無特色. 用上MMC5基本上意味著已經沒有其他擴展音源的可用了——MMC5僅僅是陪襯品.

Pulse 1 ($5000-$5003)

與2A03的方波區別:

  • $5001沒有效果, MMC5方波沒有掃描單元
  • 週期小於8並不會靜音——會輸出超聲波
  • 似乎等於0(週期為1)時才會靜音
  • 論壇上有人提出, 部分模擬器到7就靜音是錯誤的實現. 但是就自己的觀點, 模擬器發出超聲波應該需要一個高質量的濾波器, 所以這個應該算風格而不是錯誤
  • 長度計數器速率會兩倍於2A03的長度計數器運作(240Hz)
  • MMC5沒有幀計數器(序列器), 包絡(以及長度計數器)始終以240Hz運行(當然, 具體實現上, 可以借用已經實現了的幀序列器)

Pulse 2 ($5004-$5007)

第二個方波, 同上, 由於沒有掃描單元, 完全一致(2A03的兩個方波在掃描上有所區別——反碼與補碼).

PCM Mode/IRQ ($5010) Write

7 bit 0
---- ----
Ixxx xxxM
| |
| +- Mode select (0 = write mode. 1 = read mode.)
+--------- PCM IRQ enable (1 = enabled.)

PCM Mode/IRQ ($5010) Read

7 bit 0
---- ----
Ixxx xxxM MMC5A default power-on read value = $01
| |
| +- In theory but not verified: Read back of mode select (0 = write mode. 1 = read mode.)
+--------- IRQ (0 = No IRQ triggered. 1 = IRQ was triggered.) Reading $5010 acknowledges the IRQ and clears this flag.

Raw PCM ($5011)

7 bit 0
---- ----
WWWW WWWW
|||| ||||
++++-++++- 8-bit PCM data

讀取模式會忽略縮寫內容, 寫入$00不會影響輸出(PCM值可能為0啊, 需不需要實現?)

PCM IRQ

有興趣的可以自行了解.

Status ($5015, read/write)

類似$4015, 只有最低兩位使用了.

模擬金屬之光出現的問題

MMC5音源

一開始, 金屬之光使用MMC5的二號方波, 用於播放文字嗶嗶嗶的音效. 但是似乎希望, 通過往$5004寫入$00來靜音方波. 找了很久, 甚至一行一行對照其他模擬器的實現, 的確寫入$00不能靜音!

似乎陷入僵局, 又只好一步一步反彙編, 發現是通過讀取$5DD5的數據寫入$5004的, 所以結果是ExRAM實現有問題而不是方波!

之前不小心實現為:

mapper->exram_write_mask_mmc5 = 0x00;
famicom->ppu.data.ppu_mode = SFC_EZPPU_Normal;
if (mapper->exram_mode == 1) {
famicom->ppu.data.ppu_mode = SFC_EXPPU_ExGrafix;
mapper->exram_write_mask_mmc5 = 0xff;
}

金屬之光使用的是模式2——ExRAM模式, 讓所有數據寫入0了, 應該實現為:

mapper->exram_write_mask_mmc5 = 0x00;
famicom->ppu.data.ppu_mode = SFC_EZPPU_Normal;
if (mapper->exram_mode == 1)
famicom->ppu.data.ppu_mode = SFC_EXPPU_ExGrafix;
else if (mapper->exram_mode == 2)
mapper->exram_write_mask_mmc5 = 0xff;

MMC5圖像

金屬之光雖然寫入了兩段CHR-BANK切換用寄存器, 也使用了8x16精靈模式, 也就是說使用了黑科技. 但是目前來看(時間原因, 主要是沒有漢化玩不下去), 兩段CHR-BANK切換寫入的內容是一樣的, 也就是實際上沒有利用這一機能.

簡單來說有兩個問題:

  • 第一段, 令人喫驚的是, 金屬之光在大致160行生成一個IRQ, 然後取消背景(與精靈)顯示. 前面提到MMC5是檢測掃描線的, 取消的話會讓MMC5以為提前進入到了不可見階段. 不過這不是問題, 第一段是灰色的, 原因是燙燙燙: 沒有渲染實際應該是渲染黑色, 實現時直接return了.
  • 第二段, 也讓人喫驚的是, 金屬之光觸發IRQ後會修改調色板! 因為目前Ez模式是假定調色板不會在渲染時修改(所以金屬之光在160行後開始取消渲染了), 背景最多同時使用12+1種顏色. 這樣一換能使用的顏色就翻倍了, 不過這遊戲僅僅用來處理字體顏色.

第一個BUG目前來說不可能修改, 原因是因為儲存的是調色板索引, 不能表示黑色. 第二個BUG和之前的IRQ中切換BANK一樣, 有兩種解決方案:

  1. 儲存調色板實際顏色信息, 這樣其實兩個BUG都能一起解決掉.
  2. 將畫面分割成兩部分——IRQ作為分界線. 保存獨立的相關數據作為備份信息. 這樣的話能夠連帶BANK切換的問題一起解決

目前來看, 這兩種解決方案的選擇應該是: 兩個都要(我全都要)! 可以用來解決目前渲染的3個已知BUG, 交給後面完成吧(懶)!

簡單匯總

MMC5近乎20款遊戲中, 這裡僅僅測試了兩款——大航海時代金屬之光.

大航海時代使用了ExGrafix模式, 但是僅僅是方便程序猿進行場景佈置, 而沒有渲染出令人信服的畫面.

金屬之光: MMC5的三個圖像加強的功能, 金屬之光實際都沒用上(大概), MMC5的額外音源也僅僅用來放文字嗶嗶音效(大概). 可以看出這遊戲似乎一開始可能並沒有打算使用MMC5.

總的來說MMC5是一款非常強大的MMC, 導致模擬器大幅度地進行調整, 甚至在渲染層打洞來支持MMC5特性. 由於精力原因目前還沒有完全模擬: Split模式與黑科技模式沒有實現, 打上TODO等待以後慢慢補上.

(RAM寫入保護也沒有實現, 填充模式實現了, 但似乎沒用過導致沒法測試)

REF

  • MMC5
  • MMC5 audio

推薦閱讀:

相關文章