sprites en snes

8
TUTORIAL SNES: USAR SPRITES Por David Senabre, Junio 2005 INTRODUCCIÓN Y EL POR QUÉ DE ESTE TUTORIAL. En primer lugar, escribo este tutorial porque no he visto ningún documento hasta la fecha que explique adecuadamente como usar sprites en la SNES, ni en español, ni en ingles. Y a mi me ha dado bastante dolores de cabeza lograr usarlos. Hay varios documentos técnicos sobre la SNES muy buenos por internet, como los de Yoshi, pero por ejemplo, este hombre explica a menudo las cosas de una forma muy poco clara. En definitiva, hay temas, como el de los sprites, donde la información está esparcida y a veces es oscura y ambigua. Mi objetivo es explicar con detalle y suficiente claridad, el uso sencillo de sprites en la SNES, desde cero y ordenadamente. ¿A QUIÉN VA DIRIGIDO? A todo aquel que quiera usar sprites en la SNES, y por supuesto que sepa programar y tenga nociones de ensamblador, aunque no sea de ensamblador de la SNES. También se da por sabido conceptos como tile, bitplanes, o WRAM ;) Ah, y también saber qué es un registro y como usarlos. (ver otros tutoriales míos). ¿QUÉ SON LOS SPRITES? Creo que esto sobra, pero bueno, hagamos las cosas bien. En un juego, por una parte, están los escenarios, las plataformas, etc. Que forman parte de los planos de scroll, constituidos por tiles, y que sirven para representar los niveles, los mapas, o lo que sea, en definitiva, el mundo que se representa en el juego. Y por otra parte están los sprites, que son los objetos móviles que “viven” en ese mundo, tanto los enemigos, como el propio personaje que controla el jugador, o los ítems. En definitiva, los sprites son los objetos que interactúan en los juegos. Por lo tanto es imprescindible saber usarlos, a no ser que queramos limitarnos a programar demos con fondos, imágenes, texto, y sin acción. Para quien tenga experiencia en programación de la NES, resultará sencillo usarlos en la SNES, aunque aquí la cosa se complica mucho. Yo empezaré a explicarlo todo suponiendo que el lector no tiene esta experiencia previa. LA TABLA DE SPRITES (OAM) Los sprites en SNES se llaman objetos o OAM. Para manejarlos, la SNES tiene una zona de memoria llamada tabla OAM donde guarda información sobre todos los sprites. En esta tabla caben 128 sprites, y por lo tanto la SNES puede manejar un máximo de 128 sprites a la vez, aunque seguramente en la practica se ralentice si se

Upload: arquitecto-bogota

Post on 30-Jun-2015

398 views

Category:

Documents


5 download

TRANSCRIPT

Page 1: Sprites en snes

TUTORIAL SNES:USAR SPRITESPor David Senabre, Junio 2005

INTRODUCCIÓN Y EL POR QUÉ DE ESTE TUTORIAL.En primer lugar, escribo este tutorial porque no he visto ningún documento hasta la fecha que explique adecuadamente como usar sprites en la SNES, ni en español, ni en ingles. Y a mi me ha dado bastante dolores de cabeza lograr usarlos. Hay varios documentos técnicos sobre la SNES muy buenos por internet, como los de Yoshi, pero por ejemplo, este hombre explica a menudo las cosas de una forma muy poco clara. En definitiva, hay temas, como el de los sprites, donde la información está esparcida y a veces es oscura y ambigua.Mi objetivo es explicar con detalle y suficiente claridad, el uso sencillo de sprites en la SNES, desde cero y ordenadamente.

¿A QUIÉN VA DIRIGIDO?A todo aquel que quiera usar sprites en la SNES, y por supuesto que sepa programar y tenga nociones de ensamblador, aunque no sea de ensamblador de la SNES. También se da por sabido conceptos como tile, bitplanes, o WRAM ;) Ah, y también saber qué es un registro y como usarlos.(ver otros tutoriales míos).

¿QUÉ SON LOS SPRITES?Creo que esto sobra, pero bueno, hagamos las cosas bien. En un juego, por una parte, están los escenarios, las plataformas, etc. Que forman parte de los planos de scroll, constituidos por tiles, y que sirven para representar los niveles, los mapas, o lo que sea, en definitiva, el mundo que se representa en el juego.Y por otra parte están los sprites, que son los objetos móviles que “viven” en ese mundo, tanto los enemigos, como el propio personaje que controla el jugador, o los ítems. En definitiva, los sprites son los objetos que interactúan en los juegos.

Por lo tanto es imprescindible saber usarlos, a no ser que queramos limitarnos a programar demos con fondos, imágenes, texto, y sin acción. Para quien tenga experiencia en programación de la NES, resultará sencillo usarlos en la SNES, aunque aquí la cosa se complica mucho. Yo empezaré a explicarlo todo suponiendo que el lector no tiene esta experiencia previa.

