291. Captura del mando y lectura serie
Capturar los botones del mando y leerlos en serie.
Lección 291 de 356 · tests/chapter_07_controller_input/test_291_controller_capture_and_serial_read.py
Archivos creados en este paso
emulator/input/controller.pyPor qué existe este paso
La CPU de la NES no recibe el estado del mando como un byte completo desde $4016. Recibe un bit de botón cada vez. Antes de conectar ese protocolo a CpuBus, el objeto puro Controller debe saber cómo:
Referencias
https://www.nesdev.org/wiki/Standard_controller
https://www.nesdev.org/wiki/Controller_reading_code
1. capture the current button booleans into a stable snapshot
2. expose the captured bits in NES serial order
3. handle strobe high vs strobe low behaviorTérmino clave: strobe Un strobe es una señal de control escrita por la CPU. Para el mando de la NES, el strobe controla si el mando sigue capturando el estado en vivo de los botones o avanza por los bits serie ya capturados.
Ejemplo mínimo
controller.a = True
controller.write_strobe(1)
controller.write_strobe(0)
controller.read_bit() # returns A bitConcepto erróneo habitual
"The controller should return all buttons as one byte."El emulador puede almacenar internamente los botones capturados como un solo byte, pero el protocolo orientado a la CPU lee un bit cada vez.
Ejemplo de implementación sugerido
def capture_buttons(self) -> None:
value = 0
if self.a:
value |= BUTTON_A
if self.b:
value |= BUTTON_B
if self.select:
value |= BUTTON_SELECT
if self.start:
value |= BUTTON_START
if self.up:
value |= BUTTON_UP
if self.down:
value |= BUTTON_DOWN
if self.left:
value |= BUTTON_LEFT
if self.right:
value |= BUTTON_RIGHT
self.captured_buttons = value
self.read_index = 0
def write_strobe(self, value: int) -> None:
self.strobe = (value & 1) == 1
if self.strobe:
self.capture_buttons()
def read_bit(self) -> int:
if self.strobe:
self.capture_buttons()
if self.read_index >= 8:
return 1
bit = (self.captured_buttons >> self.read_index) & 1
self.read_index += 1
return bitFuera de alcance
- Enrutamiento de $4016 en CpuBus
- Mapeo de teclado de pygame
- Puerto de mando 2
- Mandos de expansión de Famicom
- Comportamiento de glitch de lectura de DMC/mando
Ejecutar esta lección
uv run pytest tests/chapter_07_controller_input/test_291_controller_capture_and_serial_read.py -v