; Routine de remplissage de rectangle en Mode X (320x240, en 256 couleurs). ; Fonctionne sur tous les VGA. Emploie une approche rapide qui étale les données ; sur les quatre plans en une seule fois pour afficher jusqu'à quatre pixels à ; la fois. Les remplit sans inclure la colonne en EndX et la rangée en EndY. ; Aucun clipping n'est effectué à l'écran. ; Testé avec TASM 4.0 par Jim Mischel 12/16/94. ; Appelable en C near comme suit: ; void FillRectangleX(int StartX, int StartY, int EndX, int EndY, ; unsigned int PageBase, int Color); SC_INDEX equ 03c4h ;Sequence Controller Index MAP_MASK equ 02h ;index dans SC du registre Map Mask SCREEN_SEG equ 0a000h ;segment de la mémoire vidéo en mode X SCREEN_WIDTH equ 80 ;largeur de l'écran en octets d'une ligne d'affichage ; à l'autre parms struc dw 2 dup (?) ; BP empilé et adresse de retour StartX dw ? ;coordonnée X du coin supérieur gauche du rectangle StartY dw ? ;coordonnée Y du coin supérieur gauche du rectangle EndX dw ? ;coordonnée X du coin inférieur droit du rectangle ; (la rangée en EndX n'est pas remplie) EndY dw ? ;coordonnée Y du coin inférieur droit du rectangle ; (la colonne en EndY n'est pas remplie) PageBase dw ? ;offset de base dans la mémoire vidéo de la page dans ; laquelle remplir le rectangle Color dw ? ;couleur dans laquelle afficher le pixel parms ends .model small .data ; Masques de plan pour clipper les bords droit et gauche du rectangle. LeftClipPlaneMask db 00fh,00eh,00ch,008h RightClipPlaneMask db 00fh,001h,003h,007h .code public _FillRectangleX _FillRectangleX proc near push bp ;préserve la stack frame de l'appelant mov bp,sp ;pointe sur la stack frame locale push si ;préserve les variables registre de l'appelant push di cld mov ax,SCREEN_WIDTH mul [bp+StartY] ;offset dans la page de la ligne d'affichage du rectangle supérieur mov di,[bp+StartX] shr di,1 ;X/4 = offset du premier pixel du rectangle dans la shr di,1 ; ligne d'affichage add di,ax ;offset du premier pixel du rectangle dans la page add di,[bp+PageBase] ;offset du premier pixel du rectangle dans ; la mémoire vidéo mov ax,SCREEN_SEG ;ES:DI pointe sur l'adresse du premier pixel mov es,ax ; du rectangle mov dx,SC_INDEX ;paramètre Sequence Controller Index pour mov al,MAP_MASK ; pointer sur le registre Map Mask out dx,al inc dx ;DX pointe sur le registre SC Data mov si,[bp+StartX] and si,0003h ;pré-calcule le masque de plan du bord mov bh,LeftClipPlaneMask[si] ; gauche à clipper & le met dans BH mov si,[bp+EndX] and si,0003h ;pré-calcule le masque de plan du bord mov bl,RightClipPlaneMask[si] ; droit à clipper & le met dans BL mov cx,[bp+EndX] ;calcule le nombre d'adresses dans le rectangle mov si,[bp+StartX] cmp cx,si jle FillDone ;saute si la largeur est 0 ou négative dec cx and si,not 011b sub cx,si shr cx,1 shr cx,1 ;nombre d'adresses dans le rectangle à remplir - 1 jnz MasksSet ;plus d'un octet à afficher and bh,bl ;il y a un seul octet, combine alors les masques de ; clipping des bords gauche et droit MasksSet: mov si,[bp+EndY] sub si,[bp+StartY] ;BX = hauteur du rectangle jle FillDone ;saute si la hauteur est 0 ou négative mov ah,byte ptr [bp+Color] ;couleur de remplissage mov bp,SCREEN_WIDTH ;stack frame n'est plus nécessaire sub bp,cx ;distance entre la fin d'une ligne d'affichage et dec bp ; le début d'une autre FillRowsLoop: push cx ;mémorise la largeur des adresses - 1 mov al,bh ;met le masque de clip du bord gauche dans AL out dx,al ;positionne le masque de plan (clip) du bord gauche mov al,ah ;met la couleur dans AL stosb ;affiche le bord gauche dec cx ;décompte l'octet du bord gauche js FillLoopBottom ;il n'y a qu'un seul octet jz DoRightEdge ;il n'y a que deux octets mov al,00fh ;les adresses du milieu sont affichés 4 pixels à la volée out dx,al ;paramètre le masque de pixel du milieu pour ne pas clipper mov al,ah ;met la couleur dans AL rep stosb ;affiche les adresses du milieu quatre pixels DoRightEdge: mov al,bl ;met le masque de clip du bord droit dans AL out dx,al ;paramètre le masque de plan (clip) du bord droit mov al,ah ;met la couleur dans AL stosb ;affiche le bord droit FillLoopBottom: add di,bp ;pointe sur le début de la prochaine ligne d'affichage ; du rectangle pop cx ;retrouve la largeur des adresses - 1 dec si ;décompte les lignes d'affichage jnz FillRowsLoop FillDone: pop di ;restaure les variables registre de l'appelant pop si pop bp ;restaure la stack frame de l'appelant ret _FillRectangleX endp end