|Previous||Table of Contents||Next|
In the previous chapter we saw how the VGAs latches can be used to copy four pixels at a time from one area of display memory to another in Mode X. Weve further seen that in Mode X the Map Mask register can be used to select which planes are copied. Thats all we need to know to be able to perform fast masked copies; we can store an image in off-screen display memory, and set the Map Mask to the appropriate mask value as up to four pixels at a time are copied.
Theres a slight hitch, though. The latches can only be used when the source and destination left edge coordinates, modulo four, are the same, as explained in the previous chapter. The solution is to copy all four possible alignments of each image to display memory, each properly positioned for one of the four possible destination-left-edge-modulo-four cases. These aligned images must be accompanied by the four possible alignments of the image mask, stored in system memory. Given all four image and mask alignments, masked copying is a simple matter of selecting the alignment thats appropriate for the destinations left edge, then setting the Map Mask with the 4-bit mask corresponding to each four-pixel set as we copy four pixels at a time via the latches.
Listing 49.2 performs fast masked copying. This code expects to receive a pointer to a MaskedImage structure, which in turn points to four AlignedMaskedImage structures that describe the four possible image and mask alignments. The aligned images are already stored in display memory, and the aligned masks are already stored in system memory; further, the masks are predigested into Map Mask register-compatible form. Given all that ready-to-use data, Listing 49.2 selects and works with the appropriate image-mask pair for the destinations left edge alignment.
LISTING 49.2 L49-2.ASM
; Mode X (320x240, 256 colors) display memory to display memory masked copy ; routine. Works on all VGAs. Uses approach of reading 4 pixels at a time from ; source into latches, then writing latches to destination, using Map Mask ; register to perform masking. Copies up to but not including column at ; SourceEndX and row at SourceEndY. No clipping is performed. Results are not ; guaranteed if source and destination overlap. C near-callable as: ; ; void CopyScreenToScreenMaskedX(int SourceStartX, ; int SourceStartY, int SourceEndX, int SourceEndY, ; int DestStartX, int DestStartY, MaskedImage * Source, ; unsigned int DestPageBase, int DestBitmapWidth); SC_INDEX equ 03c4h ;Sequence Controller Index register port MAP_MASK equ 02h ;index in SC of Map Mask register GC_INDEX equ 03ceh ;Graphics Controller Index register port BIT_MASK equ 08h ;index in GC of Bit Mask register SCREEN_SEG equ 0a000h ;segment of display memory in mode X parms struc dw 2 dup (?) ;pushed BP and return address SourceStartX dw ? ;X coordinate of upper left corner of source SourceStartY dw ? ;Y coordinate of upper left corner of source SourceEndX dw ? ;X coordinate of lower right corner of source ; (the column at SourceEndX is not copied) SourceEndY dw ? ;Y coordinate of lower right corner of source ; (the row at SourceEndY is not copied) DestStartX dw ? ;X coordinate of upper left corner of dest DestStartY dw ? ;Y coordinate of upper left corner of dest Source dw ? ;pointer to MaskedImage struct for source ; which source resides DestPageBase dw ? ;base offset in display memory of page in ; which dest resides DestBitmapWidth dw ? ;# of pixels across dest bitmap (must be multiple of 4) parms ends SourceNextScanOffset equ -2 ;local storage for distance from end of ; one source scan line to start of next DestNextScanOffset equ -4 ;local storage for distance from end of ; one dest scan line to start of next RectAddrWidth equ -6 ;local storage for address width of rectangle RectHeight equ -8 ;local storage for height of rectangle SourceBitmapWidth equ -10 ;local storage for width of source bitmap ; (in addresses) STACK_FRAME_SIZE equ 10 MaskedImage struc Alignments dw 4 dup(?) ;pointers to AlignedMaskedImages for the ; 4 possible destination image alignments MaskedImage ends AlignedMaskedImage struc ImageWidth dw ? ;image width in addresses (also mask width in bytes) ImagePtr dw ? ;offset of image bitmap in display memory MaskPtr dw ? ;pointer to mask bitmap in DS AlignedMaskedImage ends .model small .code public _CopyScreenToScreenMaskedX _CopyScreenToScreenMaskedX proc near push bp ;preserve callers stack frame mov bp,sp ;point to local stack frame sub sp,STACK_FRAME_SIZE ;allocate space for local vars push si ;preserve callers register variables push di cld mov dx,GC_INDEX ;set the bit mask to select all bits mov ax,00000h+BIT_MASK ; from the latches and none from out dx,ax ; the CPU, so that we can write the ; latch contents directly to memory mov ax,SCREEN_SEG ;point ES to display memory mov es,ax mov ax,[bp+DestBitmapWidth] shr ax,1 ;convert to width in addresses shr ax,1 mul [bp+DestStartY] ;top dest rect scan line mov di,[bp+DestStartX] mov si,di shr di,1 ;X/4 = offset of first dest rect pixel in shr di,1 ; scan line add di,ax ;offset of first dest rect pixel in page add di,[bp+DestPageBase] ;offset of first dest rect pixel in display ; memory. now look up the image thats ; aligned to match left-edge alignment ; of destination and si,3 ;DestStartX modulo 4 mov cx,si ;set aside alignment for later shl si,1 ;prepare for word look-up mov bx,[bp+Source] ;point to source MaskedImage structure mov bx,[bx+Alignments+si] ;point to AlignedMaskedImage ; struc for current left edge alignment mov ax,[bx+ImageWidth] ;image width in addresses mov [bp+SourceBitmapWidth],ax ;remember image width in addresses mul [bp+SourceStartY] ;top source rect scan line mov si,[bp+SourceStartX] shr si,1 ;X/4 = address of first source rect pixel in shr si,1 ; scan line add si,ax ;offset of first source rect pixel in image mov ax,si add si,[bx+MaskPtr] ;point to mask offset of first mask pixel in DS mov bx,[bx+ImagePtr] ;offset of first source rect pixel add bx,ax ; in display memory mov ax,[bp+SourceStartX] ;calculate # of addresses across add ax,cx ; rect, shifting if necessary to add cx,[bp+SourceEndX] ; account for alignment cmp cx,ax jle CopyDone ;skip if 0 or negative width add cx,3 and ax,not 011b sub cx,ax shr cx,1 shr cx,1 ;# of addresses across rectangle to copy mov ax,[bp+SourceEndY] sub ax,[bp+SourceStartY] ;AX = height of rectangle jle CopyDone ;skip if 0 or negative height mov [bp+RectHeight],ax mov ax,[bp+DestBitmapWidth] shr ax,1 ;convert to width in addresses shr ax,1 sub ax,cx ;distance from end of one dest scan line to start of next mov [bp+DestNextScanOffset],ax mov ax,[bp+SourceBitmapWidth] ;width in addresses sub ax,cx ;distance from end of source scan line to start of next mov [bp+SourceNextScanOffset],ax mov [bp+RectAddrWidth],cx ;remember width in addresses mov dx,SC_INDEX mov al,MAP_MASK out dx,al ;point SC Index register to Map Mask inc dx ;point to SC Data register CopyRowsLoop: mov cx,[bp+RectAddrWidth] ;width across CopyScanLineLoop: lodsb ;get the mask for this four-pixel set ; and advance the mask pointer out dx,al ;set the mask mov al,es:[bx] ;load the latches with four-pixel set from source mov es:[di],al ;copy the four-pixel set to the dest inc bx ;advance the source pointer inc di ;advance the destination pointer dec cx ;count off four-pixel sets jnz CopyScanLineLoop mov ax,[bp+SourceNextScanOffset] add si,ax ;point to the start of add bx,ax ; the next source, mask, add di,[bp+DestNextScanOffset] ; and dest lines dec word ptr [bp+RectHeight] ;count down scan lines jnz CopyRowsLoop CopyDone: mov dx,GC_INDEX+1 ;restore the bit mask to its default, mov al,0ffh ; which selects all bits from the CPU out dx,al ; and none from the latches (the GC ; Index still points to Bit Mask) pop di ;restore callers register variables pop si mov sp,bp ;discard storage for local variables pop bp ;restore callers stack frame ret _CopyScreenToScreenMaskedX endp end
|Previous||Table of Contents||Next|