查看测试代码test_258_build_pattern_table_debug_grid.py
import pytest
from emulator.ppu.chr_decoder import (
CHR_TILE_HEIGHT,
CHR_TILE_SIZE,
CHR_TILE_WIDTH,
PATTERN_TABLE_DEBUG_GRID_SIZE,
PATTERN_TABLE_SIZE,
PATTERN_TABLE_TILE_COUNT,
PATTERN_TABLE_TILES_PER_ROW,
build_pattern_table_debug_grid,
decode_pattern_table,
)
def blank_tile():
"""Create one decoded 8x8 tile filled with zero color indexes."""
return [[0 for _ in range(CHR_TILE_WIDTH)] for _ in range(CHR_TILE_HEIGHT)]
def solid_tile(value: int):
"""Create one decoded 8x8 tile filled with one color index."""
return [[value for _ in range(CHR_TILE_WIDTH)] for _ in range(CHR_TILE_HEIGHT)]
def make_decoded_tiles_with_tile(tile_index: int, tile):
"""Create 256 decoded tiles, replacing one tile at tile_index."""
tiles = [blank_tile() for _ in range(PATTERN_TABLE_TILE_COUNT)]
tiles[tile_index] = tile
return tiles
def make_synthetic_pattern_table_bytes() -> bytes:
"""Create one deterministic 4096-byte pattern table with a few known tiles."""
pattern_table = bytearray(PATTERN_TABLE_SIZE)
pattern_table[0] = 0b1100_0011
pattern_table[8] = 0b1010_0101
tile_1_start = CHR_TILE_SIZE
pattern_table[tile_1_start] = 0b0000_1111
tile_16_start = 16 * CHR_TILE_SIZE
pattern_table[tile_16_start + 8] = 0b1111_1111
return bytes(pattern_table)
def test_pattern_table_debug_grid_declares_layout_constants():
"""
Objective:
Name the debug grid layout: 16x16 tiles, each tile 8x8 pixels, total 128x128.
"""
assert PATTERN_TABLE_TILES_PER_ROW == 16
assert CHR_TILE_WIDTH == 8
assert CHR_TILE_HEIGHT == 8
assert PATTERN_TABLE_DEBUG_GRID_SIZE == 128
def test_build_pattern_table_debug_grid_rejects_non_256_tile_input():
"""
Objective:
A pattern table debug grid requires exactly 256 decoded tiles.
"""
with pytest.raises(ValueError, match="256 decoded tiles"):
build_pattern_table_debug_grid([blank_tile()] * (PATTERN_TABLE_TILE_COUNT - 1))
def test_build_pattern_table_debug_grid_returns_128_by_128_grid():
"""
Objective:
The debug grid should be 128 rows by 128 columns.
"""
grid = build_pattern_table_debug_grid([blank_tile() for _ in range(PATTERN_TABLE_TILE_COUNT)])
assert len(grid) == PATTERN_TABLE_DEBUG_GRID_SIZE
assert all(len(row) == PATTERN_TABLE_DEBUG_GRID_SIZE for row in grid)
def test_tile_0_is_placed_at_top_left_of_debug_grid():
"""
Objective:
Tile 0 should occupy pixels x=0..7 and y=0..7.
"""
tiles = make_decoded_tiles_with_tile(0, solid_tile(1))
grid = build_pattern_table_debug_grid(tiles)
assert grid[0][0:8] == [1] * 8
assert grid[7][0:8] == [1] * 8
assert grid[0][8] == 0
def test_tile_1_is_placed_to_the_right_of_tile_0():
"""
Objective:
Tile 1 should start at x=8, y=0.
"""
tiles = make_decoded_tiles_with_tile(1, solid_tile(2))
grid = build_pattern_table_debug_grid(tiles)
assert grid[0][0:8] == [0] * 8
assert grid[0][8:16] == [2] * 8
def test_tile_16_is_placed_at_start_of_second_tile_row():
"""
Objective:
Tile 16 should start the second tile row at x=0, y=8.
"""
tiles = make_decoded_tiles_with_tile(16, solid_tile(3))
grid = build_pattern_table_debug_grid(tiles)
assert grid[0][0:8] == [0] * 8
assert grid[8][0:8] == [3] * 8
def test_tile_255_is_placed_at_bottom_right_of_debug_grid():
"""
Objective:
Tile 255 should occupy the bottom-right 8x8 area.
"""
tiles = make_decoded_tiles_with_tile(255, solid_tile(1))
grid = build_pattern_table_debug_grid(tiles)
assert grid[120][120:128] == [1] * 8
assert grid[127][120:128] == [1] * 8
assert grid[119][120] == 0
def test_synthetic_pattern_table_decodes_into_expected_debug_grid_pixels():
"""
Objective:
Use deterministic synthetic bytes to verify the complete path:
bytes -> decoded tiles -> 128x128 debug grid
This avoids depending on copyrighted CHR data from a commercial ROM.
"""
pattern_table_bytes = make_synthetic_pattern_table_bytes()
assert len(pattern_table_bytes) == PATTERN_TABLE_SIZE
assert len(pattern_table_bytes) == PATTERN_TABLE_TILE_COUNT * CHR_TILE_SIZE
decoded_tiles = decode_pattern_table(pattern_table_bytes)
grid = build_pattern_table_debug_grid(decoded_tiles)
assert grid[0][0:8] == [3, 1, 2, 0, 0, 2, 1, 3]
assert grid[0][8:16] == [0, 0, 0, 0, 1, 1, 1, 1]
assert grid[8][0:8] == [2, 2, 2, 2, 2, 2, 2, 2]
测试函数 (8)
test_pattern_table_debug_grid_declares_layout_constantstest_build_pattern_table_debug_grid_rejects_non_256_tile_inputtest_build_pattern_table_debug_grid_returns_128_by_128_gridtest_tile_0_is_placed_at_top_left_of_debug_gridtest_tile_1_is_placed_to_the_right_of_tile_0test_tile_16_is_placed_at_start_of_second_tile_rowtest_tile_255_is_placed_at_bottom_right_of_debug_gridtest_synthetic_pattern_table_decodes_into_expected_debug_grid_pixels