Aula Macedonia


Curso de Programación Multimedia Bajo DOS


Artículo realizado por
José Antonio Suárez.





Capítulo 4.
Programación de tarjetas de vídeo (II).

2.1.6.- La Memoria de Vídeo


Hay que dejar una cosa clara antes de continuar. Esto es, la forma en que hacemos que la tarjeta ponga en pantalla la información que queremos. Nosotros no escribimos directamente en la pantalla, sino que lo hacemos a la memoria de vídeo, que comienza en la dirección 0A000h (la CPU la pasa a la memoria de vídeo VRAM de la tarjeta). Para nosotros es como otra zona de memoria (aunque mucho más lenta).

Es la tarjeta la que se encarga de leer de la VRAM y pasarlo a la pantalla. Con lo que lo "único" que tenemos que hacer nosotros es escribir valores en esta memoria.

Tras estas consideraciones sobre el modo 13h, pasemos a ver los siguientes efectos:

2.1.7.- Rutinas de Sprites

Los sprites son simplemente un bloque de memoria donde se contiene la información sobre un "dibujo" almacenado en forma de bytes. Hay dos tipos de sprites, los bloques (llamados bloques) y los transparentes (llamados sprites).

Los sprites de tipo bloque son totalmente rectangulares, es decir, al ponerlos en la pantalla conforman un bloque rectangular que oculta totalmente lo que hay debajo de ellos.

Los sprites de tipo transparentes no es que sean transparentes, sino que aunque originalmente también son bloques, tienen un color determinado (normalmente el negro total almacenado en el 0 del DAC de vídeo), que a la hora de volcar sobre la pantalla no se considera, volcándose realmente un objeto con contorno no lineal; es decir, si queremos poner en pantalla una pelota amarilla, el bloque a dibujar será esa pelota rodeada del primer color de la paleta. Cuando se vuelque en pantalla, sólo lo que no sea ese primer color de la paleta se verá.

La filosofía de expuesta aquí es la típica en las aplicaciones gráficas.

Consiste en mantener en memoria RAM una pantalla gráfica (64000 bytes) de la que tomamos parte de ella para conformar los sprites. Si queremos pasar un trozo de esa pantalla a la memoria de vídeo, usamos las funciones siguientes:

Para los sprites de tipo bloque:

void BloqueMcga(int xi,int yi,int xf,int yf,int ancho,int alto, BYTE *pantalla)
{
    int segmento,desplazamiento;
    segmento=FP_SEG(pantalla);
    desplazamiento=FP_OFF(pantalla);
    asm{
            push ds
            mov ax,0xA000
            mov es,ax
            mov dx,yf
            mov di,xf
            mov bx,dx
            shl dx,8
            shl bx,6
            add dx,bx
            add di,dx // Hasta ahora hemos calculado 320*Y+X destino
            mov ds,segmento
            mov si,desplazamiento
            mov dx,yi
            add si,xi
            mov bx,dx
            shl dx,8
            shl bx,6
            add dx,bx
            add si,dx // Ahora se tiene 320*Y+X de la pantalla de orígen
            mov ax,ancho
            mov dx,320
            sub dx,ax
            shr ax,1
            mov bx,alto
    }
    salto: // Se volcarán "alto" veces, pequeñas líneas de tamaño "ancho"
    asm{ // desde el valor del orígen hasta el del destino, calculados antes
            mov cx,ax
            rep movsw
            add si,dx
            add di,dx
            dec bx
            jnz salto
            pop ds
    }
}

 

Y para los sprites de tipo transparente es casi el mismo procedimiento, con la excepción de que si el valor que vamos a escribir en la memoria de vídeo es 0, no lo escribimos y pasamos al siguiente.

void SpriteMcga(int,int,int,int,int,int,BYTE *);

Estos dos procedimientos de bloque consisten en tomar un rectángulo cuya esquina superior izquierda está dado por las dos primeras variables, con el ancho y el alto dado por las variables quinta y sexta, y se volcarán a partir de las coordenadas tercera y cuarta.

Ambos leen de una zona de memoria RAM de 64000 bytes y escriben directamente a la memoria de vídeo RAM. (Para nosotros, cuando se hable de memoria de vídeo nos referiremos al segmento RAM que comienza en 0A000, a no ser que se indique que se refiere a la memoria de vídeo de la tarjeta o VRAM)

Aparte de estos procedimientos, se pueden hacer otros prácticamente iguales, pero que escriban los sprites en memoria RAM. Son útiles para otras funciones internas.
 

2.1.8.- Rutinas de Volcados

Un volcado consiste en pasar la información contenida en un bloque de 64000 de memoria RAM en la memoria de vídeo a partir de la posición 0A000h.

Esto es relativamente sencillo, y el procedimiento que lo implementa es:

void VuelcaPantallaMcga(unsigned char *pantalla)
{
    int segmento,desplazamiento;
    segmento=FP_SEG(pantalla); desplazamiento=FP_OFF(pantalla);
    asm{
            push ds
            mov ax,0xA000
            mov es,ax
            mov ds,segmento
            mov si,desplazamiento
            xor di,di
            mov cx,32000
            rep movsw
            pop ds
    }
}

