Ensamblador - Modo Gráfico 800x600 256c

 
Vista:

Modo Gráfico 800x600 256c

Publicado por Daniel (2 intervenciones) el 05/06/2004 04:57:34
Le agradecería mucho que me ayudaran a con las interrupciones para el manejo de a resolución 800 por 600 con 256 colores, no puedo ponerla, ni se como se accede a la memoria para dibujar algo en la pantalla. Gracias!
Valora esta pregunta
Me gusta: Está pregunta es útil y esta claraNo me gusta: Está pregunta no esta clara o no es útil
0
Responder
sin imagen de perfil

Pensalo bien

Publicado por Jorge (126 intervenciones) el 05/06/2004 07:40:27
Hola Dani,

yo te puedo ayudar, pero no sé si te conviene. Te cuento, cómo labura el modo y vos verás. Cuando tenés 800x600x256, lo que tenés es 800x600 bytes, que es algo así como 468,75Kb. Si alguna vez escribiste directamente un pixel en modo gráfico, sabrás que el segmento para escribir los datos de video está en A000h y que no cubre ni soñando los 468kb de ese modo. ¿Cómo se solucionó esto? bueno, en el estándar VESA definió una mecánica de trabajo por ventana. De este modo el segmento A000h es ahora una "ventana" a un determinado conjunto de datos de la memoria de video real, lo que significa que si bien podemos recorrer con nuestra ventana toda la memoria de video, sólo podemos acceder a ella de segmentos de 64Kb a la vez.; si queremos leer los 64Kb siguientes debemos mover la ventana a otra región de la memoria de video. Esto hace que tengas que hacer un desplazamiento de la ventana a medida que dibujás. También es cierto que la calidad gráfica es muchísimo mejor que en 320x200 ó 640x480 a 16 colores.

Bueno, cualquier cosa volvé a escribir y seguimos con esto.

Chau!
Valora esta respuesta
Me gusta: Está respuesta es útil y esta claraNo me gusta: Está respuesta no esta clara o no es útil
0
Comentar

RE:Pensalo bien

Publicado por Rogelio (1 intervención) el 07/06/2004 17:38:39
Es interesante este método de la ventana, pero cuando escribo en A000h byte primero, cómo escribo el byte 64 k's más adelante ?
Sigue siendo el segmento A000h ? o tengo que cambiar de segmento ?
Dos pixeles no pueden estar direccionados por el mismo byte, por ejemplo el A000:0 h.
Valora esta respuesta
Me gusta: Está respuesta es útil y esta claraNo me gusta: Está respuesta no esta clara o no es útil
0
Comentar
sin imagen de perfil

Algo de VESA

Publicado por Jorge (126 intervenciones) el 10/06/2004 06:11:45
Hola Rogelio,

bueno, el tema de la ventana viene a consecuencia de lo que decís: NO se puede direccionar tanta cantidad de memoria con el segmento de 64Kb, lo que hace el hardware (a VESA gracias) es interpretar las direcciones del segmento A000h como relativas a una porción de la memoria de video (recordemos que la memoria de video es un chip de memoria a parte de la RAM * ). Entonces, existe la posibilidad de fijar un desplazamiento en la placa de video (a través de un registro), para que escribiendo en el mismo segmento A000h podamos leer y escribir distintas secciones de la memoria de video. Esto por un lado es un mecanismo simple, pero implica más trabajo.

El resto de las operaciones no difiere mucho del tratamiento que hacemos en un modo 320x200 a 256 colores. Por lo tanto es más sencillo de programar a través de VESA que directamente, aunque implique algunas operaciones extra. Hoy día se puede acceder a toda la memoria en forma "lineal", pero ya es tema para ser tratado para gente que sepa mucho más que yo, jaja ;-)

Como tengo ganas de escribir, vamos a inicializar un modo de 800x600 a 256 colores. Básicamente nuestro programa inicializará el modo de video, limpiará la pantalla con un color determinado (de esta forma recorreremos toda la memoria de video) y hará una pausa antes de retornar al modo original. El cuerpo del programa principal será este:
Valora esta respuesta
Me gusta: Está respuesta es útil y esta claraNo me gusta: Está respuesta no esta clara o no es útil
0
Comentar
sin imagen de perfil

