348. X del viewport de scanline
Decodificar la X del viewport horizontal a partir de un estado de scanline registrado.
Lección 348 de 356 · tests/chapter_13_scrolling/test_348_scanline_viewport_x.py
Archivo a actualizar
emulator/rendering/ppu_background_renderer.pyReferencia
https://www.nesdev.org/wiki/PPU_scrollingPor qué existe este paso
El paso 347 seleccionó las dos nametables lógicas que forman un par de origen horizontal. Un compositor de filas posterior también necesita el píxel exacto en el que comienza este scanline dentro de ese par de 512 píxeles de ancho.
La dirección registrada usa el mismo formato empaquetado de scroll que t
yyy NN YYYYY XXXXXLa X del viewport horizontal usa
XXXXX coarse X tile column
low N bit horizontal nametable selection, vram_addr bit 10
state.fine_x pixel offset inside the first tileConversión de píxeles
viewport_x = nametable_x * 256 + coarse_x * 8 + fine_xEjemplo
nametable X = 1
coarse X = 5
fine X = 3
viewport X = 1 * 256 + 5 * 8 + 3 = 299¿Por qué reutilizar decode_background_viewport_position? El decodificador puro existente ya posee la conversión del campo de scroll empaquetado. Tanto t como la v registrada tienen el mismo formato de bits, así que repetir máscaras y dimensiones en este renderizador crearía dos implementaciones que podrían divergir.
Invariantes importantes
- el bit 10 de la nametable horizontal aporta 256 píxeles
- la X gruesa aporta ocho píxeles por tile
- la X fina aporta el desplazamiento final de 0-7 píxeles
- la nametable vertical, la Y gruesa y la Y fina no afectan a la X del viewport
- el resultado permanece dentro del rango lógico horizontal 0-511
- la dirección registrada no se rebobina de nuevo
- el auxiliar no realiza renderizado ni acceso a memoria
Concepto erróneo común
La dirección registrada no necesita otra corrección de dos tiles. El paso 345 ya rebobinó dos veces una copia de v antes de construir BackgroundScanlineState. Repetir el rebobinado aquí desplazaría incorrectamente cada fila renderizada dieciséis píxeles a la izquierda.
Fuera de alcance
- seleccionar direcciones lógicas de nametable
- componer filas del framebuffer
- aplicar el desbordamiento horizontal a los píxeles de destino
- la composición de la máscara de opacidad
- elegir entre los datos temporizados y el mecanismo de respaldo a nivel de frame antiguo
Implementación de ejemplo completa
# emulator/rendering/ppu_background_renderer.py
# --- NEW BLOCK: DECODE ONE SCANLINE'S HORIZONTAL VIEWPORT ---
def _scanline_viewport_x(state: BackgroundScanlineState) -> int:
viewport_x, _ = decode_background_viewport_position(
temp_vram_addr=state.vram_addr,
fine_x=state.fine_x,
)
return viewport_xEjecutar esta lección
uv run pytest tests/chapter_13_scrolling/test_348_scanline_viewport_x.py -v