2.8 KiB
Joysticks (Control Ports)
Source: https://www.c64-wiki.com/wiki/Joystick
A joystick is a gaming control device. The C64 uses the standard first seen on the Atari 2600 — eight directions and one fire button. The stick mechanically activates four switches (up/down/left/right); pushing diagonally activates two. Some joysticks have two fire buttons but they appear identical to software.
The switches and button connect to the CIA #1 ports A and B (in parallel with the keyboard matrix), which is why a joystick — especially on port 1 — can cause the machine to "type" characters when you operate it.
Reading a joystick
- Port #1 (right port): read via $DC01 (CIA 1 PRB)
- Port #2 (left port): read via $DC00 (CIA 1 PRA)
In each byte, the bits are active-low (0 = pressed):
- Bit 0 (1) — Up
- Bit 1 (2) — Down
- Bit 2 (4) — Left
- Bit 3 (8) — Right
- Bit 4 (16) — Fire
Typical values (rest position, no buttons)
| Position | Port 1 ($DC01) | Port 2 ($DC00) | +Fire (Port 1) | +Fire (Port 2) |
|---|---|---|---|---|
| middle | 255 | 127 | 239 | 111 |
| up | 254 | 126 | 238 | 110 |
| down | 253 | 125 | 237 | 109 |
| left | 251 | 123 | 235 | 107 |
| right | 247 | 119 | 231 | 103 |
| up+left | 250 | 122 | 234 | 106 |
| up+right | 246 | 118 | 230 | 102 |
| down+left | 249 | 121 | 233 | 105 |
| down+right | 245 | 117 | 229 | 101 |
Keyboard collision
Keyboard scanning uses the same CIA port bits, so reading the joystick will "see" pressed keys. To disable the keyboard while polling: POKE 56322, 224 (write %11100000 to CIA 1 DDRA so PRA pins are inputs, leaving only the rows set as output — wait, that is the opposite of "disable keyboard". The actual recipe to disable keyboard scanning is to disable CIA 1 interrupts or to set all keyboard columns to inputs).
The simpler approach is to mask out the keyboard bits and only test the low 5 bits of the joystick.
Analog inputs
The control ports also provide +5V and two analog lines (designed for paddles) — the SID reads these as 8-bit values via $D419 (X) and $D41A (Y).
Sample BASIC polling
10 J = NOT PEEK(56321)
20 PRINT CHR$(147);"JOYSTICKTEST"
30 IF (J AND 1) THEN PRINT "1-U ";
35 IF (J AND 2) THEN PRINT "1-D ";
40 IF (J AND 4) THEN PRINT "1-L ";
45 IF (J AND 8) THEN PRINT "1-R ";
50 IF (J AND 16) THEN PRINT "1-F ";
55 GOTO 10