CURSO DE PROGRAMACION GRÁFICA

Artículo 11: MODOS X: SCROLLES HARDWARE

Autor: (c) Santiago Romero.
Revista: Programación Actual (Prensa Técnica) nº 11, Febrero-1998


Este mes vamos a aprovechar las peculiaridades del modo X para usar page flipping en nuestras animaciones y realizar scrolles hardware de gran suavidad, al mismo tiempo que se aclararán los conceptos más difíciles vistos hasta ahora.

Vimos en la anterior entrega la organización del modo x y la manera de trabajar con él en cuanto a la primitiva gráfica que representa el pixel. El modo x es un modo muy complejo que requiere algo más de trabajo que los modos lineales como el 13h o la SVGA mediante VBE VESA 2.0, pero presenta algunas características que lo hacen muy útil en algunas ocasiones.

Veamos un breve repaso de la estructura del modo X para ir introduciendo conceptos nuevos muy útiles en el tema de este mes, que versa sobre la realización de scroll hardware y page flipping aprovechando las especiales características de los modos unchained.


BREVE RESUMEN

En el modo 13h disponíamos de un segmento de 65535 bytes (el segmento 0xA000) que directamente representaba el contenido de la videoram y por lo tanto de los gráficos en pantalla, con la particularidad de que cada byte representaba un pixel de una manera lineal, desde el pixel (0,0) (offset 0 del segmento) hasta el (319, 199) (offset 63999). En este modo lineal de 1 byte por pixel para calcular el offset que le correspondía a cada punto bastaba con calcularlo mediante la relación offset = (y*320)+x.

Por otra parte sabemos que hay una serie de registros internos que almacenan los parámetros mediante los cuales la tarjeta es capaz de interpretar de forma correcta los datos que hay en la videoram para trazarlos en el monitor tras cada retrazo vertical, entre 60 y 70 veces por segundo.

Todas las tarjetas VGA tienen como mínimo 256 KB de memoria, y en el modo 320x200 (=64000) sólo se aprovechan 64K. Michael Abrash reprogramó los registros VGA del modo 13h obteniendo un nuevo modo de vídeo (13X, 320x200X) con algunas particularidades especiales.


MODO X: FILOSOFIA PLANAR

El modo 13X (320x200X), en vez de ser un modo de 1 byte por pixel (1 bpp, lineal) como el 13h, es un modo "de 4 pixels por byte" (no de 4 bytes por pixel). Cada offset (cada byte de la VRAM) da acceso a 4 pixel; por ejemplo, el offset 0 representa a los pixels (0,0), (0,1), (0,2) y (0,3).

El hecho de que el mismo byte direccione 4 pixels es un concepto derivado de los modos planares. En este tipo de modos (los de 16 colores), la tarjeta tiene 4 planos (internos) donde tiene almacenado los pixels divididos en estos 4 planos. En nuestro caso el plano 0 contiene los pixels (0,0), (4,0), (8,0), etc. En el segundo plano los pixels (1,0), (5,0)... de la misma forma que vimos en la figura del número anterior.

Cuando escribimos el color 15 (blanco) en 0xA000:0000, el pixel trazado en pantalla dependerá del plano que esté seleccionado actualmente. Si es el plano 0, la tarjeta traza el pixel (0,0), y si es el 3, el (3,0), de esta manera el mismo byte sirve para representar a 4 pixels.

Esto nos obliga a hacer varias cosas a la hora de trazar un pixel: a seleccionar el plano que le corresponde, a calcular su offset y a trazarlo.

El plano en que cae coincide con los 2 últimos bytes de su coordenada X (0, 1, 2 ó 3), ya que es el resto de dividir por 4 al haber 4 planos, y lo obtenemos mediante plano = X % 4 o (más rápido) con plano = X AND 3. Con ese dato forzamos a la VGA a que cambie el plano actual al que queremos nosotros (mediante un registro de la VGA, tal y como vimos el mes pasado) y continuamos.

