Sprites

Recuerdo una de las primeras cosas que aprendi a programar fueron graficos, concretamente a redefinir los ‘UDG’ en la ZX Spectrum, máquina con la hice mis primeras armas en programación. Luego me compre una C64, la cual tenia la ventaja de ser una maquina mas poderosa, pero mas inaccesible al momento de programar.
En realidad lo mas importante que hay que saber para dibujar sprites (y toquetear todas las cosas que tiene el VIC II) es el siguiente número mágico: $d000 (53248 en decimal). Esta es la direccion base de los 47 registros que tiene la C64 para hacer maldades con el video (y mira que le sobra para hacer cosas).
De paso vamos a trabajar con bloques de datos en el macro assembler. Estos nos permiten facilmente definir cadenas (por ejemplo, en el ‘Hello World’ que hicimos previamente usamos una cadena de texto), o bloques de data, de forma muy similar a como utilizabamos DATA en BASIC. Esto es medio largo, asi que comencemos:

Para definir datos lo unico que debemos hacer es hacer una etiqueta, luego escribimos el tipo de dato (text, byte, word, bits), y a continuación el valor. En el siguiente ejemplo vamos a definir una etiqueta pacman, que contendra la definición de un sprite, como el siguiente:

 

pacman      bits ..........BBBBB.........
            bits .......BBBBBBBBBBB......
            bits ......BBBBBBBBBBBBB.....
            bits .....BBBBBBB..BBBBBB....
            bits ....BBBBBBBB.BBBBBBBB...
            bits ...BBBBBBBBBBBBBBBBBBB..
            bits ...BBBBBBBBBBBBBBBBB....
            bits ...BBBBBBBBBBBBBB.......
            bits ..BBBBBBBBBBBBB.........
            bits ..BBBBBBBBBBB...........
            bits ..BBBBBBBB..............
            bits ..BBBBBBBBBBB...........
            bits ..BBBBBBBBBBBBB.........
            bits ...BBBBBBBBBBBBBB.......
            bits ...BBBBBBBBBBBBBBBBB....
            bits ...BBBBBBBBBBBBBBBBBBB..
            bits ....BBBBBBBBBBBBBBBBB...
            bits .....BBBBBBBBBBBBBBB....
            bits ......BBBBBBBBBBBBB.....
            bits .......BBBBBBBBBBB......
            bits ..........BBBBB.........

Con esto ya tenemos los valores en memoria para el sprite. Nótese que no tuvimos que convertir de binario a decimal ni toda la parafernalia que lleva hacer eso, simplemente definimos una etiqueta que tendra los 63 bytes necesarios para la imagen, nada mas que codificados de una manera mas piola… Tambien podriamos haber puesto lo siguiente:

pacman  byte    0, 62, 0 
        byte    1, 255, 192
        .
        .
        .

Pero tenemos que tomarnos el trabajo de convertir los bits de la imagen a binario, y luego pasarlos a decimal.
Con esto ya tenemos definido el sprite, ahora tendremos que copiar estos datos a una parte de la memoria que pueda ser accesible por el VIC…

Punteros de Sprites

Los punteros de sprites son las direcciones de memoria, para cada sprite, que contienen la direccion en que estan los datos del mismo. Estas van de $07f8 (2040) para el sprite 1 a $07ff(2047) para el sprite 8. Peeero si para acceder a una direccion de memoria necesitamos 2 bytes… ¿Como podemos especificar donde estan los datos de nuestro sprite con solamente un byte?.
Los punteros de sprite se manejan de una forma muy particular. Primero de todo, solamente podemos apuntar a datos que esten en el mismo banco de memoria en el que tengamos la memoria de pantalla. Tenemos 4 bancos, el primero de ellos ($0000-$3fff) es el que se usa por defecto. Un sprite toma 63 bytes de datos, pero tienen que estar en intervalos de 64 bytes, asi que se pueden poner los datos en las direcciones $0000, $0040, $0080, $0c00, $0100 …
En cada banco del VIC podemos tener hasta 256 sprites… voila, eso es lo que podemos representar con un byte… ¿se entiende como funciona el cachivache? Si pongo el valor $0 en $07f8 los datos del sprite deberemos tenerlos en la direccion $0000, si ponemos $1 entonces en $0040… y asi hasta completar el banco… y si quisieramos hacer una animacion solamente tenemos que cambiar el puntero y tendremos la animacion con los diferentes frames.

Ahora vamos a copiar los datos del sprite a la direccion $$0400, que corresponde al puntero $10. Esta pequeña rutina a continuacion toma los datos de la etiqueta pacman y los copia a la direccion $0400

movedata    ldx #$00
loop        lda pacman, x
            sta $$0400,x
            inx
            cpx #$3f
            bne loop
            rts

Direcciones importantes del VIC II