Algo de VESA 2

Publicado por Jorge (126 intervenciones) el 10/06/2004 06:15:11
Principal PROC NEAR
mov bx, 102h ;Elegimos la resolución de video
CALL IniciarVideo ;Inicializa el modo de video
jc @ERROR ;En caso de error sale del programa
mov al, 20 ;Se elije un color
CALL LimpiarPantalla ;Limpia la pantalla
CALL Pausa ;Espera que se presione una tecla
mov bx, 3 ;Restauramos al modo texto
CALL IniciarVideo ;Restaura el modo de video

@ERROR:
mov ax, 4C00h
Int 21h ;Terminamos la ejecución del programa
ret
Principal ENDP

Comenzaremos por definir la inicialización de video:
Como el estándar VESA intenta influir lo menos posible en los modos VGA estándar, y puesto que los llamados a la Int 10h están casi todos ocupados, los modos VESA usan la subfunción AH=0F, porque esa subfunción no es usada.

Así, tenemos en AL: 02 = Set Super VGA Mode; 03 = Get Super VGA Mode.

Los modos VGA comunes toman sólo 7 bits para designar el modo de pantalla (resolución+colores), el que se indica en AL y van del 00h al 13h. Los modos del 14h al 7Fh están reservados. Por lo que los modos VESA que requieren 8 bits, tuvieron que implementarse de otra forma. Éstos modos se pasan en BX y comienzan a partir del 100h. Un breve tabla de modos es ésta:
- 100h 640x400x256c
- 101h 640x480x256c
- 102h 800x600x256c
- ...

Para nuestro caso usaremos el 102h y definimos la función IniciarVideo como sigue:

Sigue en el "Algo de VESA 3"
Valora esta respuesta
Me gusta: Está respuesta es útil y esta claraNo me gusta: Está respuesta no esta clara o no es útil
0
Comentar
sin imagen de perfil

Algo de VESA 3

Publicado por Jorge (126 intervenciones) el 10/06/2004 06:16:51
IniciarVideo PROC NEAR ;Recibe en BX el modo deseado y deja el FC=0 si todo está bien
mov ah, 0Fh ; esto indica una subfunción VESA
mov al, 02h ; escogemos setear el modo SVGA
Int 10h ; Inicializamos el modo!!!

clc
; SIEMPRE hay que comparar el resultado de AX con 4Fh, si es distinto
; hubo un error.
cmp ax, 004Fh
je @OK_VIDEO
stc
@OK_VIDEO:
ret
IniciarVideo ENDP

Hasta acá todo bien, ¿no?. Bueno, antes de seguir quería que hicieramos unos cálculos:
Si el modo es de 800x600, tenemos unos 480.000 pixels. Como cada pixel tiene 256 colores (8 bits=1 byte), tenemos 480.000 bytes, que son 468,75 Kb. Ahora, nuestro segmento de video tiene 64Kb, entonces necesitamos algo así de 7,32 segmentos de 64Kb para trabajar toda esa memoria de video. Como sólo tenemos 64kb, entonces tenemos que dividir la memoria de video en porciones de ese tamaño llamadas BANCOS. El mínimo de bancos es de 8 en este caso (con 7 no nos alcanza).
También es importante saber que los bancos representan líneas en la HORIZONTAL, es decir que (en este caso) los primeros 800 bytes del primer banco permiten acceso a la primer línea de más arriba de la pantalla, los segundos 800 a la segunda línea y así. Un banco de 64Kb puede almacenar 81,92 líneas de 800 pixels cada una. Si imaginamos esto, veremos que trazar una línea diagonal de esquina a esquina de la pantalla, implica escribir en los 8 bancos que tenemos.

Sigue en "Algo de VESA 4"
Valora esta respuesta
Me gusta: Está respuesta es útil y esta claraNo me gusta: Está respuesta no esta clara o no es útil
0
Comentar
sin imagen de perfil

Algo de VESA 4

