308. Console 渲染帧缓冲

从 Console 暴露完整的背景+精灵帧缓冲。

308 / 356 · tests/chapter_09_sprite_rendering/test_308_console_render_framebuffer.py

需要更新的文件

emulator/console.py

为什么需要这一步

前端不应该知道如何分别提取背景内存、精灵 OAM、精灵调色板 RAM 或精灵图案表。Console 负责协调 CPU/PPU 系统,因此它应该暴露一个面向前端的方法:

console.render_framebuffer()

这个方法使用以下内容返回当前可见的帧缓冲

background renderer
PPU.oam sprites
sprite palette RAM $3F10-$3F1F
sprite pattern table selected by PPUCTRL bit 3

建议的实现示例

# Add this constant to the existing ppu_background_renderer import.
from emulator.rendering.ppu_background_renderer import PALETTE_RAM_ADDR


def render_framebuffer(self) -> Framebuffer:
    background = self.render_background_framebuffer()

    sprite_palette_start = PALETTE_RAM_ADDR + 16
    sprite_palette_ram = bytes(
        self.ppu.ppu_bus.read(sprite_palette_start + offset)
        for offset in range(16)
    )
    sprite_palettes = build_sprite_palettes_from_palette_ram(sprite_palette_ram)

    pattern_table_base = (
        PATTERN_TABLE_1_ADDR
        if self.ppu.ctrl & CTRL_SPRITE_PATTERN_TABLE
        else PATTERN_TABLE_0_ADDR
    )

    pattern_table = bytes(
        self.ppu.ppu_bus.read(pattern_table_base + offset)
        for offset in range(0x1000)
    )

    return composite_background_and_sprites(
        background=background,
        oam=self.ppu.oam,
        pattern_table=pattern_table,
        sprite_palettes=sprite_palettes,
    )

重要边界

Console 可以调用纯渲染辅助函数,但 Console 不能导入 pygame。

本步骤不涉及的内容

  • sprite 0 hit
  • sprite overflow
  • 8x16 精灵
  • 精灵/背景优先级位的行为
  • pygame 显示

运行本课

uv run pytest tests/chapter_09_sprite_rendering/test_308_console_render_framebuffer.py -v