www.delorie.com/djgpp/doc/ug/graphics/vga.html   search  
Guía: Gráficos VGA en modo 13h

Uno de los modos gráficos más usados, y ciertamente el más fácil de programar, es el modo VGA 13h. Éste tiene un tamaño de 320x200, puede desplegar un máximo de 256 colores a la vez y funcionará en cualquier tarjeta gráfica compatible VGA(no es soportada por las tarhetas EGA o CGA, pero muy poca gente está ejecutando djgpp en hardware tan viejo :-)

El primer paso es seleccionar éste modo, lo que se hace llamando la interrupción 0x10 de la BIOS VGA, eg:

   #include <dpmi.h>

   void set_mode_13h()
   {
      __dpmi_regs r;

      r.x.ax = 0x13;
      __dpmi_int(0x10, &r);
   }

La parte importante aquí es el número 0x13, que se pone en el registro AX antes de llamara a la función de la BIOS. Este valor especifica qué modo quiere escoger: no hay premios por adivinar de dónde viene el nombre "modo 13h"!

Antes de finalizar su programa, debería por supuesto regresar al modo texto normal de DOS, lo que se puede hacer en la misma forma que lo hicimos antes, pero escogiendo 3 como el número del modo, por ejemplo:

   void return_to_text_mode()
   {
      __dpmi_regs r;

      r.x.ax = 3;
      __dpmi_int(0x10, &r);
   }

Luego de escojer el modo de vídeo, el siguiente paso es dibujar algo en la pantalla. La memoria VGA está localizada en la dirección física 0xA0000, por lo que necesitará usar las funciones <sys/farptr.h> o dosmemput() para accesarla: Vea el capítulo DPMI para más detalles a cerca de esto. En el nivel más básico, un simple pixel puede dibujarse en pantalla con el siguiente código:

   #include <go32.h>
   #include <sys/farptr.h>

   void putpixel_13h(int x, int y, int color)
   {
      _farpokeb(_dos_ds, 0xA0000+y*320+x, color);
   }

Despeglar gráficos como una secuencia de pixeles únicos tiende a ser muy lento, pero el mismo principio puede ser aplicado para formas más complejas y útiles como líneas, rectángulos y círculos. Una útil optimización es llamar a la función _farsetset(_dos_ds) al comienzo de la rutina y luego usar las funciones _farns*() que son un poco más rápidas para el resto del dibujado. Usando éste método, un rectángulo lleno podría implementarse como:

   void rectangle_13h(int x, int y, int w, int h, int color)
   {
      int i, j;

      _farsetsel(_dos_ds);

      for (j=y; j<y+h; j++)
	 for (i=x; i<x+w; i++)
	    _farnspokeb(0xA0000+j*320+i, color);
   }

Otra técnica útil es escribir dos o cutro pixeles a la vez con las funciones _farnspokew() o _farnspokel(): esto puede dar una mejora de hasta cuatro veces sobre las operaciónes de un solo byte!

Una aproximación alternativa es construir la imágen completa en un buffer en memoria antes de copiarla a la pantalla. Esto puede hacerce más fácilmente usando la función dosmemput(), por ejemplo:

   #include <sys/movedata.h>

   char framebuffer[320*200];
   int i;

   /* clear the framebuffer */
   memset(framebuffer, 0, sizeof(framebuffer));

   /* draw some diagonal lines */
   for (i=0; i<200; i++) {
      framebuffer[i*320+i] = i;
      framebuffer[i*320+i/2] = i;
      framebuffer[i*320+i/3] = i;
   }

   /* copy the buffer across to the screen */
   dosmemput(framebuffer, 320*200, 0xA0000);

Hasta el momento estas funciones solo están dibujando colores en la pantall como número en un rango de 0 a 255, pero para un programa real usted necesita obviamente alguna forma de saber qué color representa ése número. Esto es controlado por un componente de hardware llamado la paleta, que es una tabla que lista los valores del color actual para cada modo de cada uno de los 256 valores que puede desplegar. Cuando selecciona un modo de vídeo, las primeras 16 entradas en la paleta(colores cero a quince) tendrán los colores estándard del modo texto de DOS(negro, azul, verde, cian, rojo, magenta, marrón, gris claro, gris oscuro, azul claro, verde claro, cian pálido, rosado, magenta claro, amarillo y blanco), pero los otros 240 colores se puden cambiar a otros colores diferentes dependiendo de la máquina. Para usar cualquier otro color que no sean esos 16 colores por defecto, usted debe cambiar la palenta a algún nuevo valor, lo que se hace escribiendo el índice de la paleta en el puerto hardware 0x3C8 seguido por los tres valores RGB del color en el puerto 0x3C9, eg:

   #include <pc.h>

   void set_color(int color, int red, int green, int blue)
   {
      outportb(0x3C8, color);
      outportb(0x3C9, red);
      outportb(0x3C9, green);
      outportb(0x3C9, blue);
   }