Para este ejemplo vamos a utilizar el sprite 1, por lo que necesitaremos activarlo, posicionarlo en pantalla, darle color y especificar donde estan los datos que definen su forma. Para ello utilizaremos los siguientes registros:

$00 (0) $d000 (53248) Coordenada x sprite 0
$01 (1) $d001 (53249) Coordenada y sprite 0
$15 (21) $d015 (53269) Sprite enable. aca controlamos cual de todos activamos
$27 (39) $d027 (53287) Color sprite 0
(*) $07f8 (2040) Puntero de memoria del sprite 0

(*) no es un registro del VIC, pero necesitamos esta direccion para especificar donde estan los datos de nuestro sprite.

Para mas detalle de los registros, o si queremos utilizar otro sprite en el ejemplo: registros del VIC II.

Ejemplo con sprite 0

* = $c000
          lda            #$00      
          sta            $d020     
          sta            $d021     ; ponemos borde y fondo negro

          lda            #$01      
          sta            $$d015    ;activamos el sprite 0

          lda            #172      
          sta            $d000     
          lda            #139
          sta            $d001     ; lo centramos en la pantalla (172,139)

          lda            #$07      
          sta            $d027     ; lo ponemos color amarillo

          lda            #$10      
          sta            $07f8     ; ponemos el puntero del sprite 0 en $0100

          jsr            movedata  
          rts

movedata  ldx            #$0
loop      lda            pacman,x  
          sta            $0400,x   
          inx
          cpx            #$3f      
          bne            loop
          rts

pacman    bits           ..........BBBBB.........
          bits           .......BBBBBBBBBBB......
          bits           ......BBBBBBBBBBBBB.....
          bits           .....BBBBBBB..BBBBBB....
          bits           ....BBBBBBBB.BBBBBBBB...
          bits           ...BBBBBBBBBBBBBBBBBBB..
          bits           ...BBBBBBBBBBBBBBBBB....
          bits           ...BBBBBBBBBBBBBB.......
          bits           ..BBBBBBBBBBBBB.........
          bits           ..BBBBBBBBBBB...........
          bits           ..BBBBBBBB..............
          bits           ..BBBBBBBBBBB...........
          bits           ..BBBBBBBBBBBBB.........
          bits           ...BBBBBBBBBBBBBB.......
          bits           ...BBBBBBBBBBBBBBBBB....
          bits           ...BBBBBBBBBBBBBBBBBBB..
          bits           ....BBBBBBBBBBBBBBBBB...
          bits           .....BBBBBBBBBBBBBBB....
          bits           ......BBBBBBBBBBBBB.....
          bits           .......BBBBBBBBBBB......
          bits           ..........BBBBB.........

y el resultado final:

<–

Consideraciones a tener en cuenta

  • algo interesante que hice adrede es poner la el puntero del sprite en el inicio de la memoria de video. Toda esa basura que se puede ver en la parte superior de la pantalla es la definicion del sprite. Nótese ademas que llevé el cursor al primer caracter de la pantalla, lo que hizo aparecer un puntito en el sprite. Es interesante que podemos borrar los caracteres, y ver como se borra el sprite. Por ejemplo, puedo borrar de a 3 caracteres, lo que hara que quede como interlineado (en realidad, ponemos un caracter @ que en binario es 00000000):
  • para centrar en la pantalla en teoria deberia poner 160×100, ya que la resolucion de la C64 es de 320×200. Pero los sprites pueden estar posicionados en CUALQUIER lugar de la pantalla, haciendo algo que se conoce como apertura de bordes, asi que la posicion 0 en realidad no es al lado del borde, sino al lado del borde de la pantalla.
  • Estamos definiendo en un area de memoria el sprite, y luego lo copiamos a otra, dado que si no el VIC no podria acceder a los datos… en realidad es ineficiente, los datos del sprite habria que tenerlos en disco, aparte, y cargarlos donde correspondan, que sean accesibles por el VIC.
  • Definimos el sprite con bits ........BBBBBBBB........, pero solo para este ejemplo… en realidad es mejor utilizar alguna herramienta que nos genere esos datos y cargarlos de disco.
  • pueden toquetear el codigo, definir otro sprite, usar otros sprites (1,2,3,…7), cambiar los colores, o directamente desde BASIC, haciendo POKE’s a las direcciones correspondientes para ver como cambia… O poner una direccion mas adecuada para el puntero de datos del sprite… no se, jueguen …
Anuncios

Responder

Introduce tus datos o haz clic en un icono para iniciar sesión:

Logo de WordPress.com

Estás comentando usando tu cuenta de WordPress.com. Cerrar sesión / Cambiar )

Imagen de Twitter

Estás comentando usando tu cuenta de Twitter. Cerrar sesión / Cambiar )

Foto de Facebook

Estás comentando usando tu cuenta de Facebook. Cerrar sesión / Cambiar )

Google+ photo

Estás comentando usando tu cuenta de Google+. Cerrar sesión / Cambiar )

Conectando a %s