El offset ahora es distinto de como lo era en lo modo 13h (y*320+x). En 13X, 320 pixels se representan mediante 320/4=80 bytes (ya que cada byte accede a 4 pixels), de manera que el offset del punto es (casi igual de sencillo que en 13h) offset=(y*80)+(x/4);

Con estos datos y el plano ya seleccionado, escribimos en 0xA000:Offset el color deseado y ya tenemos el punto en pantalla. Al recibir un nuevo byte en VRAM la tarjeta comprobará cual es el plano actual y escribirá este nuevo color en uno de sus 4 planos internos (el que corresponda).

El modo 13h lineal es un truco de los fabricantes de tarjetas, que decidieron perder 192K de memoria a favor de un sistema que seleccionase automáticamente el plano en el que escribir/leer, de manera que al escribir un byte en 0xA000, la tarjeta calcula el plano en el que almacenar el nuevo color automáticamente de manera transparente al programador, con la desventaja de desaprovechar 192 KB.


VENTAJAS Y DESVENTAJAS

Empecemos primero con las desventajas. Para empezar, el cambio de plano es lento, ya que la instrucción out toma entre 13 y 20 ciclos de reloj para ejecutarse (según el bus de nuestro PC), de manera que el modo x se suele usar en operaciones que se realicen por trazado de líneas verticales. Por ejemplo, los juegos WOLF3D y DOOM están hechos en ModoX, y tras seleccionar un plano, como todos los pixels verticales de esa columna caen en el mismo plano, aprovechan para trazar las texturas por líneas verticales, para no realizar cambios de planos hasta que no se pase a la siguiente línea de la textura.

Otra desventaja es que necesitamos más cálculos, pero eso depende de nuestra capacidad de optimización. Si preparamos una tabla con las multiplicaciones por 80 precalculadas (o las sustituimos por desplazamientos) y de igual manera con las divisiones por 4, puede ganarse en velocidad.

Como vamos a ver ahora, el modo x se usa en algunos casos concretos de programas o juegos en que sus características especiales hacen que en vez de reducir la velocidad del programa, la incremente.

Un ventaja muy significativa que vamos a ver aquí es que, como vimos en el artículo de registros VGA, existe un modo de copia (seleccionable) que activa los 4 planos y permite al copiar cada byte estar copiando 4 pixels si hacemos copias de VRAM a VRAM, de manera que resulta muy rentable mantener sprites y gráficos en páginas no utilizadas para realizar esta copia a 4 veces la velocidad normal de copiado lineal (se copian la cuarta parte de bytes). De la misma manera, seleccionando los 4 planos (escribiendo 1111b al Select Write Plane), podemos rellenar 4 pixels de golpe con el mismo color al escribir el byte en VRAM; de esta manera el borrado de pantalla se reduce a, por ejemplo, 16000 escrituras MOVSB.

Su ventaja principal es el motivo de este artículo: Si cada byte representa 4 pixels, cada 320 pixels son sólo 80 bytes, y 320x200 pixels (64000), se almacenan en 64000/4=16000 bytes. Como el segmento 0xA000 es de 65536 bytes, en éste tenemos espacio para 4 pantallas de 320x200 pixels y un par de líneas más (de los 1536 bytes). Aunque escribamos valores en estas pantallas extra no alteramos el contenido de la imagen en pantalla (al menos por ahora), ya que la página activa es la página 0 (desde el offset 0 al 16000).

En estas páginas podemos pues escribir, almacenar gráficos, sprites, fondos, etc, teniendo en cuenta que son 3 pantallas más de 320x200 como la primera de que disponíamos. Pero ahora vamos a ver la particularidad del modo x que le da su funcionalidad, el posicionamiento de la ventana de visualización o cambio del start address register.


VENTANA DE VISUALIZACION

