334. 将 PPU 背景视口渲染为帧缓冲区
根据当前 PPU 滚动状态组合水平背景帧缓冲区。
第 334 / 356 · tests/chapter_13_scrolling/test_334_ppu_background_viewport_to_framebuffer.py
待更新文件
emulator/rendering/ppu_background_renderer.py参考
https://www.nesdev.org/wiki/PPU_scrolling
https://www.nesdev.org/wiki/PPU_nametables此步骤存在的原因
前面的步骤能够渲染一个所选的逻辑名称表,也能够组合两个已有的帧缓冲区。此适配器将这些机制与当前 PPU 滚动状态连接起来。
水平流程
temp_vram_addr + fine_x
|
v
decode viewport X
|
v
select horizontal logical pair
|
v
render left and right nametables
|
v
compose one 256x240 framebuffer逻辑名称表对的选择
nametable Y = 0 -> left $2000, right $2400
nametable Y = 1 -> left $2800, right $2C00名称表 X 仍然是解码后视口 X 的一部分。例如,名称表 X=1、粗 X=5、细 X=3 会得出视口 X 299。
兼容性
现有的 ppu_background_to_framebuffer() 函数继续渲染一个所选的名称表。这个新的适配器会调用它两次,然后组合结果。
范围之外
- 不透明度掩码组合
- 与 Console 集成
- 与 sprite-zero-hit 集成
- 垂直像素滚动
- pygame
完整示例实现
# emulator/rendering/ppu_background_renderer.py
# --- NEW LINES: HORIZONTAL VIEWPORT OPERATIONS ---
from emulator.rendering.background_viewport import (
compose_horizontal_framebuffer_viewport,
compose_horizontal_opaque_mask_viewport,
decode_background_viewport_position,
)
...
# --- NEW BLOCK: COMPOSE THE HORIZONTAL FRAMEBUFFER VIEWPORT ---
def ppu_background_viewport_to_framebuffer(ppu: PPU) -> Framebuffer:
viewport_x, _ = decode_background_viewport_position(
temp_vram_addr=ppu.temp_vram_addr,
fine_x=ppu.fine_x,
)
nametable_y = (ppu.temp_vram_addr >> 11) & 1
left_base = BASE_NAMETABLE_ADDR + nametable_y * 0x0800
right_base = left_base + 0x0400
left = ppu_background_to_framebuffer(
ppu,
base_nametable_addr=left_base,
)
right = ppu_background_to_framebuffer(
ppu,
base_nametable_addr=right_base,
)
return compose_horizontal_framebuffer_viewport(
left=left,
right=right,
viewport_x=viewport_x,
)运行本课
uv run pytest tests/chapter_13_scrolling/test_334_ppu_background_viewport_to_framebuffer.py -v