007. ROM en el bus de la CPU

Mapear FakeROM en el rango de direcciones de ROM de programa de la CPU.

Lección 7 de 356 · tests/chapter_01_cpu/test_007_cpu_bus_rom.py

Archivo a actualizar

emulator/bus/cpu_bus.py

Ubicación

class CpuBus

Referencia

https://en.wikibooks.org/wiki/NES_Programming/Memory_Map

Por qué existe este paso

Las direcciones de CPU $8000-$FFFF deben capturar bytes de programa desde los desplazamientos locales $0000-$7FFF de FakeROM. El bus se encarga de esta traducción; el dispositivo de memoria solo ve desplazamientos locales.

Implementación de ejemplo completa

from dataclasses import dataclass, field
from typing import Optional

from emulator.memory.memory_device import MemoryDevice
from emulator.memory.ram import RAM


@dataclass
class CpuBus:
    program_rom: Optional[MemoryDevice] = None
    ram: RAM = field(default_factory=RAM)

    def read(self, addr: int) -> int:
        if 0x0000 <= addr <= 0x1FFF:
            return self.ram.read(addr & 0x07FF)

        if 0x8000 <= addr <= 0xFFFF:
            if self.program_rom is None:
                raise ValueError("No program ROM attached")
            return self.program_rom.read(addr - 0x8000)

        raise ValueError(f"Unsupported CPU bus read: {addr:04X}")

    def write(self, addr: int, value: int) -> None:
        if 0x0000 <= addr <= 0x1FFF:
            self.ram.write(addr & 0x07FF, value)
            return

        raise ValueError(f"Unsupported CPU bus write: {addr:04X}")

Invariante importante

rom_offset = cpu_address - 0x8000

Error común

La dirección de CPU del vector de reinicio $FFFC no es el índice $FFFC de FakeROM. Tras la traducción del bus, es el índice local $7FFC.

Fuera de alcance

  • reinicio de la CPU
  • análisis y mapeadores de cartuchos reales
  • escrituras en el espacio del cartucho

Ejecutar esta lección

uv run pytest tests/chapter_01_cpu/test_007_cpu_bus_rom.py -v