Publicado por Jorge (126 intervenciones) el 10/06/2004 06:18:44
Un problema más a resolver es "¿cómo indicamos a la placa de video el banco que queremos que mapee al segmento A000h?". Bien, para esto haremos una función llamada "CambioDeBanco" que tome en DX el número de banco al que se desee cambiar.

Para esto, primero debemos:

;Definir una constante con el máximo número de bancos:
MAX_BANCOS EQU 8

;Y por otra parte siempre deberemos ser consientes
;del Nº de banco que estamos viendo, por ello:
bancoActual DB 0

Ahora programaremos la función CambioDeBanco, utilizando la subfunción VESA 05h, que toma BX=0 y en DX el número de banco al que se desea cambiar:

CambioDeBanco PROC NEAR ; Recibe en DX el Nº de banco (un número entre 0 y 7)
push ax
push bx
mov ax, 4F05h ;Elijo la subfunción
xor bx, bx ;Pongo BX a 0
cmp dx, MAX_BANCOS ;Comparo el número de banco por las dudas
ja @ErrorDeBanco
@cambiarBanco:
mov bancoActual, dl ;Guardo el número de banco
Int 10h ;Hago el cambio
pop bx
pop ax
ret
@ErrorDeBanco:
mov dx, MAX_BANCOS
jmp @cambiarBanco
CambioDeBanco ENDP

Sigue en "Algo de VESA 5"
Valora esta respuesta
Me gusta: Está respuesta es útil y esta claraNo me gusta: Está respuesta no esta clara o no es útil
0
Comentar
sin imagen de perfil

Algo de VESA 5

Publicado por Jorge (126 intervenciones) el 10/06/2004 06:20:53
Bien, con esto ya podemos elegir a voluntad la porción de memoria donde escribir. Ahora queda lo más sencillo: llenar la memoria con un valor de byte pasado por parámetro en AL. Para ello, recordemos que pintar un pixel equivale a escribir en A000h, por lo que no es difícil. Sin embargo, para darle algo de velocidad, voy a emplear la instrucción de string STOSW, que copia el contenido de AX en ES:DI e incrementa DI, combinada con REP, de modo tal que la iteracción se repita hasta llenar todo el segmento A000h.

LimpiarPantalla PROC NEAR
push ax
push dx
push cx
push es
push di ;Guardo el estado de los registros

; Pongo cx para repetir la operación tantas veces
; como BANCOS halla
mov cx, MAX_BANCOS
; Como voy a usar una operación de 16 bits, copio
; el color que me pasaron en AL en AH, así gano velocidad
mov ah, al
; Pongo DX en cero para acceder al primer banco
xor dx, dx
limpiando_Clr:
Call BankSwitch ;Elijo el banco
push cx
mov cx, 0A000h
mov es, cx ;Configuro el segmento
xor di, di ;Inicializo DI
mov cx, 32768 ;Elijo repetir la operación hasta llenar el segmento
REP stosw ;Ejecuto la copia
pop cx
inc dx ;Incremento el banco
loop limpiando_Clr

pop di ;Restauro los registros
pop es
pop cx
pop dx
pop ax
ret
LimpiarPantalla ENDP

Sigue en "Algo de VESA 6"
Valora esta respuesta
Me gusta: Está respuesta es útil y esta claraNo me gusta: Está respuesta no esta clara o no es útil
0
Comentar
sin imagen de perfil

Algo de VESA 6

Publicado por Jorge (126 intervenciones) el 10/06/2004 06:25:38
Si me han seguido el paso hasta acá, ya casi concluimos el ejemplo, pero la verdad que hasta yo me pierdo, jajaja...

Antes de seguir, espero que se den cuenta que al dar el código por partes, las mismas no sólo requieren la combinación, sino que se completen los encabezados, etc...

Bueno, nos queda hacer la pausa, que no creo que sea muy necesario explicarla, porque es parte del uso coidiano de la Int 21h y referencias encontrarán a miles.

Pausa PROC NEAR ; Espera que se presione una tecla y la devuelve en AL
push dx
push ax

wait_:
mov ah, 6
mov dl, 255
Int 21h
jz wait_

pop dx
mov ah, dh
pop dx
ret
Pausa ENDP