LA TABLA DE SPRITES (OAM)Los sprites en SNES se llaman objetos o OAM.Para manejarlos, la SNES tiene una zona de memoria llamada tabla OAM donde guarda información sobre todos los sprites. En esta tabla caben 128 sprites, y por lo tanto la SNES puede manejar un máximo de 128 sprites a la vez, aunque seguramente en la practica se ralentice si se usan tantos. Aún así esto supone una mejora, porque la NES sólo podía manejar 64.Lo que tenemos que hacer es introducir los datos de los sprites en esta tabla. Cada sprite ocupa 4 bytes.

Byte 1 : xxxxxxxx Posición X del sprite en la pantalla (0-255)Byte 2 : yyyyyyyy Posición Y del sprite en la pantalla (0-255)Byte 3 : tttttttt Número de tile que representa al spriteByte 4 : vhoopppt

De este ultimo byte:

Page 2: Sprites en snes

v : mirroring verticalh : mirroring horizontalo : bits de prioridadp : bits de paletat : bit alto de número de tile

Los 2 primeros son auto explicativos. Por ahora hablaré de los bits de paleta y de tile.

Con el byte 3 decimos que tile se mostrará como sprite. Podemos elegir un tile desde 0 hasta 255. Pero el bit t del byte 4 también vale para elegir el tile, y de hecho es el bit más significativo de esta dirección, luego:

Bit t del byte 4 = 0Byte 3 elige un tile de 0 hasta 255

Bit t del byte 4 = 1Byte 3 elige un tile de 256 hasta 511

Luego diré como saber qué tile es el 127 o el 63.Por ahora añadir que los bits p sirven para elegir la paleta del sprite, de entre 8 (ya que tenemos 3 bits para ello).

PALETAS Y COLORES.Recuerdo que la paleta de la SNES es una lista de colores que se almacenan en una memoria de la SNES, la CG-RAM, que guarda todos los colores que se pueden mostrar por pantalla en un momento dado, y que se carga por el programador con los colores que se quiera. Estos colores se reverencian por el orden que ocupan en esta lista, desde el 0, hasta el 255.

Los colores que se usan en los sprites son los que van del 128 en adelante (es decir, los que vienen después de los primeros 128).Los sprites usan 16 colores. Por lo tanto, si a un sprite le ponemos paleta 0, los 16 colores que se usarán para él serán los que van del 128 al 143, y si escoges la paleta 1, los 16 siguientes, etc.

CARGAR LA TABLA DE SPRITES (OAM)Bueno, ahora que ya sabemos esto, es el momento de aprender a meter esta información en la tabla de sprites.La tabla de sprites ocupa 512 bytes (4 bytes por 128 sprites), que sirven para almacenar la información ya explicada, pero esta tabla al final tiene otros 32 bytes que sirven para otras 2 cosas; para hacer de noveno bit en la posición X de los sprites, y para elegir el tamaño del sprite entre 2 posible. Pero de momento estos 32 bytes los pondremos a cero. Con esto seleccionaremos el tamaño por defecto, y no afectaremos a la posición X del sprite dada con antelación.

Esta tabla se carga usando los registros $2102, $2103, $2104.Los dos primeros sirven para dar la dirección del sprite en la tabla, y el tercero sirve para escribir en esa dirección el byte deseado.Cuando inicialicemos la consola, en nuestra rutina de arranque, sería bueno que llenáramos la tabla de sprites de ceros. Esto se puede hacer muy fácilmente usando DMA. La siguiente rutina sirve perfectamente. Como necesitamos llenar la tabla con ceros, yo lo que hago es copiar a la WRAM el valor cero en alguna posición de memoria, y luego copiar el contenido de esa posición a la tabla OAM.En este ejemplo usaré la dirección $0020. Se puede usar otra dirección sin problemas. Fijarse que en el registro $4300 de DMA se selecciona

Page 3: Sprites en snes

dirección fija (Fixed address), para que siempre se transfiera el mismo byte, que es lo que nos interesa. Las opciones que hay que usar para trasnferir a la tabla OAM usando DMA son:- CPU memory -> PPU- Absolute addressing- 1 address write twice, o 1 address write once- Transferir al registro $2104Y además, en esta ocasión, como es para llenar todo su contenido de un mismo valor:- Fixed address

No olvidar resetar la dirección de la tabla OAM antes de copiar.

;--------------- LDX #$0 STX $2102 ; empezar desde el comienzo de la tabla OAM

