Skip to content

Latest commit

 

History

History
419 lines (289 loc) · 13.6 KB

CS-98-026_2.md

File metadata and controls

419 lines (289 loc) · 13.6 KB

...menustart

...menuend

Mappers and ROMs

  • iNES Header
  • Bank Switching
  • MMC3

iNES Header

  • Information about the ROM
    • Number of PRG banks (16k each)
    • Number of CHR banks (8k, 2 tables each)
    • Mirroring Type (0 = horizontal, 1 = vertical)
    • Memory Mapper (0 = none, 4 = MMC3)
  • Check out header.bas in the demo ROMs

Bank Switching

  • The NES can only address 64k of memory
  • Only 32k is for ROM (code and data)
  • Large games need to be able to swap areas of memory in and out
  • Usually have a 16k bank for code and swap 16k of level data
  • Memory mappers let us swap the memory

Bank Boundaries

  • In ROM source, you may use assembly to declare bank boundaries
  • Banks usually have a base address of $8000 or $C000
asm
    .org $8000 //base address
    .bank 0 //0 = first bank
endasm

MMC3

  • iNES Mapper #4
  • Extra memory capability for battery-backed save RAM
  • Allows swapping 8k blocks of PRG memory
  • Allows swapping 64- or 128-tile blocks of CHR pattern table
  • Allows name table mirror type switching
  • Common, versatile, and easy to use
  • SMB2, SMB3, SOF, Megaman 3-6, many others

  • Splits PRG region ($8000-$ffff) into 4 banks of 8k each
  • You can swap the lower banks or the middle banks with other ROM banks.
    • Upper bank is hardwired to the last bank in the ROM.
  • I suggest you locate your game code in the upper banks and swap the lower banks for level data

MMC3 Usage

gosub mmc3_use_lower_banks //use lower banks
set mmc3_command 6 //swap to first 8k bank
set mmc3_pagenum 0 //copy from first 8k of ROM
gosub mmc3_execute_command //swap
  • Example to swap first 128 tiles of first pattern table
  • Read the source file to see available commands and functions
set mmc3_command 0 //swap 2k page to PPU $0000
set mmc3_pagenum 4 //let’s copy from here
gosub mmc3_execute_command //go!

Mapper 介绍

FC的CPU或PPU同时能寻址的数据大小有限.

类似于手表的日期显示,一个月虽然有30天,但我们只关心今天是几号,所以手表就负责每天转动日期转盘,把当天的日期显示在窗口中,有的手表还可以显示星期几,这样就有了两个转盘和两个窗口。

而Mapper芯片的作用就相当于手表的日期功能,给FC提供了窗口(Bank)和转盘(Rom)。

比如”魂斗罗”是256KB容量/Mapper 4/MMC3芯片,其PRG ROM为128KB(CHR ROM也是128KB)。

MMC3将CPU的寻址范围(0x8000~0xFFFF,共32KB)划分成4个窗口,每个窗口8KB($8000-$9FFF、$A000-$BFFF、$C000-$DFFF、$E000-$FFFF),也就是说MMC3具备4个8KB大小的CPU Bank。

那么,128KB的PRG ROM按照8KB的窗口大小将被分成32个Rom Bank,这就是转盘。

MMC3可以从这32个Rom Bank中按照需要选择4个显示在窗口中,这就是切Bank。CHR部分同理。


总共有三个转盘:PRG RAM、PRG和CHR,窗口的大小也不是固定的,可以是1k,2k,4k,8k,16k等,不同的Mapper芯片对于窗口的数量大小有不同的配置。

Mapper芯片需要通过写指令寄存器的方式来进行Rom Bank的切换.

NROM (mapper 0)

Overview

  • PRG ROM size:
    • 16 KiB for NROM-128
    • 32 KiB for NROM-256
  • PRG ROM bank size: Not bankswitched
  • PRG RAM: 2 or 4 KiB
    • not bankswitched
    • only in Family Basic (but most emulators provide 8)
  • CHR capacity: 8 KiB ROM
    • but most emulators support RAM
  • CHR bank size: Not bankswitched
  • Nametable mirroring:
    • Solder pads 焊盘 select vertical or horizontal mirroring

Banks

All Banks are fixed,

  • CPU $6000-$7FFF:
    • Family Basic only: PRG RAM, mirrored as necessary to fill entire 8 KiB window, write protectable with an external switch
  • CPU $8000-$BFFF: First 16 KB of ROM.
  • CPU $C000-$FFFF: Last 16 KB of ROM (NROM-256) or mirror of $8000-$BFFF (NROM-128).