Los colores rojo, verde y azul varían en un rango de 0 a 63, por ejemplo llamando a set_color(10, 0, 0, 0) cambiará el color número 10 a negro, mientras que set_color(10, 63, 63, 63) cambiará el color a blanco y set_color(10, 63, 40, 0) lo cambiará a naranja.

Algo bueno acerca de la paleta es que puede ser usada para alterar los colores aun despues de que ha dibujado algo en la pantall, lo que puede ser útil para hacer desdibujados y algunos tipos de animación. Por ejemplo, el color 1 es azul en la paleta por defecto, por lo que si usted dibuja muchos pixeles 1 en la pantalla estara cubierta por puntos azules. Pero si uste luego llama set_Color(1, 0, 63, 0), todos esos pixeles cambiarán automáticamente a verde!. Aparte de ser muy fácil hacer que algunos de sus gráficos se vean en diferente color, este truco puede ser usado para desvancer toda la pantalla hacia o desde el negro cambiando gradualmente los 256 colores de la paleta para hacerlos más brillantes o más oscuros, y muchos efectos interesantes se pueden lograr haciendo posteriores alteraciones a su paleta de colores.

Antes de alterar algun valor de la paleta sería una buena idea sincronizar su programa con el retrazo vertica. Este es un periodo mientras el rayo de electrones dentro del monitor ha alcanzado el final de la pantalla y se está moviendo hacia arriba listo para desplegar otra copia de la imágen, y por éste corto intervalo de tiempo la tarjeta gráfica tiene una oportunidad de descansar ya que no hay necesidad de enviar los datos del pixel al monitor. Este retrazo ocurre 70 veces en un segundo, y tarjetas más antiguas solo le permitirán cambiar un color en ése momento. Usted puede cambiar el color en el momento que quiera en muchas tarjetas recientes, y su programa aun funcionará si usted lo hace en el momento equivocado, pero podría causar algo de nieve en la pantalla, lo que es horrible y facil de evitar si siempre está seguro de sincronizarlo con el retrazo. El periodo de retrazo piede ser detectado revisando el bit 3 del puerto 0x3DA, ej:

   void vsync()
   {
      /* wait until any previous retrace has ended */
      do {
      } while (inportb(0x3DA) & 8);

      /* wait until a new retrace has just begun */
      do {
      } while (!(inportb(0x3DA) & 8));
   }

Usted debería siempre llamar ésta función antes de modificar cualquier color de la paleta, aunque es posible cambiar muchos colores con un solo retrazo, por lo que usted solo necesitaría llamar vsync() una vez aun cuando haga varias llamadas a set_color() inmediatamente luego de ella.

Eso es todo amigos! esto debería ser todo lo que necesita para tener su programa trabajando en modo VGA 13h 320x200 y las mísmas técnicas pueden ser aplicadas a otros modos VGA como el modo de 16 colores o resoluciones X. Todas las partes específicas de la programación en djgpp de estos otros modos son los mismos que los del modo 13h, por lo que usted puede combinar el materia djgpp de este documento con la informacion del hardware de las muchas fuentes disponibles en la red.


Referencias:

x2ftp - ftp://x2ftp.oulu.fi/pub/msdos/programming/
La colección de material de gráficos DOS más comprensiva en la red.
PCGPE - ftp://x2ftp.oulu.fi/pub/msdos/programming/gpe/
Una buena y clara introducción a muchas de las técnicas gráficas, aunque todos los ejemplos están en Pascal.
Abrash in DDJ - ftp://x2ftp.oulu.fi/pub/msdos/programming/docs/graphpro.lzh
Los "legendarios" artículos escritos por Michael Abrash y publicados en DDJ entre el 91/93, cubriendo los modos X, rasterización de polígonos, y muchos tópicos fascinantes.

traducido por ADnoctum


  webmaster   donations   bookstore     delorie software   privacy  
  Copyright © 1998   by DJ Delorie     Updated Jan 1998  

Please take a moment to fill out this visitor survey

You can help support this site by visiting the advertisers that sponsor it! (only once each, though)