Como podemos ver en la figura 1, aunque tenemos 4 páginas en el segmento 0xA000, lo que realmente vemos en el monitor es la primera página de las 4, la página 0 (en el offset 0). La página 1 comienza en el offset 80*200=16000 (pues hay 4 pixels por byte y 320/4=80), la página 2 en 80*200*2=32000, y la tercera en el offset 48000.
Ventana de visualizacion

Veamos un ejemplo de pseudocódigo que trazaría un pixel en cualquier página de la videoram:

Función PutPixelX( x, y, color, pagina )
{
   - Seleccionar plano x&3.
   - Calcular offset y*80+x/4
   - offset = offset+(página*16000)
   - Escribir color en 0xA000:Offset
}

Con el anterior pseudocódigo nos posicionamos en el offset de la página correcta (offset = (y*80) + (x/4) + (16000*página)) y trazamos el punto en la misma.


START ADDRESS REGISTER

Ya que podemos almacenar gráficos en las 3 páginas restantes, sería muy útil poder cambiar la ventana de visualización a cualquiera de ellas, para que la imagen que apareciese en el monitor (instantáneamente) fuera el contenido de esa página.

Esto puede hacerse gracias al Start Address Register (o registro de comienzo de dirección), que le indica a la VGA desde qué offset ha de empezar a leer bytes para representarlos en pantalla. En principio este registro vale 0, y por eso vemos en pantalla en contenido de la página 0 (empieza en el offset 0), pero nada nos impide modificar su valor a p.ej., 16000, y visualizar en el monitor el contenido de la página 1. De esta manera obtenemos 4 páginas donde trabajar con la posibilidad de trabajar en ellas por separado y cambiar a la que deseemos en cualquier momento.

El Start Address Register consta de 2 registros del CRT Controller, accesibles desde los índices de puerto 0Ch y 0Dh (ver artículos nº 9/10) para poder desplazar el “marco virtual” de la VGA (lo que vemos) a lo largo de la memoria gráfica (todas las páginas de que disponemos).

Como se ha explicado en el anterior párrafo, estos últimos registros son los encargados de indicar la posición de comienzo a partir de la cual el haz de electrones del monitor tiene que dibujar en la pantalla el mapa de bits (imagen) representado en la videomemoria.

La forma de programar este registro es:


 outportb (CRTC_ADDR , 0x0C);
 outportb (CRTC_ADDR+1 , valor >> 8);      /* byte alto */
 outportb (CRTC_ADDR , 0x0D);
 outportb (CRTC_ADDR+1 , valor & 0xFF);    /* byte bajo */

El motivo por el que hay que utilizar los dos registros para enviar el byte alto (valor>>8) y el byte bajo (valor & 0xFF) es el siguiente: el valor que mandamos al registro de la VGA es un WORD (2 bytes), y los puertos del PC son de 8 bits (1 byte) con lo que la única manera de introducirlo es utilizando dos registros que contengan cada uno un byte, uno el alto y el otro el bajo, que la tarjeta compondrá para obtener el word (0-65535) que hemos enviado. Veamos en el listado 2 un ejemplo de función SetStartAddress().

 LISTADO 2: SetStartAddress Register

void SetStartAddress( unsigned int offset )
{
  outportb (CRTC, 0x0C);
  outportb (CRTC+1, offset >> 8);
  outportb (CRTC, 0x0D);
  outportb (CRTC+1, offset & 0xFF);
}

Mediante la posibilidad de modificar el Start Address Register vamos a ver 2 efectos muy útiles tanto en efectos gráficos (demos/intros) como en juegos: hablamos del page flipping y el scroll por hardware.


PAGE FLIPPING

Hemos comentado muchas veces que al trabajar directamente sobre la memoria de vídeo el usuario puede ver como construimos la pantalla bitmap a bitmap, lo cual produce un efecto desagradable. Como remedio a esto aprendimos a usar pantallas virtuales (buffers en memoria), donde escribíamos de manera que no aparecía nada en pantalla al ser simples buffers de RAM. Al finalizar la construcción de la pantalla volcábamos el contenido del segmento en la VRAM, borrábamos la pantalla virtual y repetíamos el proceso.

