245. Conmutador de segunda escritura de PPUSCROLL
Implementa el comportamiento de desplazamiento de doble escritura de PPUSCROLL ($2005).
Lección 245 de 356 · tests/chapter_03_ppu_memory_and_graphics_data/test_245_ppuscroll_second_write_toggle.py
Implementa el comportamiento de desplazamiento de doble escritura de PPUSCROLL ($2005). !! Tómate tu tiempo para implementar esto
Referencias
https://www.nesdev.org/wiki/PPU_registers#PPUSCROLL
https://www.nesdev.org/wiki/PPU_scrolling#$2005_(PPUSCROLL)_first_write_(w_is_0)
https://www.nesdev.org/wiki/PPU_scrolling#$2005_(PPUSCROLL)_second_write_(w_is_1)Archivo a actualizar
emulator/ppu/ppu.pyMétodo a actualizar
PPU.write_register(addr, value)Por qué existe este paso
PPUSCROLL es el registro visible para la CPU en $2005. Al igual que PPUADDR ($2006), usa el conmutador compartido de primera escritura / segunda escritura:
second_write_toggle == False -> first write
second_write_toggle == True -> second writeLa primera escritura configura el desplazamiento horizontal
value bits 7-3 -> coarse X, stored in temp_vram_addr bits 0-4
value bits 2-0 -> fine X, stored in fine_xLa segunda escritura configura el desplazamiento vertical
value bits 7-3 -> coarse Y, stored in temp_vram_addr bits 5-9
value bits 2-0 -> fine Y, stored in temp_vram_addr bits 12-14Modelo importante de registro interno
vram_addr -> v, current VRAM address
temp_vram_addr -> t, temporary VRAM address
fine_x -> x, fine horizontal scroll
second_write_toggle -> w, first/second write togglePseudocódigo de implementación sugerido, siguiendo el estilo explícito de movimiento de bits:
case 0x2005:
# Keep for old compatibility.
self.scroll = value
if not self.second_write_toggle:
# Reference:
# https://www.nesdev.org/wiki/PPU_scrolling#$2005_(PPUSCROLL)_first_write_(w_is_0)
#
# PPU Scroll first write.
# Incoming value bits are named ABCDEFGH.
#
# fine_x register:
# x: FGH <- value: .....FGH
#
# In other words, save the last 3 bits as fine horizontal scroll.
self.fine_x = value & 0b0000_0111
# temp_vram_addr register:
# t: ....... ...ABCDE <- value: ABCDE...
#
# In other words, save the upper 5 bits as coarse X in bits 0-4.
# The mask keeps every temp_vram_addr bit except coarse X.
self.temp_vram_addr = (
(self.temp_vram_addr & 0b1111_1111_1110_0000)
| (value >> 3)
)
# w <- 1
# Next $2005/$2006 write will be treated as the second write.
self.second_write_toggle = True
else:
# Reference:
# https://www.nesdev.org/wiki/PPU_scrolling#$2005_(PPUSCROLL)_second_write_(w_is_1)
#
# PPU Scroll second write.
# Incoming value bits are named ABCDEFGH.
#
# temp_vram_addr register:
# t: FGH..AB CDE..... <- value: ABCDEFGH
#
# Step 1: keep only untouched bits:
# - bit 15
# - nametable bits 10-11
# - coarse X bits 0-4
#
# This clears the vertical scroll destination bits:
# - coarse Y bits 5-9
# - fine Y bits 12-14
self.temp_vram_addr = (
self.temp_vram_addr & 0b1000_1100_0001_1111
)
# Step 2: put the last 3 bits into fine Y.
# value: .....FGH
# FGH << 12 -> bits 12-14
self.temp_vram_addr = (
self.temp_vram_addr | ((value & 0b0000_0111) << 12)
)
# Step 3: put the upper 5 bits into coarse Y.
# value: ABCDE...
# (value & 11111000) << 2 -> bits 5-9
self.temp_vram_addr = (
self.temp_vram_addr | ((value & 0b1111_1000) << 2)
)
# w <- 0
# The two-write PPUSCROLL sequence is complete.
self.second_write_toggle = FalseFuera del alcance
- copiado de los bits de desplazamiento de temp_vram_addr a vram_addr durante el renderizado
- temporización de scanline/ciclo
- renderizado real del fondo
Ejecutar esta lección
uv run pytest tests/chapter_03_ppu_memory_and_graphics_data/test_245_ppuscroll_second_write_toggle.py -v