338. Increment horizontal vram addr

Increment the horizontal component of the current rendering address v.

Lesson 338 of 356 · tests/chapter_13_scrolling/test_338_increment_horizontal_vram_addr.py

File to update

emulator/ppu/ppu.py

References

https://www.nesdev.org/wiki/PPU_scrolling#Coarse_X_increment
https://www.nesdev.org/wiki/PPU_scrolling#During_rendering

Why this step exists

During background fetches, the PPU advances through one 8-pixel tile column at a time. The current rendering address v stores both the coarse X tile column and the horizontal nametable selection:

v: yyy NN YYYYY XXXXX
                   |
                   +-- coarse X, bits 0-4

horizontal nametable selection: bit 10

Normal behavior

coarse X 0  -> 1
coarse X 30 -> 31

Boundary behavior

coarse X 31, horizontal nametable 0
    -> coarse X 0, horizontal nametable 1

coarse X 31, horizontal nametable 1
    -> coarse X 0, horizontal nametable 0

The boundary toggle moves rendering across the logical left/right nametable seam. PpuBus later applies cartridge mirroring when those logical addresses are read.

Important invariants

  • only coarse X and, at wrapping, horizontal nametable may change
  • coarse Y, fine Y, and vertical nametable remain unchanged
  • fine X is separate and is not an argument to this operation
  • the helper returns a value and does not mutate PPU

Common misconception

This does not move one pixel. It advances one tile column, which represents 8 pixels. Fine X supplies the separate 0-7 pixel offset inside the first tile.

Out of scope

  • calling the helper from PPU.step()
  • choosing background-fetch dots
  • copying horizontal t bits into v
  • vertical increments
  • framebuffer rendering

Complete example implementation

# emulator/ppu/ppu.py

# --- NEW BLOCK: PURE HORIZONTAL v INCREMENT ---
def increment_horizontal_vram_addr(vram_addr: int) -> int:
    # Advance v by one background tile column.
    coarse_x = vram_addr & 0b1_1111

    if coarse_x == 31:
        vram_addr &= ~0b1_1111
        vram_addr ^= 0b100_0000_0000
        return vram_addr

    return vram_addr + 1

Run this lesson

uv run pytest tests/chapter_13_scrolling/test_338_increment_horizontal_vram_addr.py -v