LDY #$0408 ; transferir al registro $2104STY $4300 ; con dirección fijaLDY #$0020 ; desde la dirección $20STY $4302 ; que almacena el valor ceroLDY #544 ; transferir 544 bytes para llenar la tablaSTY $4305LDA #$7E ; seleccionar banco de origen,STA $4304 ; el banco 7E, comienzo de la WRAM.LDA #$01STA $420B ;hacer DMA!

;---------------

Listo, ya tenemos la OAM llena de ceros, incluida la tabla de 32 bytes.

¿Y LOS TILES?Hasta ahora todo va bien, pero aunque en la tabla OAM tengamos nuestros sprites danzando, no veremos nada en la pantalla.Para que todo esto funcione necesitamos almacenar en la VRAM los tiles que usarán los sprites, y decirle a la SNES en qué posición de memoria empiezan estos tiles. Estos tiles deben usar 4 bitplanes, para ofrecer 16 colores. Por lo tanto cada uno ocupará 32 bytes (tiles de 8x8 = 64 pixels, a 4 bits por píxel, 256 bits, que son 32 bytes). El tile 0 es el primero, el tile 1, el que está en el offset 32, el tile 2, en el offset 64, y así sucesivamente.Procedamos a definir la dirección base de estos tiles. Para ello necesitaremos el registro $2101, que me ha dado casi todos los problemas que he tenido con sprites.

$2101: sssnnbbb

Los bits b definen la dirección base de comienzo en VRAM de los tiles que usaremos en nuestros sprites. Esta dirección se da en bloques de 8k palabras (o sea, de 16Kb).Por ello, si ponemos los bits b a 010 (2), estaremos dando la dirección 2*8k palabras, $4000(w), o lo que es lo mismo, la dirección $8000 en bytes de la VRAM, aunque es mejor acostumbrarse a usar las direcciones en palabras de 16 bits cuando nos referimos a la VRAM, en lugar de en bytes. Como la VRAM tiene una capacidad de 32k palabras (64Kb), si la partimos en bloques de 8k palabras veremos que sólo hay 4 posibles posiciones donde colocar los tiles de los sprites.

Page 4: Sprites en snes

En palabras, las posibles zonas de VRAM para sprite tiles son:VRAM bits b------------------------------------| $0000-1FFF | 000 |------------------------------------| $2000-3FFF | 001 |------------------------------------| $4000-5FFF | 010 |------------------------------------| $6000-7FFF | 011 |------------------------------------

Para qué sirve el bit más significativo lo ignoro. Por ahora, lo considero siempre cero.

Los bits n sirven para seleccionar una dirección base distinta dentro de la que hemos seleccionado. Cuando un tile tiene un indice 256 o mayor, a la dirección base se le suma la seleccionada en los bits n, que definen un desplazamiento en bloques de de 1k palabra.Por ejemplo, si elegimos los bits b 010, seleccionamos el bloque

------------------------------------| $4000-5FFF | 010 |------------------------------------

Pero si hacemos los bits n 01, para tiles de indice mayor que 255, es decir, los que ocupan posiciones a partir de $5000 (la mitad del bloque), la dirección base pasará a ser:

$5000 + 400 = $5400 (se le suma un bloque de 1k palabra)

Y análogamente, para bits 10 y 11, tendremos:

$5000 + 800 = $5800 (se le suma dos bloquess de 1k palabra)$5000 + 1000 = $6000 (se le suma tres bloques de 1k palabra)

Esta técnica es muy útil para crear sprites animados de 4 frames, de una forma sencilla. Basta con colocar los tiles de esos sprites en posiciones 256 y superiores, y variar los bits n cada par de frames. Así, se irán eligiendo los tiles en posiciones separadas por 1k palabra de forma ciclica.

ACTIVAR SPRITES

Ahora tenemos que definir el modo gráfico en el que vamos a trabajar, activar los planos de scroll que vayamos a usar, y activar los sprites.

En primer lugar definimos modo1, por ejemplo, que es uno de los más sencillos para aprender. Este modo tiene disponible 3 planos de scroll, el BG1, el BG2 y el BG3. Los dos primeros usan 16 colores (tiles de 4 bitplanes), y el BG3 de 4 colores unicamente (tiles de 2 bitplanes). El registro para seleccionar modo es el $2105, en concreto sus 3 bits menos significativos.

Page 5: Sprites en snes

$2105: abcdefff

Los bits f son los bits de modo que acabo de decir.Del bit a, al d, sirven para seleccionar el tamaño de los tiles de los planos BG4 al BG1 (0=8x8, 1=16x16). Yo nunca he usado tiles que no sean de 8x8 así que no daré más información.El bit e sirve para dar máxima prioridad al BG3 en modo1. Por ahora no lo usaremos tampoco.