El modo X nos va a permitir tener 3 páginas virtuales ya que sólo una de ellas va a ser visualizada (la que esté activa mediante el offset introducido en el Start Address Register), y las otras 3 están ocultas, de manera que podemos tener una página activa mientras dibujamos en otra el siguiente fotograma del juego/animación/efecto, y cuando esté finalizada su construcción (y ahora viene lo importante), cambiar la visualización a esta página (con lo cual nos ahorramos un volcado a pantalla si trabajáramos con pantallas virtuales). A esto se le llama page flipping (o mejor dicho, true page flipping), y es muy sencillo de hacer ya que con sólo 2 páginas ya puede ser implementado, teniendo 2 páginas más libres para guardar sprites, fondos, etc.

La idea es tener una página activa (por ejemplo la 0) y dibujar el siguiente fotograma en la 1, y al finalizarlo, cambiar la visualización a la 1, y dibujar el siguiente fotograma en la 0, y así continuamente.

Un pequeño truco en estos casos es que en vez de utilizar ifs() para cambiar de página en el bucle principal:

 Bucle:
 Dibujar_en_pagina( oculta );

   if( oculta==0 )
     oculta = 1;
   else
     oculta = 0;

 Esperar_retrazo();
 Cambiar_startaddress();
 Fin bucle

Es más rápido usar esto:

  oculta = 1-oculta;

De esta manera, 1-0=1 y 1-1=0 harán el cambio correcto de la página ahorrándonos los ifs().


SCROLLES HARDWARE

Todo el mundo sabe lo que es el scroll de una imagen, que consiste en verla des/aparecer desde uno de los lados de la pantalla con un suave desplazamiento. En modo 13h esto habría que hacerlo por software copiando cada vez una porción de la imagen, pero en modo x esto puede hacerse por hardware, es decir, dejar que la CPU haga el trabajo.


EL SCROLL VERTICAL

Este tipo de scroll es el más fácil de realizar y posiblemente el más utilizado por los programadores que se inician en modox. Imaginemos nuestro marco virtual situado en la página 0 (offset 0) de la videomemoria. Imaginemos también una imagen situada en la página 1, tal y como puede verse en la figura 1.

Si incrementáramos el valor del Start Address Register en 80 unidades (320 pixels), veríamos una línea menos de la página 0 (es decir, la primera línea visualizada sería la 1, y veríamos en la última línea de la pantalla la primera línea de la siguiente página (ver la figura para orientarse)). De esta manera, incrementando continuamente el valor de este registro para avanzar una línea completa se podrá observar un scroll, siempre y cuando antes de llamar a este registro se haya esperado un retrazo vertical, encargado de ralentizar la operación para obtener un scroll tan suave.

Ya que la intención es desplazar la imagen verticalmente, para desplazarla será necesario incrementar el valor 80 unidades cada vez sobre el valor total, que se mandará al registro 0Ch y 0Dh del CRTC. Como ya sabemos, 320 pixels en la pantalla son 80 bytes en Modo X (320 pixels / 4 planos = 80 pixels por plano ), por lo tanto cada vez que se desplacen 80 pixels, la coordenada Y se moverá en la pantalla, es decir se habrá scrolleado el gráfico en el monitor.

En el listado 3 se puede ver la manera en la que se puede implementar este tipo de scroll.

  LISTADO 3: Ejemplo de scroll vertical.

void main()
{
 unsigned int y = 0;

 Set_320x200X();
 SetOffsetRegister(80);
 SetPage(0); 
 LoadImage();

 /* scrollea 1 pantalla vert. */
 while (y < 80*200)
 {
   y+=80;
   WaitVRetrace();
   SetStartAddress(y);
 }
 SetVideoMode(3);
}


EL SCROLL HORIZONTAL

