Overview
Read the standard NES controller by writing to the strobe register, then reading 8 bits serially. Each bit represents one button: A, B, Select, Start, Up, Down, Left, Right. This is the standard approach used by virtually every NES game.
Code
; =============================================================================
; CONTROLLER READING - NES
; Read controller 1 via serial interface
; Taught: Game 1 (Neon Nexus), Unit 2
; CPU: ~80 cycles | Memory: ~20 bytes
; =============================================================================
JOYPAD1 = $4016 ; Controller 1 port
JOYPAD2 = $4017 ; Controller 2 port
; Button masks
BTN_A = %10000000
BTN_B = %01000000
BTN_SELECT = %00100000
BTN_START = %00010000
BTN_UP = %00001000
BTN_DOWN = %00000100
BTN_LEFT = %00000010
BTN_RIGHT = %00000001
.segment "ZEROPAGE"
buttons: .res 1 ; Current button state
.segment "CODE"
; Read controller and store button state
; Output: buttons variable contains all 8 button states
read_controller:
; Strobe the controller
lda #1
sta JOYPAD1
lda #0
sta JOYPAD1
; Read 8 buttons into 'buttons' variable
ldx #8
@read_loop:
lda JOYPAD1
lsr a ; Bit 0 -> Carry
rol buttons ; Carry -> buttons
dex
bne @read_loop
rts
Usage:
main_loop:
jsr read_controller
; Check specific buttons
lda buttons
and #BTN_A
bne @a_pressed
lda buttons
and #BTN_UP
beq @no_up
; Handle up pressed
dec player_y
@no_up:
lda buttons
and #BTN_DOWN
beq @no_down
; Handle down pressed
inc player_y
@no_down:
jmp main_loop
@a_pressed:
; Handle A button
jmp main_loop
Trade-offs
| Aspect | Cost |
|---|---|
| CPU | ~80 cycles |
| Memory | ~20 bytes code, 1 byte variable |
| Limitation | Reads controller 1 only |
When to use: Any NES game needing player input. This is the standard approach.
When to avoid: None - this pattern works for all games.
How It Works
- Write
$01then$00to$4016to “strobe” the controller - This latches the current button state inside the controller
- Read
$4016eight times - each read returns one button in bit 0 - Button order: A, B, Select, Start, Up, Down, Left, Right
- Use
LSRandROLto shift each bit into your variable
Button Bitmask Reference
| Bit | Button | Mask |
|---|---|---|
| 7 | A | $80 |
| 6 | B | $40 |
| 5 | Select | $20 |
| 4 | Start | $10 |
| 3 | Up | $08 |
| 2 | Down | $04 |
| 1 | Left | $02 |
| 0 | Right | $01 |
Related
Patterns: NMI Game Loop
Vault: NES