; Programme pour illustrer l'affichage de pixels en mode 320x400 en 256 ; couleurs sur VGA. Affiche 8 lignes pour former un octogone, un pixel ; à la fois. Affiche 8 octogones en tout, l'un au dessus de l'autre, ; chacun dans un jeu de couleurs différent. Bien qu'inutilisée, une fonction ; lecture du pixel est également fournie. ; ; Assemblé avec TASM 4.0, lié avec TLINK 6.10 ; Testé par Jim Mischel 11/21/94 ; VGA_SEGMENT equ 0a000h SC_INDEX equ 3c4h ;registre Index de Sequence ControllerGC_INDEX equ 3ceh ;registre Index de Graphics ControllerCRTC_INDEX equ 3d4h ;registre Controller Index CRT MAP_MASK equ 2 ;index du registre Map Mask dans SC MEMORY_MODE equ 4 ;index du registre Memory Mode dans SC MAX_SCAN_LINE equ 9 ;index du registre Maximum Scan Line ;dans CRTC START_ADDRESS_HIGH equ 0ch ;index du registre Start Address High ;dans CRTC UNDERLINE equ 14h ;index du registre Underline Location ;dans CRTC MODE_CONTROL equ 17h ;index du registre Mode Control ;dans CRTC READ_MAP equ 4 ;index du registre Read Map dans GC GRAPHICS_MODE equ 5 ;index du registre Graphics Mode ;dans GC MISCELLANEOUS equ 6 ;index du registre Miscellaneous ;dans GC SCREEN_WIDTH equ 320 ;nombre de pixels en largeur SCREEN_HEIGHT equ 400 ;nombre de lignes d'affichage à ;l'écran WORD_OUTS_OK equ 1 ;à 0 pour assembler pour les ;ordinateurs qui ne peuvent pas ;traiter les outs de mot dans les ;registres VGA ; stack segment para stack 'STACK' db 512 dup (?) stack ends ; Data segment word 'DATA' ; BaseColor db 0 ; ; Structure utilisée pour contrôler l'affichage d'une ligne. ; LineControl struc StartX dw ? StartY dw ? LineXInc dw ? LineYInc dw ? BaseLength dw ? LineColor db ? LineControl ends ; ; Liste de descripteurs des lignes à afficher. ; LineList label LineControl LineControl <130,110,1,0,60,0> LineControl <190,110,1,1,60,1> LineControl <250,170,0,1,60,2> LineControl <250,230,-1,1,60,3> LineControl <190,290,-1,0,60,4> LineControl <130,290,-1,-1,60,5> LineControl <70,230,0,-1,60,6> LineControl <70,170,1,-1,60,7> LineControl <-1,0,0,0,0,0> Data ends ; ; Macro pour diriger une valeur 16bits sur un port. ; OUT_WORD macro if WORD_OUTS_OK out dx,ax else out dx,al inc dx xchg ah,al out dx,al dec dx xchg ah,al endif endm ; ; Macro pour diriger une valeur constante sur le registre indexé VGA. ; CONSTANT_TO_INDEXED_REGISTER macro ADDRESS, INDEX, VALUE mov dx,ADDRESS mov ax,(VALUE shl 8) + INDEX OUT_WORD endm ; Code segment assume cs:Code, ds:Data Start proc near mov ax,Data mov ds,ax ; ; Configure le mode 320x400 en 256 couleurs. ; call Set320By400Mode ; ; Nous sommes en mode 320x400 en 256 couleurs. Affiche chaque ligne l'une après ;l'autre. ; ColorLoop: mov si,offset LineList ;pointe sur le début de la ;liste de descripteurs de ligne LineLoop: mov cx,[si+StartX] ;paramètre la coordonnée X initiale cmp cx,-1 jz LinesDone ;descripteur de coordonnée X ; -1 marque la fin de la liste mov dx,[si+StartY] ;paramètre la coordonnée Y initiale, mov bl,[si+LineColor] ;couleur de la ligne, mov bp,[si+BaseLength] ; et le compte des pixels add bl,[BaseColor] ;ajuste la couleur de la ligne ;en fonction de BaseColor PixelLoop: push cx ;sauve les coordonnées push dx call WritePixel ;affiche ce pixel pop dx ;retrouve les coordonnées pop cx add cx,[si+LineXInc] ;paramètre les coordonnées du add dx,[si+LineYInc] ;prochain point de la ligne dec bp ;y a-t-il d'autres points? jnz PixelLoop ;oui, affichons le prochain add si,size LineControl ;pointe sur le prochain ;descripteur de la ligne jmp LineLoop ; et affiche la prochaine ligne LinesDone: call GetNextKey ;attend une touche clavier, puis inc [BaseColor] ;bump la sélection de couleur et cmp [BaseColor],8 ;vérifie si nous avons fini jb ColorLoop ;pas encore ; ; Attend une touche clavier et revient en mode texte, puis termine après ; une touche clavier. ; call GetNextKey mov ax,0003h int 10h ;mode texte mov ah,4ch int 21h ;nous avons fini ; Start endp ; ; Configure le mode 320x400 en 256 couleurs. ; ; Entrée: aucune ; ; Sortie: aucune ; Set320By400Mode proc near ; ; Premièrement, passe en mode normal 320x200 256 couleurs, qui est en fait ; un mode 320x400 256 couleurs dont chaque ligne est affichée deux fois. ; mov ax,0013h ;AH = 0 signifie mode initialisé, ;AL = 13h sélectionne ;le mode graphique 256 couleurs int 10h ;interruption vidéo du BIOS ; ; Change l'adressage CPU de la mémoire vidéo en linéaire (ni pair/impair, ; ni chaîne, ni chaîne 4), pour nous permettre d'accéder à tous les 256K ; de la mémoire vidéo. Une fois fait, la VGA ressemblera à la mémoire ; en modes 10h et 12h, excepté que chaque octet de la mémoire vidéo ; contrôlera un pixel de 256 couleurs, avec 4 pixels adjacents à toute adresse ; donnée, un pixel par plan. ; mov dx,SC_INDEX mov al,MEMORY_MODE out dx,al inc dx in al,dx and al,not 08h ;désactive la chaîne 4 or al,04h ;désactive pair/impair out dx,al mov dx,GC_INDEX mov al,GRAPHICS_MODE out dx,al inc dx in al,dx and al,not 10h ;désactive pair/impair out dx,al dec dx mov al,MISCELLANEOUS out dx,al inc dx in al,dx and al,not 02h ;désactive la chaîne out dx,al ; ; Efface maintenant l'écran en entier, car le mode 13h mode initialisé ; a effacé seulement 64K des 256K de la mémoire vidéo. ; CONSTANT_TO_INDEXED_REGISTER SC_INDEX,MAP_MASK,0fh ;active l'écriture de tous les plans, ;nous pouvons donc effacer 4 pixels à la fois mov ax,VGA_SEGMENT mov es,ax sub di,di mov ax,di mov cx,8000h ;nombre de mots dans 64K cld rep stosw ;efface toute la mémoire vidéo ; ; Règle le mode en mode 320x400 en 256 couleurs en ne parcourant pas chaque ; ligne deux fois. ; mov dx,CRTC_INDEX mov al,MAX_SCAN_LINE out dx,al inc dx in al,dx and al,not 1fh ;paramètre la ligne d'affichage ;maximale = 0 out dx,al dec dx ; ; Change le parcours CRTC du mode double mot en mode octet, permettant ; à CRTC de parcourir plus de 64K de données vidéo. ; mov al,UNDERLINE out dx,al inc dx in al,dx and al,not 40h ;désactive le double mot out dx,al dec dx mov al,MODE_CONTROL out dx,al inc dx in al,dx or al,40h ;active le bit du mode octet, la ;mémoire est parcourue pour les ; données vidéo de manière purement linéaire ; comme dans les modes 10h et 12h out dx,al ret Set320By400Mode endp ; ; Affiche un pixel dans la couleur spécifiée à l'emplacement ; spécifié en mode 320x400 en 256 couleurs. ; ; Entrée: ; CX = coordonnée X du pixel ; DX = coordonnée Y du pixel ; BL = couleur du pixel ; ; Sortie: aucune ; ; Registres altérés: AX, CX, DX, DI, ES ; WritePixel proc near mov ax,VGA_SEGMENT mov es,ax ;pointe sur la mémoire vidéo mov ax,SCREEN_WIDTH/4 ;il y a 4 pixels à chaque adresse, aussi ; chaque rangée de 320 pixels est large de 80 octets ; dans chaque plan mul dx ;pointe sur le début de la rangée ;désirée push cx ;met de coté la coordonnée X shr cx,1 ;il y a 4 pixels à chaque adresse shr cx,1 ;aussi divisons la coordonnée X ;par 4 add ax,cx ;pointe sur l'adresse du pixel pop cx ;récupère la coordonnée X and cl,3 ;récupère le numéro du plan du pixel ; mov ah,1 shl ah,cl ;paramètre le bit correspondant au ;plan dans lequel ;est le pixel mov al,MAP_MASK mov dx,SC_INDEX OUT_WORD ;paramètre l'écriture sur le plan correct ;du pixel mov es:[di],bl ;affiche le pixel ret WritePixel endp ; ; Lit la couleur du pixel à l'emplacement spécifié dans le mode 320x400 ; en 256 couleurs. ; ; Entrée: ; CX = coordonnée X du pixel à lire ; DX = coordonnée Y du pixel à lire ; ; Sortie: ; AL = couleur du pixel ; ; Registres altérés: AX, CX, DX, SI, ES ; ReadPixel proc near mov ax,VGA_SEGMENT mov es,ax ;pointe sur la mémoire vidéo mov ax,SCREEN_WIDTH/4 ;il y a 4 pixels à chaque adresse, aussi ; chaque rangée de 320 pixels est large de 80 octets ; dans chaque plan mul dx ;pointe sur le début de la rangée ;désirée push cx ;met de coté la coordonnée X shr cx,1 ;il y a 4 pixels à chaque adresse shr cx,1 ; aussi divisons la coordonnée X ; par 4 add ax,cx ;pointe sur l'adresse du pixel mov si,ax pop ax ;récupère la coordonnée X and al,3 ;récupère le numéro du plan du pixel ; mov ah,al mov al,READ_MAP mov dx,GC_INDEX OUT_WORD ;paramètre la lecture à partir du plan adéquat ; du ; pixel lods byte ptr es:[si] ;lit le pixel ret ReadPixel endp ; ; Attend une prochaine touche clavier et la retourne dans AX. ; ; Entrée: aucune ; ; Sortie: ; AX = code plein 16 bits de la touche clavier ; GetNextKey proc near WaitKey: mov ah,1 int 16h jz WaitKey ;attend une touche clavier disponible sub ah,ah int 16h ;lit la touche ret GetNextKey endp ; Code ends ; end Start