Bueno, esto es todo, seguro habré dejado mil baches, pero con que me los pregunten y me den un par de días para contestar, les estaré agradecido.

Finalmente, quiero decirles que esto es muy rústico, no está optimizado, ni siquiera es una forma "buena" de hacerlo.
Realmente faltó automatizar muchas cosas, por ejemplo la declaración de la cantidad de bancos como una constante igual a 8 va a funcionar en la gran mayoría de las máquinas, pero en algunas podrían verse rayas, porque las distintas placas de video tienen distintos tamaños de "ventana" ó "banco" predeterminados (no siempre son 64Kb) y deberían consultarse a través de la subfunción VESA 01h. Sin embargo espero que les haya gustado y estoy seguro que para empezar a hacer pruebas les servirá muy bien.

Sigue en "Algo de VESA 7"
Valora esta respuesta
Me gusta: Está respuesta es útil y esta claraNo me gusta: Está respuesta no esta clara o no es útil
0
Comentar
sin imagen de perfil

Algo de VESA 7

Publicado por Jorge (126 intervenciones) el 10/06/2004 06:27:45
Si van a emplear este modo para y trabajar con gráficos y demás, les recomiendo hacer primitivas de circulo, líneas, rectángulos y óvalos; además de la nunca bien ponderada PutPixel. Con ello van a poder hacer cosas realmente llamativas.

Un saludo a todos!!!

PD: lamento hacerlo tan cortado, pero en las respuestas a los foros hay un cierto límite respecto del número de caracteres. Por ejemplo la nota que se sigue corresponde, creo, al primer post.

* Hoy día se puede usar RAM como memoria de video, pero para simplificar es mejor verlo así que es como debería funcionar en realidad.
Valora esta respuesta
Me gusta: Está respuesta es útil y esta claraNo me gusta: Está respuesta no esta clara o no es útil
0
Comentar

RE:Algo de VESA 7

Publicado por Javier (27 intervenciones) el 10/06/2004 17:34:48
SI SEÑOR, SI SEÑOR, BRAVO, BRAVO.

Eres todo un profesional. Tu no eres un forero standard. Te aplaudo y felicito. Enhorabuena. Me has aclarado una duda que toda la vida he tenido, el programar en modo no standard. Había programado en modo texto, en modo 320 x 200 x 256 colores, pero nunca lo había hecho en 800 x 600 y creo que me ha quedado muy claro.

Ahora me surge una duda....el modo 1024 x 768 x 65536 colores (modo 16 bits de color) funciona igual ?. Yo tengo el libro donde se explican los registros de la SVGA (no recuerdo ahora mismo el título ya que estoy en el trabajo y no lo puedo mirar) pero no he logrado más que hacer alguna cosita simple (como por ejemplo desactivar el bit de video). Sin embargo no logré entender como se conmutaba de banco. Esa era mi duda. Ahora ya sé que usando la funcion 4f05h puedo lograrlo y volveré a releer el libro por lo que si necesitas alguna cosa, me pongo a tu disposición al respecto.

Saludos cordiales y FELICIDADES EN NOMBRE DEL FORO.
[email protected]
MADRID
Valora esta respuesta
Me gusta: Está respuesta es útil y esta claraNo me gusta: Está respuesta no esta clara o no es útil
0
Comentar
sin imagen de perfil

Se agradece, che

