En la entrada anterior hemos visto que el manejo de sprites (y del VIC en general) con cc65 es sencillo. Llega con conocer las estructuras de datos de _vic2.h. y hacer asignaciones de valores a los registros.
Ahora bien, se puede hacer todavía más sencillo. Si recordamos, cc65 aporta header files, es decir, constantes, funciones y otras cosas para el manejo de joystick, ratón, consola, disco, gráficos, etc. ¿Por qué no hacer lo mismo con los sprites? ¿Por qué limitarnos a las estructuras de datos de _vic2.h y similares?
Y esto es precisamente lo que me planteo en esta entrada. Inspirándonos en la librería en ensamblador para manejar sprites del Volumen II, hacer una librería equivalente en C. Y la implementación de esa librería se apoyaría en _vic2.h.
Vamos a ello. Partimos del fichero lib-v2.zip disponible aquí:
https://programacionretroc64.files.wordpress.com/2019/11/lib-v2.zip
El contenido de ese ZIP es así (hay muchas librerías para diferentes propósitos):

Y si analizamos el fichero “LibSprites.asm” veremos que contiene estas rutinas:
- Una rutina para copiar los datos de un sprite de un origen a un destino.
- Una rutina para configurar los colores multicolor.
- Una rutina para hacer la configuración básica de un sprite, es decir, para configurar su bloque, su color y activarlo.
- Una rutina para posicionar un sprite.
- Una rutina para hacer la configuración avanzada de un sprite, es decir, para configurar el multicolor, la expansión horizontal y/o vertical, y la prioridad sobre el fondo.
- Una rutina para decidir si dos sprites están o no en colisión.
Todo esto lo vamos a convertir en dos ficheros en C:
- sprites.h, que será el header file con los prototipos, constantes y demás.
- Y sprites.c, que será la implementación de las funciones.
Por claridad, los nombres de las funciones serán similares a los de las rutinas, y lo de los parámetros también, salvando las diferencias lógicas por las nomenclaturas de nombrado en ensamblador y en C.
Fichero de cabecera sprites.h:
El fichero sprites.h quedaría así. Tendría una primera parte con constantes:

Una primera constante (__SPRITES_H) serviría para controlar si el header file ya está incluido en un programa y, en tal caso, no volver a incluirlo. A partir de ahí, habría constantes para el tamaño de los sprites (64 bytes), el número de sprites (8), controlar el multicolor, la expansión X e Y, la prioridad del fondo y las colisiones.
También aprovechamos para definir el tipo byte, que equivale a un unsigned char de C. Este tipo es muy útil para programar el C64, ya que es un ordenador de 8 bits.
Y la segunda parte sería así:

Es decir, primero define una estructura (el tipo de dato) para tener acceso a los punteros de los sprites, y luego define SPRITES_PUNTEROS como un puntero a ese tipo de estructura y lo vincula la posición $07f8, que es donde empiezan los punteros de los sprites ($07f8 – $07ff).
Por último, define los prototipos de las funciones que permiten copiar los datos de un sprite, configurar los multicolores, hacer la configuración básica de un sprite (puntero / bloque, color y activación), posicionar un sprite, hacer la configuración avanzada (multicolor, expansión y prioridad del fondo) y, por último, la función que permite detectar si dos sprites han colisionado.
Por supuesto, se pueden definir más funciones con otros propósitos, por ejemplo, para animar sprites, pero lo anterior es lo básico.
Fichero de implementación sprites.c:
La implementación de la librería de sprites es el fichero sprites.c. Este fichero incluye el sprites.h (#include <sprites.h>) y, a partir de ahí, aporta implementaciones para sus funciones. Estas implementaciones lógicamente se apoyan en las estructuras de datos de _vic2.h.
A modo de ejemplo, la implementación de la función sprites_conf_basica() sería así:

Es decir:
- Recibe tres parámetros, el número de sprite, el bloque donde está almacenada la definición y el color deseado.
- Guarda el bloque recibido en el puntero del sprite.
- Guarda el color deseado en el registro del VIC encargado del color.
- Y, mediante un OR, es decir, mediante el operador | de C, activa el bit correspondiente al sprite en el registro encargado de habilitar los sprites.
Las otras funciones tienen implementaciones similares. Su revisión queda como ejercicio para el lector interesado.
Programa de ejemplo:
Lo último sería hacer un programa de ejemplo que, usando la nueva librería, maneje sprites. Para ello nos inspiramos en el ejemplo de la entrada:
La versión en C sería así:

Es decir:
- Limpia la pantalla con la función clrscr() de conio.
- Instala el driver de los joysticks.
- Configura los sprites.
- Y, a partir de ahí, entra en un bucle que mueve un sprite, analiza las posibles colisiones y espera un tiempo. Y lo mismo con el otro sprite.
Las funciones para configurar los sprites, moverlos y analizar las colisiones se apoyan en la nueva librería.
Para configurar los sprites, la función conf_sprites() hace así:

A saber, configura los multicolores, que son compartidos entre todos los sprites, copia la definición del sprite 0 en el bloque 0 (254), hace su configuración básica (pone el puntero apuntando al bloque 254, configura el color verde y activa el sprite), hace su configuración avanzada (activa el multicolor, desactiva las expansiones y da prioridad al fondo), y termina con su posición. Y algo análogo con el sprite 1.
Por otro lado, para mover los sprites las funciones mueve_sprite_0() y mueve_sprite_1() hacen así:

Es decir, leen el joystick 1 y 2 respectivamente, y, en función del movimiento leído incrementan o decrementan la coordenada X o la Y. Finalmente, vuelven a posicionar el sprite.
Por último, para detectar las colisiones la función analiza_colision():

Es decir, se apoya directamente en la función sprites_colision() de la nueva librería. Y, en caso de detectar la colisión, termina la ejecución con exit().
El resultado es un viejo conocido:

En conclusión, que no hay por qué limitarse al uso de las estructuras de datos de _vic2.h. Sobre éstas es posible programar librerías que simplifiquen todavía más la programación con sprites o del VIC en general.
Código de ejemplo: sprites