PPU scrolling

From NESdev Wiki
Revision as of 23:17, 24 March 2015 by Tepples (talk | contribs) (Consensus on talk is that everything after "The common case" is poorly written, and "Skinny" describes it better.)
Jump to navigationJump to search

Scrolling is the movement of the displayed portion of the map. Games scroll to show an area much larger than the 256x240 pixel screen. For example, areas in Super Mario Bros. may be up to 24 screens wide. The NES's first major improvement over its immediate predecessors (ColecoVision and Sega Mark 1) was pixel-level scrolling of playfields.

The common case

Ordinarily, a program writes to two PPU registers to set the scroll position in its NMI handler:

  1. Find the X and Y coordinates of the upper left corner of the visible area (the part seen by the "camera")
  2. Write the X coordinate to PPUSCROLL ($2005)
  3. Write the Y coordinate to PPUSCROLL
  4. Write the starting page (high order bit of X and Y) to bits 0 and 1 of PPUCTRL ($2000)

The scroll position written to PPUSCROLL is applied at the end of vertical blanking, just before rendering begins, therefore these writes need to occur before the end of vblank. Also, because writes to PPUADDR ($2006) can overwrite the scroll position, the two writes to PPUSCROLL must be done after any updates to VRAM using PPUADDR.

By itself, this allows moving the camera within a usually two-screen area (see Mirroring), with horizontal and vertical wraparound if the camera goes out of bounds. To scroll over a larger area than the two screens that are already in VRAM, you figure out what columns or rows of the nametable are just coming into view, and you write that to VRAM before you set the scroll, as seen in the animation below. The area that needs rewritten at any given time is sometimes called the "seam" of the scroll.

SMB1 scrolling seam.gif

Advanced

The reason you have to write PPUSCROLL last is because PPUSCROLL and PPUADDR actually write to the same register inside the PPU, just with the bits distributed differently. This was a cost-saving measure on Nintendo's part that also turned out to allow split-screen effects such as a moving playfield and still status bar. The skinny on NES scrolling gives a detailed description of scrolling behavior with diagrams and examples.