How to Program Joystick Input Handling on a C64


It is important to know how to program Joystick Input Handling on a C64. How else should we know what the player does? Read on to learn how this works.

The Joystick at the C64 can be read at the Memory Addresses $DC01 for Port 1 and $DC00 for Port 2 of the Complex Interface Adapter (CIA). If the examined Bit is 0, then the switch is closed and the corresponding action is active. Otherwise the Bit is 1.

There is a mapping from Bits to Direction/Fire Action:

Bit in Memory AddressJoystick Action
1 (%0000 0001)up / forward
2 (%0000 0010) down / backward
3 (%0000 0100) left
4 ( %0000 1000) right
5 (%0001 0000) fire
Mapping of Joystick Actions to the Bits in the CIA Memory Address

Let us look at an example where we put this knowledge into action.

C64 Program Example for Joystick Input Handling

The Complex Interface Adapter (CIA) handles the two 9-pin game ports in the C64. So you have a maximum of two Joysticks by default. A C64 Joystick is more or less digital. The switches inside open and close in alignment to axis movements and button presses. As already described above, the Bit in the memory address will be 0 if the switch is closed, or 1 otherwise.

This example will focus on the Joystick Input. Therefore we will not put fancy graphics or animations on the screen.

We will map the four directions of the joystick to the numbers 1 (left), 2 (right), 3 (up) and 4 (down). If you push the Joystick in any direction the corresponding number will appear on the screen. The fire button will print the character F.

Look at the Code and its explanation in order to understand how this works. We will discuss later where you can go from here.

Please note that our Example will only work with the Joystick in Port 1

The Assembly Code

This is a complete program for Joystick Input Handling on a C64 in Assembly Language.

This example should run without modification if you use an ACME compiler like the on in the C64 studio.

If you assemble this program, start it and randomly press into the directions or the button on the joystick, you will get something like this:

This image shows an exemplary output from our Example Program
Exemplary output from our Example Program

Line by Line Explanation

The first lines are very similar to the ones I showed you in my C64 Machine Code Hello World Example. We set the start address of our program right after the beginning of the BASIC memory. Then we use SYS to call our Assembly code.

At the beginning we clear the screen. In order to do that we jump to the built-in subroutine that does what we want. It is stored at $E544.

The label input_left_check marks the beginning of our loop. Now we check every bit for if there is something to do. Initially we load a bit mask into the Register A. We have to check if the third Bit is 1 or 0, therefore we mask the third Bit with 1. In the next line we do a bitwise and with the content in Register A.

If the result is 0, the switch is closed which means that the player moves the joystick to the left. In this case we load the character ‘1’ into the A register (represented by Hex Code 31) and print it to the screen. This is done by the built in routine CHROUT which is located at memory address $FFD2.

If the result is not equal to zero, we jump to the label input_right_check where we will proceed checking directions.

The code for the checks of right, up and down are similar to the check left. The only things that change are the bitmask (according to the direction) and the character that will be printed to the screen.

The last check adds one little extra. After the fire button there is nothing left to check. If we do nothing the program will end and return to BASIC. Therefore we jump back to the first check, our input_left_check and start over. This makes for an endless loop.

You should have noticed that this program only checks joystick input and does nothing else. In a real program you would not simply jump back to the first input check but rather do something else first.

The C64 Joystick has eight directions

The C64 Joystick can move up, down, left and right. But you can also move up and right at the same time. The same is true for up/left, down/right and down/left. This makes a total of eight directions that you can move to.

What happens if we press right/down at the same time in our example program? The number ’24’ will print, because we show 2 (right) and 4 (down) at the same time.

This image shows that the Program will print '24' if you press right/down at the same time
The Program will print ’24’ if you press right/down at the same time

Complex Interface Adapter

The Complex Interface Adapter is an Interface Chip. It controls the I/O and the internal timer (clock) of the C64. Inside the C64 there are two identical CIAs. The different usage of the chips is specific to the C64.

CIA1 has the Memory Address Area $DC00-$DCFF and controls Keyboard, Joystick, Paddles, Datasette and IRQ Control.

CIA2 has the Memory Address Area $DD00-$DDFF and controls the Serial Bus, RS-232. VIC memory and NMI control.

You can see that we only need the CIA1 for our example.

Further Exploration

First of all you could make the program read inputs from a Joystick in Port 2. This should be easy enough and will help you to internalize the new knowledge. You could use the numbers 5,6,7 and 8 for the directions and trigger a space for the fire button of the Joystick #2.

The next step would be moving sprites instead of printing numbers. You would have to create a Sprite, put it in the Sprite Register and show it on the screen. Then you would have to manipulate the Sprite Position as reaction to the user input. After that you could trigger sprite animations.

Conclusion

Now you know how to program joystick input handling on the C64. As you can see it is not that hard. You need to know which Bits to check in the correct CIA1 Memory Address. The you simply map the Inputs to Actions like showing numbers on the screen or moving a sprite. Just keep in mind that the two Joystick Ports have different Addresses in the CIA1 Memory.

Marco Lieblang

Professional Programmer since 2003, passionate Programmer since the mid 90's. Developing in many languages from C/C++ to Java, C#, Python and some more. And I also may know a bit about Assembly Languages and Retro Systems.

Recent Posts