341. Incrementar la dirección vertical de vram
Incrementar el componente vertical de la dirección de renderizado actual v.
Lección 341 de 356 · tests/chapter_13_scrolling/test_341_increment_vertical_vram_addr.py
Archivo a actualizar
emulator/ppu/ppu.pyReferencias
https://www.nesdev.org/wiki/PPU_scrolling#Y_increment
https://www.nesdev.org/wiki/PPU_scrolling#Wrapping_aroundPor qué existe este paso
En el dot 256, la PPU avanza la dirección de renderizado en una fila de píxeles. A diferencia del incremento horizontal, el movimiento vertical primero avanza la Y fina dentro del tile actual de 8 píxeles:
yyy NN YYYYY XXXXX
+++ +++++
| +---- coarse Y: bits 5-9
+------------ fine Y: bits 12-14
vertical nametable: bit 11Comportamiento de Y fina
0 -> 1 -> 2 -> ... -> 7Cuando la Y fina ya vale 7, vuelve a 0 y la Y gruesa avanza.
Comportamiento de la Y gruesa tras el desbordamiento de la Y fina
coarse Y 0-28 -> increment by one
coarse Y 29 -> 0 and toggle vertical nametable
coarse Y 30 -> 31 through the normal increment branch
coarse Y 31 -> 0 without toggling vertical nametableLas filas 0-29 son las 30 filas de tiles visibles de una nametable. Los valores 30 y 31 no son filas visibles normales, pero pueden existir porque la Y gruesa es un campo de cinco bits y las operaciones de dirección de la CPU pueden cargar esos valores.
¿Por qué sumar $1000 para un incremento normal de Y fina? La Y fina comienza en el bit 12, así que sumar 1 << 12 incrementa ese campo empaquetado en uno. Esto no significa conceptualmente desplazarse 4096 bytes por la memoria de la PPU.
Invariantes importantes
- la X gruesa horizontal y la selección de nametable permanecen sin cambios
- los bits internos de dirección no relacionados permanecen sin cambios
- la nametable vertical solo se alterna cuando la fila 29 se desborda
- el auxiliar es puro y no modifica la PPU
Concepto erróneo común
El incremento vertical no es simplemente simétrico al incremento horizontal. El movimiento horizontal avanza una columna de tiles; el movimiento vertical avanza una fila de píxeles fina y solo a veces avanza la fila de tiles gruesa.
Fuera de alcance
- invocar este auxiliar en el dot 256
- la copia vertical de t a v
- la temporización del pre-render
- el registro del viewport por scanline
- el renderizado del framebuffer
Implementación de ejemplo completa
# emulator/ppu/ppu.py
# --- NEW BLOCK: PURE VERTICAL v INCREMENT ---
def increment_vertical_vram_addr(vram_addr: int) -> int:
fine_y = (vram_addr >> 12) & 0b111
if fine_y < 7:
return vram_addr + (1 << 12)
vram_addr &= ~0b111_00_00000_00000
coarse_y = (vram_addr >> 5) & 0b1_1111
if coarse_y == 29:
coarse_y = 0
vram_addr ^= 0b000_10_00000_00000
elif coarse_y == 31:
coarse_y = 0
else:
coarse_y += 1
return (
(vram_addr & ~0b000_00_11111_00000)
| (coarse_y << 5)
)Ejecutar esta lección
uv run pytest tests/chapter_13_scrolling/test_341_increment_vertical_vram_addr.py -v