Ya hemos comentado cómo entrar a un modo gráfico dado, como dibujar un punto, dibujar líneas, círculos o elipses, como hacer rotaciones en el plano, algunas optimizaciones sencillas...
Hoy vamos a tratar cómo borrar la pantalla, como cambiar la paleta de colores, cómo sincronizar con el barrido de la pantalla, cómo escribir en la pantalla gráfica y a dar una idea sobre cómo mover datos en memoria, aplicándolo a un Scroll sencillo.
Veamos... lo de borrar la pantalla es MUY sencillo. Si
estamos en nuestro modo 320x200, 256 col., la pantalla ocupaba 64000 bytes,
que estaban a partir de la dirección $A000:0000 ¿verdad?
Pues entonces podemos situar una matriz en esa posición de la memoria, como hicimos en el primer apartado de este tema:
var pantalla: array[0..319,0..199] of byte absolute $A000:0000;
o bien simplemente
var pantalla: array[1..64000] of byte absolute $A000:0000;
fillchar(pantalla, 64000, 0);
que quiere decir "lléname la variable pantalla con ceros, ocupando 64000 bytes".
Un uso más adecuado para evitar errores, ya que "fillchar" no hace comprobaciones de tamaño, es usar "sizeof" para que el compilador sea quien calcule cuantos ceros hay que poner:
fillchar(pantalla, sizeof(pantalla), 0);
Lógicamente, si queremos borrar la pantalla empleando el color 2 en vez del 0 (que normalmente es el fondo), basta poner un 2 en vez del cero... ;-) En el caso más general, sería
procedure BorraPantalla( color: byte );
begin
fillchar(pantalla, sizeof(pantalla), color);
end;
Tenemos las siguientes direcciones importantes:
$3c7 => Dirección de lectura
$3c8 => Dirección de escritura
$3c9 => Dirección de datos (R,G y B consecutivos)
y la intensidad máxima para R, G o B será 63.
¿A que asusta? No hay motivo, es más fácil de lo que parece: para cambiar las componentes R, G y B de un color dado, hacemos
procedure FijaColor( Color, r, g, b: Byte );
begin
Port[$3c8] := Color; { Elegimos el color a modificar }
Port[$3c9] := r; { Primer dato: cuanto Rojo queremos }
Port[$3c9] := g; { Segundo: verde }
Port[$3c9] := b; { Tercero: azul }
end;
Insisto: R, G y B van de 0 a 63, lo que da un total de 262.144 posibles combinaciones de colores que podemos tomar para rellenar nuestros 256 colores "físicos".
Análogamente, para leer las componentes de un color, sería
procedure LeeColor( Color: Byte );
begin
Port[$3c7] := Color; { Elegimos el color a leer }
r := Port[$3c9]; { Primer dato: cuanto Rojo hay }
g := Port[$3c9]; { Segundo: verde }
b := Port[$3c9]; { Tercero: azul }
end;
donde se ha supuesto que R, G y B son variables globales. También podría ser una función que devolviera los datos en un array, o haber pasado R, G y B como parámetros por referencia (precedidos por la palabra "var").
Esto tiene aplicación inmediata para hacer fundidos de
pantalla y similares, o para muchos efectos vistosos. Me voy a limitar
a poner uno que funciona incluso en modo texto: vamos a hacer que el fondo
pase de negro a blanco y luego vuelva a negro.
{--------------------------}
{ Ejemplo en Pascal: }
{ }
{ Fundido de la panta- }
{ lla a blanco y luego }
{ a negro }
{ GRB4.PAS }
{ }
{ Este fuente procede de }
{ CUPAS, curso de Pascal }
{ por Nacho Cabanes }
{ }
{ Comprobado con: }
{ - Turbo Pascal 7.0 }
{ - Tmt Pascal Lt 1.01 }
{--------------------------}
program GrB4;
uses crt;
var i: byte;
procedure FijaColor( Color, r, g, b: Byte );
begin
Port[$3c8] := Color; { Elegimos el color a modificar }
Port[$3c9] := r; { Primer dato: cuanto Rojo queremos }
Port[$3c9] := g; { Segundo: verde }
Port[$3c9] := b; { Tercero: azul }
end;
begin
for i := 0 to 63 do { Recorremos todas las intensidades }
begin
FijaColor(0,i,i,i); { Igual cantidad de R, G, B => gris }
delay(10); { Esperamos antes de seguir }
end;
for i := 63 downto 0 do { Igual, descendiendo }
begin
FijaColor(0,i,i,i);
delay(15);
end;
end.
procedure Retrace;
begin
repeat until (port[$3da] and 8) = 8;
repeat until (port[$3da] and 8) <> 8;
end;
¡ Magia ! }:-D Pues basta con escribir "Retrace;" antes de empezar a dibujar, y mejorará bastante (si nuestro dibujo no es muy lento), además de que conseguimos una velocidad bastante independiente del ordenador.