CHR ROM vs. CHR RAM: Difference between revisions

From NESdev Wiki
Jump to navigationJump to search
m (moved CHR-ROM vs CHR-RAM to CHR ROM vs. CHR RAM: Terminology elsewhere on the wiki uses no dash)
(→‎Applications: technically, CJK text is a juxtaposition issue)
Line 40: Line 40:
;Compositing: Hatris and Shanghai II have a large playfield where large stacks of objects are not aligned to an 8x8 tile grid. Cocoron creates the player character's animation frames by piecing together several customizable body parts.
;Compositing: Hatris and Shanghai II have a large playfield where large stacks of objects are not aligned to an 8x8 tile grid. Cocoron creates the player character's animation frames by piecing together several customizable body parts.


;Text flexibility: Related to compositing. CHR RAM allows drawing text in a proportional font. Not a lot of NES games used this, but something like Word Munchers or Fraction Munchers might benefit. It's also the most practical way to display logographic characters, as seen in some Chinese games and the Japanese versions of Faxanadu and Bionic Commando, or characters in connected scripts such as Arabic or heavily accented scripts such as Vietnamese.
;Text flexibility
 
: Related to compositing. CHR RAM allows drawing text in a proportional font. Not a lot of NES games used this, but something like Word Munchers or Fraction Munchers might benefit. It's also the most practical way to display characters in connected scripts such as Arabic or heavily accented scripts such as Vietnamese.
;Compression
;Compression
: Contra's graphics are compressed using a run-length encoding scheme. If your game has a lot of tile data, especially if it's just a shade over the power of two boundary between one [[ROM]] size and the next, consider compression.
: Contra's graphics are compressed using a run-length encoding scheme. If your game has a lot of tile data, especially if it's just a shade over the power of two boundary between one [[ROM]] size and the next, consider compression.
Line 49: Line 49:
: Qix has horizontal lines, vertical lines, and filled areas that aren't aligned to a tile grid. Elite's graphics are wireframe 3D.
: Qix has horizontal lines, vertical lines, and filled areas that aren't aligned to a tile grid. Elite's graphics are wireframe 3D.
;Juxtaposition
;Juxtaposition
:Some CHR ROM games restrict which objects can be seen together because of what bank their CHR data is stored in. CHR RAM has no such problem because any object's tile data can be loaded at any position. This proves useful in a game like Final Fantasy, where any player characters can meet any monsters, or in a game like Dizzy or Animal Crossing, where the player can have any of several dozen items in his inventory. The extreme of this is Battletoads, which keeps only one frame of each player's animation loaded. To switch frames of animation, it copies them into CHR RAM. But then it has to turn off rendering at the top of the screen, creating a blank strip in the status bar, in order to fit the copy into blanking time. Whether you are using 8x8 or 8x16 pixel sprites, there is enough space in $1000-$1FFF to hold the current and next cel for all 64 sprites. This effect is used even more intensely in platforms with dual-ported VRAM (TurboGrafx-16, Game Boy Advance) and in platforms which have hardware-assisted memory copying to video ports other than OAM (Genesis, Super NES, Game Boy Color, Game Boy Advance).
:Some CHR ROM games restrict which objects can be seen together because of what bank their CHR data is stored in. CHR RAM has no such problem because any object's tile data can be loaded at any position. This proves useful in a game like Final Fantasy, where any player characters can meet any monsters, or in a game like Dizzy or Animal Crossing, where the player can have any of several dozen items in his inventory. The extreme of this is Battletoads, which keeps only one frame of each player's animation loaded. To switch frames of animation, it copies them into CHR RAM. But then it has to turn off rendering at the top of the screen, creating a blank strip in the status bar, in order to fit the copy into blanking time. Whether you are using 8x8 or 8x16 pixel sprites, there is enough space in $1000-$1FFF to hold the current and next cel for all 64 sprites. This effect is used even more intensely in platforms with dual-ported VRAM (TurboGrafx-16, Game Boy Advance) and in platforms which have hardware-assisted memory copying to video ports other than OAM (Genesis, Super NES, Game Boy Color, Game Boy Advance). And it's ''required'' if you want to display logographic characters, as seen in some Chinese games and the Japanese versions of Faxanadu and Bionic Commando.
;One chip
;One chip
:CHR RAM means you don't need to program a separate flash chip to act as the CHR ROM.
:CHR RAM means you don't need to program a separate flash chip to act as the CHR ROM.

Revision as of 13:55, 29 February 2012

