344. Уменьшить горизонтальный адрес vram
Отменить одно горизонтальное увеличение background-fetch на скопированном адресе.
Урок 344 из 356 · tests/chapter_13_scrolling/test_344_decrement_horizontal_vram_addr.py
Файл для обновления
emulator/ppu/ppu.pyСсылки
https://www.nesdev.org/wiki/PPU_scrolling#DetailsЗачем нужен этот шаг
Точки 321-336 выполняют prefetch первых двух background плиток для следующего scanline. Каждый fetch плитки продвигает горизонтальный v, поэтому на точке 1 адрес уже на два столбца плиток впереди пикселей, хранящихся в background shifters:
intended visible coarse X = 5
prefetch tile 5 -> v advances to 6
prefetch tile 6 -> v advances to 7
dot 1:
shifters begin displaying tile 5
v already contains coarse X 7Позже запись scanline скопирует v и отмотает эту копию дважды
7 -> 6 -> 5Эта вспомогательная функция отменяет одно увеличение. Это не синхронизированная операция PPU, и она никогда не должна перемещать реальный PPU.vram_addr назад.
Нормальное поведение
coarse X 31 -> 30
coarse X 7 -> 6
coarse X 1 -> 0Поведение на границе
coarse X 0 -> 31 and toggle horizontal nametableВажные инварианты
- только coarse X и, при переносе, горизонтальный nametable могут изменяться
- каждое вертикальное и несвязанное поле остаётся неизменным
- уменьшение является обратным протестированному горизонтальному увеличению
- функция чистая и не изменяет PPU
Распространённое заблуждение
NES PPU не выполняет это уменьшение во время рендеринга. Оно существует только для преобразования адреса fetch, который впереди дисплея, в адрес видимого viewport для существующего высокоуровневого рендерера.
Вне области действия
- вызов вспомогательной функции из PPU.step()
- запись 240 позиций scanline
- изменения framebuffer или opacity-mask
Полный пример реализации
# emulator/ppu/ppu.py
# --- NEW BLOCK: REVERSE ONE HORIZONTAL FETCH INCREMENT ---
def decrement_horizontal_vram_addr(vram_addr: int) -> int:
coarse_x = vram_addr & 0b1_1111
if coarse_x == 0:
vram_addr = (
(vram_addr & ~0b1_1111)
| 0b1_1111
)
vram_addr ^= 0b000_01_00000_00000
return vram_addr
return vram_addr - 1Запустить этот урок
uv run pytest tests/chapter_13_scrolling/test_344_decrement_horizontal_vram_addr.py -v