; Affiche tous les pixels dans la liste des lignes horizontales, en ; Mode X, le mode 320x240 en 256 couleurs non documenté du VGA. Clippe le ; rectangle spécifié par (ClipMinX,ClipMinY),(ClipMaxX,ClipMaxY). ; Affiche dans la page spécifiée par CurrentPageBase. ; Appelable en C near comme suit: ; ; void DrawHorizontalLineList(struct HLineList * HLineListPtr, ; int Color); ; ; Testé avec TASM 4.0 par Jim Mischel 12/16/94. SCREEN_WIDTH equ 320 SCREEN_SEGMENT equ 0a000h SC_INDEX equ 03c4h ;Sequence Controller Index MAP_MASK equ 2 ;index du registre Map Mask dans SC HLine struc XStart dw ? ;coordonnée X du pixel le plus à gauche dans la ligne XEnd dw ? ;coordonnée X du pixel le plus à droite dans la ligne HLine ends HLineList struc Lngth dw ? ;nombre de lignes horizontales YStart dw ? ;coordonnée Y de la ligne supérieure HLinePtr dw ? ;pointeur sur la liste des lignes horizontales HLineList ends Parms struc dw 2 dup(?) ;adresse de retour & BP empilé HLineListPtr dw ? ;pointeur sur la structure HLineList Color dw ? ;couleur de remplissage Parms ends .model small .data extrn _CurrentPageBase:word,_ClipMinX:word extrn _ClipMinY:word,_ClipMaxX:word,_ClipMaxY:word ; Plane masks for clipping left and right edges of rectangle. LeftClipPlaneMask db 00fh,00eh,00ch,008h RightClipPlaneMask db 001h,003h,007h,00fh .code align 2 ToFillDone: jmp FillDone public _DrawHorizontalLineList align 2 _DrawHorizontalLineList proc push bp ;préserve la stack frame de l'appelant mov bp,sp ;pointe sur notre stack frame push si ;préserve les variables registre de l'appelant push di cld mov dx,SC_INDEX mov al,MAP_MASK out dx,al ;SC Index pointe sur Map Mask mov ax,SCREEN_SEGMENT mov es,ax ;ES pointe sur la mémoire vidéo pour REP STOS mov si,[bp+HLineListPtr] ;pointe sur la liste de lignes mov bx,[si+HLinePtr] ;pointe sur le descripteur XStart/XEnd ; pour la première ligne horizontale (haute) mov cx,[si+YStart] ;première ligne d'affichage à afficher mov si,[si+Lngth] ;nombre de lignes d'affichage cmp si,0 ;reste-t-il d'autres lignes à afficher? jle ToFillDone ;non, nous avons fini cmp cx,[_ClipMinY] ;clippée en haut? jge MinYNotClipped ;non neg cx ;oui, abandonnons les lignes add cx,[_ClipMinY] ;clippées sub si,cx ;très peu de lignes à afficher jle ToFillDone ;il ne reste plus de ligne à afficher shl cx,1 ;lignes à sauter *2 shl cx,1 ;lignes à sauter *4 add bx,cx ;avance dans la liste de lignes mov cx,[_ClipMinY] ;commence à la ligne de clipping supérieure MinYNotClipped: mov dx,si add dx,cx ;rangée du bas à afficher + 1 cmp dx,[_ClipMaxY] ;clippée en bas ? jle MaxYNotClipped ;non sub dx,[_ClipMaxY] ;nombre de lignes à clipper en bas sub si,dx ;nombre de lignes restant à afficher jle ToFillDone ;toutes les lignes sont clippées MaxYNotClipped: mov ax,SCREEN_WIDTH/4 ;pointe sur le début de la première ligne mul cx ; d'affichage dans laquelle afficher add ax,[_CurrentPageBase] ;offset de la première ligne mov dx,ax ;ES:DX pointe sur la première ligne ; à afficher mov ah,byte ptr [bp+Color] ;couleur de remplissage FillLoop: push bx ;mémorise l'emplacement de la liste de lignes push dx ;mémorise l'offset de départ de la ligne push si ;mémorise le nombre de lignes à afficher mov di,[bx+XStart] ;bord gauche de remplissage sur cette ligne cmp di,[_ClipMinX] ;clippée au bord gauche? jge MinXNotClipped ;non mov di,[_ClipMinX] ;oui, clipper au bord gauche MinXNotClipped: mov si,di mov cx,[bx+XEnd] ;bord droit de remplissage cmp cx,[_ClipMaxX] ;clippée au bord droit? jl MaxXNotClipped ;non mov cx,[_ClipMaxX] ;oui, clipper au bord droit dec cx MaxXNotClipped: cmp cx,di jl LineFillDone ;saute si la largeur est négative shr di,1 ;X/4 = offset du premier pixel du rectangle shr di,1 ; dans la ligne d'affichage add di,dx ;offset du premier pixel du rectangle dans la mémoire vidéo mov dx,si ;XStart and si,0003h ;pré-calcule le masque de plan de bord gauche mov bh,LeftClipPlaneMask[si] ; à clipper & le met dans BH mov si,cx and si,0003h ;pré-calcule le masque de plan de bord mov bl,RightClipPlaneMask[si] ; droit à clipper & le met dans BL and dx,not 011b ;calcule le nombre d'adresses dans le rectangle sub cx,dx shr cx,1 shr cx,1 ;nombre d'adresses dans le rectangle à remplir - 1 jnz MasksSet ;plus d'un octet à afficher and bh,bl ;un seul octet, combinons les masques de ; clipping des bords gauche et droit MasksSet: mov dx,SC_INDEX+1 ;pointe déjà sur le registre Map Mask FillRowsLoop: mov al,bh ;met le masque de clipping du bord gauche dans AL out dx,al ;paramètre le masque de plan (clippng) du bord gauche mov al,ah ;met la couleur dans AL stosb ;affiche le bord gauche dec cx ;décompte les octets du bord gauche js FillLoopBottom ;il y a un seul octet jz DoRightEdge ;il y a seulement deux octets 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 mov al,ah ;met la couleur dans AL rep stosb ;affiche les adresses du milieu en quatre pixels DoRightEdge: mov al,bl ;met le masque de clipping de bord droit dans AL out dx,al ;paramètre le masque de plan (clipping) de bord droit mov al,ah ;met la couleur dans AL stosb ;affiche le bord droit FillLoopBottom: LineFillDone: pop si ;retrouve le nombre de lignes à afficher pop dx ;retrouve l'offset de départ de la ligne pop bx ;retrouve l'emplacement de la liste de lignes add dx,SCREEN_WIDTH/4 ;pointe sur le début de la prochaine ligne add bx,size HLine ;pointe sur le descripteur de la prochaine ligne dec si ;décompte les lignes jnz FillLoop FillDone: pop di ;restaure les variables registre de l'appelant pop si pop bp ;restaure la stack frame de l'appelant ret _DrawHorizontalLineList endp end