Publicado por Jorge (126 intervenciones) el 11/06/2004 06:07:43
Hola Javier,
gracias por todo lo que decís. Si bien nunca hize una aplicación de 1024x768x16 bits de color, sí te puedo asegurar que va a funcionar igual que esto, pero con más bancos y siempre teniendo en mente que vas a usar 2 bytes por pixel, y que en vez de existir una paleta (como en el caso de los de 256 colores), la combinación RGB entera está en esos 16 bits. Pero ya que estoy, aprovecho y explico algo más.
Dependiendo de la cantidad de bits por color, la placa de video interpreta distinto su RGB. Así, si se trata de un modo de 8 bits, los mismos no especifican el RGB, sino un índice a una tabla de colores que guarda internamente, si el modo es de 15 bits (que si bien usa 16 bits por cuestiones técnicas), el primer bit no se usa, y los siguientes definen el RGB en grupos de 5 (normalmente verán que se anota 1:5:5:5). Si el modo es de 16 bits, se usa el RGB como 5:6:5, esto es que la componente VERDE (G) tiene un bit más de color que el resto. Nótese que la deformación de color rojo y verde puede ser notable si no se sabe cuál modo se usa. Esta es una tabla de los modos más avanzados:
110h - 640x480 32K (1:5:5:5)
111h - 640x480 64K (5:6:5)
112h - 640x480 16.8M (8:8:8)
113h - 800x600 32K (1:5:5:5)
114h - 800x600 64K (5:6:5)
115h - 800x600 16.8M (8:8:8)
116h - 1024x768 32K (1:5:5:5)
117h - 1024x768 64K (5:6:5)
118h - 1024x768 16.8M (8:8:8)
119h - 1280x1024 32K (1:5:5:5)
11Ah - 1280x1024 64K (5:6:5)
11Bh - 1280x1024 16.8M (8:8:8)
Valora esta respuesta
Me gusta: Está respuesta es útil y esta claraNo me gusta: Está respuesta no esta clara o no es útil
0
Comentar
sin imagen de perfil

Paleta en 256 colores

Publicado por Jorge (126 intervenciones) el 11/06/2004 06:26:57
Bueno, como resulta incómodo buscar y probar qué significa cada número de color en un modo de 256 colores (como dije antes, en estos modos se especifica un índice y no un RGB), vamos a ver como se configura la paleta interna de colores.
El método es sencillo; hay tres registros fundamentales en toda placa de video asociados al color y que se mapean a los puertos: 3C7h, 3C8h y 3C9h.
Recordemos que los puertos son parte de una memoria adicional, distinta de la ram, que consta de 64kb y sirve para comunicarse directamente con los dispositivos conectados al PC. Para leer ó escribir en ellos se usan las instrucciones IN y OUT respectivamente.
Así, el puerto 3C7h sirve para indicar a la placa de video, un número de color de la paleta cuyo RGB se quiere saber. Se escribe el número (0..255) en ese puerto y se lee tres veces consecutivas el puerto 3C9h, obteniendo así 3 bytes que representan el RGB del índice indicado.
Algo igual sucede con la asignación de color a un índice determinado. Se escribe el número de color deseado en 3C8h y luego se escriben 3 bytes más en el puerto 3C9h, que simbolizan el RGB.
Recuerden además que un modo de 256 colores no significa que hay colores que no se pueden formar, sino que sólo se muestran 256 colores a la vez. Un ejemplo:

SetearColor PROC NEAR ; Recibe en AL el Nº de color de la paleta y en AH, BL, BH los valores RGB
push dx
push ax
mov dx, 3C8h
out dx, al
mov al, ah
inc dx ;DX=3C9h
out dx, al
mov al, bl
out dx, al
mov al, bh
out dx, al
pop ax
pop dx
ret
SetearColor ENDP
Valora esta respuesta
Me gusta: Está respuesta es útil y esta claraNo me gusta: Está respuesta no esta clara o no es útil
0
Comentar

RE:Modo Gráfico 800x600 256c

Publicado por Daniel (2 intervenciones) el 06/07/2004 02:54:07
Gracias por la ayuda, eres muy bueno en esto Jorge te lo agradesco, quiero preguntarte si no sabes donde consigo un desensamblador?.
Valora esta respuesta
Me gusta: Está respuesta es útil y esta claraNo me gusta: Está respuesta no esta clara o no es útil
0
Comentar

desplazamiento de pantalla

Publicado por ROSY (1 intervención) el 23/11/2004 02:33:36
HOLA ALGUIEN QUE FUERA TAN AMABLE DE AYUDARME CON UN
PROGRAMA QUE DESPLAZE UNA FIGURA A LO LARGO DE LA PANTALLA EN ENSAMBLADOR

PORFAVOR , GRACIAS
Valora esta respuesta
Me gusta: Está respuesta es útil y esta claraNo me gusta: Está respuesta no esta clara o no es útil
0
Comentar