HispaMSX

patrones bitmap

2008-03-12 13:16:59
Buenas,

le he estado dando vueltas al tema de los patrones para los modos bitmap del
MSX2 (y 2+). Creo que he encontrado una solución.
He escrito un artículo con la teoría. Aún tengo que pulir la parte hardware,
pero creo que la implementación no sería difícil.

Echale un vistazo a  ver que os parece y qué pegas le veis.

Salu2,

IvI

  ----------

Modo de patrones para V9938/58
------------------------------

1.- Introducción
2.- Desarrollo
3.- Análisis hardware
4.- Pros y contras: Incompatibilidades
5.- Método alternativo


1.- Introduccion:


El VDP de los MSX 2 y 2+ carece de modo patrones en los nuevos modos bitmap.

El principal problema para emular un modo de patrones por software, es que hay
que hacer múltiples "copias" a vídeo (de vídeo a vídeo). Es un método poco 
rápido
y limitado por el tiempo de refresco de pantalla, además de hacer que la CPU
trabaje casi en exclusiva para el chip de vídeo.

Pero, si el VDP es capaz de redibujar la pantalla 50 (o 60) veces por segundo,
quiere decir que en realidad el chip sí es lo suficientemente rápido como para
mostrar unas 64K en cada interrupcion.

Entonces, ¿por qué no se suministró un modo de patrones para los nuevos modos
bitmap? Recordemos otra evolución del chip, el incluido en las consolas SEGA
Master System, que sí incluye un modo bitmap con patrones.

Si nos fijamos en cómo funcionan otros modos de patrones, como el modo
gráfico 2 (SCREEN 2 en MSX), nos daremos cuenta de que la pantalla está 
compuesta
por un montón de patrones que son mostrados según la tabla de patrones, es 
decir,
al contrario que los modos bitmap, donde la pantalla se muestra recorriendo
linealmente la memoria de vídeo, sin saltos, en el modo patrones lo que se hace
es variar la dirección de lectura de memoria para cada grupo de 8x8 puntos.
Esto quiere decir que la tabla de patrones actúa como una tabla de punteros.

Ya que los punteros de los patrones son de 8 bits, se pueden conseguir un máximo
de 256 patrones diferentes. El resto de bits del bus de direcciones actúan de 2
maneras: por un lado unos bits son un puntero interno para los atributos 
(colores) 
de cada fila de cada patrón y, los otros bits, apuntan al grupo de 256 patrones.

De ésta manera, se pueden conseguir 3 grupos de 256 patrones. Suficientes para
llenar una pantalla de screen 2 (256x192)

Pero, si los modos bitmap carecen de modo patrones, ¿sería posible variar con
circuitería externa, el acceso del VDP a VRAM para hacer que dibuje lo que 
queramos
para cada punto?

Una posible solución sería, aprovechando el redibujado de la pantalla, sustituir
el bus de direcciones que atacan a la VRAM, por punteros a los patrones, esto 
es,
hacer que el chip de vídeo dibuje la pantalla en cada área de 8x8 con la zona
de memoria indicada por el mapa de patrones, en lugar del tradicional redibujado
lineal.



2.- Desarrollo:


Para hacer un modo fácil y a la vez potente de patrones, tomemos el modo gráfico
de 256 colores (screen 8). Este modo es ideal, ya que cada punto está 
representado
por 1 byte, lo que facilita enormemente las cuentas. Además, los nuevos modos 
del
chip V9958 tienen un mapa de memoria similar.

Para hacer que el modo patrones funcione sin interferir al resto de funciones 
gráficas
(sprites), se desplazará el área de trabajo de los sprites al segundo banco de 
64K.
De ésta manera, se puede usar el bit A16 como "interruptor" para conectar o 
desconectar el modo de patrones.

Recordar que el VDP trabaja con una ventana de 256x256 puntos en este modo, por 
eso
la tabla de patrones resultante será de 32x32 (1024 bytes).

Gracias a que la dirección de comienzo del bitmap siempre es 0 y el ancho y 
alto no
varían, no es difícil calcular qué patrón está redibujando VDP en cada momento. 
Se 
establece una relación entre la dirección VRAM y el patron a dibujar.

EL VDP dibuja la pantalla del siguiente modo (obviando dibujado de sprites):

        - Bus de direcciones a 0
        - Lectura de VRAM
        - Muestra el punto (8 bits)
        - Incrementa bus direcciones en uno (puntero lectura)
        - Repite bucle de lectura
        - Los puntos se dibujan de izquierda a derecha, siguiendo la línea de 
raster.
        - Si dibujando llega al fin de linea, salta a la siguiente linea de 
