339. 复制水平滚动位
把水平滚动字段从临时地址 t 复制到当前地址 v。
第 339 / 356 · tests/chapter_13_scrolling/test_339_copy_horizontal_scroll_bits.py
待更新文件
emulator/ppu/ppu.py参考
https://www.nesdev.org/wiki/PPU_scrolling#During_rendering
https://www.nesdev.org/wiki/PPU_scrolling#At_dot_257_of_each_scanline此步骤存在的原因
CPU 写入会把滚动字段准备到临时地址 t 中,但背景渲染使用的是当前地址 v。PPU 在水平重载点只传输水平字段:
yyy NN YYYYY XXXXX
|| +++++-- coarse X: bits 0-4
|+-------------- horizontal nametable: bit 10
+--------------- vertical nametable: bit 11, not copied here水平掩码
0b000_01_00000_11111 = 0x041F所需结果
coarse X <- t
horizontal nametable <- t
coarse Y <- original v
fine Y <- original v
vertical nametable <- original v
every other unrelated bit <- original v最小示例
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常见误解
水平重载并不是 v = t。复制整个 t 会在错误的时机替换垂直状态。后续步骤会在第 257 点应用这个已经过测试的操作。
范围之外
- 修改 PPU.step()
- 第 257 点的时序
- 水平地址递增
- 垂直 t 到 v 复制
- 帧缓冲区渲染
完整示例实现
# 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)
)运行本课
uv run pytest tests/chapter_13_scrolling/test_339_copy_horizontal_scroll_bits.py -v