Solder pad config

  • Horizontal mirroring : 'H' disconnected, 'V' connected.
  • Vertical mirroring : 'H' connected, 'V' disconnected.

Registers

  • None
  • Nevertheless, tile animation can be done by swapping between pattern tables $0000 and $1000 , using PPUCTRL bits 4-3 as a "poor man's CNROM".

MMC1 , used in Nintendo's SxROM

Banks

  • CPU $6000-$7FFF: 8 KB PRG RAM bank, fixed on all boards but SOROM and SXROM
  • CPU $8000-$BFFF: 16 KB PRG ROM bank, either switchable or fixed to the first bank
  • CPU $C000-$FFFF: 16 KB PRG ROM bank, either fixed to the last bank or switchable
  • PPU $0000-$0FFF: 4 KB switchable CHR bank
  • PPU $1000-$1FFF: 4 KB switchable CHR bank

Through writes to the MMC1 control register , it is possible for the program to swap the fixed and switchable PRG ROM banks , or to set up 32 KB PRG bankswitching.

but most games use the default setup, which is similar to that of UxROM : whole 32k bank switch.

Registers

  • 与几乎所有其他映射器不同,MMC1通过串行端口进行配置,以减少引脚数量。
  • CPU $8000-$FFFF is connected to a common shift register 公共移位寄存器.
  • Writing a value with bit 7 set to any address in $8000-$FFFF clears the shift register to its initial state.
    • $80-$FF -> $8000-$FFFF
  • To change register's value, the CPU writes five times with bit 7 clear and a bit of the desired value in bit 0
    • On the first 4 writes, the MMC1 shifts bit 0 into a shift register
    • 在第五次写入时,MMC1将位0和移位寄存器内容(拼接后) 复制到 由 地址的 bit 13/14 选择的内部寄存器中,然后清零移位寄存器。
    • 只有第五次写入的地址 才是有关系的地址
    • 第五次写入后,移位寄存器会自动清零,因此不需要再写一次 bit7 =1 来给 移位寄存器复位了。
  • 当CPU在连续的周期写入串行端口时,MMC1将忽略除第一个以外的所有写入。
    • 6502 在执行 read-modify-write (RMW)指令的时候,会发生这种情况 , 比如 DEC , ROR , 这些指令会先 writing back the old value , 然后 writing the new value on the next cycle.
    • Bill & Ted's Excellent Adventure , 通过 INC 一个内容是$FF 的ROM地址 来重置MMC1. MMC1 看到$FF 写入后重置,并忽略在下一个周期写入的$00.
  • The reason for this is that the MMC1 has explicit logic to disregard any write cycle following another write cycle.

  • To switch a bank, a program will execute code similar to the following:
;
; Sets the switchable PRG ROM bank to the value of A.
; 下面A列的 edcba 每个表示1bit, 这里为了展示方便这么写
; 下面的代码其实就是把 要切换的bank号的相关信息,放入A
; 最终这些信息会 被拷贝到 bank register
;
              ;  A          MMC1_SR  MMC1_PB
setPRGBank:   ;  000edcba    10000             Start with an empty shift register (SR).  The 1 is used
  sta $E000   ;  000edcba -> a1000             to detect when the SR has become full.
  lsr a       ; >0000edcb    a1000
  sta $E000   ;  0000edcb -> ba100
  lsr a       ; >00000edc    ba100
  sta $E000   ;  00000edc -> cba10
  lsr a       ; >000000ed    cba10
  sta $E000   ;  000000ed -> dcba1             Once a 1 is shifted into the last position, the SR is full.
  lsr a       ; >0000000e    dcba1
  sta $E000   ;  0000000e    dcba1 -> edcba    A write with the SR full copies D0 and the SR to a bank register
              ;              10000             ($E000-$FFFF means PRG bank number) and then clears the SR.
  rts

bit14/13

注意,下面 LSB -> MSB

00 ($8000-$FFFF) Load register