raster.
        - Entre las líneas no hay saltos: 
          el primer byte de una línea es justo el siguiente al último de la 
anterior.

Si se intercepta el bus de direcciones, se puede hacer que en vez de apuntar al 
punto
siguiente, el bus apunte al punto que corresponda según la tabla de patrones.

Lógicamente, el dibujado de pantalla se complica cuando hay sprites que mostrar,
pero eso no es problema si la zona de trabajo de los sprites se desplaza a las 
64K
superiores. Esto permite que, activando el bit A16, se desconecte el modo de 
patrones
y se muestren los sprites normalmente. Este efecto permitiría usar la segunda 
página
de la manera convencional.

En el funcionamiento normal del VDP, las direcciones de los puntos van asociadas
al refresco de pantalla, esto es, al mismo tiempo que el raster dibuja la 
pantalla
de izquierda a derecha, se incrementa el bus de direcciones desde cero en 
adelante.
Los puntos (o bytes) están colocados contíguos de izquierda a derecha y las 
líneas 
contíguas de arriba a abajo. Esto es un mapa de memoria plano.

El inconveniente de usar este sistema de memoria y un modo de patrones, es que 
para
redefinir un patrón habría que recalcular (cada 8 puntos), la direccion de VRAM 
a la
que escribir. Para solucionarlo habrá que redirigir las líneas de direcciones 
para
que todos los bytes del patrón sean contíguos en memoria.

El problema de usar una memoria no lineal es que el VDP sigue refrescando la 
pantalla
de la manera tradicional (de izquierda a derecha y de arriba a abajo) e 
incrementando
el bus de direcciones de uno en uno para cada punto (en screen 8). 

Si queremos que el VDP coloque cada byte en su sitio, tendremos que hacer que 
"salte"
por la memoria, controlando el byte que lee para cada punto. Esto se consigue 
con unos
cuantos cruces en las líneas de dirección.

La ventaja de usar este sistema es que para calcular la dirección donde está 
almacenado 
un determinado patrón, basta multiplicar su número por 64 (8x8=64). Además, 
basta con
64 OUTs o un OTIR para redefinir un patrón completo


*** Correspondencia entre direccion de refresco (raster) y direccion de punto 
de patrón.

Calcular las coordenadas del patron al que pertence un punto (coordenadas de 
punto):

        Considerando el raster (refresco), las coordenadas de un punto en modo 
256 colores 
        coinciden con el byte alto y el byte bajo de la direccion VRAM del 
punto. Se puede
        decir que el byte alto es la coordenada vertical (Y) y el bajo es la 
horizontal (X).

        Para saber a qué posicion en la tabla de patrones (32x32), pertence un 
punto del
        raster, basta aplicar la siguiente fórmula:

                        posicion = (Y/8)*32+(X/8)

        esto es, despreciar los 3 bits bajos, (rotar a izquierda) y recolocar 
los bits como sigue:

                X=A7 A6 A5 A4 A3 A2 A1 A0       
                Y=A15 A14 A13 A12 A11 A10 A9 A8 -> coordenadas del punto = 
direccion VRAM
                
                XY=A15 A14 A13 A12 A11 A7 A6 A5 A4 A3 ->posicion tabla patrones 
= 10 bits =  1024 bytes

        El valor leído de la tabla (P0-P7), nos dá el número de patrón 
correspondiente
        a la posición del patrón en pantalla.

        Para calcular la dirección a aplicar al bus de direcciones, 
reconstruiríamos el bus
        de direcciones de la siguiente manera:

                RAM=P7 P6 P5 P4 A11 A10 A9 A8  P3 P2 P1 P0 A3 A2 A1 A0 (siendo 
P0-P3=X, P4-P7=Y)

        Pero con esto seguiríamos teniendo el problema de la memoria lineal. 
Los bytes de 
        cada patrón no estarían contíguos.

        Con el modelo de patrones de bytes contíguos, para calcular dónde está 
almacenado 
        cada patrón, basta tomar el byte leído de la tabla y multiplicarlo por 
64 (que es
        el tamaño en bytes de cada patrón). A dicho valor habrá que añadirle 
los bits de
        dirección para que el VDP se desplace por el patrón mientras el raster 
refresca la
        pantalla.

        El valor resultante sería algo así:

                A15 A14 P7 P6 P5 P4 P3 P2 P1 P0 A10 A9 A8 A2 A1 A0


        Esta es la explicación de esta colocación de los bits:

                - Las líneas A0-A2, hacen que se muestren los 8 bytes del 
patrón en el 
                  refresco horizontal
                - Las líneas A8-A10 hacen que el raster salte, cada 8 bytes, al 
