AnteriorPosterior

Ampliación 2. Gráficos sin BGI.

  Curso: Curso de Pascal, por Nacho Cabanes

Curso de Pascal. Ampliación 2: Gráficos sin BGI.

Habíamos comentado cómo crear gráficos mediante los driversBGI que distribuye Borland.  Estos tienen como principal ventaja la gran cantidad de funciones y procedimientos que ponen a nuestra disposición.

Pero también tienen inconvenientes, principalmente dos:

  • Es incómodo tener que depender siempre de los ficheros BGI, bien por tenerlos junto a nuestros ejecutables, o bien por tener que enlazarlos con ellos.
  • No son muy rápidos.


Podemos saltarnos estos dos inconvenientes, accediendo nosotros mismos a la pantalla gráfica.  Lo haremos de dos formas: a través de la BIOS o manejando directamente la memoria de video.
 

1. A través de la Bios.


Una guía de referencia muy buena para todos aquellos que quieren programar el PC a un nivel algo más bajo del habitual (más cercano a la máquina) es la lista de interrupciones recopilada por Ralf Brown.  En ella encontramos lo siguiente:
 

 Interrupt List    Release 41        Last change 6/5/94
 This compilation is Copyright (c) 1989,1990,1991,1992,1993,1994 Ralf Brown
 [...]
 INT 10 - VIDEO - SET VIDEO MODE
    AH = 00h
    AL = mode (see #0009)

 y la lista de modos (muy resumida, dejando sólo las más habituales de las más de 600 líneas que aparecen en esta recopilación):

 Values for video mode:
      text/ text   pixel   pixel colors   disply scrn  system
      grph resol    box  resolution       pages  addr
  00h = T  40x25    8x8   320x200 16gray     8   B800 CGA
      = T  40x25    8x14  320x350 16gray     8   B800 EGA
      = T  40x25    8x16  320x400  16        8   B800 MCGA
      = T  40x25    9x16  360x400  16        8   B800 VGA
  01h = T  40x25    8x8   320x200  16        8   B800 CGA
      = T  40x25    8x14  320x350  16        8   B800 EGA
      = T  40x25    8x16  320x400  16        8   B800 MCGA
      = T  40x25    9x16  360x400  16        8   B800 VGA
  02h = T  80x25    8x8   640x200 16gray     4   B800 CGA
      = T  80x25    8x14  640x350 16gray     8   B800 EGA
      = T  80x25    8x16  640x400  16        8   B800 MCGA
      = T  80x25    9x16  720x400  16        8   B800 VGA
  03h = T  80x25    8x8   640x200  16        4   B800 CGAy
      = T  80x25    8x14  640x350  16/64     8   B800 EGA
      = T  80x25    8x16  640x400  16        8   B800 MCGA
      = T  80x25    9x16  720x400  16        8   B800 VGA
  04h = G  40x25    8x8   320x200   4     .   B800 CGA,EGA,MCGA,VGA
  05h = G  40x25    8x8   320x200  4gray  .   B800 CGA,EGA
      = G  40x25    8x8   320x200   4     .   B800 MCGA,VGA
  06h = G  80x25    8x8   640x200   2     .   B800 CGA,EGA,MCGA,VGA
  07h = T  80x25    9x14  720x350 mono   var  B000 MDA,Hercules,EGA
      = T  80x25    9x16  720x400 mono    .   B000 VGA
  0Dh = G  40x25    8x8   320x200  16     8   A000 EGA,VGA
  0Eh = G  80x25    8x8   640x200  16     4   A000 EGA,VGA
  0Fh = G  80x25    8x14  640x350 mono    2   A000 EGA,VGA
  10h = G  80x25    8x14  640x350   4     2   A000 64k EGA
      = G    .       .    640x350  16     .   A000 256k EGA,VGA
  11h = G  80x30    8x16  640x480 mono    .   A000 VGA,MCGA
  12h = G  80x30    8x16  640x480  16/256K.   A000 VGA
  13h = G  40x25    8x8   320x200 256/256K.   A000 VGA,MCGA

Es decir: para cambiar al modo 640x480 con 16 colores, tendremos que hacer:

 AH = 00   (Función de elegir el modo de pantalla)
 AL = 12h  (Modo 640x480x16, VGA)
 INT 10h   (Interrupción de video)

 Antes de ver meternos con el Pascal, vamos a ver cómo dibujar un punto:

 INT 10 - VIDEO - WRITE GRAPHICS PIXEL
    AH = 0Ch
    BH = page number
    AL = pixel color (if bit 7 set, value is xor'ed onto screen)
    CX = column
    DX = row
 Desc: set a single pixel on the display in graphics modes
 Notes:   valid only in graphics modes
    BH is ignored if the current video mode supports only one page

 y también podemos leer el color de un pixel con

 INT 10 - VIDEO - READ GRAPHICS PIXEL
    AH = 0Dh
    BH = page number
    CX = column
    DX = row
 Return: AL = pixel color
 Desc: determine the current color of the specified pixel in grahics modes
 Notes:   valid only in graphics modes
    BH is ignored if the current video mode supports only one page
 

Bueno, ya vale de parrafadas en inglés y vamos a empezar a aplicarlo. Hagamos un programa que dibuje puntos en la pantalla en modo 640x480x16:

 {--------------------------} 
 {  Ejemplo en Pascal:      } 
 {                          } 
 {    Gráficos mediante los } 
 {    servicios de la BIOS: } 
 {    640x480, 16 colores   } 
 {    GRB1.PAS              } 
 {                          } 
 {  Este fuente procede de  } 
 {  CUPAS, curso de Pascal  } 
 {  por Nacho Cabanes       } 
 {                          } 
 {  Comprobado con:         } 
 {    - Turbo Pascal 7.0    } 
 {    - Tmt Pascal Lt 1.00  } 
 {--------------------------} 
 
 program GrB1;  { Gráficos a través de la BIOS - 1 } 
 
 uses dos;                     { Usaremos interrupciones } 
 
 const NumPuntos = 10000;       { Número de puntos que dibujaremos } 
 
 var 
   regs: registers;            { Para acceder a los registros, claro } 
   bucle: word;                { Para bucles, claro } 
 
 procedure Modo640x480x16;     { Cambia a modo gráfico } 
 begin 
   regs.ah := 0;               { Función 0 } 
   regs.al := $12;             { El modo es el 12h = 18 } 
   intr($10,regs);             { Interrupción de video } 
 end;
 
 procedure ModoTexto;          { A modo texto, similar } 
 begin 
   regs.ah := 0; 
   regs.al := 3; 
   intr($10,regs); 
 end;
 
 procedure PonPixel(x,y: word; color: byte);      { Dibuja Pixel } 
 begin 
   regs.ah := $0c;             { Función 0Ch } 
   regs.bh := 0;               { Página 0 } 
   regs.al := color;           { Color } 
   regs.cx := x;               { Columna } 
   regs.dx := y;               { Fila } 
   intr($10,regs); 
 end;
 
 begin 
   Modo640x480x16; 
   for bucle := 1 to NumPuntos do 
     PonPixel( random(639), random(479), random(15) );  { Puntos 
                                                       aleatorios} 
   readln; 
   ModoTexto; 
 end.
 

Hemos conseguido un programa que dibuja puntos sin necesidad de los BGI. El EXE resultante ocupa escasamente 2.5K (compilado con TP7).

Si lo compilamos con TMT Pascal Lite, el tamaño sube hasta los 18K, pero es porque este compilador incluye mayor información adicional, para que el fichero .EXE trabaje en modo protegido del 386 (aprovechando toda la memoria de nuestro ordenador, etc).  Por cierto, la línea del "uses", si se compila con TMT, deberá ser:

   uses dos, use32;

Pero esto que hemos hecho también es mejorable: llamar a esa interrupción cada vez que queramos dibujar un punto resulta lento, especialmente cuando queramos dibujar líneas o rellenar zonas.  La forma más rápida, al menos en ciertos modos gráficos, o si se programa con cuidado, es acceder directamente a la memoria de video.
 

Actualizado el: 22-06-2009 02:04

AnteriorPosterior