; Routine de copie de mémoire vidéo à mémoire vidéo en Mode X (320x240, en 256 ; couleurs). Le coté gauche du rectangle modulo 4 source doit être égal au coté ; gauche du rectangle modulo 4 de destination. Fonctionne sur tous les VGA. Emploie ; une approche de lecture 4 pixels à la fois de la source aux latches, puis ; d'écriture des latches à la destination. Copie sans inclure la colonne ; en SourceEndX et la rangée en SourceEndY. Aucun clipping n'est effectué. ; Les résultats ne sont pas garantis si la source et la destination se ; chevauchent. ; Testé avec TASM 4.0 par Jim Mischel 12/16/94. ; Appelable en C near comme suit: ; ; void CopyScreenToScreenX(int SourceStartX, int SourceStartY, ; int SourceEndX, int SourceEndY, int DestStartX, ; int DestStartY, unsigned int SourcePageBase, ; unsigned int DestPageBase, int SourceBitmapWidth, ; int DestBitmapWidth); SC_INDEX equ 03c4h ;port registre Sequence Controller Index MAP_MASK equ 02h ;index dans SC du registre Map Mask GC_INDEX equ 03ceh ;port registre Graphics Controller Index BIT_MASK equ 08h ;index dans GC du registre Bit Mask SCREEN_SEG equ 0a000h ;segment de la mémoire vidéo en Mode X parms struc dw 2 dup (?) ;BP empilé et adresse de retour SourceStartX dw ? ;coordonnée X du coin supérieur gauche de la source SourceStartY dw ? ;coordonnée Y du coin supérieur gauche de la source SourceEndX dw ? ;coordonnée X du coin inférieur droit de la source ;(la rangée en SourceEndX n'est pas copiée) SourceEndY dw ? ;coordonnée Y du coin inférieur droit de la source ;(la colonne en SourceEndY n'est pas copiée) DestStartX dw ? ;coordonnée X du coin supérieur gauche de la destination DestStartY dw ? ;coordonnée Y du coin supérieur gauche de la destination SourcePageBase dw ? ;offset de base dans la mémoire vidé de la page dans ;laquelle réside la source DestPageBase dw ? ;offset de base dans la mémoire vidéo de la page dans ;laquelle réside la destination SourceBitmapWidth dw ? ;nombre de pixels dans la bitmap source ;(doit être un multiple de 4) DestBitmapWidth dw ? ;nombre de pixels dans la bitmap destination ;(doit être un multiple de 4) parms ends SourceNextScanOffset equ -2 ;stockage local de la distance entre la fin ;d'une ligne d'affichage source et le début de la ;suivante DestNextScanOffset equ -4 ;stockage local de la distance entre la fin d'une ;ligne d'affichage destination et le début de la ;suivante RectAddrWidth equ -6 ;stockage local de la largeur du rectangle Height equ -8 ;stockage local de la hauteur du rectangle STACK_FRAME_SIZE equ 8 .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 _CopyScreenToScreenX _CopyScreenToScreenX 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 push ds cld mov dx,GC_INDEX ;paramètre le masque de bits pour mov ax,00000h+BIT_MASK ;sélectionner tous les bits depuis les out dx,ax ;latches et aucun depuis le CPU ;nous pouvons donc écrire directement ;en mémoire ;le contenu des Latches mov ax,SCREEN_SEG ;ES pointe sur la mémoire vidéo mov es,ax mov ax,[bp+DestBitmapWidth] shr ax,1 ;convertit la largeur en adresses shr ax,1 mul [bp+DestStartY] ;ligne d'affichage supérieure du rectangle ;de destination mov di,[bp+DestStartX] shr di,1 ;X/4 = offset du premier pixel du shr di,1 ;rectangle destination dans la ligne ;d'affichage add di,ax ;offset du premier pixel du rectangle ;destination dans la page add di,[bp+DestPageBase] ;offset du premier pixel du rectangle ; destination dans la mémoire vidéo mov ax,[bp+SourceBitmapWidth] shr ax,1 ;convertit la largeur en adresses shr ax,1 mul [bp+SourceStartY] ;ligne d'affichage supérieure du rectangle ;source mov si,[bp+SourceStartX] mov bx,si shr si,1 ;X/4 = offset du premier pixel du shr si,1 ; rectangle source dans la ligne ;d'affichage add si,ax ;offset du premier pixel du rectangle add si,[bp+SourcePageBase] ;offset du premier pixel du rectangle ; source 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+SourceEndX] 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+SourceEndX] ;calcule le nombre d'adresses mov ax,[bp+SourceStartX] ; dans le rectangle cmp cx,ax jle CopyDone ;saute si la 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 ;à copier - 1 jnz MasksSet ;plus d'une adresse à afficher and bh,bl ;une seule adresse, combinons les ; masques de clipping des bords gauche ;et droit MasksSet: mov ax,[bp+SourceEndY] sub ax,[bp+SourceStartY] ;AX = hauteur du rectangle jle CopyDone ;saute si la hauteur est 0 ou négative mov [bp+Height],ax mov ax,[bp+DestBitmapWidth] shr ax,1 ;convertit la largeur en adresses shr ax,1 sub ax,cx ;distance entre la fin d'une ligne dec ax ;d'affichage destination et le début ;de la suivante mov [bp+DestNextScanOffset],ax mov ax,[bp+SourceBitmapWidth] shr ax,1 ; convertit la largeur en adresses shr ax,1 sub ax,cx ;distance entre la fin d'une ligne dec ax ;d'affichage source et le début ;de la suivante mov [bp+SourceNextScanOffset],ax mov [bp+RectAddrWidth],cx ;mémorise la largeur dans les adresses - 1 ;-----------------------BUG FIX mov dx,SC_INDEX mov al,MAP_MASK out dx,al ;le registre SC Index pointe sur Map Mask inc dx ;pointe sur le registre SC Data ;-----------------------BUG FIX mov ax,es ;DS=ES=segment d'écran pour MOVS mov ds,ax CopyRowsLoop: mov cx,[bp+RectAddrWidth] ;largeur - 1 mov al,bh ;met le masque de clipping du bord gauche ;dans AL out dx,al ;paramètre le masque de plan (clipping) du ;bord gauche movsb ;copie le bord gauche (pixels ;traversent les latches) dec cx ;décompte l'adresse du bord gauche js CopyLoopBottom ;une seule adresse jz DoRightEdge ;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 pixel du milieu à ne pas ;clipper rep movsb ;affiche les adresses du milieu en 4 ;pixels (pixels copiés via les latches) 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 movsb ;affiche le bord droit (pixels copiés ;via les latches) CopyLoopBottom: add si,[bp+SourceNextScanOffset] ;pointe sur le début des prochaines add di,[bp+DestNextScanOffset] ;lignes d'affichage source et ;destination dec word ptr [bp+Height] ;décompte les lignes d'affichage jnz CopyRowsLoop CopyDone: mov dx,GC_INDEX+1 ;restaure le masque de bits par mov al,0ffh ;défaut, qui sélectionne tous les out dx,al ;bits du CPU et aucun des latches ;(Index pointe toujours sur Bit Mask) pop ds 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 _CopyScreenToScreenX endp end