siguiente
                  patrón.
                - P0-P7 hacen que el bus de direcciones apunte al comienzo de 
cada
                  patrón, según el valor leído de la tabla (en saltos de 64 
bytes).

                - Ya que el rango de patrones va de 0 a 255, A14 y A15 actúan a 
modo de
                  selectores de banco (cuarto de pantalla).
        

*** Comparación entre el modelo de memoria tradicional y el modelo de patrones 
(de bytes contiguos)

        Usando el modelo de memoria original,
        los bytes (puntos) de cada patron, estarían dispuestos de la siguiente 
manera:

                VRAM+0    ->    12345678 -> comienzo primer patrón
                VRAM+256  ->    12345678
                VRAM+512  ->    12345678
                VRAM+768  ->    12345678
                VRAM+1024 ->    12345678
                VRAM+1280 ->    12345678
                VRAM+1536 ->    12345678
                VRAM+1792 ->    12345678 -> fin primer patrón

                VRAM+0+8  ->    12345678 -> comienzo segundo patrón
                VRAM+256+8->    12345678 -> etc. ...

        o lo que es lo mismo:

                VRAM+256x0  ->  12345678 -> comienzo primer patrón
                VRAM+256x1  ->  12345678 
                VRAM+256x2  ->  12345678
                VRAM+256x3  ->  12345678
                VRAM+256x4  ->  12345678
                VRAM+256x5  ->  12345678
                VRAM+256x6  ->  12345678
                VRAM+256x7  ->  12345678 -> fin primer patrón

                VRAM+256x0+8 -> 12345678 -> comienzo segundo patrón
                VRAM+256x1+8 -> 12345678 -> etc. ...


        Usando el modelo de patrones (de bytes contiguos), 
        los bytes (puntos) de cada patron, estarían dispuestos de la siguiente 
manera:

                VRAM+0    ->    12345678 -> comienzo primer patrón
                VRAM+8    ->    12345678
                VRAM+16   ->    12345678
                VRAM+24   ->    12345678
                VRAM+32   ->    12345678
                VRAM+40   ->    12345678
                VRAM+48   ->    12345678
                VRAM+56   ->    12345678 -> fin primer patrón

                VRAM+64  ->     12345678 -> comienzo segundo patrón
                VRAM+72->       12345678 -> etc. ...

        o lo que es lo mismo:

                VRAM+8x0  ->    12345678 -> comienzo primer patrón
                VRAM+8x1  ->    12345678 
                VRAM+8x2  ->    12345678
                VRAM+8x3  ->    12345678
                VRAM+8x4  ->    12345678
                VRAM+8x5  ->    12345678
                VRAM+8x6  ->    12345678
                VRAM+8x7  ->    12345678 -> fin primer patrón

                VRAM+8x0+64 ->  12345678 -> comienzo segundo patrón
                VRAM+8x1+64 ->  12345678 -> etc. ...





4.- Pros y contras: Incompatibilidades

* Manejo se sprites: Comprobar el funcionamiento con los diferentes modos de 
sprite
* Posibilidad de conexión desconexión del modo patrones (por compatibilidad)
* ¿Posibilidad de scroll horizontal? ¿Vertical?
* ¿Compatibilidad con comandos acelaradores VDP?


5.- Método alternativo

Modificar las líneas de direcciones de VRAM en el momento de ESCRITURA en vez 
de lectura,
para que no se perdiera la compatibilidad con los comandos y el scroll.

Para implementarlo, habría que aplicar al bus de direcciones los mismos cambios 
que
en el método de lectura.

El problema vendría cuando se quisiera escribir en una dirección de la VRAM 
concreta:
Si el número de patrón para una posición no es el original, al hacer la 
conversión de
direcciones se escribiría en el patrón mostrado en ese momento, no en la 
dirección
real a la que queremos escribir, es decir:

        Imaginar que en la tabla de patrones, hemos seleccionado en la posición 
X=1, Y=0, el
        número de patrón 2 (en vez de el número 1) para mostrar en esa posición 
el patrón 2.
        
        cuando vayamos a escribir en la VRAM correspondiente al patrón 1, por 
la conversión
        de direcciones, estaríamos escribiendo realmente al patrón 2 (que es el 
seleccionado
        para que se muestre).

Otro incoveniente sería que, modificando la tabla de patrones, no se 
modificaría lo que
el VDP muestra en pantalla, si no sólo cuando se escribe en ella.

ESTE MÉTODO NO SERÍA ADECUADO.

[Se han eliminado los trozos de este mensaje que no contenían texto]


<Anterior en la conversación] Conversación actual [Siguiente en la conversación>