292. Cpubus, mando y 4016

Enrutar las lecturas/escrituras de CpuBus en $4016 al puerto de mando 1.

Lección 292 de 356 · tests/chapter_07_controller_input/test_292_cpubus_controller_4016.py

Archivo a actualizar

emulator/bus/cpu_bus.py

Por qué existe este paso

Los pasos anteriores del mando crearon un objeto puro Controller. Ahora el bus de la CPU debe exponer ese mando a través del puerto de mando mapeado en memoria de la NES:

$4016 = controller port 1

Secuencia normal de sondeo de la NES

write 1 to $4016
write 0 to $4016
read $4016 eight times

Esas ocho lecturas devuelven

A, B, Select, Start, Up, Down, Left, Right

Referencias

https://www.nesdev.org/wiki/Standard_controller
https://www.nesdev.org/wiki/Controller_reading_code

Ejemplo de implementación sugerido

from emulator.input.controller import Controller


@dataclass
class CpuBus:
    ...
    controller_1: Controller = field(default_factory=Controller)

    def read(self, addr: int) -> int:
        ...

        # Controller port 1
        if addr == 0x4016:
            return self.controller_1.read_bit()

        # Controller port 2 / expansion input is out of scope for now.
        if addr == 0x4017:
            return 0

        ...

    def write(self, addr: int, value: int) -> None:
        ...

        # Controller port 1 strobe
        if addr == 0x4016:
            self.controller_1.write_strobe(value)
            return

        # $4017 writes are APU frame-counter writes, no-op for now.
        if addr == 0x4017:
            return

        ...

Distinción importante

$4016 read/write belongs to controller port 1.
$4017 read is controller port 2 / expansion input, out of scope for now.
$4017 write is APU frame counter, out of scope for now.

Concepto erróneo habitual

"Controller input should be handled by pygame directly in CpuBus."

No. CpuBus solo debe comunicarse con el objeto puro Controller. El mapeo de teclado de pygame actualizará más adelante los booleanos de botones de Controller desde un punto de entrada manual/frontend.

Fuera de alcance

  • Mapeo de teclado de pygame
  • Implementación del puerto de mando 2
  • Mandos de expansión de Famicom
  • Comportamiento de glitch de lectura de DMC/mando
  • Comportamiento de bits superiores de open bus

Ejecutar esta lección

uv run pytest tests/chapter_07_controller_input/test_292_cpubus_controller_4016.py -v