Programmazione della VGA

Tratteremo in questo tutorial un argomento tra i più interessanti nella 
programmazione.
Non riuscirò certo a coprire l'intero argomento, mi propongo solo di dare una
infarinatura generale lasciando poi a voi il compito di approfondire 
l'argomento, in rete si trovano molte informazioni sullaprogrammazione della 
scheda video..
Il modo grafico che considererò qui è il 13h, quello della VGA "Standard"
che lavora a 320x200 con 256 colori.
La prima cosa che un programma assembly (ma anche in ogni altro linguaggio) deve 
fare è impostare la modalità; bene, questo può essere fatto utilizzando 
l'int 10h tramite la funzione 00h. Quindi:

	Set_VGA	PROC 
		mov	ax,0013h	;ah=00  al=13h (modalità 320x200x256)
		int	10h
		RET
	Set_VGA	ENDP

Una volta terminato il programma si deve reimpostare la modalità testo, anche 
questo può essere fatto tramite l'int 10h:

	Set_TXT	PROC
		mov	ax,0003h	;ah=00 al=03h	(modalita testo 80x25)
		int	10h
		RET
	Set_TXT	ENDP

Ora che siamo riusciti ad impostare la modalità grafica voluta vediamo come si 
può mettere un Pixel sullo schermo.
Anche per questa operazione si può ricorrere all'int 10h (funzione 0Ch)

	Put_Pixel PROC
		mov	ah,0Ch
		mov	al,Color	;colore del pixel
		mov	cx,X		;coordinata X
		mov	dx,Y		;coordinata Y
		mov	bx,1		;numero di pagina (per le modalità con più pagine)
		int	10h
		RET
	Put_Pixel ENDP

Un problema di questo modo di posizionare un pixel sul video è dato dalla 
lentezza veramente insopportabile in alcune applicazioni, perciò invece di
usare la funzione del BIOS (int 10h) possiamo accedere direttamente alla memoria
video.
Il segmento in cui questa risiede è all'indirizzo A000, quindi il punto di 
coordinate 0,0 sarà allindirizzo A000:0000 quello di coordinate 319,199 a 
A000:FFFF. E il punto di coordinate 145,76??
Bene per trovare l'indirizzo di un generico punto x,y in memoria si può usare la
formula:
	
	ind = x + ( Y * 320)

Chiaro?
OK ma cosa ci mettiamo all'indirizzo calcolato??
Bene a quell'indirizzo ci va l'indice del colore del pixel.
Per capire bene questo dobbiamo fare una parentesi sulla palette.

LA PALETTE
La palette è la tavolozza dei colori da usare per realizzre il nostro disegno.
Si tratta di un array bidimensionale di 256 elementi ognuno dei quali contiene
3 valori che corrispono al livello di Rosso, Verde, Blue (R G B).
	            Palette
		     -------
		    | r|g|b |
		   0|__|_|__|
		    | r|g|b |
		   1|__|_|__|
		    |r |g|b | 
		   2|__|_|__|
		    |  | |  |


Come voi saprete mescolando in modo opporutuno il Rosso, Verde e Blue possiamo
ottnere tutti i colori che vogliamo. Le gradazioni di R G e B vanno da 0 a 63.

Per leggere il valore di R G e B di un colore dalla palette procedo nel modo 
seguente:

get_pal 	PROC
	   	mov    dx,3c7h  ;porta in cui va indicato l'indice del colore
		mov    al,col   ;col è l'indice del colore da leggere (0..255)
		out    dx,al    
                add    dx,2     ;3c9h è la porta da cui si leggono i 3 valori
                in     al,dx    
		mov    R,al  
		in     al,dx    
		mov    G,al  
		in     al,dx    
		mov    B,al  	; in R, G e B ho i valori
		RET
get_pal   ENDP

La procedura inversa, quella per impostare i valori di R G e B nella palette è
la seguente:

