|
|
Artículo realizado por
Ahora llega el turno a la tarjeta de vídeo, soporte de
los gráficos del ordenador. Vamos a conocer los tres modos de vídeo
(modos de operación de la tarjeta) siguientes:
Desde que hizo aparición en las placas base de los IBM PS/2 50,
60, y 80, allá por 1987, la VGA (Vídeo Graphics Array),
se ha convertido en un estándar para todos los ordenadores IBM y
sus clónicos compatibles.
La abreviatura VGA era para mucha gente sinónimo de resolución
aceptable (hasta 640x480 píxels) y de un ramillete de colores increíble
hasta entonces (256 de una paleta de 262144 posibles), al menos cuando
se la comparaba con las antiguas CGA y EGA.
Desgraciadamente, para usar estos 256 colores, el BIOS de la
VGA limita a los usuarios a una resolución de sólo 320x200
píxels, es decir, el conocido modo 13h estándar en el que
están programados casi todos los vídeojuegos que han aparecido.
2.1.1.- Programación de la Tarjeta de Vídeo
El procedimiento para establecer el modo de vídeo es:
Al ser este modo de vídeo de 320 píxels horizontales por
200 verticales, da un total de 64000 píxels por pantalla.
José Antonio Suárez.
Capítulo 3.
Programación de tarjetas de vídeo (I).
2.- Introducción a la Tarjeta de Vídeo VGA-SVGA
2.1.- VGA Estándar. 320x200x256c
void ModoMcga(void)
{
asm{
// Modo 13h
mov al,0x13
xor ah,ah
int 0x10
// Limpia la memoria de vídeo
mov ax,0xA000
mov es,ax
xor di,di
xor ax,ax
mov cx,32000
rep stosw
}
}
2.1.2.- Ventaja del Modo 13h
Este modo tiene una ventaja y un inconveniente. La ventaja es que cada uno de los 64000 píxels que componen la imagen gráfica en el modo 13h es fácilmente direccionable en el segmento de la memoria de vídeo que comienza en 0A000h. Por ejemplo, utilizando la siguiente fórmula:
Desplazamiento= (Y * 320) + X
se puede calcular el desplazamiento del píxel dentro de la memoria de vídeo, mediante su coordenada X y su coordenada Y. Tras ello, y si se introduce un byte en la posición A000:desplazamiento, aparecerá el color inmediatamente.
Por ejemplo: si queremos poner el color 23h en el píxel (100,10), usando la fórmula anterior sería:
10 * 320 + 100 = 3300
que en hexadecimal es 0EC4h. Si hacemos el siguiente código en ensamblador, veremos aparecer un píxel en esa dirección:
mov ax,0A000h
mov ds,ax
mov (0EC4h),23h
El procedimiento que hace esto y pone un píxel en pantalla es:
void PonerPixelMcga(int x,int y,char color)
{
asm{
mov ax,0xA000
mov es,ax
mov bx,x
mov dx,y
mov di,bx
mov bx,dx
shl dx,8
shl bx,6
add dx,bx
add di,dx
mov al,color
stosb
}
}
Este procedimiento puede parecer que es mucho más complejo que
el siguiente, que es el primero que se le ocurre a un programador.
void PonerPixelMcga(int x,int y,char color)
{
asm{
mov ax,0xA000
mov es,ax
mov bx,x
mov dx,y
mul dx,320
add bx,dx
mov di,bx
mov al,color
stosb
}
}
2.1.3.- Velocidad de las Instrucciones
Vistos estos dos procedimientos, puede parecer que el último
tendrá que ir más rápido puesto que el número
de instrucciones es menor. Pero no es así. Si miramos el documento
suministrado por INTEL sobre sus conjuntos de instrucciones de Ensamblador,
podemos ir sumando el número de ciclos de reloj que tarda cada instrucción
de cada procedimiento considerando los valores para un 486.
|
|
|
|
|
|
|
|
|
|
|
|
Hay que especificar que estos valores son medios, ya que no es lo mismo realizar la instrucción "mov" entre dos registros que entre una posición de memoria y un valor inmediato (la primera tarda la mitad).
El primer procedimiento tarda aproximadamente 18 ciclos de reloj, mientras que el segundo tarda 30 (sólo la instrucción "mul" tarda 18 ciclos). Y si en lugar de considerar los valores para un 486, lo hacemos para un 386, la diferencia entre el primero y el segundo se disparan, dando 40 y 91 respectivamente.
Por esto, y a partir de ahora, todos los procedimientos en Ensamblador parecerán que no son los más claros, pero son los más rápidos que ha sido posible implementar con la información disponible, así, en vez de usar la instrucción "mov bl,0", pondré "xor bl,bl", porque aunque las dos tarden lo mismo en los 486, en un 386 el segundo tarda 2 ticks del reloj y el primero 4.
Tras estas aclaraciones, continuemos con el tema de la tarjeta de vídeo con la resolución MCGA (VGA 320x200x256c).
Leer un píxel sería igual de simple que escribirlo, tan sólo habría que mirar el contenido del byte correspondiente en lugar de escribir otro encima de él.
Esta facilidad es el cielo comparado con los problemas que dan los planos
y los registros de máscara que se necesitan en los modos de 16 colores.
Con el modo 13h, la distancia que existía entre un algoritmo gráfico
en papel y una rutina gráfica, se redujo drásticamente a
tan sólo una fracción. Y lo que es más importante,
son incomparablemente más rápidos (sobre todo si se esfuerzan
un poco los programadores e intentan aprovecharse de la información
sobre las instrucciones del Ensamblador y sus distintos retardos).
2.1.4.- Desventaja del Modo 13h
Pasemos ahora a la desventaja que antes mencionamos. El modo 13h está limitado a una sola página, es decir, la VGA tan sólo puede mostrar una pantalla a la vez, mientras que los modos de 16 colores permiten varias, permitiendo esto mostrar al usuario cualquiera de ellas en cada momento determinado y dibujar o cambiar el contenido de las que están ocultas. Este procedimiento conocido como "page flipping" o cambio de páginas es muy importante a la hora de realizar animaciones sin parpadeo.
Por otro lado, en el modo 13h es casi imposible conseguir un scroll suave de pantalla utilizando la tarjeta tal cual. Pero como siempre hay puertas ocultas en el mundo de la informática, podemos aprovecharnos de los puertos programables de la VGA para hacer un curioso efecto visual, con el que conseguiremos que la suavidad en los scrolls grandes sea bastante aceptable, y elimine casi en todos los casos el molesto efecto de "nieve" que se suele ver en numerosas aplicaciones gráficas y vídeojuegos.
El procedimiento que consigue esto es el siguiente:
void EsperarBarrido(void)
{
asm{
mov dx,0x3da
}
l1:
asm{
in al,dx
and al,0x08
jnz l1
}
l2:
asm{
in al,dx
and al,0x08
jz l2
}
}
Al concepto en que se basa este procedimiento se le llama Barrido
Vertical. Se basa "simplemente" en uno de los muchos
registros de la VGA, pero que se convierte en uno de los más útiles
para la animación y los efectos de paleta.
2.1.5.- Teoría del Barrido Vertical
Hay un cañón de electrones en la parte posterior del monitor que mantiene los píxels "refrescados" con sus correctos valores cada 1/60 segundos o 1/70 segundos dependiendo de la frecuencia del monitor. Ese cañón dispara un haz de electrones a cada píxel, fila a fila. El retraso vertical es el tiempo que tarda el haz de electrones en retornar desde la esquina inferior derecha, en su orientación hacia la esquina superior izquierda, donde comienza de nuevo el barrido de la pantalla. Durante ese tiempo no se emiten electrones.
Este es un período extremadamente corto en el que apenas parece que dé tiempo a nada, pero no es así. Durante este tiempo se puede cambiar cualquier parte de la memoria de vídeo sin que la circuitería de vídeo se entere, por lo tanto no se actualizarán los cambios en pantalla. De esta forma, los gráficos actualizados no se verán afectados por esos efectos que todos hemos visto y que suelen ser los siguientes:
Cuando la pantalla completa o un sprite muy grande se desplaza desde la izquierda hasta la derecha, suele aparecer como cortada, es decir, una parte superior está más desplazada hacia una dirección que la parte inferior. Esto ocurre porque el barrido vertical pilla a la actualización de la memoria de vídeo antes de que termine, por lo que aparecerá la parte actualizada superior y la todavía no actualizada inferior, y así vamos propagando los retrasos.
Otro efecto es el de la nieve o "fuzz" (como llaman los angloparlantes). Se produce cuando hay algún efecto de paleta, como por ejemplo un fundido en negro donde se va oscureciendo paulatinamente la imagen. Entonces aparecen unas líneas a veces, otras veces son numerosos puntos blancos, e incluso otras, la imagen se distorsiona. Esto ocurre porque para realizar los efectos de paleta, el decremento hasta el color negro en este ejemplo, se hace de forma continua y el barrido vertical "pilla" continuamente a la actualización de los valores del DAC de vídeo de donde toma la intensidad que le tiene que asignar al electrón que tiene que lanzar en ese momento.
El último efecto y muy importante sobre todo para los vídeojuegos, es que cuandono se utiliza esta técnica y hemos creado por ejemplo, una animación donde se desplazan a la vez decenas de pequeños sprites, dependiendo del ordenador en que se esté ejecutando irá más rápido o más lento, algo no deseable en estos casos. Imaginemos que estamos jugando a la enésima versión del conocido Tetris y no implementa esta técnica. Si el que lo programó lo hizo en un 386, lo verá "bien" en su ordenador, y todos los que tengan este modelo, también. Pero supongamos que lo ejecutamos sobre un 8086. Irá terriblemente lento y casi injugable, puesto que como el programador lo veía bien en su ordenador, no se esforzó mucho en optimizar las rutinas. Sin embargo, si ese mismo programa se ejecuta en un Pentium Pro a 200Mhz, el jugador se desesperará igualmente, pero no porque sea lentísimo, sino porque apenas le dará tiempo a ver las piezas y terminará la partida casi antes de empezar. Por el contrario, si se piensa en la técnica del barrido vertical, se podrá aprovechar un detalle: no importa la velocidad del ordenador, casi todos los monitores tienen la misma frecuencia de barrido, con lo que si se usa el procedimiento anterior, se verá ese programa a la misma velocidad en cualquier ordenador, puesto que lo único que hace el procedimiento es esperar y retener al procesador mientras el barrido esté activo, y liberarlo cuando el haz de electrones retorne a su posición inicial. De esta forma se controla la velocidad de una forma cómoda. Y añadiéndole que soluciona los anteriores problemas de la nieve y los scrolles cortados, parece que puede ser bastante interesante su uso.
|
|