293. Validation cpu reads controller 4016

VALIDATION TEST: CPU program reads controller bits from $4016.

Lesson 293 of 356 · tests/chapter_07_controller_input/test_293_VALIDATION_cpu_reads_controller_4016.py

This is not a student implementation step.

There is nothing new to build in this file. This test validates that already-built pieces work together:

CPU instructions
    -> CpuBus.write($4016, value)
    -> Controller.write_strobe(value)
    -> CpuBus.read($4016)
    -> Controller.read_bit()
    -> CPU stores observed bits into RAM

Why this validation exists

The previous tests proved the Controller object and CpuBus $4016 routing in isolation. This test proves that a real CPU instruction sequence can use that path.

References

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

NES controller polling shape

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

The eight reads return

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

Tiny program used here

LDA #$01
STA $4016     ; strobe high, capture live buttons

LDA #$00
STA $4016     ; strobe low, serial reads advance

LDA $4016
STA $0000     ; A bit

LDA $4016
STA $0001     ; B bit

... repeated through Right bit ...

Important distinction

This validation stores each serial bit in a separate RAM byte for readability. Many NES assembly examples shift the bits into one result byte. That is game-code policy, not controller hardware behavior.

Out of scope

  • pygame keyboard mapping
  • main.py loop
  • controller port 2
  • Famicom expansion controllers
  • DMC/controller read glitch behavior
  • commercial ROM fixtures

Run this lesson

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