; Programme pour illustrer l'utilisation du registre Read Map en mode read 0. ; Anime en copiant une image 16 couleurs depuis la mémoire VGA vers la mémoire système ; un plan à la fois, puis en recopiant l'image à un nouvel emplacement de la ; mémoire VGA. ; ; Assemblé avec TASM 4.0, lié avec TLINK 6.10 ; Testé par Jim Mischel 11/21/94 ; stack segment word stack 'STACK' db 512 dup (?) stack ends ; data segment word 'DATA' IMAGE_WIDTH EQU 4 ;en octets IMAGE_HEIGHT EQU 32 ;en pixels LEFT_BOUND EQU 10 ;en octets RIGHT_BOUND EQU 66 ;en octets VGA_SEGMENT EQU 0a000h SCREEN_WIDTH EQU 80 ;en octets SC_INDEX EQU 3c4h ;registre Index SC GC_INDEX EQU 3ceh ;registre Index GC MAP_MASK EQU 2 ;index du registre Map Mask dans SC READ_MAP EQU 4 ;index du registre Read Map dans GC ; ;Motif de base pour une image 16 couleurs. ; PatternPlane0 label byte db 32 dup (0ffh,0ffh,0,0) PatternPlane1 label byte db 32 dup (0ffh,0,0ffh,0) PatternPlane2 label byte db 32 dup (0f0h,0f0h,0f0h,0f0h) PatternPlane3 label byte db 32 dup (0cch,0cch,0cch,0cch) ; ;Stockage temporaire pour une image 16 couleurs pendant l'animation. ; ImagePlane0 db 32*4 dup (?) ImagePlane1 db 32*4 dup (?) ImagePlane2 db 32*4 dup (?) ImagePlane3 db 32*4 dup (?) ; ;Emplacement & direction de l'image courante. ; ImageX dw 40 ;en octets ImageY dw 100 ;en pixels ImageXDirection dw 1 ;en octets data ends ; code segment word 'CODE' assume cs:code,ds:data Start proc near cld mov ax,data mov ds,ax ; ; Sélectionne le mode graphique 10h. ; mov ax,10h int 10h ; ; Affiche l'image initiale. ; mov si,offset PatternPlane0 call DrawImage ; ; Boucle pour animer en copiant l'image depuis la mémoire VGA vers la mémoire ; système en effaçant l'image, et en copiant l'image depuis la mémoire système vers un ; nouvel emplacement dans la mémoire vidéo. Termine après la réception d'une touche ; clavier. AnimateLoop: ; ; Copie l'image de la mémoire VGA dans la mémoire système. ; mov di,offset ImagePlane0 call GetImage ; ; Efface l'image de la mémoire VGA. ; call EraseImage ; ; Avance la coordonnée X de l'image, en inversant la direction si l'un des coté ; de l'écran est atteint. ; mov ax,[ImageX] cmp ax,LEFT_BOUND jz ReverseDirection cmp ax,RIGHT_BOUND jnz SetNewX ReverseDirection: neg [ImageXDirection] SetNewX: add ax,[ImageXDirection] mov [ImageX],ax ; ; Affiche l'image en la copiant depuis la mémoire système dans la mémoire VGA. ; mov si,offset ImagePlane0 call DrawImage ; ; Ralentit un peu la vitesse par souci de visibilité (l'ajuste en fonction des besoins) ; mov cx,0 DelayLoop: loop DelayLoop ; ; Vérifie si une touche clavier a été pressée pour terminer le programme. ; mov ah,1 int 16h jz AnimateLoop ; ; Revient en mode texte, puis à DOS. ; sub ah,ah int 16h mov ax,3 int 10h mov ah,4ch int 21h Start endp ; ; Affiche l'image à l'offset DS:SI à l'emplacement de l'image courante ; dans la mémoire VGA. ; DrawImage proc near mov ax,VGA_SEGMENT mov es,ax call GetImageOffset ;ES:DI est l'adresse de destination ;pour l'image en mémoire VGA mov dx,SC_INDEX mov al,1 ;traite le plan 0 en premier DrawImagePlaneLoop: push di ;l'image est affichée au même offset ;dans chaque plan push ax ;préserve le plan sélectionné mov al,MAP_MASK ;index Map Mask out dx,al ;Index SC pointe sur le registre Map ; Mask pop ax ;récupère le plan sélectionné inc dx ;pointe sur le registre index SC out dx,al ;configure Map Mask pour permettre ;l'écriture dans le plan intéressant dec dx ;repointe sur le registre Data SC mov bx,IMAGE_HEIGHT ;nombre de lignes d'affichage ;dans l'image DrawImageLoop: mov cx,IMAGE_WIDTH ;nombre d'octets dans l'image rep movsb add di,SCREEN_WIDTH-IMAGE_WIDTH ;pointe sur la prochaine ligne ;d'affichage de l'image dec bx ;y a-t-il d'autres lignes ;d'affichage ? jnz DrawImageLoop pop di ;récupère l'offset du début de ;l'image dans la mémoire VGA shl al,1 ;positionne Map Mask pour le prochain ;plan cmp al,10h ;avons-nous fait les quatre plans? jnz DrawImagePlaneLoop ret DrawImage endp ; ; Copie l'image depuis son emplacement courant dans la mémoire VGA dans le ; tampon à DS:DI. ; GetImage proc near mov si,di ;déplace l'offset de destination dans ; SI call GetImageOffset ;DI est l'offset de l'image dans ;la mémoire VGA xchg si,di ;SI est l'offset de l'image, DI ;est l'offset de destination push ds pop es ;ES:DI est la destination mov ax,VGA_SEGMENT mov ds,ax ;DS:SI est la source ; mov dx,GC_INDEX sub al,al ;traite le plan 0 en premier GetImagePlaneLoop: push si ;l'image provient du même offset dans ;chaque plan push ax ;préserve le plan sélectionné mov al,READ_MAP ;index Read Map out dx,al ;Index GC pointe sur le registre Read ;Map pop ax ;récupère le plan sélectionné inc dx ;pointe sur le registre Index GC out dx,al ;configure Read Map pour sélectionner ;les lectures dans ;le plan intéressant dec dx ;repointe sur le registre de données ; GC mov bx,IMAGE_HEIGHT ;nombre de lignes d'affichage ;dans l'image GetImageLoop: mov cx,IMAGE_WIDTH ;nombre d'octets dans l'image rep movsb add si,SCREEN_WIDTH-IMAGE_WIDTH ;pointe sur la prochaine ligne ;d'affichage de l'image dec bx ;y a-t-il d'autres lignes ;d'affichage ? jnz GetImageLoop pop si ;récupère l'offset du début de l'image inc al ;Positionne Read Map pour le prochain ;plan cmp al,4 ;avons-nous fait les quatre plans? jnz GetImagePlaneLoop push es pop ds ;restaure DS original ret GetImage endp ; ; Efface l'image à son emplacement courant. ; EraseImage proc near mov dx,SC_INDEX mov al,MAP_MASK out dx,al ;Index SC pointe sur le registre Map ;Mask inc dx ;pointe sur le registre Data SC mov al,0fh out dx,al ;configure Map Mask pour ;permettre les écritures ;d'accéder aux 4 plans mov ax,VGA_SEGMENT mov es,ax call GetImageOffset ;ES:DI pointe sur l'adresse de ;départ ; de l'image sub al,al ;efface avec zéro mov bx,IMAGE_HEIGHT ;nombre de lignes d'affichage ;dans l'image EraseImageLoop: mov cx,IMAGE_WIDTH ;nombre d'octets dans l'image rep stosb add di,SCREEN_WIDTH-IMAGE_WIDTH ;pointe sur la prochaine ligne d'affichage ;de l'image dec bx ;y a-t-il d'autres lignes ;d'affichage ? jnz EraseImageLoop ret EraseImage endp ; ; Retourne l'offset courant de l'image dans le segment VGA dans DI. ; GetImageOffset proc near mov ax,SCREEN_WIDTH mul [ImageY] add ax,[ImageX] mov di,ax ret GetImageOffset endp code ends end Start