Hay dos formas de escribir texto:
Una, que no vamos a tratar, consiste en definir nuestra propias letras,
o saber dónde está la definición de las que trae el
ordenador, para mirar esa zona de memoria, analizarla y escribir las letras
pixel a pixel.
Otra más sencilla, aunque menos versátil, es con la orden
"write" igual que hacíamos en modo texto. Para ello, basta usar
la unidad CRT pero indicando DirectVideo := false
con lo que la escritura pasa a través de la BIOS, en vez de hacerse
directamente en la memoria de pantalla. Así conseguimos que se pueda
enviar a la pantalla gráfica. Veremos un ejemplo al final
del tema, en el ejemplo de Scroll.
Finalmente, para copiar zonas de memoria podemos utilizar move,
que tiene el formato move (org, dest, cuanto) Esto
no nos sirve directamente para zonas rectangulares de la pantalla, porque
el origen debe ser una sóla zona contigua, lo que no ocurre en un
rectángulo, pero podemos evitarlo copiando fila a fila con un bucle.
¿Y cómo se usa? Pues vamos a ver un ejemplillo,
aprovechando que en nuestro modo de pantalla cada byte se corresponde con
un pixel, para hacer un Scroll (desplazamiento) de parte de la pantalla,
para que aparezca un texto:
{--------------------------}
{ Ejemplo en Pascal: }
{ }
{ Scroll sencillo en la }
{ parte inferior de la }
{ pantalla }
{ GRB5.PAS }
{ }
{ Este fuente procede de }
{ CUPAS, curso de Pascal }
{ por Nacho Cabanes }
{ }
{ Comprobado con: }
{ - Turbo Pascal 7.0 }
{ - Tmt Pascal Lt 1.01 }
{--------------------------}
Uses
Crt, dos;
Const
Fila = 23; { Fila (-1) en la que se escribe el mensaje (base 0) }
Var
pixel, LetraActual : Byte; { Para bucles }
regs: registers; { Para interrupciones (ModoPantalla) }
tecla: char; { Para absorber la tecla que se pulse }
procedure ModoPantalla( modo: byte ); { Cambia a un modo dado }
begin
regs.ah := 0; { Función 0 }
regs.al := modo; { El modo indicado }
intr($10,regs); { Interrupción de video }
end;
procedure Retrace; { Espera el barrido de la pantalla }
begin
repeat until (port[$3da] and 8) = 8;
repeat until (port[$3da] and 8) <> 8;
end;
Procedure Mueve; { Desplaza el texto a la izqda un pixel }
Var
LineaAct : Word; { La línea que se está moviendo }
begin
{ Desplaza las 8 líneas 1 pixel hacia la izqda }
For LineaAct := (Fila * 8) to (Fila * 8) + 7 DO
Move(Mem[$A000 : LineaAct * 320 + 1], Mem[$A000 : LineaAct * 320], 319);
{ Borra los pixels del final }
For LineaAct := (Fila * 8) to (Fila * 8) + 7 DO
Mem[$A000 : LineaAct * 320 + 319] := 0;
end;
procedure ScrollInferior(mensaje:string); { Esto es lo importante }
begin
ModoPantalla($13); { Modo Mcga/Vga 320x200x256 }
DirectVideo := False; { Para escribir texto en modo gráfico }
GotoXY(1, Fila + 1); { Vamos a la posición }
repeat
For LetraActual := 1 to Length(Mensaje) do { Para cada letra }
begin
For pixel := 1 to 8 do { Los 8 pixels de ancho }
begin
Mueve; { Mueve el letrero }
Retrace; { Espera al barrido }
if keypressed then exit; { Si se pulsa tecla: fuera }
end;
GotoXY(40, Fila+1); { En la posición adecuada }
Write(Mensaje[LetraActual]); { Se escribe la sgte letra }
end;
until keypressed;
end;
begin
ScrollInferior('Esto es un - S C R O L L - ');
tecla := readkey; { Vacía el buffer del teclado }
ModoPantalla(3); { Vuelve a modo texto }
end.
Una recomendación final: en vuestros programas (si es que los haceis X-D ) no se os ocurra copiar el procedimiento "linea", "modopantalla" y similares cada vez. Lo más cómodo es crear una unidad, meter nuestros procedimientos y funciones relacionados con los gráficos y acceder a ella cuando nos interese.
Así además, si encontrais otro procedimiento más
rápido para dibujar líneas (los hay, si trabajamos en ensamblador,
por ejemplo) o cualquier otra mejora, todos los programas la tendrán
sólo con recompilar.