233. Устройство памяти VRAM
Создать простое устройство памяти VRAM.
Урок 233 из 356 · tests/chapter_03_ppu_memory_and_graphics_data/test_233_vram_memory_device.py
Файл для создания
emulator/memory/vram.pyКласс для реализации
VRAMЗачем нужен этот шаг
У PPU собственное адресное пространство, отдельное от адресного пространства CPU. RAM CPU — не то место, где обычно живёт состояние фоновой/спрайтовой графики. PPU нужна ориентированная на видео память, к которой он может обращаться через PPUADDR/PPUDATA и, позже, через логику рендеринга.
Важная ментальная модель
CPU address space: $0000-$FFFF
handled by CpuBus
PPU address space: $0000-$3FFF
will be handled by PpuBusДля этого раннего шага VRAM — простое перезаписываемое хранилище для адресного пространства со стороны PPU. Позже PpuBus решит, как PPU-адреса отображаются в CHR ROM, VRAM таблиц имён, RAM палитры и зеркала.
Почему VRAM отделена от регистров PPU
Регистры PPU, такие как $2006 и $2007, — это видимые для CPU порты управления/данных. Они не являются самой памятью.
Пример потока данных в будущем
CPU writes $20 to $2006
CPU writes $00 to $2006
CPU writes $AA to $2007Значение
PPU internal address becomes $2000
PPUDATA writes $AA into PPU-side memory at $2000CPU обращается к регистру $2007, но фактический адрес видеопамяти — это внутренний адрес PPU, а не CPU-адрес $2007.
Текущая область действия
- VRAM — это MemoryDevice
- VRAM хранит 0x4000 байт
- VRAM.read(addr) возвращает сохранённый байт по адресу addr
- VRAM.write(addr, value) сохраняет только младший байт значения value
Важное разделение ответственности
VRAM не должна применять addr & 0x3FFF. Нормализация/маршрутизация адресов — задача PpuBus, потому что карта адресов PPU принадлежит PpuBus. VRAM — только хранилище.
Предлагаемый псевдокод реализации
from dataclasses import dataclass, field
from emulator.memory.memory_device import MemoryDevice
VRAM_SIZE = 0x4000
@dataclass
class VRAM(MemoryDevice):
_data: bytearray = field(
default_factory=lambda: bytearray(VRAM_SIZE),
init=False,
)
def write(self, addr: int, value: int) -> None:
self._data[addr] = value & 0xFF
def read(self, addr: int) -> int:
return self._data[addr]Вне области действия
- маршрутизация PpuBus
- отображение CHR ROM
- зеркалирование таблиц имён
- палитра RAM
- рендеринг
Запустить этот урок
uv run pytest tests/chapter_03_ppu_memory_and_graphics_data/test_233_vram_memory_device.py -v