El scroll horizontal no es tan sencillo como el vertical, y existen varias maneras de hacerlo. Antes de empezar con el scroll se tiene que programar la dimensión que va a tener la memoria. La memoria la hemos representado antes como 4 pantallas una sobre otra (seguidas verticalmente en videomemoria), pero nada nos impide colocarlas como en la figura 2, donde están colocadas seguidas horizontalmente en la memoria. En este caso, la manera de trazar pixels con y=80*y+x/4 no sirve, ya que como puede verse no hay 80 bytes por línea, sino 320, ya que las 4 pantallas están seguidas en memoria, pero la filosofía es la misma. También podemos colocar las páginas en formato 2x2(2 horizontales y 2 verticales).

Modo 4x1

Estos tamaños se programan con el CRTC y el índice 13h (Offset Register), en concreto para obtener 4x1 pantallas habría que reprogramarlo con el valor 160 (ver listado 1). Lo que nos interesa ahora es comprender el concepto del scroll horizontal, así que imaginemos la memoria en formato 4x1 y con una imagen en la página 1.

Simplemente incrementando en 1 el Start Address Register de una manera continua se puede obtener el deseado desplazamiento horizontal (listado 4).

 LISTADO 1: Set Offset register.

/*
SetOffsetRegister();
Se le pasa el valor del número de bytes que queremos como anchura partido por 2.

Valores de Anchura:                                                     
  40  à (80  bytes por línea, 1x4).
  80  à (160 bytes por línea, 2x2).
  160 à (320 bytes por línea, 4x1).
*/

void SetOffsetRegister( unsigned char anchura )
{
 outportb( CRTC, 0x13 );
 outportb( CRTC+1, anchura );
}


 LISTADO 4: Ejemplo de scroll horizontal.

 void main()
{
 unsigned int x = 0;

 Set_320x200X();
 SetOffsetRegister(160);
 SetPage(0); 
 LoadImage();

 /* scrollea 3 pantallas horiz. */
 while (x < 240)
 {
   WaitVRetrace();
   SetStartAddress(x);
   x++;
  }
 SetVideoMode(3);
}

Un punto que hay que tener en cuenta siempre que se realice este tipo de scroll, es que cuando se incrementa la variable en 1 se desplaza la pantalla en 4 pixels. Esto es debido a los 4 planos del Modo X. El hecho de que se desplace en 4 pixels no indica que el scroll no vaya a ser suave, sino que la velocidad es cuatro veces mayor que si se realizara pixel a pixel.

Si de lo contrario, se desea realizar el scroll incrementando y desplazando la pantalla en 1 pixel, se tendrá que recurrir al HPP (Horizontal Pixel Panning Register), encargado de realizar este trabajo. Este registro se encuentra en el índice 13h del ATTRIBUTE CONTROLLER (3C0h), pero este es un tema que requiere mucha experimentación por parte del programador, siendo necesario primero entender todos los sistemas simples de scroll, que son los que vamos a comentar.


EL SCROLL MULTIDIRECCIONAL

Una vez se domine la manera de realizar los anteriores modelos de scroll, se puede efectuar una combinación muy útil para juegos, introducciones o demostraciones gráficas. Utilizando el índice 0Ch y 0Dh del CRTC, se pueden combinar los scrolls como muestra el listado 5. Véase el ejemplo de scroll 2x2 del CD en el que se scrollea un PCX de 640x400 dibujado en videomemoria.

 LISTADO 5: Scroll multidireccional.

void main()
{
 unsigned int x , y;
 char inc_x , inc_y;

 Set_320x200X();
 SetOffsetRegister(160);
 SetPage(0);

 x = y = inc_x = inc_y = 1;

 while ( !kbhit() )
 {
  WaitVRetrace ();
  SetStartAddress(x);
  x = x + inc_x;
  y = y + inc_y;
  if (x <= 0 || x >= 80) inc_x = inc_x * -1;
  if (y <= 0 || y >= 200) inc_y = inc_y * -1;
 }

 SetVideoMode(3);
}