;-----------------------lda #$01 ;mode 1, 8x8 tiles (16 colores para BG1 + BG2 y 4 para BG3)sta $2105 ;-----------------------

Y para activar los planos de scroll que queramos, al igual que los sprites, está el registro $212C

$212C: 000abcde

Los 3 bits altos no se usan.El bit a se refiere a los sprites.El bit b al BG4El bit c al BG3El bit d al BG2El bit e al BG1Un bit a 1 significa activado, a 0, desactivado.

;-----------------------lda #$17 ;Activar todos los planos del modo 1, y spritessta $212C;-----------------------

ACTUALIZAR LA TABLA OAM

Hemos aprendido a resetar la tabla de sprites. Ahora vamos a necesitar llenar esta tabla con información correcta sobre cada sprite, de su posición, tile y atributos. Esto lo haremos de la siguiente manera.En primer lugar, designaremos una zona de memoria donde almacenaremos nuestra tabla de forma temporal, y durante la rutina de refresco de pantalla, copiaremos esta tabla temporal a la tabla OAM, usando DMA, como antes.

Por ejemplo, dediquemos la zona de WRAM $0040-$25F a almacenar nuestra tabla temporal.

;---------------.DEFINE Sprites $40 ;544 bytes, $220;---------------

Con el identificativo Sprites, designaremos el offset de inicio.Ahora debemos ir copiando aquí la información que se transferirá a la tabla OAM cada frame, en el mismo formato claro, y dejando los últimos 32 bytes a cero de momento. Los primeros 512 bytes estarán disponibles para usar hasta 128 sprites. Por ejemplo, añadamos un sprite en la posición X = 16, Y = 191, que use el tile $80, paleta cero, y sin atributos de prioridad o mirroring. Este será nuestro sprite cero, luego lo copiamos al inicio de nuestra tabla en WRAM, por ejemplo de la siguiente forma:

Page 6: Sprites en snes

;--------------- LDY #$BF10 STY Sprites + 0 LDY #$0080 STY Sprites + 2;---------------

Y si queremos un segundo sprite, a continuación.;--------------- LDY #$B710 STY Sprites+4 LDY #$0081 STY Sprites+6;---------------

Etc.Lo que resta es volcar esta tabla temporal a la tabla OAM cada refresco de pantalla, como hacemos con el resto de planos de scroll, por ejemplo, y esto se hace fácilmente usando DMA, y una rutina casi idéntica a la de inicialización de antes, sólo que ahora usaremos como dirección origen la dirección de nuestra tabla temporal, y no se usará dirección fija (Fixed address), sino autoincremento, para ir copiando uno tras otro todos los bytes de la tabla temporal. Es decir, seleccionar:- CPU memory -> PPU- Absolute addressing- 1 address write twice, o 1 address write once- Transferir al registro $2104- Auto address inc/decrement.- Automatic increment.

;---------------LDX.w #$0

STX $2102 ; resetar la dirección de la tabla OAM

LDY #$0400 ; copiar al registro $2104 (OAM)STY $4300 ; incrementar dirección LDY #Sprites ; copiar desde el inicio de nuestraSTY $4302 ; tabla temporalLDY #544STY $4305 ; numero de bytesLDA #$7E ; banco 7E, primer banco de la WRAMSTA $4304 ;LDA #$01STA $420B ; DMA!

;---------------

También se puede copiar manualmente, sin usar DMA. Es muy sencillo PERO ojo, hay que usar un registro de 8 bits para la transferencia u obtendrás resultados indeseables. Esta rutina funciona perfectamente, y es equivalente a la anterior:;---------------LDX.w #$0STX $2102 ; resetear dirección OAMSEP #$20 ; el registro A debe estar configurado en 8 bits LDY #$00CopySpr: LDA Sprites, Y STA $2104 INY CPY #544

Page 7: Sprites en snes

BNE CopySpr;---------------

Con esto doy por concluído el tutorial. Creo que con esta información no será problema meter un par de sprites que revoloteén por ahí, y den alegría a un frío plano de scroll ;)Dejo para más adelante el uso de sprites de más de 8x8 pixels, y otras cosillas más avanzadas.

CUADRO RESUMEN:1º copiar los tiles que usarán los sprites a un dirección de VRAM.Esta tiene que ser una de las siguientes.VRAM bits b------------------------------------| $0000-1FFF | 000 |------------------------------------| $2000-3FFF | 001 |------------------------------------| $4000-5FFF | 010 |------------------------------------| $6000-7FFF | 011 |------------------------------------

2º Establecer la dirección base de estos tiles en el registro $21013º Seleccionar modo gráfico en el registro $21054º Activar los sprites en el registro $212C5º Limpiar la tabla OAM6º Cada refresco de pantalla actualizar la tabla

Mucha suerte.