Manejo del ratón con mouse.h

Programación retro del Commodore 64

  • Programación retro del Commodore 64
  • “Programación Retro del Commodore 64” es un blog sobre el hardware, el sistema operativo, y la programación del Commodore 64. Y más específicamente sobre programación en ensamblador. Pretende ser un blog con información de calidad, y referencia en español de la programación retro de esta maravillosa máquina.
    • Mi blog
« Publicado el: 17/09/2022 »

Lo del ratón merece algo de explicación previa:

Tipos de ratón en el C64:

Los ratones son dispositivos apuntadores que se suelen usar en ordenadores con interfaz de usuario gráfica, por ejemplo, un PC con Windows o un MAC. Sin embargo, la interfaz de usuario normal del C64 era en modo texto (pantalla de 40×25), aunque, por supuesto, también estaba GEOS.

A pesar de eso, el C64 y otros ordenadores Commodore sí soportaron el uso de ratón, aunque no era tan habitual encontrarlos como el joystick. De hecho, en el C64 había dos tipos de ratones:

  • Ratones en modo joystick o digital: En este modo, la lectura del ratón arrojaba una dirección análoga a la de un joystick (norte, sur, este, oeste, noroeste, noreste, suroeste o sureste), así como la pulsación de un botón. Esencialmente, era lo mismo que usar un joystick, pero manejando un ratón.
  • Ratones en modo proporcional o analógico: En este modo, la lectura del ratón arroja una posición (X, Y) que, además, puede cambiar más rápido o más despacio en función de la velocidad con que se mueva el ratón. Adicionalmente, permite la lectura de dos o más botones.

Un ejemplo del primer tipo de ratón era el Commodore 1350, y del segundo el Commodore 1351:

Inspección de mouse.h:

La librería mouse.h está en cc65\include, como todos los header files de cc65. Si le echamos un vistazo vemos cosas parecidas a las que vimos en joystick.h:

  • Constantes y funciones para manejar drivers de ratones.
  • Constantes para identificar el botón izquierdo y derecho.
  • Tipos de datos (structs de C) para manejar la posición del ratón, así como el estado de los botones.
  • Funciones para mover el ratón y leer su posición.
  • Etc.

Por ejemplo, aquí tenemos un extracto:

De especial interés son las estructuras “mouse_pos” y “mouse_info”, porque nos van a permitir leer la posición y los botones del ratón. Recordemos que los structs de C sólo son tipos de datos; luego hay que declarar variables de esos tipos.

Vamos a hacer un programa de ejemplo muy parecido al de joystick.h. Primero instalaremos el driver para el ratón, y luego leeremos y pintaremos su posición.

Instalación del driver:

El programa principal, es decir, la función main(), es como sigue:

Este programa:

  • Borra la pantalla con la función clrscr().
  • Instala el driver con la función mouse_install().
  • En caso de error en la instalación del driver, llama a error_driver() y termina.
  • Entra en un bucle infinito que lee el ratón con mouse_pos() y pinta su posición con pinta_mouse().

Lectura del ratón:

La lectura del ratón se hace con la función mouse_pos(). Esta función es equivalente a joy_read() en el caso del joystick.

La principal diferencia entre ambas funciones es que leer un joystick se resuelve con un byte (de hecho, con 5 bits, uno por cada dirección y otro para el disparo), mientras que leer un ratón requiere una estructura de datos más compleja (una coordenada X, una coordenada Y, y el estado de los botones).

Por este motivo, la función joy_read() simplemente devuelve un char (un byte), mientras que la función mouse_pos() no puede devolver un valor, que tendría que ser de un tipo de dato simple en C (ej. un char), sino que recibe la dirección de (un puntero a) una estructura de tipo “mouse_pos”. Con este puntero, la función puede acceder al contenido de la variable de tipo “mouse_pos” y cambiar su contenido. Esto es lo que en C y otros lenguajes se llama “pasar variables por referencia”, en oposición a “pasarlas por valor”.

Bueno, al final en la variable “pos”, que es de tipo “mouse_pos”, lo que tenemos es la lectura del ratón. “pos” es una estructura con dos campos:

  • pos.x: La coordenada X del ratón.
  • pos.y: La coordenada Y del ratón.

La forma de acceder a los campos de una estructura en C (struct) es mediante el punto (.).

Por último, hay que pintar la posición del ratón. Esto se hace en la función pinta_mouse():

Lo que hace esta función es:

  • Coloca el cursor en la posición (0, 0) con la función gotoxy() de conio.h.
  • Pinta la coordenada X del ratón con printf().
  • Pinta la coordenada Y del ratón con printf().

No hay que confundir el parámetro “pos”, que es local a la función pinta_mouse(), con la variable “pos”, que es de la función main(). El parámetro “pos” es un puntero a la variable “pos”. Por eso al llamar a pinta_mouse() se usa &pos, siendo & el operador que obtiene la dirección de la variable “pos”.

Siendo “pos” un puntero a la variable “pos” (jaja, parece un trabalenguas), la forma de acceder a sus campos x e y es mediante el operador -> . Este operador de C es muy gráfico, porque parece una flecha, recordándonos que el parámetro “pos” es un puntero.

Quizás podíamos haber llamado “pos” a la variable y “ppos” al parámetro, significando la primera “p” que es un puntero a “pos”.

Ratón y VICE:

Como sabemos, en VICE es posible simular el joystick con el teclado. Pues bien, también es posible simular el ratón del C64 con el ratón del PC en que se ejecuta VICE.

Para ello, hay que ir a la opción Settings > Control port settings… y poner en el puerto de control 1 un ratón 1351:

A partir de ese momento, se le puede indicar a VICE que capture los eventos del ratón del PC como si fueran del ratón del C64, lo cual se hace con Alt + Q o Settings > Mouse settings… y Grab mouse events:

El problema de hacerlo así es que veréis que el ratón del PC deja de responder, es decir, deja de moverse el puntero del ratón del PC. Esto es así porque esos movimientos ya los está capturando VICE. Pero tampoco se aprecia nada en VICE porque el programa que corre en el C64 (de momento ninguno, el intérprete de BASIC) tampoco está preparado para ello.

Por tanto, lo que hay que hacer es compilar el programa en C (esto damos por conocido cómo se hace), cargar el programa arrastrando el fichero PRG hasta VICE, y luego configurar VICE con un mouse 1351 en el puerto de control 1 y empezar a capturar eventos del ratón con Alt + Q. Veréis algo así:

De hecho, si movéis el ratón del PC veréis que las coordenadas X e Y van cambiando. Éstas oscilan desde (0, 0) hasta (319, 199). ¿De dónde salen estos valores? Pues muy fácil: 40 caracteres de ancho * 8 pixels = 320 pixels; 25 caracteres de alto * 8 pixels = 200. Y como empezamos en el (0, 0), que es la esquina superior izquierda, la esquina inferior derecha es la (319, 199). ¡¡Todo encaja!!

Ah, y una cosa importante: para salir del modo captura de eventos del ratón hay que volver a pulsar Alt + Q. Por tanto, Alt + Q sirve tanto para entrar como para salir del modo captura de eventos.

El lector interesado puede completar este ejemplo definiendo un sprite con la forma de un puntero de ratón, y moviéndolo por la pantalla del C64 en función de la lectura (X, Y) del ratón.

Chulo, ¿no?

Código de ejemplo: mouse