En este caso necesitamos reprogramar el offset register a 80 (160/2, ver listado 1) para obtener 2x2 pantallas en modo x. Si estamos haciendo un juego o efecto, borramos los sprites que hayan en pantalla escribiendo porciones de fondo encima previamente almacenadas antes de trazarlos (técnica conocida como Dirty Rectangles), y luego scrolleamos.


SCROLL CON SPLIT-SCREEN

Este tipo de scroll (split screen o pantalla partida), como su nombre indica, determina la pantalla de forma partida, en la cual existe una zona con posibilidad de movimiento y otra estática. La naturaleza de este efecto radica en el desplazamiento de una zona de la pantalla mientras que otra zona se queda fija superpuesta a la zona anterior (siempre aparece encima), todo esto por hardware, sin necesidad alguna de rutinas de dibujo por nuestra parte. Tenemos así la posibilidad de crear marcadores, ventanas de ayuda e información, de esta manera podemos dejar fija una zona de la pantalla y scrollear la otra, p. ej.

El secreto está en el registro Line Compare o Split-Screen. Este registro es el encargado de determinar la línea en la cual se divide la pantalla. En la figura 3 se puede observar la estructura de la pantalla en esta modalidad.

Split Screen

Internamente la VGA trabaja de forma que, durante la representación de una imagen en pantalla, esta va contando internamente la línea actual. Este número no se puede leer a traves de los registros de la tarjeta (grave error de los diseñadores en las tarjetas del PC) pero otro registro (Line Compare, del CRTC, índice 18h) se puede utilizar para una comparación de línea. La VGA sabe la línea actual en que está dibujando de videomemoria a pantalla mientras este registro compara el valor que contiene con el valor que la tarjeta cuenta.

De este modo cuando este valor es alcanzado, el contador de direcciones se carga con un 0, lo que indica que la representación comienza en esta línea con los datos que se encuentran en el Offset 0 de la memoria de vídeo. En pocas palabras, el Line Compare Register actúa como un límite en el que la VGA pasa a redibujar a partir del offset 0, de manera que vemos un número determinado de líneas de la página actual, y cuando la VGA llega al límite, comienza a redibujar desde el offset 0, pudiendo así ver media pantalla de la página 1 y media de la 0 al mismo tiempo que se realiza un scroll.

Dado que el número de línea no se puede guardar en 8 bits (ya que la VGA no reconoce ningún modo con menos de 350 líneas y los modos de 200 líneas son generados por 400 líneas físicas (fenómeno conocido como duplicación de líneas)), el registro Line Compare suele estar dividido en tres registros (que contienen más bits para poder representar valores 0-350), teniendo en las tarjetas Super-VGA hasta cuatro. En el listado 4 se puede observar, para el manejo del Line Compare, la utilización de extensiones de los bits del Line Compare, como el OverFlow Register.

Para utilizar el Line Compare necesitamos pues acceder a dos registros más. Esto se hace de una manera muy sencilla:

El primero de los registros es el Overflow Register (CRTC, índice 7). El bit 4 de este mismo registro será el utilizado en este caso, que se encarga concretamente de cargar en su lugar el bit 8 del Line Compare. El bit 4 del registro Overflow es el único entre los demás que no está protegido por el bit de protección del registro 11h. El bit 9 del registro de comparación de linea se encuentra en el segundo registro que se tiene que utilizar, que es el Maximum Row Address (CRTC, índice 9), concretamente en el bit 6. Para programar por tanto el Line Compare se tendrán que cargar los bits mediante desplazamientos y enmascaramiendos entre estos registros. Este trabajo es realizado por la rutina que se puede observar en el listado 6.

 LISTADO 6: SplitScreen();

