El mundillo de
las demos (a partir de ahora scene) es bastante amplio.. Por esta razón
, estos 'funamentos' varian en cada efecto. Estaras bastante de acuerdo
conmigo que no tiene nada que ver un efecto relacionado con la rotación
3D con otro que nos dibuje un plasma en la pantalla. Sin emabargo en casi
todas las demos se utilizan una serie de bloques que nos seran muy útiles,
no solo en la programación de demos sino tambien en la de videojuegos..
Se recomienda
entender bien estas rutinas y procedimientos, ya que serán los mas
utilizados , asi como serviran de base para explicaciones futuras:
Ensamblador: el lenguaje por excelencia de las demos
Modos Gráficos
Dibujando nuestro primer pixel
La paleta gráfica
Pantallas virtuales
Retrazado vertical
Truco de la artimetica Fija
Texto en modo gráfico
Formato gráfico lineal
Donwload de las rutinas y ejemplos
Ensamblador: el lenguaje por excelencia de las demos
A pesar de que en esta Web se toca a fondo el lenguaje Pascal, existe un lenguaje por excelencia en el mundillo de las demos: el ensamblador. Las principales caracteristicas de dicho lenguaje son:
- es un lenguaje de bajo nivel, lo
cual significa quue las instrucciones en ensamblador se ejecutan muchísimo
más rápido que sus correspondientes en otros lenguajes
de alto nivel como el Pascal o el C
- el código generado es muy
compacto, lo que hace que el tamaño del programa final sea muy pequeño
-al generar un código muy compacto
la velocidad del programa es increiblemente rápida, cosa fundamental
en las demos, donde lo que queremos es "exprimir" las posibilidades de
la CPU
- tenemos total acceso a todos los
recursos de la CPU, algo impensable en algunos lenguajes de programación
Pero claro, esto seria demasiado bonito
si no hubiese un pega :( La pega está en la sintaxis y reglas
de propio ensamblador. Por poner un ejemplo: En los lenguajes de programación
existen una seria de palabras llamadas PALABRAS RESERVADAS. Dichas
palabras reservadas realizan una determinada tarea (escribir un texto en
pantalla, introducir un nombre, abrir un fichero...). Estas palabras reservadas
tienen un significado "mas o menos" orientativo, que nos da una idea aproximada
de lo que hace, asi por ejemplo la funcion WRITE ("hola mundo")
nos imprimira en pantalla el texto "hola mundo". Veamos el progama en Pascal
y el mismo programa en ensamblador para que veas realmente donde esta la
pega :) (creo que te daras cuenta tu solo :)
PROGRAM hola;
Begin
WRITE ("hola mundo");
End.
Programa en Ensamblador que muestra "hola mundo" en la pantalla del ordenador:
CR equ 13
;retorno de carro
LF equ
10
;salto de linea
;segmento de datos
DATOS SEGMENT
TEXTO DB
"hola mundo",CR,LF
DB "$"
DATOS ENDS
;segmento de pila
PILA
SEGMENT STACK
DB 128 DUP ('PILA')
PILA
ENDS
;segmento de codigo
CODIGO SEGMENT
EJEMPLO PROC FAR
ASSUME CS:CODIGO,DS:DATOS,SS:PILA
PUSH DS
SUB
AX,AX
PUSH AX
MOV AX,DATOS
MOV DS,AX
LEA
DX,TEXTO
CALL ESCRIBIR
RET
EJEMPLO ENDP
ESCRIBIR PROC
PUSH AX
MOV AH,9
INT 21h
POP AX
RET
ESCRIBIR ENDP
CODIGO ENDS
END EJEMPLO
Si pretendemos
hacer una demo deberemos conocer mas o menos bien el funcionamiento interno
del ordenador. Esto no es absolutamente imprescindible, pero si muy recomendable.
Lógicamente si pretendemos hacer una demo deberemos pasar a un modo
grafico de video, aunque kizas hayas visto demos en modo texto. Actualmente
es posible, gracias a las tarjetas aceleradoras conseguir resuluciones
de hasta 1600x1200 pixels con millones de colores, cosa impensable a principio
de los noventa, donde lo mas normalito era tener una ISA de 1 Mega de memoria
RAM.
La gran mayoria
de efectos que veras en esta Web estan en el mismo modo grafico: el modo
13h, aunque existen muchisimos mas (como los modos VESA, que permiten altas
resoluciones, o los modos X (no, no pienses mal :) que permiten hacer scrolles
por hardware, etc)
Como veras,
el modo 13h es posiblemente el mas fácil de programar, ya que su
estructura es LINEAL, y no como los demas modos donde tenemos distintos
bancos (modos Vesa) y distintas páginas (modos X)
La caracteristica
principal de los modos de video son:
-resolución horizontal :.......320 pixels en modo 13h
-resolución vertical :...........200 pixels en modo 13h
y -numero de colores simultaneos : 256 colores en modo 13h
Como habras
podido notar, este modo gráfico es el que en muchos juegos esta
como "baja resolución". Si ya se, ahora diras que en baja resolución
los juegos se ven muy mal, pero...los gráficos los vas a hacer tú,
y a menos que seas un artista, cuanto mas grande sea la resolución
mejor se veran los fallos :) No en serio, "baja resolución" no implica
necesariamente peor calidad, mas bien y pensando positivamente implica
mas facilidad de manejo :)
Bueno, estarás
diciendo que vale ya de tanta teoria y vamos a lo que nos interesa!! Bueno,
no seas tan impaciente, que ahora voy!! :)
Para comutar
al modo 13h deberemos hechar mano de los servicios "gratuitos" :) que pone
a nuestra disposición las INTERRUPCIONES de nuestro ordenador. Interrupciones?
Sip, son como una especie de "funciones" especificas que la CPU pone a
nuestra disposición. Pueden ser debidas al Hardware (Interrupciones
BIOS) o debidas al software del sistema operativo instalado. Dichas "funciones"
nos posibilitan el acceso directo y reprogramacion de todos los componentes
del ordenador, pudiendo llegar a reprogramar el Timer, la PIC, los puertos
de Comunicaciones, el CD-rom, el sistema de video,...
Por esta razón ya dije antes
que era importante saber el funcionamiento intermo de los componentes de
un ordenador, aunque kizas muchos de estos componentes no los usaremos
nunca.
Bueno, pues
que ya voy!. Para conmutar a modo 13h utilizaremos lo que se conoce como
la interrupción de Video que pone a nuestra disposicion la BIOS.
Dicha interrupción es la 10h. La función para cambiar el
modo de video es la 0 y para activar el modo 13h....pues será el
valor 13h :).
es decir:
INT
10h
AH = 0h (vamos a cambiar de modo de video)
AL = 13h (modo de video 13h, 320x200 pixels x 256colores)
AL = 3h (modo texto 80x25 columnas x 16 colores)
y su traducción
al Pascal/ensamblador:
PROCEDURE SetVga;assembler;
Asm
mov ah,0h
mov al,13h
int 10h
End.
PROCEDURE SetTexto;assembler;
Asm
mov ah,0h
mov al,3h
int 10h
End.
(Te recomiendo que te bajes los tutores de ensamblador si no has entendido muy bien como inicializar el modo grafico o como se usan los registros en Asm)
Bien, con esto
ya tendriamos comnutado a un modo gráfico, ahora solo nos queda
'dibujar algo :)
Dibujando nuestro primer pixel
Una vez que ya estamos en modo gráfico
estamos en disposición de dibujar cualquier cosa. Lo mas simple
es dibujar un punto en la pantalla. A este punto se le conoce como pixel,
y es la unidad minima que podemos dibujar en la pantalla.
Para poder dibujar un pixel (y en
extensión cualquier otra cosa, ya que no dejarán de ser una
serie de pixels) deberemos conocer lo que se denomina offset.
Por poner un ejemplo muy simple. Ya
hemos dicho que el modo 13h es lineal. Esto implica
que si tenemos un punto en la coordenada 160,100 su offset seria: 32160
Vale, y de donde sale este numero?
Pues de la siguiente fórmula:
Si ya has mirado los tutores en ensamblador
sabras que el offset nunca esta 'solo', siempre tenemos la pareja segmento:offset
Por lo cual tenemos que conocer el segmento donde tenemos
que dibujar nuestro pixel. El segmento es una dirección de memoria.
Resulta que la dirección A000h es la que esta asociada con
la memoria de video. Por lo tanto para dibujar un pixel tendremos que tener
una estructura parecida a esta:
PROCEDURE PonPixel (X,Y:integer;Color:byte);
Begin
Mem[$A000:(320*y+x)]:=color
End;
aunque claro, siempre tendremos un equivalente en ensamblador que va un 'poquito' más rápido :)
PROCEDURE
PonPixel (X,Y:Integer;Color:byte);assembler;
Asm
mov ax,$A000
mov es,ax
mov al,Color
mov di,Y
mov bx,X
mov dx,di
xchg dh,dl
shl di,6
add di,dx
add di,bx
mov es:[di],al
End;
Si quisiesemos dibujar un pixel en las coordenadas (259, 140) con el color 1 hariamos en ambos casos:
Bien, bien. ahora ya sabemos como dibujar un pixel, pero
y si lo queremos dibujar rojo, cual es el color rojo, el 1, el 2, el 46?
Los pixels que vemos en nuestro ordenador,
al igual que los que vemos en nuestra tele de casa, no son mas que electrones
impactando sobre una capa de fosforo, la cual reacciona de forma diferente
segun la trayectoria de impacto (menuda explicación !! :)
Pues bien, lo que nos insteresa a
nosotros es saber que un pixel no esta formado por un unico color, si no
por la mezcla de tres colores primarios: ROJO,
VERDE y AZUL.
(en inglés R G B , Red, Green & Blue)
En
modo13h estas componentes tienen 64 valores posibles:.desde
el 0 al 63. Haciendo un poco de cálculo vemos que tenemos 64 x 64
x 64 =262.144 posibles combinaciones. Pues bien, este es el máximo
numero de colores disponibles en modo 13h, de los cuales podemos visualizar
simultaneamente 256.
La estructura de la paleta se suele
guardar en una matriz de 768 elementos:
256 colores dibididos en:
256 porcentajes de Rojo
256 porcentajes de Verde
256 porcentajes de Azul
haciendo un total de 256+256+256 = 768 bytes.
De una forma más 'informatica':
COLOR[0]= [rojo_0,verde_0,azul_0]
COLOR[1]= [rojo_1,verde_1,azul_1]
......
COLOR[255]= [rojo_255,verde_255,azul_255]
Para cambiar las componentes Roja, verde y azul de un
detreminado color deberemos usar los puertos 3C8h y 3C9h.
En el puerto 3C8h deberemos indicar que color vamos a
modificar (0-255). A continuación debermos indicar en porcentaje
de rojo, verde y azul (EN ESE ORDEN: ROJO, VERDE y AZUL)
Presentamos la forma de realizar este proceso en lenguaje Pascal:
PROCEDURE PutColor(Color,R,G,B:Byte);
Begin
Port[$3C8]:=Color;
Port[$3C9]:=R;
Port[$3C9]:=G;
Port[$3C9]:=B;
End;
Normanlmente no necesitaremos que este proceso sea muy rápido, de todas formas aqui esta el equivalente en Ensamblador:
PROCEDURE PutColor (Color,R,G,B:Byte);assembler;
Asm
mov dx,03C8h
mov al,Color
cli
out dx,al
inc dx
mov al,R
out dx,al
mov al,G
out dx,al
mov al,B
out dx,al
sti
End;
Si quieres el color negro las tres componentes deben ser
0 : (Color,0,0,0)
Si quieres el color blanco las tres componentes deben
ser 63: (Color,63,63,63)
Un ejemplo, supongamos que el color 239 quieres que sea azul intenso, en ambos casos harias:
Si quieres que sea amarillo fuerte: (amarillo: verde + azul )
Como ves, las combinaciones posibles son enormes, en concreto 262.144 combinaciones posibles
La paleta suele guardarse en una estructura especial:
TYPE
Color= record
Rojo:byte;
Verde:byte;
Azul:byte;
end;
TipoPaleta=array[0..255]
of Color;
VAR
Paleta:TipoPaleta;
De esta forma, por ejemplo, para modificar la componente verde del color 239 hariamos:
Hasta ahora hemos visto que podiamos
dibujar un pixel en el modo de video. Sin embargo a la hora de realizar
un efecto o juego deberemos tener en cuenta que no nos llegara la memoria
de video para poder realizar nuestros cálculos. Tendremos que usar
lo que se conoce como pantalla virtual.
La pantalla virtual no es mas que
otro segmento de la memoria, colocado en una dirección que nos ha
dado un puntero. En dichas pantallas podremos modificar las imagenes, ya
que si modificamos las imagenes el propio segmento de video se verá
un parpadeo muy molesto.
Suponer este ejemplo: tengo una pelota
en la posicion (1,100). La quiero mover a la posicion (320,100) en incrementos
de X=10. Si realizo esto directamente en la pantalla de video se produce
un parpadeo y la animación se verá muy mal.
Lo que hago es lo siguiente:
Como ves lo que se esta haciendo es copiar-borrar, copiar-borrar.
Rutina de copiado.
Lo que realmente hace la rutina de copiado es MOVER X
cantidad de bytes del segmento origen (pantalla virtual) al segmento destino
(normalmente segmento de video).
Tanto en el caso de copiado como en el de borrado si
que es necesario utilizar ensamblador, ya que estos bloques se van a ejecutar
muchas veces por ciclo, con lo cual deben estar optimizadas al maximo.
La rutina que aqui presentamos utiliza registros de 32 bits (va realmente
rápido :)
-rutina de copiado
en ensamblador:
PROCEDURE Copy64K (SegOrg,SegDes:Word);assembler;
Asm
push ds
mov ax,SegOrg
mov ds,ax
mov ax,SegDes
mov es,ax
xor di,di
xor si,si
mov cx,16000
db
66h;rep movsw
pop ds
End;
Rutina de borrado.
La rutina de borrado lo que hace es rellenar un segmento
de la memoria con un byte especificado (del 0 - 255), si rellenamos con
el byte 0 y este representa el color negro 'borraremos' la pantalla con
el color 0, si borramos con el byte 25 y este representa el color naranja,
'borraremos' la pantalla con el color naranja. Esta rutina tambien debe
estar optimizada al máximo ya que se realiza muchas veces por ciclo.
Tambien se usan registros de 32 bits:
-rutina de borrado en ensamblador:
PROCEDURE Fill64k (Where:word;Col
: Byte); assembler;
asm
push
es
mov
cx, 16000;
mov
es,[where]
xor
di,di
mov
al,[col]
mov
ah,al
mov
dx, ax
db
$66, $C1, $E0, $10 {shl eax, 16}
mov
ax, dx
db
$F3, $66, $AB {rep
stosd}
pop
es
End;
Bien, estas 2 rutinas utilizan un segmento 'virtual'.
Para poder usarlo deberemos obtenerlo, para ello usaremos una variable
tipo puntero, que nos devolverá la dirección de memoria.
Al principio parece un poco complicado , pero ya veras que se muy sencillo.
1º definimos una variable Ppantalla como un
puntero:
2º definimos otra variable Psegmento como
un word, que nos servira para saber el segmento de dicho puntero:
3º para poder utilizar dicho puntero deberemos
reservar una 'zona' en la memoria
4º una vez acabado el programa es necesario
liberar esa 'zona' de la memoria.
Las definiciones serian:
VAR
Ppantalla:pointer;
Psegmento:word;
Begin
GetMem (Ppantalla,64000)
Psegmento:=SEG(Ppantalla^);
vale, ahora supon, que quiero 'borrar' la pantalla virutal con el color 0, utilizando la rutina de borrado:
Notad una cosa, hemos reservado
64.000 bytes. Esto implica un segmento entero
Por restricciones del compilador y del modo de trabajo del Ms-2 solo podemos
reservar 64.000 bytes por segmento. Esto puede dar un quebradero de cabeza
a mas de alguno, pero con un poco de pericia y algun que otro truco veremos
que podemos acceder a toda la memoria del ordenador.
Por cierto, la memoria que se reserva
es memoria convencional, por lo que NO podemos reservar 'muchos' punteros
ya que si lo hacemos asi nos quedaremos rapidamente sin memoria. Si haceis
unas pocas cuentas vereis que como mucho se pueden reservar 10 punteros,
suponiendo que tengamos 640 Kbytes de memoria convencional. En la practica
se suelen reservar 2 punteros y en raras ocasiones mas de 2.
El retrazado vertical es una caracteristica
del monitor, no de la CPU. Los puntos en el monitor no se dibujan instantaneamte,
sino que se van dibujando empezando por la esquina superior izquierda y
acaba en la esquina inferior derecha, tal como se indica en la FIG 2.
Una vez que se ha dibujado el ultimo
punto el haz de electrones vuelve a la esquina superior izquierda. FIG
3.
-rutina para esperar el retrazado vertical en ensamblador:
PROCEDURE VerticalRetrace;assembler;
Asm
mov dx,3DAh
@@1:
in
al,dx
test al,8
jnz @@1
@@2:
in
al,dx
test al,8
jz
@@2
End;
Por lo tanto en el bucle principal de nuestro programa deberiamos tener la siguiente estructura antes de copiar una pantalla virtual:
Normalmente cuando necesitamos cálculos
para nuestras demos o videojuegos casi siempre utilizamos numeros enteros.
En raras ocasiones utilizamos numeros reales, es decir, con decimales.
En una gran parte de los cálculos
siempre entervienen las formulas trigonometricas del SENO y del
COSENO.
El Pascal, al igual que otros lenguajes
de programación, ponen a nuestra disposición funciones que
calculan el SENO y el COSENO. Pero dichas funciones son extremadamente
lentas, ya que usan numeros reales.
Alguno de vosotros puede pensar que
podemos REDONDEAR el valor de el SENO o del COSENO para poder convertirlo
a un numero sin decimales, a un entero, pero esto no es posible ya que
estas funciones trigonometricas solo tienen valores posibles entre el -1
y el 1:
Bien, y todo esto para que, te estarás
preguntado?. Ahora lo veras:
Supuner que tenemos que hacer esta operación:
100 * SIN (45)
1º Si lo hacemos con una calculadora veremos
que da lo siguiente:
SIN (45) = 0'70710678; 0'70710678
* 100 = 70'710678
2º Ahora emplearemos lo que hemos aprendido
sobre las rotaciones de bits
SIN (45) = 0'70710678; 0'70710678
* 256 = 181'01934
181 * 100 = 18100
18100 / 256 = 70'703125
o bien
SIN (45) = 0'70710678; 0'70710678
SHL 8 = 181'01934
181 * 100 = 18100
18100 SHR 8 = 70'703125
Es decir:
Con calculadora: 70'710678
Con punto fijo:
70'703125
Como vemos las diferencias empiezan en las centenas,
con lo que es totalmente valida.
En este caso el resultado de 100
* SIN (45) seria 71.
(redondeo de 70'703125 por exceso)
Como veis, este metodo es muchisimo mas rápido
y el resultado es casi identico.
Bueno, alguno se estara preguntando
porque no usar otro factor de multiplicacion en lugar de X SHL 8
o de division en lugar de X SHR 8?. La respuesta es muy simple. Las instrucciones
SHL y SHR se realizan en 1 solo ciclo de reloj de la CPU debido a que son
multiplicaciones y divisiones de factor 2 ( 2, 4, 8, 16, 32, 64, 128 y
256). Podriamos haber hecho el calculo otro numero, por ejemplo 317:
SIN (45) = 0'70710678; 0'70710678
* 317 = 224'15285
224 * 100 = 22400
22400 / 317 = 70'662461
Como vemos tambien da 71 (redondeo por exceso).
Pero en este caso multiplicar y dividir entre 317 en mas lento que hacerlo
entre 256, ya que 317 no es multiplo divisor de 2, con lo cual la operacion
se hace demasiado lenta.
Bueno, creo que queda bastante explicado
es numero 'misterioso' que es el 256 que suele salir tantas veces en los
listados y no sabemos realmente lo que hace.
Texto
en modo gráfico
Muchas veces se nos presenta que tenemos
que representar un numero en pantalla y en formato grafico. El problema
que tenemos es que el lenguaje Pascal tiene una funcion llamada OutText
que hace esto pero tenemos que usar la libreria Graph del Turbo Pascal.
Esta libreria es bastante lenta (pero bastante bastante :).
Por esta razon tendremos que construirnos
una rutina capaz de mostrar un numero en modo grafico, para poder representar,
por ejemplo, el numero de vidas que tenemos, cuantos puntos llevamos, etc
Para hacer esto, lo primero que tenemos
que saber es donde estan guardadas las fuentes en la ROM. Esto lo averiguaremos
con un puntenro, ya que llamando a la funcion 11 y subfuncion 30 de la
interrupcion de video ( la 10h) nos devolvera el segmento:offset donde
se halla dicho juego de caracteres:
-rutina para hallar el juego de caracteres:
VAR
fofs,fseg:word;
PROCEDURE GetFont; assembler;
ASM
mov ax,1130h
mov bh,6
int 10h
mov fseg,es
mov fofs,bp
End;
Bien, con esta rutina ya sabemos la
direccion exacta del juego de caracteres: fseg:fofs
Bien, tenemos que implementar una rutina que nos 'escriba'
en modo grafico:
-rutina que escribe un texto en modo grafico:
PROCEDURE WriteTXT(segm,x,y:word;
txt:string;color:byte);
VAR i,j,k:byte;
Begin
for i:=1 to length(txt)
do for j:=0 to 15 do for k:=0 to 7 do
if ((mem[fseg:fofs+ord(txt[i])*16+j]
shl k) and 128) <> 0 then begin
mem[segm:(y+j)*320+(i*8)+x+k]:=color;
end;
End;
Bien, y ahora si queremos escribir un numero deberemos
convertirlo a formato String (cadena) ya que como se ve en el procedimiento
WriteTXT la variable TXT es del tipo string.
Para ello utilizaremos la funcion STR del propio pascal:
-rutina para convertir una cadena String a un numero de 5 digitos
Function Num2String (numero:Longint):String;
VAR cadena:String[5];
Begin
STR (numero,cadena);
Num2String : = cadena;
End;
Bien, ahora supongamos que queremos escribir : PUNTOS : 3421 en las coordenadas (1,1) y con el color 23:
Como veis he
escrito diriectamente en la pantalla de video (SegA000), pero lo podria
haber hecho sobre cualquier otro segmento virtual
y luego copiarlo todo a video.
La rutina GetFont
carga el juego de caracteres normalizado. Sin embargo podemos modificar
dicho juego de caracteres y hacer que la fuente de la letra sea distinta.
Lo unico que debemos hacer es cargar en memoria el nuevo juego de caracteres
y hacer que fseg:fofs apunten a este nuevo juego en lugar de al
normalizado.
Por otro lado
el procedimiento WriteTXT escribe un texto con
de forma normal. Podemos modificar esta rutina para que el texto sea multicolor,
de mayor tamaño, italico, negrita, inverso, etc.
Todas estas modificaciones las
encontraras en el area de Downloads :)
El formato gráfico lineal, tambien
conocido como formato crudo es el mas sencillo de manejar. Existen muchos
formatos graficos: PCX, GIF, JPG, PNG, BMP, TIFF, TGA,.... La gran mayoria
de estos formatos graficos poseen algoritmos para que los datos almacenados
en ellos ocupen menos espacio, de esta forma se consigue que el tamaño
del fichero sea mas pequeño.El ejemplo mas claro es en los archivos
JPG donde la compresion puede llegar a ser de 3:1.
Sin embargo, cuanto mas comprimida
esta una imagen mas proceso de calculo es necesario para descomprimirla.
En cambio el formato lineal no posee ningun tipo de compresion.
Los datos del fichero son exactamente los que se visualizaran en
pantalla. El problema de estos ficheros es su gran tamaño,
ya que es posible que la misma imagen en otro formato ocupe la mitad de
espacio en el disco duro. Pero por contrapartida, al no poseer ningun tipo
de compresión su manejo es cosa de niños :)
Al tratarse de un fichero lineal y al estar en modo 13h,
la longitud de este sera = 320 x 200 = 64.000 bytes
Basicamente hay 2 tipos de ficheros en formato lineal:
1º El primero tiene una longitud
de 64.768 bytes. En este fichero puede haber 2 variantes:
1.1: que los
primeros 768 bytes sean de la paleta y el resto el dibujo
1.2: que los
ultimos 768 bytes sean de la paleta y los primeros 64.000 el dibujo
2º Tener un fichero nombre.xxx
de 64.000 bytes y tener otro fichero paleta.xxx de 768 bytes
En ambos casos se trabaja de la misma forma. Yo personalmente
me gusta mas el modelo 2º, ya que de esta forma, y si dos pantallas
tienen la misma paleta, solo es necesario tener 1 fichero de paleta para
las 2 (3, 4, o mas) pantallas.
En primer lugar y como casi siempre nos definiremos una
variable puntero donde almacenar los datos leidos del fichero, tambien
nos tendremos que definir la variable para el segmento del puntero, asi
como la variable para el manejo de la paleta:
TYPE
Color = record
Rojo:byte;
Verde:byte;
Azul:byte;
end;
TipoPaleta=array[0..255]
of Color;
VAR
Ppantalla:pointer;
Psegmento:word;
PALETA:TipoPaleta;
A continuacion deberemos tener los procedimientos que nos cargan los datos del fichero:
PROCEDURE CargaImagen(nombre:STRING);
var F:file;
BEGIN
assign (F,nombre);
reset (f,1);
blockread(f,Ppantalla^,64000);
close (f);
END;
Como veis la carga es sencillisima.Si queremos cargar la pantalla IMAGEN.SCR llamariamos a este procedimiento:
PROCEDURE CargaPaleta(nombre:STRING);
var F:file;
BEGIN
assign (f,nombre);
reset (f,1);
blockread (f,PALETA,768);
close (f);
END;
Como veis, el procedimiento es casi identico, solo cambia la variable contenedora de los datos (en este caso PALETA) y la cantidad de bytes a leer (768 en este caso)
Bien, una vez cargada la paleta deberemos activarla, esto lo conseguiremos utilizando los procedimientos PutColor vistos anteriormente, para los 256 colores disponibles.
Bien y ya para acabar deberemos
copiar el contenido del puntero a video usando el procedimiento Copy64k.
El programa principal quedaria
algo asi:
SetVga;
Getmem (Ppantalla,64000);
Psegmento:=seg(Ppantalla^);
CargaImagen ('pk.scr');
CargaPaleta ('pk.pal');
EstablecerPaleta(PALETA);
Copy64k (Psegmento,segA000);
repeat until keypressed;
Freemem (Ppantalla,64000);
SetTexto;
(recordar siempre que es una buena
medida liberar el espacio reservado por GetMEM)
Download
de rutinas y ejemplos
|
|
|
|
|
Programa que permite editar y/o modificar un juego de caracteres para poder usarlos posteriormente. |
|
|
35 ficheros en formato lineal de fuentes para poder usarlas con los ejemplos. |
|
|
Ejemplo que muestra la carga de una pantalla en formato lineal. Ademas se incluye un efecto de Fading, para mostrar lo que se puede hacer con la paleta |
|
|
Programa que nos muestra las 262.144 combinaciones posibles de colores de la paleta variando sus 3 componentes basicas |
|
|
Programa que nos permite convertir un fichero PCX de 320x200 pixels a 256 colores a un formato lineal con paleta independiente. |
|
|
Rutinas para la visualizacion de caracteres y numero en modo grafico, tal y como se ha explicado en el apartado de texto en modo grafico |
|
|
Rutinas que permiten cargar un determinado tipo de fuente (ya sea generada por el programa FontEdit o en formato lineal) en modo grafico. Ademas se incluyen efectos como letras multicolores, centradas, negritas, italicas, de mayor tamaño... |
|
|
Rutinas que permiten cambiar el tipo de letra en modo texto. Recomendable para cambiar el aspecto del texto bajo MS-2.Permite el uso de fuentes en formato lineal o generadas por FontEdit |
|
|
Unidad 'basica' creada con todos los procedimientos de estos fundamentos. |