322. Posición del sprite zero hit del PPU
Extraer la posición de solapamiento del sprite 0 del estado actual del PPU.
Lección 322 de 356 · tests/chapter_11_sprite_zero_hit/test_322_ppu_sprite_zero_hit_position.py
Archivo a actualizar
emulator/rendering/sprite_zero_hit.pyPor qué existe este paso
El helper puro existente requiere datos de renderizado explícitos
find_sprite_zero_hit_position(
sprite_zero,
pattern_table,
background_opaque_mask,
)Esa API es útil para tests centrados, pero un futuro paso de Console parte de un PPU. Este paso añade un pequeño adaptador que extrae los datos requeridos del estado actual del PPU y delega en el helper puro existente.
Mantener ambas funciones en sprite_zero_hit.py queda claro con el tamaño actual del proyecto:
find_sprite_zero_hit_position(...)
explicit data -> overlap position
ppu_sprite_zero_hit_position(ppu)
PPU state -> explicit data -> overlap positionLa segunda función es un adaptador, no otro algoritmo de solapamiento.
Extracción requerida
- decodificar solo la entrada 0 de OAM
- construir la máscara de opacidad del fondo mediante ppu_background_to_opaque_mask(ppu)
- seleccionar la tabla de patrones de sprite usando el bit 3 de PPUCTRL
- leer PATTERN_TABLE_SIZE bytes a través de PpuBus
- delegar en find_sprite_zero_hit_position(...)
Ejemplo de implementación sugerido
from emulator.ppu.chr_decoder import PATTERN_TABLE_SIZE, decode_chr_tile
from emulator.ppu.ppu import CTRL_SPRITE_PATTERN_TABLE, PPU
from emulator.rendering.ppu_background_renderer import (
PATTERN_TABLE_0_ADDR,
PATTERN_TABLE_1_ADDR,
ppu_background_to_opaque_mask,
)
from emulator.rendering.sprite_renderer import (
SpriteEntry,
decode_sprite_attributes,
decode_sprite_entry,
)
...
def ppu_sprite_zero_hit_position(
ppu: PPU,
) -> SpriteZeroHitPosition | None:
sprite_zero = decode_sprite_entry(
oam=ppu.oam,
sprite_index=0,
)
background_opaque_mask = ppu_background_to_opaque_mask(ppu)
sprite_pattern_table_base = (
PATTERN_TABLE_1_ADDR
if ppu.ctrl & CTRL_SPRITE_PATTERN_TABLE
else PATTERN_TABLE_0_ADDR
)
sprite_pattern_table = bytes(
ppu.ppu_bus.read(sprite_pattern_table_base + offset)
for offset in range(PATTERN_TABLE_SIZE)
)
return find_sprite_zero_hit_position(
sprite_zero=sprite_zero,
pattern_table=sprite_pattern_table,
background_opaque_mask=background_opaque_mask,
)Distinción importante
La opacidad del fondo usa la ruta de selección de la tabla de patrones del fondo, que se basa en el bit 4 de PPUCTRL. Los datos CHR del sprite 0 usan el bit 3 de PPUCTRL. Las dos selecciones pueden apuntar a tablas de patrones distintas.
Límite importante
Esta función solo devuelve una posición. No establece PPUSTATUS ni llama a PPU.set_sprite_zero_hit_position(). La conexión de Console queda para un paso posterior.
Fuera del alcance
- Conexión de Console
- programación automática
- reglas de activación de renderizado de PPUMASK
- reglas de recorte del borde izquierdo
- excepción de hardware en x=255
- corrección de Y+1 de OAM
- validación con Super Mario Bros.
Ejecutar esta lección
uv run pytest tests/chapter_11_sprite_zero_hit/test_322_ppu_sprite_zero_hit_position.py -v