Joystick, es decir, el fichero joystick.h y la implementación correspondiente, es la librería de cc65 para el manejo de joysticks. Recordemos que al C64 se le pueden conectar uno o dos joysticks.
El fichero joystick.h, al igual que todos los header files de cc65, está en cc65\include. Si le echamos un vistazo vemos que define:
- Constantes y funciones para manejar drivers de joysticks.
- Constantes para identificar el joystick 1 y el joystick 2.
- Macros para identificar si un joystick se está moviendo hacia arriba, abajo, izquierda o derecha, o pulsando un botón de disparo. Una macro del preprocesador de C es parecida a una constante, es decir, una instrucción #define, pero con parámetros.
- Etc.
Aquí vemos un extracto del fichero joystick.h:

Como en el caso de conio.h, podemos hacer de programa de ejemplo en C para ver si nos detecta los joysticks en VICE, que en el fondo se simulan mediante teclas del PC donde se ejecuta VICE:
Instalación del driver:
En informática un “driver” suele referirse a un software que permite que un ordenador se comunique con un dispositivo. Pues bien, cc65 maneja el concepto de “driver” para tener acceso a los joysticks.
Esto me resulta un tanto confuso porque, como ya vimos hace tiempo en este blog, el joystick 1 viene a equivaler al registro CIAPRB = $dc01 y el joystick 2 viene a equivaler al registro CIAPRA = $dc00. Vamos, que no veo mucha necesidad de que ningún software o driver intermedie entre esos registros y la aplicación. Bastaría con leer esas posiciones de memoria y actuar en consecuencia. Esto con cc65 debería ser fácil, porque cc65 permite definir variables y vincularlas a determinadas posiciones de memoria (ej. $dc00 o $dc01).
Quizás el motivo radique en que cc65 no sólo está pensando para el C64, sino también para otros ordenadores basados en el 6502, que podrían ser más complejos en cuanto al manejo del joystick. En este contexto, tener una interfaz de programación unificada para manejar los joysticks podría ser de utilidad.
Sea como fuere, para conseguir leer los joysticks en VICE, que se simulan con el teclado del PC donde corre VICE, he tenido que instalar un driver:

Como se puede ver, el programa en C anterior:
- Borra la pantalla con la función clrscr().
- Instala el driver con la función joy_install().
- En caso de error en la instalación del driver, llama a la función error_driver(), que básicamente saca un mensaje por pantalla.
- Entra un bucle infinito que lee el joystick 2 con la función joy_read() y pinta un mensaje significativo con la función pinta_joy().
Lectura del joystick:
Estrictamente hablando, la lectura del joystick se hace con la función joy_read(). Ahora bien, tras leer el joystick, que en este caso es el JOY_2, hay que actuar en consecuencia, en función de que el joystick apunte arriba, abajo, a la izquierda, a la derecha, o a una combinación de estas direcciones. Además, tenemos el disparo.
Este “actuar en consecuencia” en este ejemplo consiste simplemente en mostrar un mensaje por pantalla. En un ejemplo más realista se trataría de mover un sprite, por ejemplo.
Pues bien, esto se hace con la función pinta_joy():

La función pinta_joy() hace uso de las macros JOY_UP(), JOY_DOWN(), JOY_LEFT(), JOY_RIGHT() y JOY_BTN_1(). Las macros son instrucciones del preprocesador de C que se definen con #define. Por tanto, son muy parecidas a las constantes, pero tienen algún parámetro, en este caso el byte (o char) que se ha leído previamente del joystick.
Al final, lo que hace el preprocesador antes de compilar es sustituir la macro por su definición. Es decir, JOY_UP(joy) se sustituiría por (joy & JOY_UP_MASK), donde & es la operación AND y JOY_UP_MASK es una máscara (una constante) que representa el movimiento hacia arriba. De este modo, si ese AND es distinto de cero, o “cierto” en C, eso significa que el joystick efectivamente se está empujando hacia arriba.
Al final, en función de la dirección en que se empuje el joystick, lo que hace pinta_joy() es pintar con Conio “Arriba”, “Abajo”, “Izquierda”, “Derecha” o “Disparo” en la esquina superior izquierda de la pantalla (posición (0, 0)). A las cadenas les ponemos algunos espacios extra al final porque, al ser “Izquierda” la cadena más larga (9 caracteres), conviene borrar los posibles caracteres sobrantes si después de mover a la izquierda movemos en otra dirección cuya cadena representativa tiene menos caracteres.
Joystick y VICE:
A estas alturas del blog, con varios libros sobre C64 a nuestras espaldas, yo creo que todos sabemos que VICE simula los joysticks mediante el teclado del PC donde se ejecuta, y que hay que ir al menú Settings > Joystick settings > Joystick settings… para configurar los joysticks:

Sobre el joystick 2, que es el que usa nuestro programa, seleccionamos “Keyset A” (o B, el que más rabia nos dé) y luego “Configure Keyset A”. Y en la pantalla emergente, configuramos las teclas del PC que queremos asociar con cada movimiento del joystick 2, por ejemplo, los cursores y Control:

A partir de aquí, compilamos el programa en C con cl65.exe (damos por sabido cómo se hace), arrastramos el fichero PRG hasta VICE, y observamos algo así, que va cambiando según movemos el joystick 2 / pinchamos las teclas:

Total, ¡¡ya sabemos usar los joysticks desde C!! Fácil, ¿no?
Código de ejemplo: joystick