Blogia
Las Pequeñas Paranoyas de Motagirl

Codificación de colores en modo texto de VGA

¡Otro post mágico sobre periféricos! Y probablemente esta semana y la que viene haya algunos más, puesto que tengo el examen de prácticas el martes y el de teoría el lunes siguiente.

Recordemos los capítulos anteriores porque probablemente serán útiles en este:

- Punteros y modelos de memoria

- Acceso a ROM para obtener los patrones de bits de los caracteres

- Modificación de los patrones de bits de los caracteres

- Acceso a la Tabla de Vectores de Interrupción

Bien, dicho esto, también nos será útil saber cómo organiza VGA el acceso a los colores.

Sabemos que, si escribo un carácter directamente en memoria  de video (en nuestro caso -80x25- el segmento comienza en 0xB800), este ocupará 2bytes repartidos tal que así:

8bits: carácter
1bit: parpadeo
3bits:  color de fondo
4bits: color de carácter

Sabiendo esto, podemos usar 4 bits para el color, es decir, que tenemos 16 colores distintos a elegir. En realidad, cada uno de esos colores está apuntando a una paleta, que a su vez indexa 256 registros de un conversor analógico digital (DAC), en  el que cada color (rojo, verde, azul) ocupa 6bits. O sea, 3 colores de 6 bits cada uno (64 posibilidades por cada color) nos da 256 bonitos colores para usar.

La manera en que utilizaremos esto es la siguiente: modificaremos la paleta de un color determinado (en este caso, el 5, violeta) para que indexe otro color del DAC. Entonces, cada vez que pintemos algo de ese color, se estará pintando en realidad del color con el que lo hayamos modificado.

¿Lo primero que necesitamos saber? A donde apunta (en el DAC) el color que hemos elegido. Esta función es útil para eso:

int indiceDAC(int indcolor) {
/* dice a que registro DAC apunta una entrada del registro de paleta */
struct REGPACK r;
r.r_ax=0x1007;
r.r_bx=indcolor;
intr(0x10,&r);
return(r.r_bx>>8);
}

Una vez sabemos cuál es el índice del DAC que vamos a modificar, probablemente queramos saber sus componentes originales:

int lee_paleta(int indDAC, int *R, int *V, int *A) {
/* lee componentes RVA para una entrada DAC */
struct REGPACK r;
r.r_ax=0x1015;
r.r_bx=indDAC;
intr(0x10,&r);
*R=(r.r_dx>>8);
*V=(r.r_cx>>8);
*A=(r.r_cx<<8)>>8;
return(0);
}

Y por supuesto, alguna manera de modificarlo:

int establece_color(int indDAC, int R, int V, int A) {
/* establece componentes RVA para una entrada DAC */
struct REGPACK r;
r.r_ax=0x1010;
r.r_dx=R<<8;
r.r_cx=(V<<8)+A;
r.r_bx=indDAC;
intr(0x10,&r);
return(0);
}

Ahora que sabemos todo esto, lo suyo sería comprobarlo. Para ello,  dibujaremos un cuadrado directamente en memoria de video y lo rellenaremos del color 5.  Esto es tan simple como un par de bucles anidados en los que asignamos valores de caracter y color a un  cacho de memoria de video.

Cuadrado VGA

Podemos cambiar de color directamente (leer  paleta,modificar colores, establecer color) o hacerlo interactivo:  creando una nueva interrupción (así), en la que leemos el buffer de teclado (puerto 0x60) y en función de las teclas pulsadas modificaremos los colores.  En mi caso: A y Z modifican los rojos, S y X los verdes y C y D los azules. Para hacerlo aún más pijotero, podemos hacer  un bucle mágico para escribir los valores actuales de cada color en la memoria de video.

Y esto es lo que tenemos al final:


(si os sale que el video no está disponible, entrad aqui)

Credits: Las funciones "establece_color", "lee_paleta" e "indice_DAC" han sido sacadas del libro de apuntes de la asignatura, descargable aquí.

 

2 comentarios

jon -

Muchas gracias Marta. Está de lujo tu trabajo. Gracias también por los apuntes de periféricos que he descargado. Por cierto, he visto algunas fotos y eres guapísima, una escultura humana. Mucha suerte

lsp -

¿Cómo dibujas el rectángulo en modo texto? Es que yo lo estaba haciendo en modo gráfico 13h, bastante fácil, hasta que me he dado cuenta en el enunciado que lo estaba haciendo mal. Estoy haciendo dos bucles anidados y pongo *(cuadrado + i +j)=' ' y me sale un minirectangulo verde, y no sé ni porque es verde ni como ponerlo en el centro.