An NES cartridge has at least two memory chips on it: PRG (connected to the CPU) and CHR (connected to the PPU). There is always at least one PRG ROM, and there may be an additional PRG RAM to hold data. Some cartridges have a CHR ROM, which holds a fixed set of graphics tile data available to the PPU from the moment it turns on. Other cartridges have a CHR RAM that holds data that the CPU has copied from PRG ROM through a port on the PPU. (A few have both CHR ROM and CHR RAM.)

The PPU can see only 8 KiB of tile data at once. So once your game has more than that much tile data, you'll need to use a mapper to load more data into the PPU. Some mappers bankswitch the CHR ROM so that the PPU can see different "pages". Other mappers are designed for CHR RAM; they let the CPU switch to a PRG ROM bank containing CHR data and copy it to CHR RAM.

CHR ROM

Advantages

  • Takes less time and code to get at least something displayed. The "hello world" program for a CHR ROM mapper is shorter.
  • Switching tiles is fast, needs no vblank time, and can be done mid-frame or even mid-scanline.
  • Can be used together with MMC3 and PRG RAM on a cartridge. Only two games have a board with MMC3 + PRG RAM + CHR RAM, and both are Japan-exclusive RPGs. Only three NES games use TGROM (MMC3 + CHR RAM) and two NES games use TQROM (MMC3 + CHR RAM + CHR ROM) even without PRG RAM.

Applications

Big static screens
Smash TV's title screen alone uses more than 8 KB of tile data.
Dedicated bank for status bar
A horizontal status bar might use a separate set of tiles from the playfield. This needs either a mapper with a raster interrupt or a sprite 0 overlap trigger. (e.g. Super Mario Bros. 3)
Artifact blanking
A game that scrolls in all four directions will often have artifacts on one side of the screen because the NES doesn't have enough VRAM to keep the "seam" where new map data is loaded clean. To hide this, a game such as Jurassic Park might display tiles from a blank pattern table for the first or last 8 to 16 scanlines.[1]
Pseudo texture mapping
In some pseudo-3D games, each row of the floor texture can be stored in a separate bank. Both CHR ROM and CHR RAM let the program switch the background between CHR banks in $0000 and $1000 using PPUCTRL ($2000),[2] but CHR ROM allows far more than two banks to be used, as seen in a forward-scrolling shooter called Cosmic Epsilon.
Workaround for PRG/CHR divide
A drawback of using CHR ROM is that the split between PRG ROM and CHR ROM fragments your data, but it can be worked around. If your PRG ROM is slightly bigger than a power of two, but you have a bit of spare CHR ROM left, you can stash the data in CHR ROM and read it out through $2006/7. For instance, Super Mario Bros. keeps its title screen map data at the end of CHR ROM and copies it into RAM to draw it. However, you can't read this data while rendering is turned on, and due to the DMA glitch, reading $2007 while playing sampled sound is unreliable.

CHR RAM

Advantages

  • Can switch tiles in small increments, and the granularity of switching does not depend on the mapper's complexity.
  • Tile data can be compressed in ROM.
  • Tile data can be otherwise generated in real time.
  • Only one chip to rewire and put on the board when replicating your work on cartridge.
  • All data is stored in one address space, as opposed to a small amount being inaccessible when rendering is on and unreliable when DPCM is on.

Applications

Compositing
Hatris and Shanghai II have a large playfield where large stacks of objects are not aligned to an 8x8 tile grid. Cocoron creates the player character's animation frames by piecing together several customizable body parts.
Text flexibility
Related to compositing. CHR RAM allows drawing text in a proportional font. Not a lot of NES games used this, but something like Word Munchers or Fraction Munchers might benefit. It's also the most practical way to display characters in connected scripts such as Arabic or heavily accented scripts such as Vietnamese.
Compression
Contra's graphics are compressed using a run-length encoding scheme. If your game has a lot of tile data, especially if it's just a shade over the power of two boundary between one ROM size and the next, consider compression.
Drawing
A few games allow the user to edit tiles. These include paint programs such as Videomation and Color a Dinosaur, or moddable titles such as a shooter maker released in Japan (which appears to have been called Dezaemon, and whose stock sprites were reused in Recca).
Vector graphics
Qix has horizontal lines, vertical lines, and filled areas that aren't aligned to a tile grid. Elite's graphics are wireframe 3D.
Juxtaposition
Some CHR ROM games restrict which objects can be seen together because of what bank their CHR data is stored in. CHR RAM has no such problem because any object's tile data can be loaded at any position. This proves useful in a game like Final Fantasy, where any player characters can meet any monsters, or in a game like Dizzy or Animal Crossing, where the player can have any of several dozen items in his inventory. The extreme of this is Battletoads, which keeps only one frame of each player's animation loaded. To switch frames of animation, it copies them into CHR RAM. But then it has to turn off rendering at the top of the screen, creating a blank strip in the status bar, in order to fit the copy into blanking time. Whether you are using 8x8 or 8x16 pixel sprites, there is enough space in $1000-$1FFF to hold the current and next cel for all 64 sprites. This effect is used even more intensely in platforms with dual-ported VRAM (TurboGrafx-16, Game Boy Advance) and in platforms which have hardware-assisted memory copying to video ports other than OAM (Genesis, Super NES, Game Boy Color, Game Boy Advance). And it's required if you want to display logographic characters, as seen in some Chinese games and the Japanese versions of Faxanadu and Bionic Commando.
One chip
CHR RAM means you don't need to program a separate flash chip to act as the CHR ROM.

