Mirroring

From NESdev Wiki
Revision as of 22:16, 4 March 2013 by Tepples (talk | contribs) (→‎Single-Screen: Magic drugs? No, Magic Floor.)
Jump to navigationJump to search

There are two types of mirroring that appear commonly within the scope of NES emulation.

Nametable Mirroring

Nametable mirroring affects what is shown past the right and bottom edges of the current nametable. When mirroring is enabled for a particular axis (horizontal and/or vertical), the coordinates simply wrap around on the current nametable. A background "mirrored" in this way is repeated, not flipped. When mirroring is disabled, a second nametable is used. There are four common combinations of mirroring:

Horizontal

A A
B B

A vertical arrangement of the nametables results in horizontal mirroring, which create a 32x60 tilemap.

This is most commonly used for games which only scroll vertically or in all directions.

Doing any horizontal scrolling using horizontal mirroring is hard to do smoothly because the data on the right of the screen is immediately show on the left due to mirroring. Clever use of hardware left-side screen clipping will hide all name table glitches, but because the attribute tables have a resolution of 2x2 tiles, there will always be attribute glitches on the left and/or the right side of the screen. The best possible way to hide it is to have 4 pixels with potentially wrong attributes on both sides, but most commercial games did worse than that having usually 8 or even more glitchy pixels, so that is why so many NES games have color glitches on the border of the screen.

Some televisions overscan up to 8 pixels on both left and right border, but most doesn't. Perfectionist programmers could use solid black sprites on the right border to hide attribute glitches and make the screen look symmetrical and hide absolutely all attribute glitches, as in the game Alfred Chicken, but very few games do this because it reduces the number of sprites per scanline to 7 and wastes a lot of OAM space (roughly 1/4 in 8x16 pixel sprite mode).

To configure a cartridge board for horizontal mirroring, connect PPU A11 to CIRAM A10. On cartridge boards made by Nintendo, this is selected by shorting the "V" solder pad (for "vertical arrangement"). Note using inverse logic may make more sense, "Leaving the 'H' jumper open gives horizontal mirroring" on Nintendo boards.

Vertical

A B
A B

A horizontal arrangement of the nametables results in vertical mirroring, which makes a 64x30 tilemap.

This is most commonly used for games which only scroll horizontally. Games that scroll vertically (by any amount and without status bar) and that does never scroll horizontally by more than one screen would use this mirroring (e.g. Lode Runner, Bomberman, Fire Emblem, Crystal Mines), so that they don't have to load anything when scrolling horizontally.

Of course it is also used for games which scroll in both directions without a status bar. Because data that is on the top/bottom of the screen will immediately show up on the other side, a clever use of NTSC overscan can make it glitch-less multidirectional scrolling, but glitches will appear on PAL televisions (and NTSC televisions with a overscan range which is a little off). The best possible way to hide glitches is to make 4 pixels with wrong tiles and 4 additional pixels with wrong color on both sides, but most commercial games did much worse than this, that's why they look so bad if overscan is disabled.

Perfectionist programmers could use raster split to hide glitches (and possibly also provide more blanking time to update VRAM) as in the games Jurassic Park and M.C. Kids, but it was rarely done because it complicates the code a lot for little benefits.

To configure a cartridge board for vertical mirroring, connect PPU A10 to CIRAM A10. On cartridge boards made by Nintendo, this is selected by shorting the "H" solder pad (for "horizontal arrangement"). Note using inverse logic may make more sense, "Leaving the 'V' jumper open gives vertical mirroring" on Nintendo boards.

Single-Screen

A A
A A
B B
B B

Single-screen mirroring is only available with certain mappers, such as the AxROM, SxROM, and TLSROM boards, resulting in two 32x30 tilemaps.

Its main advantage is that it allows using a status bar at the top or bottom of the screen while also allowing the playfield to extend equally in any direction - this can be done by storing the status bar in one nametable, rendering the playfield in the other nametable, and switching mirroring (and scrolling parameters) at the appropriate screen location during rendering.

There is also a lot of other things that can be drastically simplified when using 1-screen mirroring: The formulas used to calculate PPU address of data to be updated to the screen are also significantly simpler, and if the status bar have a variable size or is scrolling, all this would be a headache without 1-screen mirroring.

When this mirroring is used to scroll horizontally, similar glitches and scrolling problems that those of horizontal mirroring will happen. However, as long as there is a status bar, no glitches will happen vertically since the data that falls off the bottom (or the top) of the screen will come in the area that is "hidden" by the status bar, regardless of overscan factors.

