Páginas

15 junio 2016

Sprites MSX · Desaparece por la izquierda (Early Clock)

En un post anterior comenté como ocultar un sprite o grupo de sprites (ocúltate en la 208), pero en esta ocasión vamos a tratar el como hacer desaparecer un sprite por los bordes laterales de la pantalla.

Si mostramos un sprite en la posición 0,0 se situaría en la esquina superior izquierda de la pantalla y si lo movemos hacia la derecha llegaría un momento en el que empezaría a desaparecer por el borde derecho de la pantalla. Esta posición empieza en la coordenada 241 y va hasta la 255, pero en esta última posición no se acaba de ocultar todo el sprite ya que se mostraría la primera linea, por lo que el siguiente paso seria sacarlo de la pantalla, por ejemplo posicionandolo en la coordenada Y = 209.

Pero... ¿como hacemos que desaparezca por el lado izquierdo?

Las figuras móviles (sprites), disponen de un byte para el valor de posicionamiento horizontal, dentro de la tabla de atributos OAM (Object Attribute Memory), por lo que queda limitado a 256 posiciones, las mismas que el ancho de la pantalla. Para poder desplazar 16 pixels más, necesitaríamos un bit más pero nuestro VDP solo dispone de registros de 8bits. Por suerte el TMS9918 ha solucionado el problema utilizando un bit de otro atributo.

Este bit es el llamado Early Clock (EC) lo tenemos dentro del valor de color del sprite. Como para el color solo es necesario de 4 bits el VDP aprovecha uno de los sobrantes para este menester, en concreto el número 7.

¿Que pasa si ponemos a 1 este bit?
Es muy simple. Desplaza 32 pixels a la izquierda la posición que tengamos marcada en la coordenada X. Eso quiere decir, que si tenemos el sprite en la posición 0, al activar el bit de EC desaparecerá completamente de la pantalla ya que se encontrará oculto en la coordenada -32 de la pantalla. Para que nuestra figura desaparezca como es debido tendremos que controlar la coordenada X, por lo que si nuestro sprite queremos situarlo en la posición -1, le tendremos que dar el valor 31.

Una forma de ilustrar como se programaría, en Basic seria de la siguiente manera:
vramaddr = tablaOAM+(planosprite*4)
VPOKE vramaddr+3 , 128+color
VPOKE vramaddr+1 , 24:REM coordenada X=-8
La dirección en la VRAM de la tabla OAM es la misma en screen 1 y 2 y se sitúa en la posición 1B00h.

Ejemplo:
10 SCREEN 1,2
20 FOR i=14336 TO 14367:VPOKE i,255:NEXT
30 PUT SPRITE 0,(0,88),7,0
40 PUT SPRITE 1,(24,104),3,0
50 v=BASE(18):REM direccion tabla OAM
60 VPOKE v+3,128+7:REM activa bit EC + color
70 VPOKE v+1,32-8:REM coordenada X
Nota: Una vez ejecutado este ejemplo puedes probar a cambiar la coordenada X escribiendo con VPOKE en la dirección 6913 (equivale al valor de X para el plano de sprite 0).


En el ejemplo podemos ver como dos sprites colocados en la misma posición horizontal (el del plano 0 le hemos dado el valor 24 en la línea 70), el de colo cían se muestra en la posición -8, gracias a la activación del bit EC (línea 60).

Si programas en MSX Basic la forma del ejemplo anterior no es necesaria ya que utilizando la instrucción Put Sprite, ya lo hace todo por nosotros. Solo tendrás que introducir el valor negativo de desplazamiento para la coordenada X y ya esta!

Ejemplo:
PUT SPRITE 0,(-8,88),7,0

¿Y en el V9938?
Ya que estamos, vamos a ver como ha evolucionado este concepto en el VDP de los MSX2.

Este video procesador ademas de la OAM, contiene una nueva tabla para los colores de los sprites, que ahora permite asignar un color por linea y como en el TMS9918, aprovecha los bits libres para añadir más funcionalidad. El Early clock también se encuentra en el bit 7 y de igual modo generará un desplazamiento de 32 pixels hacia la izquierda, pero en este caso se tendrá que modificar en los valores de todas las lineas. Personalmente no se me ocurre una idea práctica para querer desplazar diferentes partes de un sprite, pero la posibilidad ahí esta para aquellos que lo necesiten.

En screen 5 y 6, la tabla de colores de los sprites se encuentra en la posición 7400h, mientras que en screen 7 la tenemos en F800h.


Referencias: