Aula Macedonia


Curso de Programación Multimedia Bajo DOS


Artículo realizado por
José Antonio Suárez.





Código fuente para los capítulos 3,4,5,6,7,8 y 9.


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
 }
}
 




AULA MACEDONIA
a
MACEDONIA Magazine