4bit0
-----
CPPMM
|||||
|||++- Mirroring (0: one-screen, lower bank; 1: one-screen, upper bank;
|||               2: vertical; 3: horizontal)
|++--- PRG ROM bank mode (0, 1: switch 32 KB at $8000, ignoring low bit of bank number;
|                         2: fix first bank at $8000 and switch 16 KB bank at $C000;
|                         3: fix last bank at $C000 and switch 16 KB bank at $8000)
+----- CHR ROM bank mode (0: switch 8 KB at a time; 1: switch two separate 4 KB banks)
  • If you are using the SGROM or SNROM board to provide an environment similar to UNROM,
    • with 8 KB of CHR RAM, a fixed PRG ROM bank at $C000, and a 16 KB switchable PRG ROM bank at $8000,
    • do this in your init code after the mapper has been reset:
  lda #$0E   ; vertical mirroring, fixed $C000, 8 KB CHR pages
  sta $8000  ; (use $0F instead for horizontal mirroring)
  lsr a
  sta $8000
  lsr a
  sta $8000
  lsr a
  sta $8000
  lsr a
  sta $8000

01 ($A000-$BFFF) CHR bank 0

4bit0
-----
CCCCC
|||||
+++++- Select 4 KB or 8 KB CHR bank at PPU $0000 (low bit ignored in 8 KB mode)

MMC1 can do CHR banking in 4KB chunks. Known carts with CHR RAM have 8 KiB, so that makes 2 banks. RAM vs ROM doesn't make any difference for address lines. For carts with 8 KiB of CHR (be it ROM or RAM), MMC1 follows the common behavior of using only the low-order bits: the bank number is in effect ANDed with 1.

10 ($C000-$DFFF) CHR bank 1

4bit0
-----
CCCCC
|||||
+++++- Select 4 KB CHR bank at PPU $1000 (ignored in 8 KB mode)

11 ($E000-$FFFF) PRG bank

4bit0
-----
RPPPP
|||||
|++++- Select 16 KB PRG ROM bank (low bit ignored in 32 KB mode)
+----- PRG RAM chip enable (0: enabled; 1: disabled; ignored on MMC1A)
  • Some revisions of the MMC1 IC might power up in a mode other than fixed-$C000, requiring that the vectors and the start of the init code be placed in all banks, much as in BxROM or AxROM or GxROM.
  • Other revisions guarantee that the fixed bank is loaded at power on.
  • To make sure your code works on all MMC1 revisions, put the following code in the last 16 bytes of each 16384 byte bank.
reset_stub:
  sei
  ldx #$FF
  txs        ; set the stack pointer
  stx $8000  ; reset the mapper
  jmp reset  ; must be in $C000-$FFED
  .addr nmiHandler, reset_stub, irqHandler
  • Then to switch PRG ROM banks, load the bank number (0-15) into A and call this subroutine:
mmc1_load_prg_bank:
  sta $E000
  lsr a
  sta $E000
  lsr a
  sta $E000
  lsr a
  sta $E000
  lsr a
  sta $E000
  rts

MMC3 , used in Nintendo's TxROM

Banks

  • CPU $6000-$7FFF: 8 KB PRG RAM bank
  • CPU $8000-$9FFF (or $C000-$DFFF): 8 KB switchable PRG ROM bank
  • CPU $A000-$BFFF: 8 KB switchable PRG ROM bank
  • CPU $C000-$DFFF (or $8000-$9FFF): 8 KB PRG ROM bank, fixed to the second-last bank
  • CPU $E000-$FFFF: 8 KB PRG ROM bank, fixed to the last bank
  • PPU $0000-$07FF (or $1000-$17FF): 2 KB switchable CHR bank
  • PPU $0800-$0FFF (or $1800-$1FFF): 2 KB switchable CHR bank
  • PPU $1000-$13FF (or $0000-$03FF): 1 KB switchable CHR bank
  • PPU $1400-$17FF (or $0400-$07FF): 1 KB switchable CHR bank
  • PPU $1800-$1BFF (or $0800-$0BFF): 1 KB switchable CHR bank
  • PPU $1C00-$1FFF (or $0C00-$0FFF): 1 KB switchable CHR bank

Registers

  • The MMC3 has 4 pairs of registers at $8000-$9FFF, $A000-$BFFF, $C000-$DFFF, and $E000-$FFFF
    • even addresses ($8000, $8002, etc.) select the low register ,
    • and odd addresses ($8001, $8003, etc.) select the high register in each pair.
  • 这些可以分成两个独立的功能单元:
    • memory mapping ($8000, $8001, $A000, $A001)
    • and scanline counting ($C000, $C001, $E000, $E001).