339. Copy horizontal scroll bits

Copy horizontal scrolling fields from temporary address t into current address v.

Lesson 339 of 356 · tests/chapter_13_scrolling/test_339_copy_horizontal_scroll_bits.py

File to update

emulator/ppu/ppu.py

References

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

Why this step exists

CPU writes prepare scrolling fields in temporary address t, but background rendering uses current address v. The PPU transfers only the horizontal fields at the horizontal reload point:

yyy NN YYYYY XXXXX
    ||       +++++-- coarse X: bits 0-4
    |+-------------- horizontal nametable: bit 10
    +--------------- vertical nametable: bit 11, not copied here

Horizontal mask

0b000_01_00000_11111 = 0x041F

Required result

coarse X                    <- t
horizontal nametable       <- t
coarse Y                    <- original v
fine Y                      <- original v
vertical nametable         <- original v
every other unrelated bit  <- original v

Minimal example

v: coarse X 3,  horizontal nametable 0, vertical state A
t: coarse X 20, horizontal nametable 1, vertical state B

result: coarse X 20, horizontal nametable 1, vertical state A

Common misconception

The horizontal reload is not v = t. Copying all of t would replace vertical state at the wrong time. A later step will apply this already-tested operation at dot 257.

Out of scope

  • modifying PPU.step()
  • dot-257 timing
  • horizontal address increments
  • vertical t-to-v copies
  • framebuffer rendering

Complete example implementation

# emulator/ppu/ppu.py

# --- NEW LINE: COARSE X AND HORIZONTAL NAMETABLE FIELDS ---
HORIZONTAL_SCROLL_BITS = 0b000_01_00000_11111


# --- NEW BLOCK: PURE HORIZONTAL t-TO-v COPY ---
def copy_horizontal_scroll_bits(
    vram_addr: int,
    temp_vram_addr: int,
) -> int:
    return (
        (vram_addr & ~HORIZONTAL_SCROLL_BITS)
        | (temp_vram_addr & HORIZONTAL_SCROLL_BITS)
    )

Run this lesson

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