|
|
Artículo realizado por
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:
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 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á. 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)
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)
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:
José Antonio Suárez.
Capítulo 4.
Programación de tarjetas de vídeo (II).
2.1.6.- La Memoria de Vídeo
2.1.7.- Rutinas de Sprites
{
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
}
}
{
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
}
}
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.
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:
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.
|
|