; Routine de remplissage d'un rectangle par un motif 4x4 en Mode X (320x240, en 256 ; couleurs). Le coin supérieur gauche du motif est toujours aligné sur une colonne ou ; une rangée multiple de 4. Fonctionne sur tous les VGA. Emploie l'approche de copie de ; motif dans la mémoire vidéo off-screen, puis charge les ; latches avec le motif de chaque ligne d'affichage et remplit chaque ligne ; quatre pixels à la fois. Les remplit sans inclure la colonne en ; EndX et la rangée en EndY. ; Aucun clipping n'est effectué. ; Testé avec TASM 4.0 par Jim Mischel 12/16/94. ; Appelable en C near comme suit: ; ; void FillPatternX(int StartX, int StartY, int EndX, int EndY, ; unsigned int PageBase, char* Pattern); SC_INDEX equ 03c4h ;port du registre Sequence Controller Index MAP_MASK equ 02h ;index dans SC du registre Map Mask GC_INDEX equ 03ceh ;port du registre Graphics Controller Index BIT_MASK equ 08h ;index dans GC du registre Bit Mask PATTERN_BUFFER equ 0fffch ;offset dans la mémoire d'écran du tampon utilisé ;pour stocker chaque motif lors de l'affichage SCREEN_SEG equ 0a000h ;segment de la mémoire vidéo en Mode X SCREEN_WIDTH equ 80 ;largeur de l'écran dans les adresses 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 Pattern dw ? ;motif 4x4 avec lequel remplir le rectangle parms ends NextScanOffset equ -2 ;stockage local de la distance entre la fin d'une ligne ;d'affichage et le début de la prochaine RectAddrWidth equ -4 ;stockage local pour la largeur du rectangle Height equ -6 ;stockage local pour la hauteur du rectangle STACK_FRAME_SIZE equ 6 .model small .data ; Masques de plan pour clipper les bords gauche et droit du rectangle. LeftClipPlaneMask db 00fh,00eh,00ch,008h RightClipPlaneMask db 00fh,001h,003h,007h .code public _FillPatternX _FillPatternX proc near push bp ;préserve la stack frame de l'appelant mov bp,sp ;pointe sur la stack frame locale sub sp,STACK_FRAME_SIZE ;alloue de l'espace aux variables locales push si ;préserve les variables registre de l'appelant push di cld mov ax,SCREEN_SEG ;ES pointe sur la mémoire vidéo mov es,ax ;copie le motif dans le tampon de la mémoire vidéo mov si,[bp+Pattern] ;pointe sur le motif de remplissage mov di,PATTERN_BUFFER ;ES:DI pointe sur le tampon du motif mov dx,SC_INDEX ;Sequence Controller Index pointe sur mov al,MAP_MASK ;Map Mask out dx,al inc dx ;pointe sur le registre SC Data mov cx,4 ;4 quadruplés de pixel dans le motif DownloadPatternLoop: mov al,1 ; out dx,al ;sélectionne le plan 0 pour l'écriture movsb ;copie le prochain pixel du motif du plan 0 dec di ;reste à la même adresse pour le prochain plan mov al,2 ; out dx,al ;sélectionne le plan 1 pour l'écriture movsb ;copie le prochain pixel du motif du plan 1 dec di ;reste à la même adresse pour le prochain plan mov al,4 ; out dx,al ;sélectionne le plan 2 pour l'écriture movsb ;copie le prochain pixel du motif du plan 2 dec di ;reste à la même adresse pour le prochain plan mov al,8 ; out dx,al ;sélectionne le plan 3 pour l'écriture movsb ;copie le prochain pixel du motif du plan 3 ; et avance l'adresse loop DownloadPatternLoop mov dx,GC_INDEX ;paramètre le masque de bits pour sélectionner ;tous les bits mov ax,00000h+BIT_MASK ;depuis les latches et aucun depuis out dx,ax ;le CPU, nous pouvons donc écrire directement ;le contenu des latches en mémoire mov ax,[bp+StartY] ;ligne d'affichage supérieure du rectangle mov si,ax and si,011b ;ligne d'affichage supérieure du rectangle ;modulo 4 add si,PATTERN_BUFFER ;pointe sur la ligne d'affichage du motif qui ;correspond à la ligne supérieure du rectangle à ;afficher mov dx,SCREEN_WIDTH mul dx ;offset dans la page de la ligne d'affichage supérieure du ;rectangle mov di,[bp+StartX] mov bx,di 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 and bx,0003h ;pré-calcule le masque de plan du bord mov ah,LeftClipPlaneMask[bx] ;gauche à clipper mov bx,[bp+EndX] and bx,0003h ;pré-calcule le masque de plan du bord mov al,RightClipPlaneMask[bx] ;droit à clipper mov bx,ax ;met les masques dans BX mov cx,[bp+EndX] ;calcule le nombre d'adresses dans le rectangle mov ax,[bp+StartX] cmp cx,ax jle FillDone ;saute si largeur est 0 ou négative dec cx and ax,not 011b sub cx,ax shr cx,1 shr cx,1 ;nombre d'adresses dans le rectangle à remplir - 1 jnz MasksSet ;plus d'un pixel à afficher and bh,bl ;il y a un seul pixel, combinons les masques de clipping ;des bords gauche et droit MasksSet: mov ax,[bp+EndY] sub ax,[bp+StartY] ;AX = hauteur du rectangle jle FillDone ;saute si la hauteur est 0 ou négative mov [bp+Height],ax mov ax,SCREEN_WIDTH sub ax,cx ;distance entre la fin d'une ligne d'affichage et le dec ax ; début de la suivante mov [bp+NextScanOffset],ax mov [bp+RectAddrWidth],cx ;mémorise la largeur des adresses - 1 mov dx,SC_INDEX+1 ;pointe sur le registre Sequence Controller Data ; (SC Index pointe toujours sur Map Mask) FillRowsLoop: mov cx,[bp+RectAddrWidth] ;largeur - 1 mov al,es:[si] ;lit la mémoire vidéo pour verrouiller le motif ;de la ligne d'affichage inc si ;pointe sur la ligne d'affichage du prochain motif, jnz short NoWrap ; en revenant au début du motif si nous sub si,4 ; avons passé la fin NoWrap: mov al,bh ;met le masque de clipping du bord gauche dans AL out dx,al ;positionne le masque de plan (clipping) du bord gauche stosb ;affiche le bord gauche (pixels des latches; ;les valeurs écrites par le CPU n'importent pas) dec cx ;décompte l'adresse du bord gauche js FillLoopBottom ;une seule adresse jz DoRightEdge ;il y a seulement deux adresses mov al,00fh ;les adresses du milieu sont affichées 4 pixels à la volée out dx,al ;paramètre le masque de pixels du milieu pour ne pas ;clipper rep stosb ;affiche les quatre pixels du milieu ;(depuis les latches; peu importe les valeurs écrites) DoRightEdge: mov al,bl ;met le masque de clipping du bord droit dans AL out dx,al ;paramètre le masque de plan (clipping)du bord droit stosb ;affiche le bord droit (depuis les latches; peu importe ;les valeurs écrites) FillLoopBottom: add di,[bp+NextScanOffset] ;pointe sur le début de la prochaine ; ligne d'affichage du rectangle dec word ptr [bp+Height] ;décompte les lignes d'affichage jnz FillRowsLoop FillDone: mov dx,GC_INDEX+1 ;restaure le masque de bits par défaut, mov al,0ffh ;qui sélectionne tous les bits du CPU out dx,al ;et aucun des latches (Index GC ;Index pointe toujours sur Bit Mask) pop di ;restaure les variables registre de l'appelant pop si mov sp,bp ;abandonne le stockage des variables locales pop bp ;restaure la stack frame de l'appelant ret _FillPatternX endp end