There are several different ways to configure a cartridge board for single-screen mirroring. Some boards have single screen mirroring which is mapper controlled like the MMC1 and AxROM. For AxROM connect the output of a register (e.g. 74HC161) to CIRAM A10 (AxROM latches PRG D4). A simpler way to create one screen mirroring that's fixed (non-changable by software) is to simply connect CIRAM A10 to Gnd or Vcc. The board that implements iNES Mapper 218 wires CIRAM A10 to PPU A10, A11, A12, or A13, so that without having any CHR ROM or CHR RAM in the cartridge.

Other

A B
B A
A B
C C
A C
B C

Custom types of mirroring are available with TxSROM boards and with boards using the MMC5 or Namco 163 mapper, where the program can freely specify which nametable is which part of VRAM. The MMC5 also has RAM for a third nametable, so this opens many possibilities. So far only the MMC5 version of Castlevania 3 really uses this.

Diagonal mirroring would appear to offer nearly glitch-free scrolling in all four directions without a status bar. Any glitches would show up on the corners, not a whole edge. (anyone have a proof of it ?)

4-screen VRAM

A B
C D

With additional RAM present on the cartridge, 4 unique nametables can be addressed, creating a 64x60 tilemap, allowing for more flexible screen layouts. Very few games use this method due to cost.

There are three ways to implement this on a cartridge board:

  • Add an extra 2 KB of RAM on the board. Decoder logic enables CIRAM only for $2000-$27FF and the cartridge RAM $2800-$2FFF.
  • Add a 6264 8 KB RAM on the board. CIRAM /CE is pulled high, and the cartridge RAM is enabled at $2000-$3FFF. The PPU itself never uses $3000-$3FFF during rendering, but 8 KB RAMs are easier to find than 4 KB RAMs.
  • Add a larger RAM on the board and map it to the entire PPU address space. This allows 8 KB of CHR RAM at $0000-$1FFF and 4 KB of nametables at $2000-$2FFF.

Mirroring chart

This table helps to choose which mirroring to use, it is of course not an ultimate chart or anything, just a guide if someone is writing a game and don't know which mirroring to use.

Scrolling Type With Status Bar Without Status Bar Game example Comment
Horizontal Only Vertical Vertical Super Mario Bros.
Vertical Only Vertical/Single screen Horizontal Gun.Smoke
Horizontal/Vertical aligned screens Vertical Alternate H/V Metroid, Air Fortress, Guardian Legend For use if scrolling direction changes only on a screen-based pattern, as in Metroid.
Bidirectional, field limited vertically Horizontal ** Horizontal ** Super Mario Bros. 3 No data has to be loaded at all when scrolling vertically, but the area is limited to two screens (less the status bar if present).
Bidirectional, field limited horizontally - Vertical * Fire Emblem No data has to be loaded at all when scrolling horizontally, but the area is limited to two screens.
Free bidirectional Single Screen **, Horizontal ** Vertical *, Horizontal ** If using horizontal mirroring with a status bar there are 2 possibilities

1) The status bar will have to change address when scrolling vertically (Double Dragon series, Conquest of Crystal Palace, Gradius II)

2) The playfield will have to be written twice to memory (Kirby's Adventure, Little Nemo: The Dream Master), which only works if the status's bar size remains constant.

* : vertical glitches on PAL screens and on NTSC that doesn't overscan. ** : Horizontal glitches will be unavoidable when scrolling (see above).

Memory Mirroring

Memory mirroring refers to the appearance of memory or I/O registers at more than one range of addresses, with the same byte being accessible at more than one address. This occurs when the full address isn't completely decoded, that is, when a chip ignores one or more address lines. Because completely decoding an address usually takes a lot more pins on a chip, incomplete decoding is used to reduce the hardware required; if the mirror occupies otherwise unused address space, it poses no problems.

Within the NES, many things are mirrored:

  • System memory at $0000-$07FF is mirrored at $0800-$0FFF, $1000-$17FF, and $1800-$1FFF - attempting to access memory at, for example, $0173 is the same as accessing memory at $0973, $1173, or $1973.
  • PPU I/O registers at $2000-$2007 are mirrored at $2008-$200F, $2010-$2017, $2018-$201F, and so forth, all the way up to $3FF8-$3FFF.
  • The single registers on most simple mappers are mirrored throughout $8000-$FFFF.
  • Registers on many common ASIC mappers (such as the MMC1 and MMC3) are also mirrored, in groups, throughout $8000-$FFFF.
  • Nametable mirroring, as described above, happens due to memory mirroring within PPU $2000-$2FFF (hence its name). However, in this case the memory mirroring is intentional and necessary.
  • In NROM-128, the 16k PRG ROM is mirrored into both $8000-$BFFF and $C000-$FFFF.
  • In most mappers, banks past the end of PRG or CHR ROM show up as mirrors of earlier banks. For example, UNROM PRG banks 8-15 are duplicates of banks 0-7 respectively.

See also