abrash-black-book/48-04.md
2013-12-30 17:51:31 +11:00

187 lines
9.9 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

------------------------ --------------------------------- --------------------
[Previous](48-03.html) [Table of Contents](index.html) [Next](48-05.html)
------------------------ --------------------------------- --------------------
**LISTING 48.3 L48-3.ASM**
; Mode X (320x240, 256 colors) display memory to display memory copy
; routine. Left edge of source rectangle modulo 4 must equal left edge
; of destination rectangle modulo 4. Works on all VGAs. Uses approach
; of reading 4 pixels at a time from the source into the latches, then
; writing the latches to the destination. Copies up to but not
; including the column at SourceEndX and the row at SourceEndY. No
; clipping is performed. Results are not guaranteed if the source and
; destination overlap. C near-callable as:
;
; 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 ;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 row at SourceEndX is not copied)
SourceEndY dw ? ;Y coordinate of lower-right corner of source
; (the column 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
SourcePageBase dw ? ;base offset in display memory of page in
; which source resides
DestPageBase dw ? ;base offset in display memory of page in
; which dest resides
SourceBitmapWidth dw ? ;# of pixels across source bitmap
; (must be a multiple of 4)
DestBitmapWidth dw ? ;# of pixels across dest bitmap
; (must be a 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
Height equ -8;local storage for height of rectangle
STACK_FRAME_SIZE equ 8
.model small
.data
; Plane masks for clipping left and right edges of rectangle.
LeftClipPlaneMask db 00fh,00eh,00ch,008h
RightClipPlaneMask db 00fh,001h,003h,007h
.code
public _CopyScreenToScreenX
_CopyScreenToScreenX proc near
push bp ;preserve caller’s stack frame
mov bp,sp ;point to local stack frame
sub sp,STACK_FRAME_SIZE ;allocate space for local vars
push si ;preserve caller’s register variables
push di
push ds
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]
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
mov ax,[bp+SourceBitmapWidth]
shr ax,1 ;convert to width in addresses
shr ax,1
mul [bp+SourceStartY] ;top source rect scan line
mov si,[bp+SourceStartX]
mov bx,si
shr si,1 ;X/4 = offset of first source rect pixel in
shr si,1 ; scan line
add si,ax ;offset of first source rect pixel in page
add si,[bp+SourcePageBase] ;offset of first source rect
; pixel in display memory
and bx,0003h ;look up left edge plane mask
mov ah,LeftClipPlaneMask[bx] ; to clip
mov bx,[bp+SourceEndX]
and bx,0003h ;look up right-edge plane
mov al,RightClipPlaneMask[bx] ; mask to clip
mov bx,ax ;put the masks in BX
mov cx,[bp+SourceEndX] ;calculate # of addresses across
mov ax,[bp+SourceStartX] ; rect
cmp cx,ax
jle CopyDone ;skip if 0 or negative width
dec cx
and ax,not 011b
sub cx,ax
shr cx,1
shr cx,1 ;# of addresses across rectangle to copy - 1
jnz MasksSet ;there’s more than one address to draw
and bh,bl ;there’s only one address, so combine the
; left- and right-edge clip masks
MasksSet:
mov ax,[bp+SourceEndY]
sub ax,[bp+SourceStartY] ;AX = height of rectangle
jle CopyDone ;skip if 0 or negative height
mov [bp+Height],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
dec ax ; start of next
mov [bp+DestNextScanOffset],ax
mov ax,[bp+SourceBitmapWidth]
shr ax,1 ;convert to width in addresses
shr ax,1
sub ax,cx ;distance from end of one source scan line to
dec ax ; start of next
mov [bp+SourceNextScanOffset],ax
mov [bp+RectAddrWidth],cx ;remember width in addresses - 1
;----------------------BUG FIX
mov dx,SC_INDEX
mov al,MAP_MASK
out dx,al ;point SC Index reg to Map Mask
inc dx ;point to SC Data reg
;----------------------BUG FIX
mov ax,es ;DS=ES=screen segment for MOVS
mov ds,ax
CopyRowsLoop:
mov cx,[bp+RectAddrWidth] ;width across - 1
mov al,bh ;put left-edge clip mask in AL
out dx,al ;set the left-edge plane (clip) mask
movsb ;copy the left edge (pixels go through
; latches)
dec cx ;count off left edge address
js CopyLoopBottom ;that’s the only address
jz DoRightEdge ;there are only two addresses
mov al,00fh ;middle addresses are drawn 4 pixels at a pop
out dx,al ;set the middle pixel mask to no clip
rep movsb ;draw the middle addresses four pixels apiece
; (pixels copied through latches)
DoRightEdge:
mov al,bl ;put right-edge clip mask in AL
out dx,al ;set the right-edge plane (clip) mask
movsb ;draw the right edge (pixels copied through
; latches)
CopyLoopBottom:
add si,[bp+SourceNextScanOffset] ;point to the start of
add di,[bp+DestNextScanOffset] ; next source & dest lines
dec word ptr [bp+Height] ;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 ds
pop di ;restore caller’s register variables
pop si
mov sp,bp ;discard storage for local variables
pop bp ;restore caller’s stack frame
ret
_CopyScreenToScreenX endp
end
------------------------ --------------------------------- --------------------
[Previous](48-03.html) [Table of Contents](index.html) [Next](48-05.html)
------------------------ --------------------------------- --------------------
* * * * *
Graphics Programming Black Book © 2001 Michael Abrash