
   Tutorial:   Programacion avanzada de la VGA - Tut: 1
   ------------------------------------------------------------------------
   Titulo:     Intro. a la programacion de la VGA y modos no-encadenados

   Autor:      Macross

   E-Mail:     balleste@uv.es

   Sumario:    Si ya sabes programar la VGA usando las interrupciones BIOS
	       y crees que no hay nada mas..., sencillamente te equivocas!
	       Si programas en C y entiendes un poco el ensamblador, podras
	       aprender el verdadero poder de la VGA. Pero para ello, debes
	       trabajar duro y empaparte lo que cuente aqui. Animo, los
	       resultados son sorprendentes.
	       En este primer tutorial dare los cimientos basicos de la
	       programacion avanzada de la VGA. Veremos como guarda los
	       datos, como los visualiza, y como podemos explotar estas
	       cualidades.
	       Por cierto, aqui trabajaremos solo los modos a 256 colores.
	       (al menos de momento).

   Comentario: NECESITO ALGUN TIPO DE RESPUESTA. UN SIMPLE 'ESTOY VIVO Y
	       HE LEIDO TU TUTORIAL' ME BASTA, PERO OS RUEGO ME MANDEIS
	       ALGO!!!!
	       Respondere a cualquier cuestion que me pregunteis (no, no se
	       si Dios existe, gracioso!). Tan solo decidme vuestro E-Mail.
	       Y por si no lo habeis visto, mi E-Mail es:

				balleste@uv.es

   Disclaimer: El de siempre: No me hago responsable de ningun danyo que os
	       pudiese surgir (no se como) como consecuencia de la lectura
	       de este tutorial o los ficheros que lo acompanyan.

   Indice:     0 - Introduccion a los modos graficos
		   y al modo 13h (320x200-256 colores)
	       1 - Fundamentos de la VGA
	       2 - Lectura/escritura en la memoria de video de la VGA
	       3 - El modo 320x200 no-encadenado. Introduccion a los modos
		   extendidos
	       4 - Establecimiento del modo 320x200 no encadenado. Dibujar
		   puntos
	       5 - Terminando
	       6 - El proximo tutorial...
   ------------------------------------------------------------------------

   0 - Introduccion a los modos graficos y al modo 13h (320x200-256 colores)
   ------------------------------------------------------------------------
   Si estas leyendo esto, probablemente conoceras como cambiar el modo de
   video, haciendo uso de una llamada a la BIOS. Es tan sencillo como esto:

		  mov ah, 00h
		  mov al, modo
		  int 10h

   Si ponemos el modo que queremos en 'al', la interrupcion BIOS 10h se
   encargara de hacer vete-tu-a-saber-que y tendremos el modo que queriamos.
   Cuantos modos hay? Muchos. Cuantos modos a 256 colores hay? UNO. Este es
   el conocido modo 13h (MCGA). Es un modo de 320x200 a 256 colores y es de
   una sencillisima programacion (probablemente eso ya debes saberlo). Para
   dibujar un punto en la pantalla, basta con situar el numero de color
   en el offset 320*y+x del segmento de video A000. El segmento de video es
   de 64k, un poco mas que los 320*200=64000 visibles por pantalla. Conocido
   esto y como modificar la paleta, poco mas es necesario para programar
   la VGA a 256 colores. Esto es aproximadamente lo que yo conocia hasta que
   llego a mis oidos algo que decia llamarse Modo X. Si este es tu estado
   actual..., preparate a descubrir el nuevo mundo.

   Antes de continuar voy a hacer algunas preguntas que puede te hayas hecho
   antes y que te daran algo de contexto:

   Pregunta- Mi VGA es de 256k, pero el segmento de video es de solo 64k;
	     debo reclamar mi dinero?
   Resp.   - No! Lo que tienes que hacer es seguir leyendo para aprender a
	     usar los 192k restantes.

	  P- Por que 320x200, son numeros magicos acaso?
	  R- No, no lo son. De hecho, se escogio este numero porque era
	     el que mejor optimizaba la relacion simplicidad/npuntos.
	     Veremos como modificar las dimensiones de la pantalla.

	  P- Que es el Modo X?
	  R- Es un modo grafico de 320x240 a 256 colores no encadenado

	  P- No encadenado?, ...que es eso?
	  R- Aaaaah... te pille: tendras que leerte el texto

	  P- Merece la pena invertir mi valioso tiempo en aprender algo que
	     me esta pareciendo muy COMPLICADO, el lugar de aprender los
	     secretos de mi fantastica SVGA?
	  R- Si tu orgullo como GRAN programador no te hace empaparte el
	     texto hasta que tengas que pinzar tus parpados para que no
	     caigan muertos mientras tus ojos lloran de dicha al aprender
	     y... bla,bla,bla..., te voy a dar mejores motivos:
	     - Los modos VGA a 256 colores son cienes y cienes de veces mas
	       rapidos que los de las SVGAs.
	     - Las resoluciones alcanzadas puede llegar a ser suficientemente
	       pequenyas para tu gusto, aunque a costa de memoria.
	     - Necesitas mas de 256 colores? Has visto alguna caja de
	       rotuladores que sobrepase los 100?!!!
	     - 256 colores significa un byte por pixel y eso se traduce en
	       muchas ventajas para el programador.
	     - Todo es deliciosamente compatible.
	     Si aun no te he convencido de que sigas leyendo, creo que...
	     mira, dejalo,por que...que es la vida?...por que estamos aqui?
	     ...por que estare yo escribiendo este tutorial? ...por que no
	     dejare de decir idioteces?


   1 - Fundamentos de la VGA
   ------------------------------------------------------------------------
   Antes de empezar con cosas demasiado complicadas, vamos a comenzar con
   algunos fundamentos. Puede que ya los conozcas, pero siempre es didactico
   escuchar enfoques diferentes de algo que ya sabes. Todo lo que sigue lo
   escribo pensando en el modo 13h. Voy a suponer que conoces como funciona
   este modo grafico. Si no es asi, dimelo y hare un tutorial sobre como
   programar en este modo... si, un tutorial introductorio a la programacion
   de la VGA a 256 colores (ya sabes, E-Mail to me).
   Antes hemos dicho que para dibujar algo en la pantalla grafica, debemos
   modificar el segmento de video A000h-AFFFh. Esto son 64k exactas. Sin
   embargo sabemos que nuestra VGA dispone de mas memoria: 256k (o mas). Que
   pasa con esas 192k que quedan sueltas? Alguien podria decir que no son
   necesarias, ya que con las 64k del segmento de video quedan cubiertas las
   necesidades de representacion del modo 13h. Esto es cierto, y justo en
   eso reside su sencillez de uso. Sin embargo, en el modo 13h solo
   disponemos de una pagina, y no mas como en otros modos. Si has programado
   algo de animacion, sabras que tener varias paginas permite realizar unas
   animaciones suaves y sin parpadeos. Esto no es posible en el modo 13h, ya
   que disponemos tan solo de una pagina. El recurso usado habitualmente es
   montar una pantalla virtual, trabajar en ella y luego transferirla lo mas
   rapidamente posible al segmento de video. Esto significa un gasto, a veces
   importante, de memoria. El motivo es que una buena animacion suele
   necesitar 2 o 3 pantallas virtuales (una de fondo, otra de trabajo, etc.).

   Que hace la VGA, cuando trabaja en modo 13h, con esas 192k? Realmente, la
   VGA las ESTA USANDO pero, como vamos a ver, de modo muy ineficiente. El
   motivo de esta ineficiencia, como siempre, sera facilitar la vida al tio
   que la programa.
   Ademas, hay que anyadir que la resolucion de la pantalla de 320x200, se
   escogio porque su producto (poco menos de 64k) apuraba al maximo las
   posibilidades de este modo 13h (un modo encadenado, como veremos). Puede
   que sepas que la resolucion de la pantalla la determina la CRTC que es
   un chip controlador del trazado de rayos. Si le decimos que pinte 320
   en cada linea, eso sera lo que hara. Cuando sepamos controlar la CRTC,
   veremos que las posibilidades se multiplican. Pero eso vendra si vosotros
   quereis (o sea, si veo que alguien LEE ESTO).

   2 - Lectura/escritura en la memoria de video de la VGA
   ------------------------------------------------------------------------
   Veremos inicialmente una version simplificada del funcionamiento de la
   VGA, ya que el pastel es increiblemente empalagoso si se come todo de una
   sola vez.
   Supongamos que tenemos una VGA de 256k. Para dibujar puntos, nos ha sido
   asignado un pedazo de memoria de 64k. Este es el segmento de video (A000).
   Coco nos ensenyo de pequenyos las ideas de grande, mas grande y el mayor.
   De modo que parece dificil direccionar 256k si solo podemos direccionar
   las 64k del segmento de video. Los disenyadores de la VGA, que son unos
   tios muy listos, vieron facilmente la solucion: rompemos las 256k en
   cuatro bloques de 64k y permitimos que el programador seleccione el bloque
   donde quiera que se escriban. Se te habia ocurrrrido ehhhh?
   Bien. De modo que ya sabemos como usar las 256k, basta tan solo con
   seleccionar el bloque y ya esta. Para ello la VGA tiene un registro
   (un puerto de E/S) donde debemos escribir el bloque donde queremos mandar
   el byte. Claro, claro,... y entonces el modo 13h debe usar uno de esos
   bloques, no? ...digamos el 0, no? Pues NO. Usa los 4 bloques a la vez, en
   lo que se conoce como modo encadenado. Veamos que significa esto.
   Imaginemos el segmento de video:
	     123456789................(320)  <-- columna
	    Ŀ
  Filas>1 12345678..................78
           Ĵ
       ->2 ........................... 

   Cada posicion (x,y) contiene un byte que se guarda en la direccion de
   memoria [A000:(y*320+x)]. Por simplicidad les he llamado byte 1, byte 2,
   etc. hasta el byte 8. Luego se repiten y llenan todo el segmento.
   Esto es lo que ve un programador cuando trabaja en el modo 13h. Sin
   embargo, la VGA trabaja de un modo que en principio no es el logico, el
   cual, podria haber sido seleccionar un bloque y trabajar con el.
   Este era mi modo de pensar antes de estudiarlo a fondo y supongo que
   tambien el del posible lector. Veremos que esta completamente justificado.
   Cuando, estando en el modo 13h, el programador rellena el segmento de
   video asi:
	     123456789................320  <-- columna
	    Ŀ
  Filas>1 12345678..................78
           Ĵ
       ->2 ........................... 

    ...lo que realmente se graba en la memoria de la VGA es esto:

			   Ŀ
    Bloque 3 > ...4...8...4...         ...8
		       ĿĴ
    Bloque 2 > ..3...7...3...          ..7.   
		   ĿĴ   
    Bloque 1 > .2...6...2...           .6..      
	       ĿĴ      
    Bloque 0 >1...5...1...            5...         
	       Ĵ         
	                                            

   donde los puntos son bytes que se quedan en blanco... y sin usar! Si te
   fijas, al superponerlos, queda justo lo de arriba:

   tenemos esto,
	       Ŀ
    Bloque 3 >...4...8...4...         ...8
	       Ŀ
    Bloque 2  ..3...7...3...          ..7.
	       Ŀ
    Bloque 1 >.2...6...2...           .6..
	       Ŀ
    Bloque 0 >1...5...1...            5...
	       Ĵ

   y superponemos:
	       Ŀ
	       12345678..................78
	       Ĵ
	       ........................... 

   Resultado: la complicacion de los bloques queda completamente
   transparente al programador, que ve tan solo uno.
   Para lograr esto, el modo 13h pone activo un bit de configuracion
   llamado Chain-4. Cuando este bit esta activo, la VGA seleciona de forma
   automatica el bloque donde se debe guardar el byte, de modo que lo
   guarda en el desplazamiento (320*y+x) pero en diferentes bloques segun
   el punto. Esto quiere decir que ignora el valor que haya en el registro
   de seleccion de bloque.
   El bloque escogido por la VGA es el correspondiente a los 2 bits de
   menor peso del desplazamiento, o lo que es lo mismo:

		(320*y+x) mod 4

		    bits   Bloque
		     00      0
		     01      1
		     10      2
		     11      3

   Asi, si queremos poner el color 5 en las coordenadas [15,2] vemos que
   estas coordenadas se corresponde con el desplazamiento: 2*320+15=655.
   Los 2 ultimos bits son 11, o sea, que se guardara en el bloque 3.
   Este modo de trabajo que selecciona automaticamente el bloque a usar
   se llama modo encadenado, y creo que el nombre esta del todo justificado.
   Cuando Chain-4 vale 0, la VGA guarda el byte en el bloque que indique
   el registro de seleccion de bloque. Esto nos permite no desperdiciar
   memoria de video.

   Este es el modo en que se guardan los bytes. Veamos ahora el modo en el
   que se visualizan. Esto es lo verdaderamente crucial para comprender
   correctamente todo el tinglado. La VGA tiene 2 indices que le indican
   (oooooh, es increiiible que un incide indique algo indicable):
		- Desplazamiento en la memoria de video
		- Contador de puntos visualizados
   Digamos que se comienza a dibujar la pantalla y ambos valen 0. Pintamos,
   claro esta, el color correspondiente al byte del desplazamiento 0 del
   bloque 0. Para dibujar el siguiente punto, la VGA 'mira' el bit Chain-4.
   Si este vale 1, selecciona el bloque de donde tiene que leer, tomando
   los dos ultimos bits del desplazamiento. Tras visualizar el punto, tanto
   el desplazamiento como el contador de puntos se incrementan.

		123456789  < desplazamiento
	       Ŀ
    Bloque 3 >...3...7...           ...319
	       Ŀ
    Bloque 2  ..2...6...            ..318.
	       Ŀ
    Bloque 1 >.1...5...             .317..
	       Ŀ
    Bloque 0 >0...4...              316...
	       Ĵ

   La secuencia (bloque,desp) sera:

		(0,0)-(1,1)-(2,2)-(3,3)-(0,4)-(1,5)-(2,6)-(3,7)-....

   Como de los bloques ya se encarga la VGA, solo necesitamos calcular
   el desplazamiento para dibujar un punto:

		despl = 320*y+x

   Si por el contrario ponemos Chain-4 a 0, se incrementara el contador de
   caracteres por cada punto, pero solo se incrementara el indice de
   desplazamiento cuando se haya leido de los cuatro bloques:

		123456789  < desplaz>  (80)      <- FIJATE QUE EL
	       Ŀ         DESPLAZAMIENTO DEL
    Bloque 3 >37......              ...319         ULTIMO ES 320/4=80
	       Ŀ
    Bloque 2  26......              ..318.
	       Ŀ
    Bloque 1 >15......              .317..
	       Ŀ
    Bloque 0 >04......              316...
	       Ĵ

   La secuencia (bloque,desp) sera:

		(0,0)-(1,0)-(2,0)-(3,0)-(0,1)-(1,1)-(2,1)-(3,1)-....

   Visto como visualiza la VGA, queda claro que si trabajamos con Chain-4
   puesto a 0, debemos operar como sigue:
   Imaginemos que queremos dibujar 2 puntos. Uno situado en las coordenadas
   de la pantalla (0,0) y otro en las coordenadas (1,0). Ya hemos dicho que
   el (0,0) lo leera del desplazamiento 0 del bloque 0. Yo quiero saber
   de donde leera el (1,0) para ponerlo alli. El (1,0) es el siguiente al
   (0,0) y como Chain-4 esta a 0, solo se incrementa el bloque, por lo que
   debo ponerlo en el desplazamiento 0 del bloque 1. En la pantalla los
   dos puntos apareceran, como ya esperabamos, juntos. Las ecuaciones que
   nos dan el desplazamiento y el bloque son (operadores en C):

		bloque = (320*y+x)%4
		despl  = (int)((320*y+x)/4)

   3 - El modo 320x200 no-encadenado. Introduccion a los modos extendidos
   ------------------------------------------------------------------------
   Ahora que ya tenemos una perspectiva apropiada, podemos empezar a jugar.
   Si has prestado suficiente atencion, no se te habra pasado por alto que
   he dicho que con el modo no encadenado podemos aprovechar toda la
   memoria de video. Esto son 256k, o sea 4 paginas de video con las que
   poder hacer lo-que-nos-de-la-gana! Pero para eso tenemos que conocer una
   version menos simplificada de la que tenemos (pero aun falta bastante para
   la completa). Sin embargo, no sera dificil entenderla... si tienes claro
   lo anterior. Vamos a ello.

   Con Chain-4 puesto a uno (activo), los bloques son completamente
   transparentes al usuario y se desperdician 3/4 de la memoria de video. No
   nos detendremos en este caso. Las cosas interesantes surgen con Chain-4
   puesto a 0. Como establecer el valor de Chain-4 y el resto de los
   registros que iran surgiendo, es algo que veremos en su momento. Por ahora
   centrate en enterder esto. Hemos visto como se guardan las cosas y como
   se visualizan cuando, partiendo del modo 13h ponemos Chain-4 a 0. Las
   ecuaciones que nos dan el bloque y el desplazamiento son:

		bloque = (320*y+x)%4
		despl  = (int)((320*y+x)/4)

   Bueno, realmente tendremos que hacer alguna cosilla mas aparte de poner
   Chain-4 a cero para poder trabajar bien. Todo en su momento.
   Debes comprender perfectamente por que son estas ecs. Yo creo que estan
   bastante claras, ya que no hacen sino formalizar los esquemas graficos
   que he presentado. Si no sabes de donde salen, enviame un E-Mail e
   intentare aclarartelo.
   Vamos a analizarlas. El punto (0,0) se guarda en (bloq,desp)=(0,0). Este
   es el primer punto de la pantalla. Donde se guarda el ultimo? Este es el
   punto (319,199). Apliquemos las ecuaciones:

		 bloque = (320*199+319)%4 = 63999%4 = 3
		 despl  = (int)(63999/4) = 15999

   Imaginemos que llenamos el segmento de video de puntos. De cada bloque
   de 64k que disponemos, solo llenamos los primeros 16000 bytes. Que
   ocurre con el resto? Pues que no se ven, por que le hemos dicho que
   trabaje con esos 16000 bytes por bloque primeros. Este es un matiz del
   que antes no habia hablado, y el secreto de las paginas multiples. Yo
   dije que el punto (0,0) se correspondia con el desplazamiento 0 del
   bloque 0. Sin embargo, hay un registro de la VGA que permite modificar
   la direccion de inicio de la pantalla. Supongamos que ahora modificamos
   esta direccion y la igualamos a 16000. Todo sera exactamente igual,
   excepto que ahora se representara el segundo grupo de 16000 bytes.
   Ahora el primer punto representado en la pantalla se leera del
   desplazamiento 16000 del bloque 0, el segundo punto del desplazamiento
   16000 del bloque 1, el tercer punto del bloque 3 ...y como antes.
   Seleccionar la tercera y cuarta pagina es igualmente sencillo. Bastara
   con proporcionar el desplazamiento adecuado.

   Dado que el modo 320x200 no se puede lograr mediante una llamada a la
   BIOS, se habla de el como un modo extendido. No es el unico, hay muchos.
   A lo largo del desarrollo he asumido completamente que la pantalla
   tenia unas dimensiones de 320x200. Sin embargo, podriamos indicarle a la
   CRTC, que en lugar de volver a (0,0) cuando llege al final de la linea
   numero 200, siga otras 40 lineas mas. Para poder ver bien la imagen,
   tendriamos que achatarlo todo un poco, lo cual se consigue modificando
   otros registros. Ahora, cuando llegara al desplazamiento 15999, en lugar
   de volver al 0 seguiria hasta (en nuestro ejemplo):
		desp = (int)(320*240/4) = 19199
   ...y veriamos 40 lineas adicionales!
   Para llegar ha hacer cosas como estas tendremos que conocer a fondo los
   registros de la VGA y de la CRTC, pero solo lo hare SI ALGUIEN ME LO
   PIDE. DE MODO QUE SI QUIERES MAS TUTORIALES, PIDELOS!!! Yo estare
   encantado de hacerlos.


   4 - Establecimiento del modo 320x200 no encadenado. Dibujar puntos
   ------------------------------------------------------------------------
   Junto a este texto hay un fichero en ensamblador decentemente documentado
   (como a mi me gustan), donde podras encontrar las funciones en C y ASM que
   hacen los minimos en este modo. Veras que se cambian algunos registros
   de la VGA, documentare estos y otros muchos mas en futuros tutoriales.

   Para establecer este modo, partiremos del modo 13h y lo 'desencadenaremos'
   Lo hacemos asi por que todavia no conocemos como establecerlo nosotros
   pispos. Fijate que es esto lo que se hace en la rutina de ensamblador.

   Respecto al dibujo de puntos, las rutinas no hacen mas que poner en
   ensamblador lo que hemos contado arriba. Fijate en el detalle de como
   se halla el modulo 4 y la division por cuatro:

		x%4        es equivalente a x&3  (AND logico)
	       (int)x/4    es equivalente a x>>2 (desplazamiento)

   Lo conocias? Me alegro. Y me alegro en cualquier caso, ya que si no lo
   conocias, te he presentado el modo mas eficiente de hacerlo. De hecho
   es un truco de optimizacion que suele ser usado en los compiladores (lo
   se, lo he visto con mis ojitos!!). Si quieres conocer el porque de las
   equivalencias..., que tienes que hacer, eh? Llamarme, llamarme y llamarme.

   Ademas hay otras funciones de interes como, por ejemplo, seleccionar la
   direccion del desplazamiento inicial, volver al modo de texto, etc.

   5 - Terminando
   ------------------------------------------------------------------------
   Comence a escribir este tutorial por varios motivos. Uno de ellos era
   la completa ausencia de documentos en lengua hispana (espero no ofender
   a nadie, ruego me disculpen si lo he hecho) sobre CUALQUIER materia.
   Creo que es una lastima. Ademas, yo comprendo mucho mejor cualquier texto
   en mi propia lengua que en otra, y creo que los demas tambien. Otro de
   los motivos es la escasez de tutoriales en general. No hay gran variedad
   y en ocasiones no son faciles de entender. Quiero contribuir a aumentar
   esa variedad y a la difusion de tutoriales sobre CUALQUIER tema. Estamos
   en la era de la informacion. Yo mismo exploro la Internet en busca de
   esta informacion. Este tutorial ha sido posible, en gran medida, por la
   informacion (dispersa, a veces) que guarda la red Internet. El resto, lo
   he puesto yo. La informacion que he encontrado sobre esta tema (la VGA)
   si bien existente, resultaba a veces poco extensa. Yo contribuire en este
   y, tal vez, otros temas (si alguien lo pide).

   Agradeceria comentariarios a la exposicion, efoque, etc.

   Si alguien lo solicita, como ya he dicho, hare tutoriales sobre
   programacion basica.

   6 - El proximo tutorial...
   ------------------------------------------------------------------------
   Este tutorial no ha sido mas que una presentacion de lo que viene. Veremos
   en el proximo tutorial como la memoria de video se puede 'formatear' como
   una hoja grande de las dimensiones que queramos, de la cual nosotros solo
   vemos un fragmento. Veremos tambien como se puede tambien alterar las
   dimensiones de ese fragmento que vemos nosotros. Y esto, que dicho asi
   suena tan raro, no es mas que alterar la resolucion de nuestra pantalla.
   Por que usar una resolucion de 320x200 cuando podemos alcanzar incluso
   una resolucion de 400x600 a 256 colores con nuestra VGA? Todo se vera.
   Primero la idea,... y luego los registros! Espero vuestro E-Mail.

   Por cierto, para aquellos que quieran empezar a indagar, los ficheros
   fuente que acompanyan a este texto contienen bastante informacion de
   interes. Leelos con atencion... aunque lo bueno este por venir!

        Macross, Valencia, Spain



