255. CHR 图块解码器

实现一个 CHR 图块解码器。

255 / 356 · tests/chapter_03_ppu_memory_and_graphics_data/test_255_chr_tile_decoder.py

参考资料

https://www.nesdev.org/wiki/PPU_pattern_tables

需要创建的文件

emulator/ppu/chr_decoder.py

需要实现的函数

decode_chr_tile(tile_bytes: bytes) -> list[list[int]]

什么是 CHR 图块?一个 CHR 图块是一个 8x8 的图形图块,存储为 16 字节。

它不存储最终的 RGB 颜色,而是存储 2 位的颜色索引:

0, 1, 2, or 3

这些索引之后会与调色板 RAM 结合,用来选出实际的 NES 颜色。

CHR 图块的字节布局

bytes 0-7   -> low bitplane, one byte per row
bytes 8-15  -> high bitplane, one byte per row

对每一行来说

low_byte  = tile_bytes[row]
high_byte = tile_bytes[row + 8]

对每一列来说,从左到右读取各个比特位

column 0 -> bit 7
column 1 -> bit 6
...
column 7 -> bit 0

建议的实现示例

def decode_chr_tile(tile_bytes: bytes) -> list[list[int]]:
    if len(tile_bytes) != 16:
        raise ValueError("To decode CHR tile, tile must be 16 bytes")

    rows = []

    for row in range(8):
        low_byte = tile_bytes[row]
        high_byte = tile_bytes[row + 8]
        columns = []

        for col in range(8):
            bit_position = 7 - col

            low = (low_byte >> bit_position) & 1
            high = (high_byte >> bit_position) & 1

            pixel = (high << 1) | low
            columns.append(pixel)

        rows.append(columns)

    return rows

不在本步骤范围内

  • 图案表的渲染
  • RGB/NES 调色板颜色
  • 名称表背景渲染
  • 精灵渲染
  • PPU 时序

运行本课

uv run pytest tests/chapter_03_ppu_memory_and_graphics_data/test_255_chr_tile_decoder.py -v