233. Dispositivo de memoria vram

Crea un dispositivo de memoria VRAM sencillo.

Lección 233 de 356 · tests/chapter_03_ppu_memory_and_graphics_data/test_233_vram_memory_device.py

Archivo a crear

emulator/memory/vram.py

Clase a implementar

VRAM

Por qué existe este paso

La PPU tiene su propio espacio de direcciones, separado del espacio de direcciones de la CPU. La RAM de la CPU no es donde normalmente vive el estado gráfico de fondo/sprites. La PPU necesita memoria orientada a vídeo a la que pueda acceder a través de PPUADDR/PPUDATA y, más adelante, a través de la lógica de renderizado.

Modelo mental importante

CPU address space: $0000-$FFFF
    handled by CpuBus

PPU address space: $0000-$3FFF
    will be handled by PpuBus

En este paso inicial, VRAM es un simple almacén de escritura para el espacio de direcciones del lado de la PPU. Más adelante, PpuBus decidirá cómo se asignan las direcciones de la PPU a la CHR ROM, la VRAM de nametables, la RAM de paletas y los espejos.

Por qué VRAM está separada de los registros de la PPU

Registros de la PPU como $2006 y $2007 son puertos de control/datos visibles para la CPU. No son la memoria en sí.

Ejemplo de flujo posterior

CPU writes $20 to $2006
CPU writes $00 to $2006
CPU writes $AA to $2007

Significado

PPU internal address becomes $2000
PPUDATA writes $AA into PPU-side memory at $2000

La CPU accede al registro $2007, pero la dirección de memoria de vídeo real es la dirección interna de la PPU, no la dirección $2007 de la CPU.

Alcance actual

  • VRAM es un MemoryDevice
  • VRAM almacena 0x4000 bytes
  • VRAM.read(addr) devuelve el byte almacenado en addr
  • VRAM.write(addr, value) almacena solo el byte bajo de value

División de responsabilidades importante

VRAM no debe aplicar addr & 0x3FFF. La normalización/enrutamiento de direcciones pertenece a PpuBus, porque PpuBus es quien posee el mapa de direcciones de la PPU. VRAM es solo almacenamiento.

Pseudocódigo de implementación sugerido

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]

Fuera de alcance

  • enrutamiento de PpuBus
  • mapeo de CHR ROM
  • espejado de nametables
  • RAM de paletas
  • renderizado

Ejecutar esta lección

uv run pytest tests/chapter_03_ppu_memory_and_graphics_data/test_233_vram_memory_device.py -v