Set_VGA PROC mov ax,0013h ;ah=00 al=13h (modalità 320x200x256) int 10h RET Set_VGA ENDPUna 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 ENDPOra che siamo riusciti ad impostare la modalità grafica voluta vediamo come si può mettere un Pixel sullo schermo.
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 ENDPUn 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.
(infatti 320*200-1=63999=F9FFh oppure: 319+ (199*320)=63999=F9FFh)E il punto di coordinate 145,76??
ind = x + ( Y * 320)Chiaro?
LA PALETTE
La palette è la tavolozza dei colori da usare per realizzare 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 opportuno il Rosso, Verde e Blue possiamo ottenere 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 ENDPLa procedura inversa, quella per impostare i valori di R G e B nella palette è la seguente:
set_pal PROC mov dx,3c8h ;porta in cui 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 ENDPSpero 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 pgm che simula l'effetto neve che si vede sui
televisori rotti o non sintonizzati.
Questo è un programma "random", infatti utilizza un generatore di numeri (pseudo)casuali.
NOTE SUL PRG:
SNOW.COM SNOW.ASM ;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 (diverso da 0 e pari) ; (vedi nota finale) 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 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,0C8h ;200 jne Ciclo_y inc bx cmp bx,0140h ;320 jne Ciclo_x mov ax,0003h int 10h ;imposto modalità txt RETN SNOW ENDP ; stampa un pixel alle coordinate y*256 + x*64 ; (se c'Š overflow vale l'implementazione circolare) 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
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_palecco cosa fa: imposta i colori della tavolozza tutti grigi. Siccome i grigi sono 64 e i colori della palette sono 256, questo ciclo intelligentemente ripete la serie dei grigi per 256/64=4 volte. Solo che c'è un errore:
cmp al,0FFhsenza cambiare il tipo di salto (cioè ci rimane jne loop_pal). Infatti quando al ritorna a 0, dopo che il colore numero 255 è stato impostato, la inc imposta il flag di zero per la prima volta! Oppure avrei dovuto riscrivere il ciclo in maniera differente.
L'algoritmo di D.Lehmer dà una serie nulla (dà tutti 0) se num_rnd_mul è 0, percui se uno lo cambia a 0, quando esegue SNOW si vedrà lo schermo completamente nero.
Mi sono divertito a cambiare i numeri:
num_rnd_val dw 12345 ; A caso num_rnd_mul dw 9421 ; A casoho messo al posto di num_rnd_mul un numero pari e al posto di num_rnd_val vari valori ed ho ottenuto che molto rapidamente lo schermo diventatava di un solo colore. Preciso quindi che alcuni valori, forse tutti i valori pari di num_rnd_mul (ci vuole un matematico qui!) non danno l'effetto neve desiderato.
Un'altra cosa da precisare: Put_Pixel non è una procedura general-purpose, (provate a scriverla voi una Put_Pixel "normale"), ma stampa il pixel alle coordinate y*256 + x*64; questa espressione, che può dare overflow, è propria di questo algoritmo (cioè di questa simulazione dell'effetto neve).
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.
Assembly Page di Antonio |
|