set_pal 	PROC
		mov    dx,3c8h		;porta incui va indicato l'indice del colore
					;da scrivere (NB è diverso dal precedente!!)
		mov    al,col
   		out    dx,al		;scrivo sulla porta il colore
   		inc    dx			;3c9 è la porta su cui scrivere i 3 valori R G B 
   		mov    al,R
   		out    dx,al
   		mov    al,G
   		out    dx,al
   		mov    al,B
   		out    dx,al		;ora nella palette c'è il nuovo colore
   		RET
set_pal	ENDP

Spero di aver chiarito cosìè e come funziona la palette.

Tornando al discorso della put_pixel che agisce direttamente in memoria si 
diceva che all'indirizzo calcolato dalla formula si doveva scrivere l'indice
del colore, beh ora è chiaro no? Metto l'indice che il colore ha nella palette.

Per concludere il discorso vi lascio un esempio che utilizza un po' tutte le
funzioni viste. Si tratta di un pgmche simula l'effetto neve che si vede sui
televisori rotti o non sintonizzati.

;SNOW.ASM - By b0nu$, 1997
.286
SEG_A     SEGMENT
          ASSUME CS:SEG_A, DS:SEG_A
          ORG     100H

SNOW	  PROC FAR
	  INIT:   JMP     START
	     
rgb			db	3 dup(?)	; Array che contiene i valori di R G B del colore
num_rnd_val	dw	12345	; A caso
num_rnd_mul	dw	9421		; A caso



        START:  
		mov	ax,0013h
		int	10h		;imposto modalità 320x200
		
		xor	ax,ax
		
loop_pal:	mov	rgb[0],al
		mov	rgb[1],al
		mov	rgb[2],al
		CALL 	Set_Pal	; imposto la palette con tutte le tonalità di 
						; grigio nel quale si ha R=G=B.
		inc	al
		cmp	al,0FFh
		jne	loop_pal		
		
		xor	bx,bx		;x=0
Ciclo_x:	xor	dx,dx		;y=0	;parto da 0,0
		
Ciclo_y:	push	dx			;questo ciclo posiziona a caso pixel sullo schermo
		push	dx	
		CALL	Random
		pop	dx
  		CALL Put_Pixel
		pop	dx
		inc	dx
		cmp	dx,0C7h	;199
		jne	Ciclo_y
		inc	bx
		cmp	bx,013Fh	;319
		jne	Ciclo_x
		
		mov	ax,0003h
		int	10h		;imposto modalità txt
          RETN
SNOW      ENDP

Put_Pixel	PROC 		;dx=y  bx=x   ah=col
		push	ax		;usa l'accesso diretto in memoria video
		mov  ax,0A000h
   		mov  es,ax
		push	bx
		mov	dh,dl
		xor	dl,dl
		shl	bx,6
		add	dx,bx
		pop	bx
		add	bx,dx
		mov	di,bx
		xor	al,al
		pop	ax	;prelevo il colore
		mov	es:[di],ah
		RET
Put_Pixel	ENDP

Set_Pal	PROC				;al=colore
		mov    dx,3c8h
   		;mov    al,[col]
	   	out    dx,al
   		inc    dx
   		mov    al,rgb[0]	;red
	 	out    dx,al
   		mov    al,rgb[1]	;green
   		out    dx,al	
  	 	mov    al,rgb[2]	;blue
   		out    dx,al
		RET
Set_Pal	ENDP

Random	PROC			;Genera un numero casuale con l'algoritmo
					; di D.Lehmer 
		mov	ax,num_rnd_val
		mul	num_rnd_mul
		inc	ax
		mov	num_rnd_val,ax
		RET
Random	ENDP

SEG_A     ENDS
          END     INIT


Naturalmente non pretendo certo di aver coperto l'intero l'argomento, prendetelo 
solo come un introduzione, un punto di partenza da cui spiccare il salto verso la
grafica avanzata.
Qui spero solo di avervi fatto capire alcuni meccanismi che stanno alla base 
della programmazione della scheda video VGA.


** [email protected] **