GRAFICOS.H
#include <alloc.h>
#include <stdio.h>
#include <dos.h>
#include <stdlib.h>
#include <time.h>
/////////////
// GENERAL //
/////////////
// Modos de video
#define TEXTO 0x3
#define MCGA 0x13
#define VGA 0x12
// Buffer para el modo 4 planos
#define ANCHO_BUFFER 640
// Direcci¢n de comienzo de la memoria de video "Compact"
#define SEG_VGA 0xA000
#define BYTE unsigned char
#define WORD unsigned int
/////////
// FLI //
/////////
// Memoria de video "Large" para los .FLI
#define video ((char far*)0xa0000000L) /* Handy for loading a GIF directly
*/
// Buffer para aumentar la velocidad en la exposici¢n de un .FLI
#define BUFSIZE 15000
// Tipos de bloques de un .FLI
#define FLI_COLOR 11
#define FLI_LC
12
#define FLI_BLACK 13
#define FLI_BRUN 15
#define FLI_COPY 16
// Buffer de entrada y salida para los .FLI
static char *VBuf;
// Estructura de la cabecera de un .FLI
typedef struct
{
unsigned long size;
WORD magic;
WORD frames;
WORD width;
WORD height;
WORD bits;
WORD flags;
WORD speed;
unsigned long next;
unsigned long frit;
BYTE expand[102];
}CABECERA_FLI;
// Estructura de la cabecera de los frames de un .FLI
typedef struct
{
unsigned long size;
WORD magic;
WORD chunks;
BYTE expand[8];
}CABECERA_FRAME;
////////////////////////
// Variables Globales //
////////////////////////
// Declaraci¢n del array de la paleta: 0-767 de ternas de RGB
typedef BYTE PALETA[768];
/////////////////////////////
// Modo de v¡deo 80x25x16c //
/////////////////////////////
void ModoTexto(void);
void Humo(void);
//////////////////////
// MCGA 320x200x256 //
//////////////////////
// Modo de v¡deo 320x200x256c
void ModoMcga();
// Lee un fichero .PCX de 320x200x256c y asigna la paleta directamente
void LeePcxMcga(char [12], BYTE *);
// Lee un fichero .PCX de 320x200x256c y almacena la paleta
void LeePcxMcgaR(char [12],BYTE *,PALETA);
// Espera un refresco vertical con una duraci¢n de 14.2 ms entre
cada uno
void EsperarBarrido(void);
// Lee del DAC de video una terna de valores RGB pertenecientes a un
color
void Leer1ColorPaleta(BYTE,BYTE *,BYTE *,BYTE *);
// Establece los tres valores RGB de un color en el DAC de video
void Establecer1ColorPaleta(BYTE,BYTE,BYTE,BYTE);
// Establece 256 colores en el DAC de video
void EstablecerPaleta(PALETA);
// Pone todos los colores de la paleta a R=0,G=0,B=0
void PaletaNegra(void);
// Pone todos los colores de la paleta a R=63,G=63,B=63
void PaletaBlanca(void);
// Lee la paleta del DAC de video y la almacena
void SalvarPaleta(PALETA);
// Hace un filtro de color a la paleta; =1 Rojo,=2 Verde, =3 Azul,
=4 Gris
// =5 oscurece.
void FiltroDePaleta(char);
// Enciende una paleta partiendo de una paleta negra a la paleta dada
// El retardo nulo es 1, retardo>=1
void EncenderPaleta(PALETA,BYTE);
// Rota la paleta hasta que se pulse una tecla. Par metro de velocidad>=0
void RotarPaleta(BYTE);
// Apaga la paleta usando como partida la dada y decrementa los valores
// hasta R=0,G=0,B=0 en todos los registros del DAC de video; retardo>=1
void ApagarPaleta(PALETA,BYTE);
// Pone un p¡xel en memoria de video en el modo 320x200x256c
void PonerPixelMcga(int,int,char);
// Lee un p¡xel de la memoria de video en el modo 320x200x256c
BYTE LeerPixelMcga(int,int);
// Lee un p¡xel=byte de la zona de memoria accedida por 320*y+x1
BYTE LeerPixelMem(int,int,BYTE *);
// Vuelca un bloque de memoria de 64000 bytes a partir de A000
void VuelcaPantallaMcga(BYTE *);
// Vuelca el contenido de la memoria de v¡deo en la zona de memoria
dada
void VuelcaMcgaPantalla(BYTE *);
// Copia 64000 bytes de una direcci¢n en otra; origen->destino
void CopiaPantallaMem(BYTE *,BYTE *);
// Vuelca 64000 bytes a la memoria de video con un determinado orden
void VuelcaEfecto(BYTE *,BYTE *,BYTE);
// Vuelca 64000 bytes con un valor £nico y determinado = CLS
void VolcarPantallaColor(BYTE);
// Dibuja una l¡nea en el modo 320x200x256c xi,yi,xf,yf,color
void Linea(int,BYTE,int,BYTE,BYTE);
// Copia un bloque dentro de una zona de memoria a otra zona de memoria;
// xi,yi,xf,yf,ancho,alto
// El ancho debe ser un n£mero par, si es impar, el bloque saldr¡a
oblicuo
void BloqueMem(int,int,int,int,int,int,BYTE *,BYTE *);
// Copia un bloque a excepci¢n de los bytes con valor 0 a una
zona de
// memoria; xi,yi,xf,yf,ancho,alto
void SpriteMem(int,int,int,int,int,int,BYTE *,BYTE *);
// Copia un bloque a la memoria de video; xi,yi,xf,yf,ancho,alto
void BloqueMcga(int,int,int,int,int,int,BYTE *);
// Copia un bloque menos los bytes=0 a la memoria de video;
// xi,yi,xf,yf,ancho,alto
void SpriteMcga(int,int,int,int,int,int,BYTE *);
// Lee y visualiza un fichero .FLI en el modo 320x200x256c; velocidad>=0
void VerFLIMcga(char [12],int,BYTE *);
// Reduce una zona de memoria sobre otra
void ReducePantalla(BYTE *,BYTE *,int,int,int,int,int,int,int);
////////////////////
// 4P 320x200x256 //
////////////////////
// Establece el modo de video 320x200 encadenado
void ModoGraficoMcga4P(void);
// Establece la esquina superior izquierda de la visualizaci¢n
void PosicionVentana4P(int,int);
// Limpia la memoria de video con un color
void VolcarColor4P(BYTE);
// Pone un p¡xel en memoria de video con unos l¡mites virtuales
de 640x400
void PonerPixelMcga4P(int,int,char);
// Lee un p¡xel de la memoria de video. Rango = 640x400
BYTE LeerPixelMcga4P(int,int);
// Copia un bloque a la memoria de v¡deo
void Bloque4P(int xi,int yi,int xf,int yf,int ancho,int alto,
BYTE *pantalla);
// Copia 64000 bytes en una de las 4 posiciones; zona:0=izq,arr;1=der,arr;
// 2=izq,abj;3=der,abj
void VolcarPantalla4P(char,BYTE *);
// Copia 64000 bytes en cualquier posici¢n dentro de los 640x400
void VolcarPantalla4PA(int,int,int,int,int,BYTE *);
//////////////////////
// VESA 640x480x256 //
//////////////////////
// Establece el modo de video de 640x480x256c VESA
void ModoVESA64x48(void);
// Cambia el banco de escritura dentro de la tarjeta de video
void CambiaBancoVESA(BYTE);
// Lee un fichero .PCX y lo segmenta en 4 partes de 65535 bytes y
// uno de 45060 bytes. Asigna la paleta al DAC de video
void LeePcx64x48(char [12],BYTE *,BYTE *,BYTE *,BYTE *,BYTE *);
// Lee un fichero .PCX y lo segmenta en 4 partes de 65535 bytes y
// uno de 45060 bytes. Almacena la paleta
void LeePcx64x48R(char [12],BYTE *,BYTE *,BYTE *,BYTE *,BYTE *,PALETA);
// Vuelca 307200 bytes divididos en 5 segmentos
void VuelcaPantalla64x48(BYTE *,BYTE *,BYTE *,BYTE *,BYTE *);
// Borra la pantalla con el color dado
void ClsPantalla64x48(BYTE);
GRAFICOS.C
#include "graficos.h"
/////////////////////
// TEXTO 80x25x16c //
/////////////////////
void ModoTexto(void)
{
asm{
mov al,TEXTO
xor ah,ah
int 0x10
}
}
void Humo(void)
{
char far *mem_video=(char far *)0xb8000000;
register char far *p;
int bandera=0;
do
{
bandera=0;
for (p=mem_video;p<mem_video+80*25*2;p++,p++)
{
if ((*p!=0) && (*p!=32))
{
(*p)++;
bandera=1;// A£n quedan caracteres
}
}
}
while (bandera);
}
///////////////////////
// MCGA 320x200x256c //
///////////////////////
void ModoMcga(void)
{
asm{
// Modo 13h
mov al,MCGA
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
}
}
void LeePcxMcga(char nombre[12],BYTE *pantalla)
{
register WORD cont,cont2;
BYTE *direscrt,byte,r,g,b,filas;
FILE *fichero;
fichero=fopen(nombre,"rb");
if (!fichero)
{
ModoTexto();
printf("\nNo se encuentra el fichero %s",nombre);
exit (0);
}
fseek(fichero,128,0);
direscrt=pantalla;
cont=64000;
while (cont>0)
{
byte=getc(fichero);
if (byte<=192)
{
*direscrt++=byte;
cont--;
}
else
{
cont2=byte&63;
byte=getc(fichero);
for(;cont2>0;cont2--)
{
*direscrt++=byte;
cont--;
}
}
}
getc(fichero);
for (cont2=0;cont2<256;cont2++)
{
r=getc(fichero)>>2;
g=getc(fichero)>>2;
b=getc(fichero)>>2;
Establecer1ColorPaleta(cont2,r,g,b);
}
fclose(fichero);
}
void LeePcxMcgaR(char nombre[12],BYTE *pantalla,PALETA paleta)
{
register WORD cont,cont2;
BYTE *direscrt,byte,r,g,b,filas;
FILE *fichero;
fichero=fopen(nombre,"rb");
if (!fichero)
{
ModoTexto();
printf("\nNo se encuentra el fichero %s",nombre);
exit (0);
}
fseek(fichero,128,0);
direscrt=pantalla;
cont=64000;
while (cont>0)
{
byte=getc(fichero);
if (byte<=192)
{
*direscrt++=byte;
cont--;
}
else
{
cont2=byte&63;
byte=getc(fichero);
for(;cont2>0;cont2--)
{
*direscrt++=byte;
cont--;
}
}
}
getc(fichero);
for (cont2=0;cont2<768;cont2++)
{
paleta[cont2]=getc(fichero)>>2;
}
fclose(fichero);
}
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
}
}
void Leer1ColorPaleta(BYTE color,BYTE *rojo,BYTE *verde,BYTE *azul)
{
BYTE rrojo,vverde,aazul;
asm{
mov dx,0x3c7
mov al,color
out dx,al
mov dx,0x3c9
in al,dx
mov rrojo,al
in al,dx
mov vverde,al
in al,dx
mov aazul,al
}
*rojo=rrojo;
*verde=vverde;
*azul=aazul;
}
void Establecer1ColorPaleta(BYTE color,BYTE rojo,BYTE verde,BYTE azul)
{
asm{
mov al,color
mov dx,0x3c8
out dx,al
mov al,rojo
mov dx,0x3c9
out dx,al
mov al,verde
mov dx,0x3c9
out dx,al
mov al,azul
mov dx,0x3c9
out dx,al
}
}
void EstablecerPaleta(PALETA paleta)
{
register int cont,cont2;
for (cont=0,cont2=0;cont<256;cont2+=3,cont++)
{
Establecer1ColorPaleta(cont,paleta[cont2],paleta[cont2+1],paleta[cont2+2]);
}
}
void PaletaNegra(void)
{
register int cont;
for (cont=0;cont<=255;cont++)
{
Establecer1ColorPaleta(cont,0,0,0);
}
}
void PaletaBlanca(void)
{
register int cont;
for (cont=0;cont<=255;cont++)
{
Establecer1ColorPaleta(cont,63,63,63);
}
}
void SalvarPaleta(PALETA paleta)
{
register int cont,cont2;
BYTE *rojo,*verde,*azul;
for (cont=0,cont2=0;cont<256;cont++,cont2+=3)
{
Leer1ColorPaleta(cont,rojo,verde,azul);
paleta[cont2]=*rojo;
paleta[cont2+1]=*verde;
paleta[cont2+2]=*azul;
}
}
void FiltroDePaleta(char valor)
{
register int cont,cont2;
BYTE r,g,b;
div_t division;
for (cont=0;cont<256;cont++)
{
Leer1ColorPaleta(cont,&r,&g,&b);
switch (valor)
{
case 1: // Paleta Roja
Establecer1ColorPaleta(cont,r,0,0);
break;
case 2: // Paleta Verde
Establecer1ColorPaleta(cont,0,g,0);
break;
case 3: // Paleta Azul
Establecer1ColorPaleta(cont,0,0,b);
break;
case 4: // Paleta Gris
cont2=r+g+b; division=div(cont2,3); cont2=division.quot;
Establecer1ColorPaleta(cont,cont2,cont2,cont2);
break;
case 5: // Paleta m s oscura
division=div(r,2); r=division.quot;
division=div(g,2); g=division.quot;
division=div(b,2); b=division.quot;
Establecer1ColorPaleta(cont,r,g,b);
break;
}
}
}
void RotarPaleta(BYTE velocidad)
{
WORD cont1,cont2;
BYTE cont3,r1,g1,b1,r2,g2,b2;
do
{
for(cont2=0;cont2<256;cont2++)
{
Leer1ColorPaleta(1,&r1,&g1,&b1);
for (cont1=1;cont1<255;cont1++)
{
Leer1ColorPaleta(cont1+1,&r2,&g2,&b2);
for (cont3=0;cont3<velocidad;cont3++)
{
Leer1ColorPaleta(cont1+1,&r2,&g2,&b2);
}
Establecer1ColorPaleta(cont1,r2,g2,b2);
}
Establecer1ColorPaleta(255,r1,g1,b1);
}
}
while(!kbhit());
}
void ApagarPaleta(PALETA paleta,BYTE retardo)
{
asm{
push ds
xor cx,cx
mov ah,retardo
}
SIGUE_APAGANDO:
asm{
mov dx,0x3C8
xor al,al
out dx,al
mov dx,0x3DA
}
ESPERA_FIN_RETR:
asm{
in al,dx
and al,0x8
jnz ESPERA_FIN_RETR
}
ESPERA_INI_RETR:
asm{
in al,dx
and al,0x8
jz ESPERA_INI_RETR
dec ah
jnz ESPERA_FIN_RETR
mov ah,retardo
mov dx,0x3c9
lds SI,paleta
}
OTRO_DAC:
asm{
mov al,[si]
sub al,ch
jge DEC_ROJO
xor al,al
}
DEC_ROJO:
asm{
out dx,al
mov al,[si+1]
sub al,ch
jge DEC_VERDE
xor al,al
}
DEC_VERDE:
asm{
out dx,al
mov al,[si+2]
sub al,ch
jge DEC_AZUL
xor al,al
}
DEC_AZUL:
asm{
out dx,al
add si,3
inc cl
jnz OTRO_DAC
inc ch
cmp ch,00111111b
jl SIGUE_APAGANDO
pop ds
}
}
void EncenderPaleta(PALETA paleta,BYTE retardo)
{
asm{
push ds
mov ah,retardo
mov ch,00111111b
xor cl,cl
}
SIGUE_ENCENDIEN:
asm{
mov dx,0x3C8
xor al,al
out dx,al
mov dx,0x3da
}
ESPERA_FIN_RET:
asm{
in al,dx
test al,00001000b
jnz ESPERA_FIN_RET
}
ESPERA_INI_RET:
asm{
in al,dx
test al,00001000b
jz ESPERA_INI_RET
dec ah
jnz ESPERA_FIN_RET
mov ah,retardo
mov dx,0x3c9
lds SI,paleta
}
OTR_DAC:
asm{
mov al,[si]
sub al,ch
jge INC_ROJO
xor al,al
}
INC_ROJO:
asm{
out dx,al
mov al,[si+1]
sub al,ch
jge INC_VERDE
xor al,al
}
INC_VERDE:
asm{
out dx,al
mov al,[si+2]
sub al,ch
jge INC_AZUL
xor al,al
}
INC_AZUL:
asm{
out dx,al
add si,3
dec cl
jnz OTR_DAC
cmp ch,00000000b
jz FIN_ENCENDER
dec ch
jmp SIGUE_ENCENDIEN
}
FIN_ENCENDER:
asm{
pop ds
}
}
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
}
}
BYTE LeerPixelMcga(int x,int y)
{
char color;
asm{
mov ax,0xA000
mov es,ax
/* Lo de abajo entre barras es lo mismo que esto. Hay que comprobar
*/
/* cu l v m s r pido */
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 bx,y
mov bh,bl
xor bl,bl
mov ax,y
mov ah,al
xor al,al
shr ax,2
add ax,bx
add ax,x
mov di,ax
*/
mov cl,es:[di]
mov color,cl
}
return(color);
}
BYTE LeerPixelMem(int x,int y,BYTE *pantalla)
{
int segmento,desplazamiento;
char color;
segmento=FP_SEG(pantalla);
desplazamiento=FP_OFF(pantalla);
asm{
mov ax,segmento
mov es,ax
mov bx,y
mov bh,bl
xor bl,bl
mov ax,y
mov ah,al
xor al,al
shr ax,2
add ax,bx
add ax,x
mov di,ax
add di,desplazamiento
mov cl,es:[di]
mov color,cl
}
return(color);
}
void VuelcaPantallaMcga(BYTE *pantalla)
{
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
}
}
void VuelcaMcgaPantalla(BYTE *pantalla)
{
int segmento,desplazamiento;
segmento=FP_SEG(pantalla);
desplazamiento=FP_OFF(pantalla);
asm{
push ds
mov ax,0xA000
mov es,segmento
mov ds,ax
mov di,desplazamiento
xor si,si
mov cx,32000
rep movsw
pop ds
}
}
void CopiaPantallaMem(BYTE *pantalla,BYTE *memoria)
{
int segmento1,desplazamiento1,segmento2,desplazamiento2;
segmento1=FP_SEG(pantalla);
segmento2=FP_SEG(memoria);
desplazamiento1=FP_OFF(pantalla);
desplazamiento2=FP_OFF(memoria);
asm{
push ds
mov es,segmento2
mov di,desplazamiento2
mov ds,segmento1
mov si,desplazamiento1
mov cx,32000
rep movsw
pop ds
}
}
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++;
}
}
}
}
void VolcarPantallaColor(BYTE color)
{
asm{
mov ax,0xA000
mov es,ax
xor di,di
mov al,color
mov ah,al
mov cx,32000
rep stosw
}
}
int Signo(float a)
{
if (a>0) {return (+1);}
if (a<0) {return (-1);}
if (a==0) {return (0);}
}
void Linea(int a,BYTE b,int c,BYTE d,BYTE color)
{
BYTE h,d1y,d2y;
register int i,s,m,n,u,d1x,d2x,v;
u=c-a;
v=d-b;
d1x=Signo(u);
d1y=Signo(v);
d2x=d1x;
d2y=0;
m=abs(u);
h=m;
n=abs(v);
if (!(m>n))
{
d2x=0;
d2y=d1y;
m=n;
n=h;
}
s=m>>2;
for (i=0;i<=m;i++)
{
asm{
mov ax,0xA000
mov es,ax
mov bx,a
xor dh,dh
mov dl,b
mov di,bx
mov bx,dx
shl dx,8
shl bx,6
add dx,bx
add di,dx
mov al,color
stosb
}
s=s+n;
if (!(s<m))
{
s=s-m;
a=a+d1x;
b=b+d1y;
}
else
{
a=a+d2x;
b=b+d2y;
}
}
}
void BloqueMem(int xi,int yi,int xf,int yf,int ancho,int alto,
BYTE *pantalla,BYTE *memoria)
{
int segmento1,desplazamiento1,segmento2,desplazamiento2;
segmento1=FP_SEG(pantalla);
segmento2=FP_SEG(memoria);
desplazamiento1=FP_OFF(pantalla);
desplazamiento2=FP_OFF(memoria);
asm{
push ds
mov es,segmento2
mov di,desplazamiento2
mov dx,yf
add di,xf
mov bx,dx
shl dx,8
shl bx,6
add dx,bx
add di,dx
mov ds,segmento1
mov si,desplazamiento1
mov dx,yi
add si,xi
mov bx,dx
shl dx,8
shl bx,6
add dx,bx
add si,dx
mov ax,ancho
mov dx,320
sub dx,ax
shr ax,1
mov bx,alto
}
salto:
asm{
mov cx,ax
rep movsw
add si,dx
add di,dx
dec bx
jnz salto
pop ds
}
}
void SpriteMem(int xi,int yi,int xf,int yf,int ancho,int alto,
BYTE *pantalla,BYTE *memoria)
{
int segmento1,desplazamiento1,segmento2,desplazamiento2;
segmento1=FP_SEG(pantalla);
segmento2=FP_SEG(memoria);
desplazamiento1=FP_OFF(pantalla);
desplazamiento2=FP_OFF(memoria);
asm{
push bp
push ds
mov es,segmento2
mov di,desplazamiento2
mov dx,yf
add di,xf
mov bx,dx
shl dx,8
shl bx,6
add dx,bx
add di,dx
mov ds,segmento1
mov si,desplazamiento1
mov dx,yi
add si,xi
mov bx,dx
shl dx,8
shl bx,6
add dx,bx
add si,dx
mov ax,ancho
mov dx,320
sub dx,ax
mov bp,alto
}
salto:
asm{
mov cx,ax
}
salto2:
asm{
mov bl,ds:[si]
cmp bl,0
jz salto5
movsb
jmp salto3
}
salto5:
asm{
inc si
inc di
}
salto3:
asm{
dec cx
jnz salto2
add si,dx
add di,dx
dec bp
jnz salto
pop ds
pop bp
}
}
void BloqueMcga(int xi,int yi,int xf,int yf,int ancho,int alto,
BYTE *pantalla)
{
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
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
mov ax,ancho
mov dx,320
sub dx,ax
shr ax,1
mov bx,alto
}
salto:
asm{
mov cx,ax
rep movsw
add si,dx
add di,dx
dec bx
jnz salto
pop ds
}
}
void SpriteMcga(int xi,int yi,int xf,int yf,int ancho,int alto,
BYTE *pantalla)
{
int segmento,desplazamiento;
segmento=FP_SEG(pantalla);
desplazamiento=FP_OFF(pantalla);
asm{
push bp
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
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
mov ax,ancho
mov dx,320
sub dx,ax
mov bp,alto
}
salto:
asm{
mov cx,ax
}
salto2:
asm{
mov bl,ds:[si]
cmp bl,0
jz salto5
movsb
jmp salto3
}
salto5:
asm{
inc si
inc di
}
salto3:
asm{
dec cx
jnz salto2
add si,dx
add di,dx
dec bp
jnz salto
pop ds
pop bp
}
}
void VerFLIMcga(char fichero[12],int retardo,BYTE *pant)
{
register WORD pixel,vc;
int segmento,desplazamiento;
FILE *fli;
CABECERA_FLI hdr;
CABECERA_FRAME frm;
unsigned long size;
WORD type,pakets,cnt,lines,change,i,c,f,cont,cont2;
BYTE skip,v,*aux,rojo,verde,azul;
signed char s;
clock_t tiks;
PALETA paleta;
// Apertura del fichero
fli=fopen(fichero,"rb");
if (!fli)
{
ModoTexto();
printf("\nNo se encuentra el fichero %s",fichero);
exit (0);
}
// M ximo buffer para dar velocidad en la carga del fichero
setvbuf(fli,VBuf,_IOFBF,BUFSIZE);
// Lectura de la cabeza
fread(&hdr,sizeof(CABECERA_FLI),1,fli);
// Para cada frame...
for (f=0;f<hdr.frames;f++)
{
tiks=clock();
// Lee una cabecera de frame
fread(&frm,sizeof(CABECERA_FRAME),1,fli);
if (frm.size!=0L)
for (i=0;i<frm.chunks;i++)
{
// Cabecera del chunk
fread(&size,sizeof(long),1,fli);
type=getw(fli);
// Dependiendo del tipo del frame
switch (type)
{
// L¡nea comprimida
case FLI_LC:
// N£mero de l¡neas que son iguales al frame
anterior
lines=getw(fli);
// N£mero de l¡neas que han cambiado
change=getw(fli);
// Pasado a ensamblador: cont=(256*lines+64*lines) ==
320*lines
asm{
mov vc,4
mov ax,lines
mov bx,ax
shl ax,8
shl bx,6
add ax,bx
mov cont,ax
}
cont2=cont;
for(c=0;c<change;c++)
{
pakets=getc(fli);
asm{
inc vc
}
while (pakets>0)
{
skip=getc(fli);
asm{
dec pakets
inc vc
xor ah,ah
mov al,skip
add cont,ax
inc vc
}
s=getc(fli);
if (s>0)
{
asm{
xor ah,ah
mov al,s
add vc,ax
}
salto:
rojo=getc(fli);
asm{
mov ax,0xA000
mov es,ax
mov di,cont
mov al,rojo
stosb
inc cont
dec s
jnz salto
}
}
else
{
s=-s;
v=getc(fli);
asm{
inc vc
xor ch,ch
mov cl,s
mov ax,0xA000
mov es,ax
mov di,cont
mov al,v
rep stosb
xor ah,ah
mov al,s
add cont,ax
}
}
}
asm{
add cont2,320
}
cont=cont2;
}
// Si ha habido un n£mero impar de bytes, se lee
el de relleno
if (vc&1) getc(fli);
break;
case FLI_BRUN:
// Para contar el n£mero de bytes descomprimidos
asm{
mov vc,0
mov cont,0
}
// Compresi¢n l¡nea por l¡nea
for (skip=0;skip<200;skip++)
{
// N£mero de paquetes en la l¡nea
pakets=getc(fli);
asm{
inc vc
}
while (pakets>0)
{
// N£mero de veces que se repite un byte
s=getc(fli);
asm{
inc vc
dec pakets
}
// Si s es negativo, el n£mero de bytes es -s y
est n en
// los siguientes s bytes: no est comprimido
if (s<0)
{
s=-s;
asm{
xor ah,ah
mov al,s
add vc,ax
}
salto1:
rojo=getc(fli);
asm{
mov ax,0xA000
mov es,ax
mov di,cont
mov al,rojo
stosb
inc cont
dec s
jnz salto1
}
}
// Si es positivo, se repite el siguiente byte s veces:
// est comprimido
else
{
v=getc(fli);
asm{
inc vc
mov ax,0xA000
mov es,ax
mov ax,cont
mov di,ax
mov al,v
mov cl,s
xor ch,ch
rep stosb
xor ah,ah
mov al,s
add cont,ax
}
}
}
}
// Si se han obtenido un n£mero inpar de bytes,
entonces falta
// otro byte que es de relleno
if (vc&1) getc(fli);
break;
// Cambiar un n£mero determinado de colores
case FLI_COLOR:
// N£mero de paquetes comprimidos
pakets=getw(fli);
asm{
mov vc,2
mov c,0
}
while (pakets--)
{
// Cu ntos colores se saltan
skip=getc(fli);
asm{
inc vc
// Cada 3 bytes representa 1 color: rojo, verde y azul,
por lo
// que se saltar n 3*n£mero de colores bytes
mov al,skip
xor ah,ah
mov cl,3
mul cl
add c,ax
inc vc
}
// Cu ntos colores se cambian
cnt=getc(fli);
// Si es 0, se interpreta como 256, de 0 a 255 colores a cambiar
if (cnt==0)
asm{
mov cnt,256
}
while (cnt--)
{
// Se asignan los valores RGB de cada color a la paleta
paleta[c]=getc(fli);
asm{
inc c
}
paleta[c]=getc(fli);
asm{
inc c
}
paleta[c]=getc(fli);
asm{
inc c
add vc,3
}
}
}
// Se hace efectivo el cambio de paleta
for (lines=0,change=0;lines<256;change+=3,lines++)
{
rojo=paleta[change];
verde=paleta[change+1];
azul=paleta[change+2];
asm{
mov ax,lines
mov dx,0x3c8
out dx,al
mov al,rojo
mov dx,0x3c9
out dx,al
mov al,verde
out dx,al
mov al,azul
out dx,al
}
}
// Si ha habido un n£mero impar de bytes, se lee el de
relleno
if (vc&1) getc(fli);
break;
// 64000 bytes sin comprimir
case FLI_COPY:
aux=pant;
// Se leen los 64000 p¡xeles de la pantalla
for (pixel=0;pixel<64000;pixel++) *aux++=getc(fli);
// Se vuelcan de una vez
segmento=FP_SEG(pant);
desplazamiento=FP_OFF(pant);
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
}
// Aqu¡ no hay comprobaci¢n del n£mero
de vc, 64000 es par
break;
// Cls a negro
case FLI_BLACK:
asm{
mov ax,0xA000
mov es,ax
xor di,di
xor ax,ax
mov cx,32000
rep stosw
}
break;
// Si no se reconoce se intenta avanzar hasta algo conocido
default:
ModoTexto();
printf("\nVersi¢n incorrecta de archivo FLI");
exit (0);
}
}
// Espera hasta el n£mero especificado de ticks del reloj
while (clock()-tiks<retardo);
}
fclose(fli);
}
void ReducePantalla(BYTE *origen,BYTE *destino,int orgx,int orgy,int
destx,
int desty,int destancho,int
destalto,int factor)
{
asm{
push ds
mov ax,orgy
mov dx,320
mul dx
add ax,word ptr orgx
add word ptr origen,ax
mov ax,desty
mov dx,320
mul dx
add ax,word ptr destx
add word ptr destino,ax
lds si,origen
les di,destino
mov cx,destancho
mov dx,destalto
cld
}
REDUCE_MAS:
asm{
push cx
push si
push di
}
REDUCE_LINE:
asm{
mov al,[si]
mov es:[di],al
add si,factor
inc di
loop REDUCE_LINE
pop di
pop si
mov cx,factor
}
REDUCELO:
asm{
add si,320
loop REDUCELO
add di,320
pop cx
dec dx
jnz REDUCE_MAS
pop ds
}
}
//////////////////////////////
// 4 PLANOS 320x200x256 x 4 //
//////////////////////////////
void ModoGraficoMcga4P(void)
{
asm {
mov ax,0x13
int 0x10
mov dx,0x3c4
mov ax,0x404
out dx,ax
mov dx,0x3d4
mov ax,0x014
out dx,ax
mov ax,0xc317
out dx,ax
mov ah,80
mov al,0x13
out dx,ax
}
PaletaNegra();
VolcarColor4P(0);
}
void PosicionVentana4P(int x,int y)
{
unsigned long offset;
offset=(long)ANCHO_BUFFER*(long)y+(long)x;
outportb(0x3d4,0x0d);
outportb(0x3d5,offset>>2);
outportb(0x3d4,0x0c);
outportb(0x3d5,offset>>10);
outportb(0x3c0,0x13|0x20);
outportb(0x3c0,(offset&3)<<1);
}
void VolcarColor4P(BYTE color)
{
register unsigned long i;
asm{
mov al,0x2
mov dx,0x3c4
out dx,al
}
for (i=0;i<65536L;i++)
{
asm{
mov al,15
mov dx,0x3c5
out dx,al
}
*((BYTE *)MK_FP(SEG_VGA,i))=color;
}
}
void PonerPixelMcga4P(int x,int y,char color)
{
BYTE desp;
desp=0x1<<(x&3);
asm{
mov al,0x2
mov dx,0x3c4
out dx,al
inc dx
mov al,desp
out dx,al
mov ax,SEG_VGA
mov es,ax
mov bx,x
shr bx,2
mov di,bx
mov dx,y
mov bx,dx
shl bx,7
shl dx,5
add dx,bx
add di,dx
mov al,color
stosb
}
}
BYTE LeerPixelMcga4P(int x,int y)
{
BYTE desp,color;
desp=x&3;
asm{
mov al,0x4
mov dx,0x3ce
out dx,al
inc dx
mov al,desp
out dx,al
mov ax,SEG_VGA
mov es,ax
mov bx,x
shr bx,2
mov di,bx
mov dx,y
mov bx,dx
shl bx,7
shl dx,5
add dx,bx
add di,dx
mov cl,es:[di]
mov color,cl
}
return (color);
}
void Bloque4P(int xi,int yi,int xf,int yf,int ancho,int alto,BYTE *pantalla)
{
BYTE *puntero,color,desp;
register int x,y;
int xfi,yfi,desplaza;
xfi=xf+ancho;
yfi=yf+alto;
desplaza=320-ancho;
puntero=pantalla;
puntero+=320*yi+xi;
for (y=yf;y<yfi;y++)
{
for (x=xf;x<xfi;x++)
{
color=*puntero;
desp=0x1<<(x&3);
asm{
mov al,0x2
mov dx,0x3c4
out dx,al
inc dx
mov al,desp
out dx,al
mov ax,SEG_VGA
mov es,ax
mov bx,x
shr bx,2
mov di,bx
mov dx,y
mov bx,dx
shl bx,7
shl dx,5
add dx,bx
add di,dx
mov al,color
stosb
}
puntero++;
}
puntero+=desplaza;
}
}
void VolcarPantalla4P(char zona,BYTE *pantalla)
{
BYTE *color,desp,col;
register int cont,cont2,cont3,salto,incre;
switch (zona)
{
case 0:salto=0;incre=80;break;
case 1:salto=80;incre=160;break;
case 2:salto=32000;incre=32080;break;
case 3:salto=32080;incre=32160;break;
}
color=pantalla;
cont2=salto;
cont3=incre;
desp=0x01;
asm{
mov al,0x2
mov dx,0x3c4
out dx,al
inc dx
mov al,desp
out dx,al
}
for (cont=0;cont<16000;cont++)
{
if ((cont3-cont2)==0)
{
cont3+=160;
cont2+=80;
}
col=*color;
asm{
mov ax,SEG_VGA
mov es,ax
mov di,cont2
mov al,col
stosb
}
cont2++;
color+=4;
}
desp=0x01<<1;
asm{
mov al,0x2
mov dx,0x3c4
out dx,al
inc dx
mov al,desp
out dx,al
}
cont2=salto;
cont3=incre;
color=pantalla;
color++;
for (cont=0;cont<16000;cont++)
{
if ((cont3-cont2)==0)
{
cont3+=160;
cont2+=80;
}
col=*color;
asm{
mov ax,SEG_VGA
mov es,ax
mov di,cont2
mov al,col
stosb
}
cont2++;
color+=4;
}
desp=0x01<<2;
asm{
mov al,0x2
mov dx,0x3c4
out dx,al
inc dx
mov al,desp
out dx,al
}
cont2=salto;
cont3=incre;
color=pantalla;
color+=2;
for (cont=0;cont<16000;cont++)
{
if ((cont3-cont2)==0)
{
cont3+=160;
cont2+=80;
}
col=*color;
asm{
mov ax,SEG_VGA
mov es,ax
mov di,cont2
mov al,col
stosb
}
cont2++;
color+=4;
}
desp=0x01<<3;
asm{
mov al,0x2
mov dx,0x3c4
out dx,al
inc dx
mov al,desp
out dx,al
}
cont2=salto;
cont3=incre;
color=pantalla;
color+=3;
for (cont=0;cont<16000;cont++)
{
if ((cont3-cont2)==0)
{
cont3+=160;
cont2+=80;
}
col=*color;
asm{
mov ax,SEG_VGA
mov es,ax
mov di,cont2
mov al,col
stosb
}
cont2++;
color+=4;
}
}
// Avance indica
void VolcarPantalla4PA(int avance,int x0,int y0,int tamx,int tamy,
BYTE *pantalla)
{
BYTE *puntero,color,desp;
int x,y,xf,yf;
char far *punto;
xf=x0+tamx;
yf=y0+tamy;
puntero=pantalla;
puntero+=avance*320;
for (y=y0;y<yf;y++)
{
for (x=x0;x<xf;x++)
{
color=*puntero;
desp=0x1<<(x&3);
asm{
mov al,0x2
mov dx,0x3c4
out dx,al
inc dx
mov al,desp
out dx,al
mov ax,SEG_VGA
mov es,ax
mov bx,x
shr bx,2
mov di,bx
mov dx,y
mov bx,dx
shl bx,7
shl dx,5
add dx,bx
add di,dx
mov al,color
stosb
}
puntero++;
}
}
}
//////////////////////
// VESA 640x480x256 //
//////////////////////
void ModoVESA64x48(void)
{
asm{
mov ah,0x4f
mov al,0x2
mov bx,0x101
int 0x10
}
}
void CambiaBancoVESA(BYTE banco)
{
asm{
mov ah,0x4f
mov al,0x5
xor bx,bx
xor dh,dh
mov dl,banco
int 0x10
}
}
void LeePcx64x48(char nombre[12],BYTE *p1,BYTE *p2,BYTE *p3,BYTE *p4,
BYTE *p5)
{
register unsigned long total;
register BYTE byte,contador;
BYTE r,g,b;
int cont;
FILE *fichero;
BYTE *aux,*aux2,*aux3,*aux4,*aux5;
fichero=fopen(nombre,"rb");
if (!fichero)
{
ModoTexto();
printf("\nNo se encuentra el fichero %s",nombre);
exit (0);
}
// Salta la cabecera de 128 bytes
fseek(fichero,128,0);
// Punteros auxiliares que apuntan a las cinco zonas de memoria
en donde
// se almacenara el fichero
aux=p1;
aux2=p2;
aux3=p3;
aux4=p4;
aux5=p5;
// 640 x 480 = 307200 bytes
total=307200;
while (total>0)
{
byte=getc(fichero);
// Si no indica comprimido
if(byte<=0xC0)
{
// En cada zona de memoria se almacenar n 65535 bytes,
menos en la £ltima,
// en la que se almacenar n 45060 bytes
if(total>241665)
{
*aux++=byte;
}
else if (total>176130)
{
*aux2++=byte;
}
else if (total>110595)
{
*aux3++=byte;
}
else if (total>45060)
{
*aux4++=byte;
}
else *aux5++=byte;
total--;
}
// Si indica comprimido
else
{
contador=byte&0x3F;
byte=getc(fichero);
for(;contador>0;contador--)
{
// Igual al anterior caso
if(total>241665)
{
*aux++=byte;
}
else if (total>176130)
{
*aux2++=byte;
}
else if (total>110595)
{
*aux3++=byte;
}
else if (total>45060)
{
*aux4++=byte;
}
else *aux5++=byte;
total--;
}
}
}
// Salta la indicaci¢n de separaci¢n entre pixels
y paleta
getc(fichero);
// Asigna la paleta al DAC de video
for(cont=0;cont<256;cont++)
{
r=getc(fichero)>>2;
g=getc(fichero)>>2;
b=getc(fichero)>>2;
Establecer1ColorPaleta(cont,r,g,b);
}
fclose(fichero);
}
void LeePcx64x48R(char nombre[12],BYTE *p1,BYTE *p2,BYTE *p3,BYTE *p4,
BYTE *p5,PALETA paleta)
{
register unsigned long total;
register BYTE byte,contador;
BYTE r,g,b;
int cont;
FILE *fichero;
BYTE *aux,*aux2,*aux3,*aux4,*aux5;
fichero=fopen(nombre,"rb");
if (!fichero)
{
ModoTexto();
printf("\nNo se encuentra el fichero %s",nombre);
exit (0);
}
// Salta la cabecera de 128 bytes
fseek(fichero,128,0);
// Punteros auxiliares que apuntan a las cinco zonas de memoria
en donde
// se almacenara el fichero
aux=p1;
aux2=p2;
aux3=p3;
aux4=p4;
aux5=p5;
// 640 x 480 = 307200 bytes
total=307200;
while (total>0)
{
byte=getc(fichero);
// Si no indica comprimido
if(byte<=0xC0)
{
// En cada zona de memoria se almacenar n 65535 bytes,
menos en la £ltima,
// en la que se almacenar n 45060 bytes
if(total>241665)
{
*aux++=byte;
}
else if (total>176130)
{
*aux2++=byte;
}
else if (total>110595)
{
*aux3++=byte;
}
else if (total>45060)
{
*aux4++=byte;
}
else *aux5++=byte;
total--;
}
// Si indica comprimido
else
{
contador=byte&0x3F;
byte=getc(fichero);
for(;contador>0;contador--)
{
// Igual al anterior caso
if(total>241665)
{
*aux++=byte;
}
else if (total>176130)
{
*aux2++=byte;
}
else if (total>110595)
{
*aux3++=byte;
}
else if (total>45060)
{
*aux4++=byte;
}
else *aux5++=byte;
total--;
}
}
}
// Salta la indicaci¢n de separaci¢n entre pixels
y paleta
getc(fichero);
// Asigna la paleta a la variable de tipo PALETA
for (cont=0;cont<768;cont++)
{
paleta[cont]=getc(fichero)>>2;
}
fclose(fichero);
}
void VuelcaPantalla64x48(BYTE *banco0,BYTE *banco1,BYTE *banco2,
BYTE *banco3,BYTE
*banco4)
{
register int segmento0,segmento1,segmento2,segmento3,segmento4;
register int desplaza0,desplaza1,desplaza2,desplaza3,desplaza4;
segmento0=FP_SEG(banco0);
desplaza0=FP_OFF(banco0);
segmento1=FP_SEG(banco1);
desplaza1=FP_OFF(banco1);
segmento2=FP_SEG(banco2);
desplaza2=FP_OFF(banco2);
segmento3=FP_SEG(banco3);
desplaza3=FP_OFF(banco3);
segmento4=FP_SEG(banco4);
desplaza4=FP_OFF(banco4);
asm{
push ds
mov ds,segmento0
mov si,desplaza0
// Cambio de banco=0
mov ah,0x4f
mov al,0x5
xor bx,bx
xor dh,dh
mov dl,0
int 0x10
// Destino: la memoria buffer a la que accede la tarjeta:A000h
mov ax,0xA000
mov es,ax
xor di,di
// 65534 veces [ds:si]->[es:di]. 65534 bytes = 32767 words
mov cx,32767
rep movsw
// El byte que falta de los 1§s 65535. 1 vez [ds:si]->[es:di]
movsb
// Primer byte de la segunda zona de memoria y que completan
// los 65536 bytes -> 64 kbytes asignables al primer banco de
la Svga
mov ds,segmento1
mov si,desplaza1
movsb
// Cambio al banco 1
mov ah,0x4f
mov al,0x5
xor bx,bx
xor dh,dh
mov dl,1
int 0x10
// Destino, buffer de video
mov ax,0xA000
mov es,ax
xor di,di
// Forzar posici¢n par en memoria
movsb
// 65532 veces lo mismo que antes
mov cx,32766
rep movsw
movsb
// Ahora el desfase es de 2 bytes y se ir incrementando
en 1
mov ds,segmento2
mov si,desplaza2
movsw
// Cambio al banco 2
mov ah,0x4f
mov al,0x5
xor bx,bx
xor dh,dh
mov dl,2
int 0x10
// Y vuelta a empezar con la siguiente zona de memoria
mov ax,0xA000
mov es,ax
xor di,di
// 65532 veces lo mismo que antes
mov cx,32766
rep movsw
// Byte que falta: 32766 words + 1 byte = 65533
movsb
// Desfase= 3 bytes
mov ds,segmento3
mov si,desplaza3
movsw
movsb
// Cambio al banco 3
mov ah,0x4f
mov al,0x5
xor bx,bx
xor dh,dh
mov dl,3
int 0x10
// Siguiente zona de memoria
mov ax,0xA000
mov es,ax
xor di,di
// Forzar posici¢n par en memoria
movsb
// 65530 veces lo mismo que antes
mov cx,32765
rep movsw
movsb
// Desfase= 4 bytes
mov ds,segmento4
mov si,desplaza4
movsw
movsw
// Cambio al banco 4
mov ah,0x4f
mov al,0x5
xor bx,bx
xor dh,dh
mov dl,4
int 0x10
// Siguiente zona de memoria y ultima
mov ax,0xA000
mov es,ax
xor di,di
// 45056 veces lo mismo que antes 22528
mov cx,22528
rep movsw
pop ds
}
}
void ClsPantalla64x48(BYTE color)
{
asm{
push ds
// Cambio de banco=0
mov ah,0x4f
mov al,0x5
xor bx,bx
xor dh,dh
mov dl,0
int 0x10
// Destino: la memoria buffer a la que accede la tarjeta:A000h
mov ax,0xA000
mov es,ax
xor di,di
mov al,color
mov ah,al
mov cx,32768
rep stosw
// Cambio de banco=1
mov ah,0x4f
mov al,0x5
xor bx,bx
xor dh,dh
mov dl,1
int 0x10
// Destino: la memoria buffer a la que accede la tarjeta:A000h
mov ax,0xA000
mov es,ax
xor di,di
mov al,color
mov ah,al
mov cx,32768
rep stosw
// Cambio de banco=2
mov ah,0x4f
mov al,0x5
xor bx,bx
xor dh,dh
mov dl,2
int 0x10
// Destino: la memoria buffer a la que accede la tarjeta:A000h
mov ax,0xA000
mov es,ax
xor di,di
mov al,color
mov ah,al
mov cx,32768
rep stosw
// Cambio de banco=3
mov ah,0x4f
mov al,0x5
xor bx,bx
xor dh,dh
mov dl,3
int 0x10
// Destino: la memoria buffer a la que accede la tarjeta:A000h
mov ax,0xA000
mov es,ax
xor di,di
mov al,color
mov ah,al
mov cx,32768
rep stosw
// Cambio de banco=4
mov ah,0x4f
mov al,0x5
xor bx,bx
xor dh,dh
mov dl,4
int 0x10
// Destino: la memoria buffer a la que accede la tarjeta:A000h
mov ax,0xA000
mov es,ax
xor di,di
mov al,color
mov ah,al
mov cx,32768
rep stosw
// Cambio de banco=5
mov ah,0x4f
mov al,0x5
xor bx,bx
xor dh,dh
mov dl,5
int 0x10
// Destino: la memoria buffer a la que accede la tarjeta:A000h
mov ax,0xA000
mov es,ax
xor di,di
mov al,color
mov ah,al
// 45056 veces lo mismo que antes 22528
mov cx,22528
rep movsw
pop ds
}
}