En este procedimiento se realiza la transferencia de palabras (words) desde la memoria RAM a la de vídeo un total de 32000 veces. Mediante la instrucción movsw, la circuitería del PC internamente incrementa los registros di y si para que apunten a la siguiente palabra.

Veamos un resumen de cómo funciona este procedimiento y cómo la teoría de la memoria de vídeo toma realidad, de forma gráfica:

Además del procedimiento para volcar una pantalla, se puede definir otro que se encargue de hacer "casi" lo mismo que el procedimiento anterior, con la única diferencia de que en vez de copiar a memoria de vídeo, copie a RAM para tener dos versiones de la misma pantalla y poder manipular una de ellas sabiendo que en cualquier momento podemos restaurarla al disponer de una segunda copia (para aplicarlo con la misma idea presentada cuando se comentaba el funcionamiento del cursor del ratón y su necesidad de ocultarlo al realizar los cambios en pantalla).

Otro procedimiento más, que es muy sencillo de hacer, es el CLS del Sistema Operativo, pero con la particularidad de que se hace en modo gráfico y además podemos elegir el color del borrado de pantalla. Su definición podría ser la siguiente:

void VolcarPantallaColor(BYTE);

La única variación entre este procedimiento y VuelcaPantallaMcga es que en el que ahora tratamos, siempre sabemos cuál es el valor a escribir en memoria de vídeo, no es necesario leerlo de memoria RAM (con lo que es casi el doble de rápido).

El último procedimiento y más vistoso de todos es el siguiente:

void VuelcaEfecto(BYTE *pantalla,BYTE *efecto,BYTE numcol)
{
    int segmento,desplazamiento,valor=0x0A000;
    register int x,y;
    BYTE *puntero,gris;
    segmento=FP_SEG(pantalla); desplazamiento=FP_OFF(pantalla);
    for (gris=0;gris<numcol;gris++)
    {
        puntero=efecto;
        for (y=0;y<200;y++)
        for (x=0;x<320;x++)
        {
            if ((*puntero==gris))
            asm{
                    mov es,segmento
                    mov bx,x
                    mov di,bx
                    mov dx,y
                    mov bx,dx
                    shl dx,8
                    shl bx,6
                    add dx,bx
                    add di,dx
                    add di,desplazamiento
                    mov al,es:[di]
                    mov es,valor
                    sub di,desplazamiento
                    stosb
             }
             puntero++;
        }
    }
}

 
Antes de explicar el procedimiento, es necesario introducir el concepto de máscara.

Una máscara para nosotros es una pantalla o bloque de la pantalla que tiene un dibujo principal y un color el cual deseamos que cuando se vuelque en la memoria de vídeo, no se vea. De esta forma podemos tener un dibujo de, por ejemplo, una letra en tres dimensiones, la cual se dibujará sobre un fondo que ya estaba en la pantalla. Lo que queremos es que no se dibuje el bloque entero que contiene a la letra, sino sólo la letra. Es el mismo concepto que los sprites transparentes que antes vimos, pero ahora hay que pensar en una pantalla completa y no en un trozo de ella con forma de rectángulo.

Ahora ya podemos afrontar la explicación de lo que hace este vistoso procedimiento el cual puede usarse de infinitas formas. Me explico:

Hasta ahora, cuando volcamos una pantalla completa para que se vea mediante la rutina VuelcaPantallaMcga, se vuelca de una sola vez, machacando lo que antes había. Muy rápido y efectivo, pero demasiado simple para las ansias espectaculares de cualquier aplicación gráfica.

El objetivo de VuelcaEfecto es volcar una pantalla, igual que VuelcaPantallaMcga, pero no de una sola vez, sino paulatinamente, mediante un orden arbitrario que se le puede determinar de la forma en que queramos. Esto quiere decir que si quiero volcar una pantalla con este procedimiento, necesito darle otra pantalla que va a determinar la "forma" en que se va a volcar la primera.

La forma de hacer esto es jugando con la paleta de colores, más concretamente con sus posiciones que con sus valores.

Aunque posteriormente veremos lo que es el DAC de vídeo, ahora hace falta una pequeña referencia a él.

El DAC de vídeo tiene 256 posiciones distintas [0-255], donde se almacenan los valores de los colores que se van a visualizar.

VuelcaEfecto volcará una pantalla en un número determinado de iteraciones. Supongamos que queremos que se haga en 32 pasos. Esto quiere decir que vamos a utilizar las primeras 32 posiciones del DAC de vídeo.

En la primera iteración vamos a volcar todos los píxels que referencien a la primera celda del DAC, esto es: el 0.

Más detalladamente es lo siguiente:

Primera iteración: Segunda iteración: Y así hasta 32 veces.

Con este método, podemos volcar una pantalla dando la apariencia de que aparece como si fuese un telón de un teatro, o que aparezca en forma circular o cuadrada, o cualquier otra forma geométrica, o con forma de escalera, de cisne, de caballo, de enchufe...

El único límite es que como mínimo tiene que haber 1 iteración y como máximo 256 (la longitud del DAC).

Ya sólo queda aclarar qué es la pantalla "mascara". Es otra pantalla cualquiera pero con la característica de que usará los colores consecutivos de la paleta, desde el 0 al X, siendo X+1 el número de iteraciones en que se volcará la pantalla que queramos.




AULA MACEDONIA
a
MACEDONIA Magazine