Effects possible with both types

Tile animation. Think of the animated ? blocks in Super Mario Bros. 3 or the animated grass in Super Mario Bros. 2, or the independent parallax scrolling of distant repeating tile patterns in Batman: Return of the Joker, Crisis Force, and Metal Storm.

With CHR ROM, you'd make a separate bank for each frame of animation that you want to display, or for each offset between the distant pattern's scroll position and the foreground pattern's scroll position. It works best on a mapper with CHR banks smaller than 4 KB, such as MMC3.

With CHR RAM, you'd copy the tiles into VRAM as needed. Assuming moderately unrolled VRAM loading code, the NTSC vblank is long enough to copy about 160 bytes per frame plus the OAM display list without turning rendering on late. This is enough for 10 tiles alone, or 8 tiles plus a nametable row, nametable column, or entire palette.

Technically, juxtaposition isn't impossible with CHR ROM mappers, but almost no mappers support assigning a separate tile bank for each space in a nametable. MMC5 has an "ExGrafix" mode that allows this, regardless of page boundaries within the CHR ROM, as long as the game doesn't combine vertical scrolling with a status bar in the background. Thus only MMC5 can properly handle Chinese characters without needing each message to be rendered to a separate page.

Switching to CHR RAM

It's straightforward to change an existing project using NROM to use CHR RAM.

  1. Start with an NROM-256 project, and make sure at least 8300 bytes are free in the PRG ROM. We want to make sure CHR RAM works before dealing with mapper bankswitch.
  2. Remove the CHR ROM data from your build process, whether it be .incbin "mytiles.chr" after the IRQ vector or copy /b game.prg+mytiles.chr game.nes after assembly and linking.
  3. In your program's iNES header, set the number of CHR banks to 0 (which signifies CHR RAM).
  4. In your program's init code, after the PPU has stabilized but before you turn on rendering, jsr copy_mytiles_chr which is listed below.
  5. Rebuild your project. The size should end up as 32,784 bytes (16 bytes of header and 32,768 bytes of PRG ROM).
; for ca65
PPUMASK = $2001
PPUADDR = $2006
PPUDATA = $2007
.segment "CODE"
.proc copy_mytiles_chr
src = 0
  lda #<mytiles_chr  ; load the source address into a pointer in zero page
  sta src
  lda #>mytiles_chr
  sta src+1

  ldy #0       ; starting index into the first page
  sty PPUMASK  ; turn off rendering just in case
  sty PPUADDR  ; load the destination address into the PPU
  sty PPUADDR
  ldx #32      ; number of 256-byte pages to copy
loop:
  lda (src),y  ; copy one byte
  sta PPUDATA
  iny
  bne loop  ; repeat until we finish the page
  inc src+1  ; go to the next page
  dex
  bne loop  ; repeat until we've copied enough pages
  rts
.endproc

.segment "RODATA"
mytiles_chr: .incbin "mytiles.chr"

The original NROM-256 board is designed to take a mask ROM or a JEDEC-pinout EPROM in the CHR ROM position, not a 6264 SRAM. Because the board needs to be rewired slightly for CHR RAM, a few emulators do not emulate iNES Mapper 000 (NROM) with CHR RAM. For these, you'll need to use iNES Mapper 034 (BNROM), which has CHR RAM and 32 KiB bank switching.

The next step after this is to switch to a mapper that allows switching PRG banks. See Programming UNROM and Programming MMC1.

Notes