void SplitScreen ( unsigned char row )
{
asm {   
     mov bl, [row]
     xor bh, bh
     shl bx, 1    /* duplicamos líneas */
     mov cx, bx

/* Reg. 7 (Overflow Low) */
     mov dx, CRTC
     mov al, 07h  
     out dx, al
     inc dx
     in al, dx

     and al, 11101111b
     shr cx, 4
     and cl, 16
     or al, cl
     out dx, al

     dec dx

/* Reg. 9 (Maximum Row Address) */
     mov al, 09h
     out dx, al
     inc dx
     in al, dx
     and al, 10111111b
     shr bl, 3
     and bl, 64
     or al, bl
     out dx, al

     dec dx
/* Registro 18h (Line Compare/Split Screen) */
     mov al, 18h  
     mov ah, [row]
     shl ah, 1
     out dx, ax
    }
}

Lo primero que nos indica el procedimiento de este listado es la duplicación del valor en el modo de 200 líneas. Después se selecciona el Overflow Register para cargar en el bit 4 el bit 8 del valor de la línea mediante desplazamiento y enmascaramiento del mismo. Para esto hay que desplazar 4 bits hacia la derecha en el valor de la línea (SHR valor, 4) con tal de dejar el bit 8 en la posición del bit 4.

A continuación se realiza con este último valor obtenido un AND con 16 para saber si dicho bit (bit 8 del valor, ahora bit 4) está activado o no. Una vez hechos los cálculos se activa o no el bit 4 del Overflow Register dependiendo de si lo está o no al hacer el AND con 16. Estos mismos cálculos se realizan ahora con el bit 9 del la línea y el bit 6 del registro 9h. Finalmente se colocan los restantes 8 bits del número de línea en el registro 18h (Line Compare o Split Screen).

El resultado de esto es la modificación del valor del line compare register, que usado convenientemente nos permite hacer verdaderas maravillas con la tarjeta gráfica.


MODO X

Todo la información vista hasta ahora sobre el modo 13x tiene una utilidad muy sencilla: si bien tener un modo 320x200 puede ser muy útil para determinadas situaciones, la utilidad real es cuando modificamos los registros del modo 13X y obtenemos el verdadero modo X: 320x240. Esos 40 pixels extra de resolución vertical corrigen el ratio del modo 13x y hacen parecer las imágenes más cuadradas, es decir (ratio 4:3), que se ve una relación más correcta que en 320x200, donde un círculo perfecto puede parecer una elipse debido las escasas 200 líneas de resolución vertical. Con la modificación de los registros se pueden conseguir resoluciones como 320x240, 360x360, 400x300, 320x400, etc. En el CD de la revista, en GRAFPROG\UTILS\VGAREGS encontrareis una utilidad y ficheros fuente que os permitirán inicializar estos modos.


NOTA SOBRE LAS SVGA

En el artículo dedicado a los registros VGA se comentó que las tarjetas SVGA permitían programar los registros VGA por compatibilidad descendente. Esto es cierto para casi todos los casos, aunque en la información devuelta por las funciones de la VESA 2.0 hay un bit llamado VGA COMPATIBLE, que determina si una tarjeta SVGA es compatible o no (es decir, puede ser programada) con los registros VGA en ese tipo de modos gráficos. Aunque personalmente nunca hemos encontrado ninguna SVGA que no fuera compatible VGA, es posible que las haya, y ante ese caso habremos de sustituir los cambios de registros por llamadas a la BIOS VESA 2.0. Nótese que la VESA 1.2 no incluye este bit, de lo cual podemos deducir que el 99% de las SVGA son compatibles VGA, y que tan sólo un par de modelos (si es que hay alguno) no lo son.


EN LA PRÓXIMA ENTREGA.

Para algunos lectores recién iniciados este puede ser un tema especialmente complejo, pero basta mirar los ejemplos del CD para reconocer que vale la pena su estudio. Con este artículo finalizamos ya la incursión en los modos x, y en la próxima entrega, más fundamentos de programación gráfica.

Pulse aquí para bajarse los ejemplos y listados del artículo (62 Kb).

Figura 1: "Vídeomemoria en el modo X 1x4."
Figura 2: "Vídeomemoria en el modo X 2x2."
Figura 3: "Estructura del Split Screen."

Santiago Romero


Volver a la tabla de contenidos.