2565 lines
130 KiB
NASM
2565 lines
130 KiB
NASM
;---------------------------Module-Header------------------------------;
|
|
; Module Name: dib2vga.asm
|
|
;
|
|
; Copyright (c) 1992 Microsoft Corporation
|
|
;-----------------------------------------------------------------------;
|
|
;-----------------------------------------------------------------------;
|
|
;
|
|
; VOID vDIB2VGA(DEVSURF * pdsurfDst, DEVSURF * pdsurfSrc,
|
|
; RECTL * prclDst, POINTL * pptlSrc, UCHAR *pConv,
|
|
; BOOL fDfbTrg );
|
|
;
|
|
;+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
|
; NOTE: This routine will be entirely unhappy if the area to be copied
|
|
; is wider than 2048 pixels.
|
|
;+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
|
|
;
|
|
; Performs accelerated copies of DIB pixels to the VGA screen.
|
|
;
|
|
; pdsurfDst = pointer to dest surface, which must be the VGA
|
|
;
|
|
; pdsurfSrc = pointer to source surface, which must be a 4 bpp DIB. Only the
|
|
; lNextScan and pvBitmapStart fields need to be set
|
|
;
|
|
; prclDst = pointer to rectangle describing area of VGA to be copied to
|
|
;
|
|
; pptlSrc = pointer to point structure describing the upper left corner
|
|
; of the copy in the source DIB
|
|
;
|
|
; pConv = pointer to set of four 256-byte tables used for conversion
|
|
; from DIB4 to VGA, created by vSetDIB4ToVGATables
|
|
;
|
|
; fDfbTrg = flag set to 0 if target is VGA or 1 if target is DFB
|
|
;
|
|
;-----------------------------------------------------------------------;
|
|
;-----------------------------------------------------------------------;
|
|
;
|
|
; VOID vSetDIB4ToVGATables(UCHAR * pucConvTable);
|
|
;
|
|
; Creates the four 256-byte tables used for conversion from DIB4 to VGA.
|
|
;
|
|
; pucConvTable = pointer to 1K of storage into which the conversion
|
|
; tables are placed
|
|
;
|
|
;-----------------------------------------------------------------------;
|
|
;-----------------------------------------------------------------------;
|
|
;
|
|
; Note: Assumes the destination rectangle has a positive height and width.
|
|
; Will not work properly if this is not the case.
|
|
;
|
|
; Note: The source must be a standard DIB4 bitmap, and the destination
|
|
; must be VGA display memory.
|
|
;
|
|
; Note: Performance would benefit if we did more scans at a time in each
|
|
; plane on processor/VGA combinations that supported higher conversion
|
|
; and display memory writing speeds.
|
|
;
|
|
;-----------------------------------------------------------------------;
|
|
|
|
;-----------------------------------------------------------------------;
|
|
; [BUGFIX] - byte reads from plane 3 of video memory must be done twice
|
|
; on the VLB CL5434 or they don't always work
|
|
;-----------------------------------------------------------------------;
|
|
|
|
.486
|
|
|
|
.model small,c
|
|
|
|
assume ds:FLAT,es:FLAT,ss:FLAT
|
|
assume fs:nothing,gs:nothing
|
|
|
|
.xlist
|
|
include stdcall.inc ;calling convention cmacros
|
|
include i386\egavga.inc
|
|
include i386\strucs.inc
|
|
|
|
.list
|
|
|
|
;-----------------------------------------------------------------------;
|
|
|
|
|
|
|
|
; Do not change this value unless you know exactly what you are doing.
|
|
; It is used to store up to 32 scans whose number of pixels total 2048
|
|
; (or 1024 bytes) or less. Also, each scan needs an extra dword padding
|
|
; for an extra write that always gets done, and an extra dword of padding
|
|
; for spacers which are added when shifting right.
|
|
|
|
BUF_SIZE equ (1024+(32*(4+4)))
|
|
|
|
|
|
.data
|
|
|
|
|
|
;-----------------------------------------------------------------------;
|
|
; Masks to be applied to the source data for the 8 possible clip
|
|
; alignments.
|
|
;-----------------------------------------------------------------------;
|
|
|
|
jLeftMasks db 0ffh, 07fh, 03fh, 01fh, 00fh, 007h, 003h, 001h
|
|
jRightMasks db 0ffh, 080h, 0c0h, 0e0h, 0f0h, 0f8h, 0fch, 0feh
|
|
|
|
|
|
.code
|
|
|
|
_TEXT$01 SEGMENT PARA USE32 PUBLIC 'CODE'
|
|
ASSUME DS:FLAT, ES:FLAT, SS:NOTHING, FS:NOTHING, GS:NOTHING
|
|
|
|
;-----------------------------------------------------------------------;
|
|
|
|
cProc vSetDIB4ToVGATables,4,< \
|
|
uses esi edi ebx, \
|
|
pucConvTable : dword >
|
|
|
|
mov ebx,pucConvTable
|
|
|
|
; Generate the table used to multiplex bits from form accumulated from DIB4
|
|
; to VGA planar byte format for plane 0. Translation is from 64207531 source
|
|
; DIB format (where 0 is leftmost, 7 is rightmost) to 76543210 VGA
|
|
; format (where 7 is leftmost, 0 is rightmost).
|
|
|
|
mov ecx,256
|
|
sub al,al
|
|
plane0_conv_table_loop:
|
|
sub dl,dl
|
|
mov ah,al
|
|
and ah,10h
|
|
shl ah,3
|
|
or dl,ah
|
|
mov ah,al
|
|
and ah,01h
|
|
shl ah,6
|
|
or dl,ah
|
|
mov ah,al
|
|
and ah,20h
|
|
or dl,ah
|
|
mov ah,al
|
|
and ah,02h
|
|
shl ah,3
|
|
or dl,ah
|
|
mov ah,al
|
|
and ah,40h
|
|
shr ah,3
|
|
or dl,ah
|
|
mov ah,al
|
|
and ah,04h
|
|
or dl,ah
|
|
mov ah,al
|
|
and ah,80h
|
|
shr ah,6
|
|
or dl,ah
|
|
mov ah,al
|
|
and ah,08h
|
|
shr ah,3
|
|
or dl,ah
|
|
mov [ebx],dl
|
|
inc al
|
|
inc ebx
|
|
dec ecx
|
|
jnz plane0_conv_table_loop
|
|
|
|
; Generate the table used to multiplex bits from form accumulated from DIB4
|
|
; to VGA planar byte format for plane 1. Translation is from 46025713 source
|
|
; DIB format (where 0 is leftmost, 7 is rightmost) to 76543210 VGA
|
|
; format (where 7 is leftmost, 0 is rightmost).
|
|
|
|
mov ecx,256
|
|
sub al,al
|
|
plane1_conv_table_loop:
|
|
sub dl,dl
|
|
mov ah,al
|
|
and ah,20h
|
|
shl ah,2
|
|
or dl,ah
|
|
mov ah,al
|
|
and ah,02h
|
|
shl ah,5
|
|
or dl,ah
|
|
mov ah,al
|
|
and ah,10h
|
|
shl ah,1
|
|
or dl,ah
|
|
mov ah,al
|
|
and ah,01h
|
|
shl ah,4
|
|
or dl,ah
|
|
mov ah,al
|
|
and ah,80h
|
|
shr ah,4
|
|
or dl,ah
|
|
mov ah,al
|
|
and ah,08h
|
|
shr ah,1
|
|
or dl,ah
|
|
mov ah,al
|
|
and ah,40h
|
|
shr ah,5
|
|
or dl,ah
|
|
mov ah,al
|
|
and ah,04h
|
|
shr ah,2
|
|
or dl,ah
|
|
mov [ebx],dl
|
|
inc al
|
|
inc ebx
|
|
dec ecx
|
|
jnz plane1_conv_table_loop
|
|
|
|
; Generate the table used to multiplex bits from form accumulated from DIB4
|
|
; to VGA planar byte format for plane 2. Translation is from 20643175 source
|
|
; DIB format (where 0 is leftmost, 7 is rightmost) to 76543210 VGA
|
|
; format (where 7 is leftmost, 0 is rightmost).
|
|
|
|
mov ecx,256
|
|
sub al,al
|
|
plane2_conv_table_loop:
|
|
sub dl,dl
|
|
mov ah,al
|
|
and ah,40h
|
|
shl ah,1
|
|
or dl,ah
|
|
mov ah,al
|
|
and ah,04h
|
|
shl ah,4
|
|
or dl,ah
|
|
mov ah,al
|
|
and ah,80h
|
|
shr ah,2
|
|
or dl,ah
|
|
mov ah,al
|
|
and ah,08h
|
|
shl ah,1
|
|
or dl,ah
|
|
mov ah,al
|
|
and ah,10h
|
|
shr ah,1
|
|
or dl,ah
|
|
mov ah,al
|
|
and ah,01h
|
|
shl ah,2
|
|
or dl,ah
|
|
mov ah,al
|
|
and ah,20h
|
|
shr ah,4
|
|
or dl,ah
|
|
mov ah,al
|
|
and ah,02h
|
|
shr ah,1
|
|
or dl,ah
|
|
mov [ebx],dl
|
|
inc al
|
|
inc ebx
|
|
dec ecx
|
|
jnz plane2_conv_table_loop
|
|
|
|
; Generate the table used to multiplex bits from form accumulated from DIB4
|
|
; to VGA planar byte format for plane 1. Translation is from 02461357 source
|
|
; DIB format (where 0 is leftmost, 7 is rightmost) to 76543210 VGA
|
|
; format (where 7 is leftmost, 0 is rightmost).
|
|
|
|
mov ecx,256
|
|
sub al,al
|
|
plane3_conv_table_loop:
|
|
sub dl,dl
|
|
mov ah,al
|
|
and ah,80h
|
|
or dl,ah
|
|
mov ah,al
|
|
and ah,08h
|
|
shl ah,3
|
|
or dl,ah
|
|
mov ah,al
|
|
and ah,40h
|
|
shr ah,1
|
|
or dl,ah
|
|
mov ah,al
|
|
and ah,04h
|
|
shl ah,2
|
|
or dl,ah
|
|
mov ah,al
|
|
and ah,20h
|
|
shr ah,2
|
|
or dl,ah
|
|
mov ah,al
|
|
and ah,02h
|
|
shl ah,1
|
|
or dl,ah
|
|
mov ah,al
|
|
and ah,10h
|
|
shr ah,3
|
|
or dl,ah
|
|
mov ah,al
|
|
and ah,01h
|
|
or dl,ah
|
|
mov [ebx],dl
|
|
inc al
|
|
inc ebx
|
|
dec ecx
|
|
jnz plane3_conv_table_loop
|
|
|
|
cRet vSetDIB4ToVGATables ;done
|
|
|
|
endProc vSetDIB4ToVGATables
|
|
|
|
;-----------------------------------------------------------------------;
|
|
|
|
cProc vDIB2VGA,24,< \
|
|
uses esi edi ebx, \
|
|
pdsurfDst: ptr DEVSURF, \
|
|
pdsurfSrc: ptr DEVSURF, \
|
|
prclDst: ptr RECTL, \
|
|
pptlSrc : ptr POINTL, \
|
|
pConv : dword, \
|
|
fDfbTrg : dword >
|
|
|
|
local ulBytesPerPlane:dword ;# of bytes in a whole scan line
|
|
local ulDstLeftEdge:dword ;working copy of prclDst.xLeft
|
|
local ulDstRightEdge:dword ;working copy of prclDst.xRight
|
|
|
|
local ulWholeDwordCount:dword ;# of whole VGA dwords to copy to
|
|
local ulSourceDwordWidth:dword ;# of DIB dwords from which to copy
|
|
; (rounded up to the nearest dword)
|
|
local ulLeftMask:dword ;low byte = mask for new pixels at
|
|
; left edge;
|
|
;high byte = mask for dest at left
|
|
; edge;
|
|
;high word = 0ffffh
|
|
local ulRightMask:dword ;low byte = mask for new pixels at
|
|
; partial left edge;
|
|
;high byte = mask for destination at
|
|
; partial right edge;
|
|
;high word = 0ffffh
|
|
local ulPlane0Scans:dword ;# of scans to copy in plane 0 in burst
|
|
local ulPlane1Scans:dword ;# of scans to copy in plane 1 in burst
|
|
local ulPlane2Scans:dword ;# of scans to copy in plane 2 in burst
|
|
local ulPlane3Scans:dword ;# of scans to copy in plane 3 in burst
|
|
local ulSrcDelta:dword ;offset from end of one source scan to
|
|
; copy to start of next in working
|
|
; source (either DIB or temp buffer)
|
|
local ulTrueSrcDelta:dword ;offset from end of one source scan to
|
|
; copy to start of next in DIB if temp
|
|
; buffer is being used
|
|
local ulDstDelta:dword ;offset from end of one destination
|
|
; scan to copy to start of next
|
|
local pSrc:dword ;pointer to working drawing src start
|
|
; address (either DIB or temp buffer)
|
|
local pTrueSrc:dword ;pointer to drawing src start address
|
|
; in DIB if temp buffer is being used
|
|
local pDst:dword ;pointer to drawing dst start address
|
|
local pTempBuffer:dword ;pointer to buffer used for alignment
|
|
local ulCurrentTopScan:dword ;top scan to copy to in current bank
|
|
local ulBottomScan:dword ;bottom scan line of copy rectangle
|
|
local ulAlignShift:dword ;# of bits to shift left (+) or right
|
|
; (-) to dword align source to dest
|
|
local ulBurstMax:dword ;max # of scans to be done in a single
|
|
; plane before switching to the next
|
|
; plane (to avoid flicker)
|
|
local pAlignmentRoutine:dword ;pointer to routine to be used to
|
|
; copy & align the source with the dest
|
|
local DIB4_to_VGA_plane0_table:dword ;pointers to conversion tables
|
|
local DIB4_to_VGA_plane1_table:dword ; for the four planes
|
|
local DIB4_to_VGA_plane2_table:dword
|
|
local DIB4_to_VGA_plane3_table:dword
|
|
local ulCopyControlFlags:dword ;upper bits indicate which portions of
|
|
; copy are to be performed, as follows:
|
|
|
|
local aTempBuf[BUF_SIZE]:byte
|
|
|
|
ODD_WHOLE_WORD equ 80000000h ;there are an odd # of VGA words to
|
|
; copy to
|
|
.errnz ODD_WHOLE_WORD-80000000h ; (note that this *must* be bit 31,
|
|
; because the sign status is used to
|
|
; detect this case)
|
|
WHOLE_WORDS equ 40000000h ;whole words to be copied
|
|
LEADING_BYTE equ 20000000h ;leading byte should be copied
|
|
TRAILING_BYTE equ 10000000h ;trailing byte should be copied
|
|
LEADING_PARTIAL equ 08000000h ;partial leading byte should be copied
|
|
TRAILING_PARTIAL equ 04000000h ;partial trailing byte should be copied
|
|
|
|
|
|
;-----------------------------------------------------------------------;
|
|
|
|
cld
|
|
|
|
mov esi,prclDst ;point to rectangle to which to copy
|
|
mov eax,[esi].xLeft
|
|
mov ulDstLeftEdge,eax ;save working copy of prclDst.xLeft
|
|
mov edx,[esi].xRight
|
|
mov ulDstRightEdge,edx ;save working copy of prclDst.xRight
|
|
|
|
;-----------------------------------------------------------------------;
|
|
; Point to the source start address (nearest dword equal or less).
|
|
;-----------------------------------------------------------------------;
|
|
|
|
mov ebx,pptlSrc ;point to coords of source upper left
|
|
mov esi,pdsurfSrc ;point to surface to copy from (DIB4)
|
|
mov edi,pdsurfDst ;point to surface to copy to (VGA)
|
|
mov eax,[ebx].ptl_y
|
|
imul [esi].dsurf_lNextScan ;offset in bitmap of top src rect scan
|
|
mov edx,[ebx].ptl_x
|
|
shr edx,1 ;source byte X address
|
|
and edx,not 11b ;round down to nearest dword
|
|
add eax,edx ;offset in bitmap of first source dword
|
|
add eax,[esi].dsurf_pvBitmapStart ;pointer to first source dword
|
|
mov pSrc,eax
|
|
|
|
;-----------------------------------------------------------------------;
|
|
; Set the pointers to the DIB->VGA conversion tables for the four
|
|
; planes; those tables are created at start-up, and found via the PDEV.
|
|
;-----------------------------------------------------------------------;
|
|
|
|
mov eax,pConv ;first conversion table
|
|
mov DIB4_to_VGA_plane0_table,eax
|
|
inc ah ;add 256 to point to next table
|
|
mov DIB4_to_VGA_plane1_table,eax
|
|
inc ah ;add 256 to point to next table
|
|
mov DIB4_to_VGA_plane2_table,eax
|
|
inc ah ;add 256 to point to next table
|
|
mov DIB4_to_VGA_plane3_table,eax
|
|
|
|
;-----------------------------------------------------------------------;
|
|
; Set up various variables for the copy.
|
|
;
|
|
; At this point, EBX = pptlSrc, EDI = pdsurfDst.
|
|
;-----------------------------------------------------------------------;
|
|
|
|
mov esi,prclDst ;point to rectangle to which to copy
|
|
sub ecx,ecx ;accumulate copy control flags, which
|
|
; describe the various portions of the
|
|
; copy we want to perform
|
|
|
|
;first, check for partial-byte edges
|
|
mov eax,ulDstLeftEdge
|
|
and eax,111b ;left edge pixel alignment
|
|
jz short @F ;whole byte, don't need leading mask
|
|
or ecx,LEADING_PARTIAL ;do need leading mask
|
|
@@:
|
|
mov edx,-1 ;set high word, so copy control bits
|
|
; aren't wiped out by AND
|
|
mov dl,jLeftMasks[eax] ;mask to apply to source to clip
|
|
mov dh,dl
|
|
not dh ;mask to apply to dest to preserve
|
|
mov ulLeftMask,edx ;remember mask
|
|
|
|
mov eax,ulDstRightEdge
|
|
and eax,111b ;right edge pixel alignment
|
|
jz short @F ;whole byte, don't need trailing mask
|
|
or ecx,TRAILING_PARTIAL ;do need trailing mask
|
|
@@:
|
|
mov edx,-1 ;set high word, so copy control bits
|
|
; aren't wiped out by AND
|
|
mov dl,jRightMasks[eax] ;mask to apply to source to clip
|
|
mov dh,dl
|
|
not dh ;mask to apply to dest to preserve
|
|
mov ulRightMask,edx ;remember mask
|
|
|
|
;now, see if there are only partial
|
|
; bytes, or maybe even only one byte
|
|
mov eax,ulDstLeftEdge
|
|
add eax,111b
|
|
and eax,not 111b ;round left up to nearest byte
|
|
mov edx,ulDstRightEdge
|
|
and edx,not 111b ;round right down to nearest byte
|
|
sub edx,eax ;# of pixels, rounded to nearest byte
|
|
; boundaries (not counting partials)
|
|
ja short check_whole_bytes ;there's at least one whole byte
|
|
;there are no whole bytes; there may be
|
|
; only one partial byte, or there may
|
|
; be two
|
|
jb short one_partial_only ;there is only one, partial byte
|
|
;if the dest is left- or right-
|
|
; justified, then there's only one,
|
|
; partial byte, otherwise there are two
|
|
; partial bytes
|
|
cmp byte ptr ulLeftMask,0ffh ;left-justified in byte?
|
|
jz short one_partial_only ;yes, so only one, partial byte
|
|
cmp byte ptr ulRightMask,0ffh ;right-justified in byte?
|
|
jnz short set_copy_control_flags ;no, so there are two partial
|
|
; bytes, which is exactly what
|
|
; we're already set up to do
|
|
one_partial_only:: ;only one, partial byte, so construct a
|
|
; single mask and set up to do just
|
|
; one, partial byte
|
|
mov eax,ulLeftMask
|
|
and eax,ulRightMask ;intersect the masks
|
|
mov ah,al
|
|
not ah ;construct the destination mask
|
|
mov ulLeftMask,eax
|
|
mov ecx,LEADING_PARTIAL ;only one partial byte, which we'll
|
|
; treat as leading
|
|
jmp short set_copy_control_flags ;the copy control flags are set
|
|
|
|
align 4
|
|
check_whole_bytes::
|
|
;check for leading and trailing odd
|
|
; (non-word-aligned) whole bytes
|
|
mov eax,ulDstLeftEdge ;check for leading whole byte
|
|
and eax,1111b ;intra-word address
|
|
jz short @F ;whole leading word, so no whole byte
|
|
cmp eax,8 ;is start at or before second byte
|
|
; start?
|
|
ja short @F ;no, so no whole byte
|
|
or ecx,LEADING_BYTE ;yes, there's a leading byte
|
|
@@:
|
|
|
|
mov eax,ulDstRightEdge ;check for trailing whole byte
|
|
and eax,1111b ;intra-word address
|
|
jz short @F ;whole trailing word, so no whole byte
|
|
cmp eax,8 ;is start before second byte start?
|
|
jb short @F ;no, so no whole byte
|
|
or ecx,TRAILING_BYTE ;yes, there's a trailing byte
|
|
@@:
|
|
|
|
;finally, calculate the number of whole
|
|
; aligned words and pairs thereof we'll
|
|
; process
|
|
mov eax,ulDstLeftEdge
|
|
add eax,1111b
|
|
shr eax,4 ;round left up to nearest word
|
|
mov edx,ulDstRightEdge
|
|
shr edx,4 ;round down to nearest word
|
|
sub edx,eax ;# of whole aligned words
|
|
jz short set_copy_control_flags ;no whole aligned words
|
|
or ecx,WHOLE_WORDS ;mark that we have whole aligned words
|
|
inc edx
|
|
shr edx,1 ;# of whole dwords, or fractions
|
|
mov ulWholeDwordCount,edx ; thereof
|
|
jc short set_copy_control_flags ;no odd word
|
|
or ecx,ODD_WHOLE_WORD ;mark that we have an odd word to copy
|
|
|
|
set_copy_control_flags::
|
|
mov ulCopyControlFlags,ecx
|
|
|
|
;-----------------------------------------------------------------------;
|
|
; If we're going to have to read from display memory, set up the Graphics
|
|
; Controller to point to the Read Map, so we can save some OUTs later.
|
|
;
|
|
; At this point, EBX = pptlSrc, ECX = ulCopyControlFlags, ESI = prclDst,
|
|
; EDI = pdsurfDst.
|
|
;-----------------------------------------------------------------------;
|
|
|
|
cmp fDfbTrg,0 ;if DbfTrg flag set...
|
|
jne @F ;skip VGA specific code
|
|
|
|
test ecx,LEADING_PARTIAL or TRAILING_PARTIAL
|
|
jz short @F
|
|
mov edx,VGA_BASE + GRAF_ADDR
|
|
mov al,GRAF_READ_MAP
|
|
out dx,al ;leave GRAF_ADDR pointing to Read Map
|
|
@@:
|
|
|
|
;-----------------------------------------------------------------------;
|
|
; Set up the offsets to the next source and destination scans.
|
|
;
|
|
; At this point, EBX = pptlSrc, ESI = prclDst, EDI = pdsurfDst.
|
|
;-----------------------------------------------------------------------;
|
|
|
|
mov eax,ulDstLeftEdge
|
|
shr eax,3 ;left edge byte
|
|
mov edx,ulDstRightEdge
|
|
add edx,111b ;byte after right edge
|
|
shr edx,3
|
|
sub edx,eax ;# of bytes across dest
|
|
mov eax,[edi].dsurf_lNextPlane
|
|
mov ulBytesPerPlane,eax ;save for later use
|
|
mov eax,[edi].dsurf_lNextScan
|
|
|
|
sub eax,edx ;offset from last byte dest copied to on one
|
|
mov ulDstDelta,eax ; scan to first dest byte copied to on next
|
|
|
|
mov ecx,pdsurfSrc
|
|
mov eax,ulDstLeftEdge
|
|
mov edx,ulDstRightEdge
|
|
sub edx,eax ;width in pixels
|
|
push edx ;remember width in pixels
|
|
mov eax,[ebx].ptl_x ;source left edge
|
|
add edx,eax ;source right edge
|
|
shr eax,1 ;source left start byte
|
|
and eax,not 11b ;source left start rounded to nearest dword
|
|
inc edx
|
|
shr edx,1 ;source right byte after last byte copied
|
|
add edx,11b
|
|
and edx,not 11b ;round up to source right dword after last byte
|
|
; copied
|
|
sub edx,eax ;source width in bytes, rounded to dwords
|
|
; (because we always work with source dwords)
|
|
mov eax,[ecx].dsurf_lNextScan
|
|
sub eax,edx ;offset from last source byte copied from on
|
|
mov ulSrcDelta,eax ; one scan to first source byte copied to on
|
|
; next
|
|
|
|
;-----------------------------------------------------------------------;
|
|
; Set up the maximum burst size (# of scans to do before switching
|
|
; planes).
|
|
;
|
|
; At this point, EBX = pptlSrc, ESI = prclDst, EDI = pdsurfDst.
|
|
;-----------------------------------------------------------------------;
|
|
|
|
pop edx ;retrieve width in pixels
|
|
mov eax,1 ;assume we'll only do one scan per burst
|
|
; (the minimum number)
|
|
test edx,not 3ffh ;>1023 pixels?
|
|
jnz short @F ;yes, so do one scan at a time, to avoid
|
|
; flicker as separate planes are done
|
|
|
|
;<1024 pixels, so we can do more scans per
|
|
; plane, thereby saving lots of OUTs. The exact
|
|
; # of scans depends on how wide the copy is;
|
|
; the wider it is, the fewer scans
|
|
add eax,eax ;try 2 per plane
|
|
test edx,not 1ffh ;>511 pixels?
|
|
jnz short @F ;yes, so do two scans at a time
|
|
mov al,4 ;assume we'll do four scans per plane
|
|
test dh,1 ;256 or more wide?
|
|
jnz short @F ;512>width>=256, four scans will do the job
|
|
mov al,8 ;assume we'll do eight scans per plane
|
|
add dl,dl ;128 or more wide?
|
|
jc short @F ;256>width>=128, eight scans is fine
|
|
mov al,16 ;assume we'll do sixteen scans per plane
|
|
js short @F ;128>width>=64, sixteen will do fine
|
|
mov al,32 ;<64 wide, so we'll do 32 scans per plane
|
|
@@:
|
|
mov ulBurstMax,eax ;this is the longest burst we'll do in a single
|
|
; plane
|
|
|
|
;-----------------------------------------------------------------------;
|
|
; Determine whether any shift is needed to align the source with the
|
|
; destination.
|
|
;
|
|
; At this point, EBX = pptlSrc, ESI = prclDst, EDI = pdsurfDst.
|
|
;-----------------------------------------------------------------------;
|
|
|
|
|
|
mov eax,[ebx].ptl_x
|
|
and eax,111b ;source X modulo 8
|
|
mov edx,ulDstLeftEdge
|
|
and edx,111b ;dest X modulo 8
|
|
sub eax,edx ;(source X modulo 8) - (dest X modulo 8)
|
|
mov ulAlignShift,eax ;remember the shift
|
|
jz set_initial_banking ;if it's 0, we have no alignment to
|
|
; do, and are ready to roll
|
|
|
|
;-----------------------------------------------------------------------;
|
|
; Alignment is needed, so set up the alignment variables.
|
|
;
|
|
; At this point, EBX = pptlSrc, ESI = prclDst, EDI = pdsurfDst,
|
|
; EAX = shift, in range -7 to 7.
|
|
;-----------------------------------------------------------------------;
|
|
|
|
mov edx,ulSrcDelta ;remember the real source width; we'll fake
|
|
mov ulTrueSrcDelta,edx ; ulSrcDelta for the drawing routines
|
|
|
|
;set ulSrcDelta to either 0 or 4,
|
|
; depending on whether the last dword
|
|
; we rotate is needed (because we
|
|
; always generate as many dest dwords as
|
|
; there are source dwords on left shifts,
|
|
; and we always generate dest dwords = # source
|
|
; dwords + 1 on right shifts, whether we need
|
|
; the last dword or not; we only need it when
|
|
; the right edge shifts left)
|
|
mov ecx,ulDstRightEdge
|
|
sub ecx,ulDstLeftEdge
|
|
add ecx,[ebx].ptl_x ;CL = lsb of source right edge
|
|
dec ecx ;adjust to actual right X, rather than X+1
|
|
mov ch,byte ptr ulDstRightEdge ;CH = lsb of dest right edge
|
|
dec ch ;adjust to actual right X, rather than X+1
|
|
and ecx,0707h ;right source and dest intrabyte addresses
|
|
sub edx,edx ;assume we need the last byte, in which case
|
|
; the source in the temp buffer (from which we
|
|
; always copy after rotation) is contiguous
|
|
cmp ch,cl ;right or left shift at right edge?
|
|
jb short @F ;left shift at right edge, so every byte in the
|
|
; temp buffer will be used
|
|
add edx,4 ;right shift at right edge, so the last byte in
|
|
; the temp buffer won't be used, thus skip it
|
|
@@:
|
|
mov ulSrcDelta,edx ;delta to next scan in temp buffer
|
|
|
|
and eax,eax ;shift left or right?
|
|
js short @F ;shift right
|
|
;shift left
|
|
|
|
mov edx,offset align_burst_lshift_486 ;shifting left, assume 486
|
|
jmp short set_shift_vec ;486
|
|
|
|
align 4
|
|
@@: ;shifting right
|
|
|
|
and eax,7 ;for left shift, shift value is already
|
|
; correct; for right shift, this is equivalent
|
|
; to 8 - right shift, since we always shift
|
|
; left (remember, EAX is currently negative for
|
|
; right shifts)
|
|
mov edx,offset align_burst_rshift_486 ;486
|
|
set_shift_vec::
|
|
mov pAlignmentRoutine,edx ;routine to be used to shift into
|
|
; alignment with destination
|
|
shl eax,2 ;multiply by 4 because we're dealing with
|
|
; 4-bit pixels
|
|
mov ulAlignShift,eax ;remember the shift amount
|
|
mov eax,ulDstRightEdge
|
|
sub eax,ulDstLeftEdge ;pixel width of rectangle to copy
|
|
mov edx,[ebx].ptl_x ;left pixel of source
|
|
and edx,111b ;distance in pixels from left pixel to pixel at
|
|
; start of left dword
|
|
add eax,edx ;pixel width from start of left dword to right
|
|
; edge of copy in source
|
|
add eax,7 ;round up to nearest dword (8 pixel set)
|
|
shr eax,3 ;# of dwords spanned by source
|
|
mov ulSourceDwordWidth,eax ;always pick up this number of dwords
|
|
; when aligning
|
|
|
|
lea eax,aTempBuf ;use 2K stack buffer as temp storage
|
|
mov pTempBuffer,eax ; temporary-use buffer
|
|
|
|
mov eax,pSrc ;remember the real source pointer; we'll fake
|
|
mov pTrueSrc,eax ; pSrc for the drawing routines
|
|
|
|
;-----------------------------------------------------------------------;
|
|
; Copy all banks in the destination rectangle, one at a time.
|
|
;
|
|
; At this point, ESI = prclDst, EDI = pdsurfDst
|
|
;-----------------------------------------------------------------------;
|
|
|
|
set_initial_banking::
|
|
|
|
;-----------------------------------------------------------------------;
|
|
; Map in the bank containing the top scan to copy to, if it's not mapped
|
|
; in already.
|
|
;-----------------------------------------------------------------------;
|
|
|
|
mov eax,[esi].yBottom
|
|
mov ulBottomScan,eax ;bottom scan to which to copy
|
|
mov eax,[esi].yTop ;top scan line of copy
|
|
mov ulCurrentTopScan,eax ;this will be the copy top in 1st bank
|
|
|
|
cmp fDfbTrg,0 ;if DbfTrg flag set...
|
|
jne init_bank_mapped ;skip banking code
|
|
|
|
cmp eax,[edi].dsurf_rcl1WindowClip.yTop ;is copy top less than
|
|
; current bank?
|
|
jl short map_init_bank ;yes, map in proper bank
|
|
cmp eax,[edi].dsurf_rcl1WindowClip.yBottom ;copy top greater than
|
|
; current bank?
|
|
jl short init_bank_mapped ;no, proper bank already mapped
|
|
map_init_bank::
|
|
|
|
; Map in the bank containing the top scan line of the copy dest.
|
|
|
|
ptrCall <dword ptr [edi].dsurf_pfnBankControl>,<edi,eax,JustifyTop>
|
|
|
|
init_bank_mapped::
|
|
|
|
;-----------------------------------------------------------------------;
|
|
; Compute the starting address for the initial dest bank.
|
|
;-----------------------------------------------------------------------;
|
|
|
|
mov eax,ulCurrentTopScan ;top scan line to which to copy in
|
|
; current bank
|
|
imul [edi].dsurf_lNextScan ;offset of starting scan line
|
|
mov edx,ulDstLeftEdge ;left dest X coordinate
|
|
shr edx,3 ;left dest byte offset in row
|
|
add eax,edx ;initial offset in dest bitmap
|
|
|
|
; Note that the start of the bitmap will change each time through the
|
|
; bank loop, because the start of the bitmap is varied to map the
|
|
; desired scan line to the banking window.
|
|
|
|
add eax,[edi].dsurf_pvBitmapStart ;initial dest bitmap address
|
|
mov pDst,eax ;remember where to start drawing
|
|
|
|
;-----------------------------------------------------------------------;
|
|
; Main loop for processing copying to each bank.
|
|
;
|
|
; At this point, EDI->pdsurfDst
|
|
;-----------------------------------------------------------------------;
|
|
|
|
bank_loop::
|
|
|
|
; Calculate the # of scans to do in this bank.
|
|
|
|
mov ebx,ulBottomScan ;bottom of destination rectangle
|
|
|
|
cmp fDfbTrg,0 ;if DbfTrg flag set...
|
|
jne @F ;skip banking code
|
|
|
|
cmp ebx,[edi].dsurf_rcl1WindowClip.yBottom
|
|
;which comes first, the bottom of the
|
|
; dest rect or the bottom of the
|
|
; current bank?
|
|
jl short @F ;copy bottom comes first, so draw to
|
|
; that; this is the last bank in copy
|
|
mov ebx,[edi].dsurf_rcl1WindowClip.yBottom
|
|
;bank bottom comes first; draw to
|
|
; bottom of bank
|
|
@@:
|
|
sub ebx,ulCurrentTopScan ;# of scans to copy in bank
|
|
|
|
;-----------------------------------------------------------------------;
|
|
; Copy to the screen in bursts of either ulBurstMax size or remaining
|
|
; number of scans in bank, whichever is less.
|
|
;
|
|
; At this point, EBX = # of scans remaining in bank.
|
|
;-----------------------------------------------------------------------;
|
|
|
|
copy_burst_loop::
|
|
mov eax,ulBurstMax ;most scans we can copy per plane
|
|
sub ebx,eax ;# of scans left in bank after copying that many
|
|
jnle short @F ;there are enough scans left to copy max #
|
|
add eax,ebx ;not enough scans left; copy all remaining scans
|
|
sub ebx,ebx ;after this, no scans remain in bank
|
|
@@:
|
|
push ebx ;# of scan lines remaining in bank after burst
|
|
;EAX = # of scans in burst
|
|
mov ulPlane0Scans,eax ;set the scan count for each of the plane
|
|
mov ulPlane1Scans,eax ; loops
|
|
mov ulPlane2Scans,eax
|
|
mov ulPlane3Scans,eax
|
|
|
|
;-----------------------------------------------------------------------;
|
|
; If necessary, align the dwords in this burst so that the left edge is
|
|
; on a dword boundary.
|
|
;
|
|
; At this point, AL = # of scans in burst.
|
|
;-----------------------------------------------------------------------;
|
|
|
|
mov ecx,ulAlignShift
|
|
and ecx,ecx ;is alignment needed?
|
|
jz proceed_with_copy ;no, so we're ready to copy
|
|
|
|
mov ch,al ;# of scans to copy
|
|
mov esi,pTrueSrc ;copy from current source location
|
|
mov edi,pTempBuffer ;copy to the temp buffer
|
|
|
|
jmp pAlignmentRoutine ;perform the copy
|
|
|
|
;-----------------------------------------------------------------------;
|
|
; Loops to align this burst's scans for left or right shift.
|
|
;
|
|
; Input: CH = # of scans to copy in this burst (max burst = 256)
|
|
; CL = # of bits to shift left to dword align
|
|
; ESI = first dword of first DIB scan to convert
|
|
; EDI = first dword of buffer into which to shift
|
|
; ulSourceDwordWidth = # of dwords across source
|
|
; ulTrueSrcDelta = distance from end of one source scan (rounded up to
|
|
; nearest dword) to start of next
|
|
;
|
|
; All loops alway flush (write) the last dword, so one more dword
|
|
; is written to the dest than is read from the source. This requires the
|
|
; dest buffer to have room for an extra dword.
|
|
;-----------------------------------------------------------------------;
|
|
|
|
;-----------------------------------------------------------------------;
|
|
; Macro to copy and align the current burst for left shift.
|
|
;-----------------------------------------------------------------------;
|
|
|
|
ALIGN_BURST_LSHIFT macro Is486
|
|
local align_burst_lshift_loop,align_last_lshift,align_odd_lshift
|
|
local align_lshift_loop
|
|
align_burst_lshift_loop:
|
|
mov ebx,ulSourceDwordWidth ;# of dwords across source
|
|
mov edx,[esi] ;load the initial source dword
|
|
add esi,4 ;point to next source dword
|
|
bswap edx ;make it big endian
|
|
dec ebx ;any more dwords to shift?
|
|
jz short align_last_lshift ;no, do just this one
|
|
inc ebx
|
|
shr ebx,1 ;double dword count
|
|
jnc short align_odd_lshift ;do odd dword
|
|
align 4
|
|
align_lshift_loop:
|
|
mov eax,[esi] ;get next dword to align
|
|
add esi,4 ;point to next source dword
|
|
bswap eax ;make it big endian
|
|
shld edx,eax,cl ;shift to generate a 32-bit shifted value
|
|
bswap edx ;make it big endian
|
|
mov [edi],edx ;store it
|
|
add edi,4 ;point to next dest dword
|
|
mov edx,eax ;set up for the next shift
|
|
align_odd_lshift:
|
|
mov eax,[esi] ;get next dword to align
|
|
add esi,4 ;point to next source dword
|
|
bswap eax ;make it big endian
|
|
shld edx,eax,cl ;shift to generate a 32-bit shifted value
|
|
bswap edx ;make it big endian
|
|
mov [edi],edx ;store it
|
|
add edi,4 ;point to next dest dword
|
|
mov edx,eax ;set up for the next shift
|
|
dec ebx ;count down dwords to shift
|
|
jnz align_lshift_loop ;do next dword, if any
|
|
align_last_lshift: ;do the last dword, which doesn't require a
|
|
; new source byte
|
|
shl edx,cl ;shift it into position
|
|
bswap edx ;make it big endian
|
|
mov [edi],edx ;store it
|
|
add edi,4 ;point to next dest dword
|
|
|
|
add esi,ulTrueSrcDelta ;point to next source scan
|
|
dec ch ;count down scans in burst
|
|
jnz align_burst_lshift_loop
|
|
ENDM ;ALIGN_BURST_LSHIFT
|
|
|
|
;-----------------------------------------------------------------------;
|
|
; Macro to copy and align the current burst for right shift.
|
|
;-----------------------------------------------------------------------;
|
|
|
|
ALIGN_BURST_RSHIFT macro Is486
|
|
local align_burst_rshift_loop,align_odd_rshift,align_rshift_loop
|
|
align_burst_rshift_loop:
|
|
mov ebx,ulSourceDwordWidth ;# of dwords across source
|
|
inc ebx
|
|
shr ebx,1 ;double dword count
|
|
jnc short align_odd_rshift ;do odd dword
|
|
align 4
|
|
align_rshift_loop:
|
|
mov eax,[esi] ;get next dword to align
|
|
add esi,4 ;point to next source dword
|
|
bswap eax ;make it big endian
|
|
shld edx,eax,cl ;shift to generate a 32-bit shifted value
|
|
bswap edx ;make it little endian
|
|
mov [edi],edx ;store it
|
|
add edi,4 ;point to next dest dword
|
|
mov edx,eax ;set up for the next shift
|
|
align_odd_rshift:
|
|
mov eax,[esi] ;get next dword to align
|
|
add esi,4 ;point to next source dword
|
|
bswap eax ;make it big endian
|
|
shld edx,eax,cl ;shift to generate a 32-bit shifted value
|
|
bswap edx ;make it little endian
|
|
mov [edi],edx ;store it
|
|
add edi,4 ;point to next dest dword
|
|
mov edx,eax ;set up for the next shift
|
|
dec ebx ;count down dwords to shift
|
|
jnz align_rshift_loop ;do next dword, if any
|
|
|
|
;do the trailing destination dword
|
|
shl edx,cl ;shift into position
|
|
bswap edx ;make it little endian
|
|
mov [edi],edx ;store it
|
|
add edi,4 ;point to next dest dword
|
|
|
|
add esi,ulTrueSrcDelta ;point to next source scan
|
|
dec ch ;count down scans in burst
|
|
jnz align_burst_rshift_loop
|
|
ENDM ;ALIGN_BURST_RSHIFT
|
|
;-----------------------------------------------------------------------;
|
|
|
|
align 4
|
|
align_burst_rshift_486::
|
|
ALIGN_BURST_RSHIFT 1
|
|
jmp short set_alignment_source
|
|
|
|
align 4
|
|
align_burst_lshift_486::
|
|
ALIGN_BURST_LSHIFT 1
|
|
|
|
;-----------------------------------------------------------------------;
|
|
; Set up the pointers for a copy from the temp buffer, and advance the
|
|
; real pointer.
|
|
;-----------------------------------------------------------------------;
|
|
set_alignment_source::
|
|
mov pTrueSrc,esi ;remember where to start next time in source
|
|
mov esi,pTempBuffer ;copy from the temp buffer
|
|
mov pSrc,esi ;remember where the copy source is (DIB or
|
|
; temp buffer)
|
|
|
|
proceed_with_copy::
|
|
|
|
; Load ECX with the copy control flags; this stays set throughout the
|
|
; copying of this burst.
|
|
|
|
mov ecx,ulCopyControlFlags
|
|
|
|
; Copy the DIB scan to VGA plane 0.
|
|
|
|
mov esi,pSrc
|
|
mov edi,pDst
|
|
|
|
cmp fDfbTrg,0 ;if DbfTrg flag set...
|
|
jne @F ;skip VGA specific code
|
|
|
|
; Map in plane 0 for writes.
|
|
|
|
mov edx,VGA_BASE + SEQ_DATA
|
|
mov al,MM_C0
|
|
out dx,al ;map in plane 0 for writes (SEQ_ADDR points to the Map
|
|
; Mask by default)
|
|
|
|
; Map in plane 0 for reads if and only if we need to handle partial edge
|
|
; bytes, which require read/modify/write cycles.
|
|
|
|
test ecx,LEADING_PARTIAL or TRAILING_PARTIAL
|
|
jz short @F
|
|
mov edx,VGA_BASE + GRAF_DATA
|
|
mov al,RM_C0
|
|
out dx,al ;map in plane 0 for reads (GRAF_ADDR already points to
|
|
; Read Map)
|
|
@@:
|
|
jmp DIB4_to_VGA_plane0_copy
|
|
|
|
align 4
|
|
copy_burst_plane0_done::
|
|
|
|
; Copy the DIB scan to VGA plane 1.
|
|
|
|
cmp fDfbTrg,0 ;if DbfTrg flag NOT set...
|
|
je @F ;skip DFB specific code
|
|
mov eax,ulBytesPerPlane
|
|
add pDst,eax ;dest scan mod 4 now == 1
|
|
@@:
|
|
mov esi,pSrc
|
|
mov edi,pDst
|
|
|
|
cmp fDfbTrg,0 ;if DbfTrg flag set...
|
|
jne @F ;skip VGA specific code
|
|
|
|
; Map in plane 1 for writes.
|
|
|
|
mov edx,VGA_BASE + SEQ_DATA
|
|
mov al,MM_C1
|
|
out dx,al ;map in plane 1 for writes (SEQ_ADDR points to the Map
|
|
; Mask by default)
|
|
|
|
; Map in plane 1 for reads if and only if we need to handle partial edge
|
|
; bytes, which require read/modify/write cycles.
|
|
|
|
test ecx,LEADING_PARTIAL or TRAILING_PARTIAL
|
|
jz short @F
|
|
mov edx,VGA_BASE + GRAF_DATA
|
|
mov al,RM_C1
|
|
out dx,al ;map in plane 1 for reads (GRAF_ADDR already points to
|
|
; Read Map)
|
|
@@:
|
|
jmp DIB4_to_VGA_plane1_copy
|
|
|
|
align 4
|
|
copy_burst_plane1_done::
|
|
|
|
; Copy the DIB scan to VGA plane 2.
|
|
|
|
cmp fDfbTrg,0 ;if DbfTrg flag NOT set...
|
|
je @F ;skip DFB specific code
|
|
mov eax,ulBytesPerPlane
|
|
add pDst,eax ;dest scan mod 4 now == 2
|
|
@@:
|
|
mov esi,pSrc
|
|
mov edi,pDst
|
|
|
|
cmp fDfbTrg,0 ;if DbfTrg flag set...
|
|
jne @F ;skip VGA specific code
|
|
|
|
; Map in plane 2 for writes.
|
|
|
|
mov edx,VGA_BASE + SEQ_DATA
|
|
mov al,MM_C2
|
|
out dx,al ;map in plane 2 for writes (SEQ_ADDR points to the Map
|
|
; Mask by default)
|
|
|
|
; Map in plane 2 for reads if and only if we need to handle partial edge
|
|
; bytes, which require read/modify/write cycles.
|
|
|
|
test ecx,LEADING_PARTIAL or TRAILING_PARTIAL
|
|
jz short @F
|
|
mov edx,VGA_BASE + GRAF_DATA
|
|
mov al,RM_C2
|
|
out dx,al ;map in plane 2 for reads (GRAF_ADDR already points to
|
|
; Read Map)
|
|
@@:
|
|
jmp DIB4_to_VGA_plane2_copy
|
|
|
|
align 4
|
|
copy_burst_plane2_done::
|
|
|
|
; Copy the DIB scan to VGA plane 3.
|
|
|
|
cmp fDfbTrg,0 ;if DbfTrg flag NOT set...
|
|
je @F ;skip DFB specific code
|
|
mov eax,ulBytesPerPlane
|
|
add pDst,eax ;dest scan mod 4 now == 3
|
|
@@:
|
|
mov esi,pSrc
|
|
mov edi,pDst
|
|
|
|
cmp fDfbTrg,0 ;if DbfTrg flag set...
|
|
jne @F ;skip VGA specific code
|
|
|
|
; Map in plane 3 for writes.
|
|
|
|
mov edx,VGA_BASE + SEQ_DATA
|
|
mov al,MM_C3
|
|
out dx,al ;map in plane 3 for writes (SEQ_ADDR points to the Map
|
|
; Mask by default)
|
|
|
|
; Map in plane 3 for reads if and only if we need to handle partial edge
|
|
; bytes, which require read/modify/write cycles.
|
|
|
|
test ecx,LEADING_PARTIAL or TRAILING_PARTIAL
|
|
jz short @F
|
|
mov edx,VGA_BASE + GRAF_DATA
|
|
mov al,RM_C3
|
|
out dx,al ;map in plane 3 for reads (GRAF_ADDR already points to
|
|
; Read Map)
|
|
@@:
|
|
jmp DIB4_to_VGA_plane3_copy
|
|
|
|
align 4
|
|
copy_burst_plane3_done::
|
|
|
|
mov pSrc,esi ;remember where we are, for next burst
|
|
mov pDst,edi
|
|
|
|
pop ebx ;get back remaining length in bank
|
|
and ebx,ebx ;anything left in this bank?
|
|
jnz copy_burst_loop ;continue if so
|
|
|
|
; Done with bank; are there more banks to do?
|
|
|
|
cmp fDfbTrg,0 ;if DbfTrg flag set...
|
|
jne @F ;skip banking and VGA code
|
|
|
|
mov edi,pdsurfDst
|
|
mov eax,[edi].dsurf_rcl1WindowClip.yBottom ;is the copy bottom in
|
|
cmp ulBottomScan,eax ; the current bank?
|
|
jnle short next_bank ;no, map in the next bank and copy to
|
|
; it
|
|
;yes, we're done
|
|
@@:
|
|
|
|
;-----------------------------------------------------------------------;
|
|
; Restore default Map Mask and done.
|
|
;-----------------------------------------------------------------------;
|
|
|
|
cmp fDfbTrg,0 ;if DbfTrg flag set...
|
|
jne @F ;skip VGA specific code
|
|
|
|
mov edx,VGA_BASE + SEQ_DATA
|
|
mov al,MM_ALL
|
|
out dx,al ;map in all planes
|
|
@@:
|
|
cRet vDIB2VGA ;done!
|
|
|
|
;-----------------------------------------------------------------------;
|
|
; Advance to the next bank and copy to it.
|
|
;-----------------------------------------------------------------------;
|
|
align 4
|
|
next_bank::
|
|
mov ulCurrentTopScan,eax ;remember where the top of the bank
|
|
; we're about to map in is (same as
|
|
; bottom of bank we just did)
|
|
mov ecx,[edi].dsurf_pvBitmapStart
|
|
sub pDst,ecx ;offset of current position in screen
|
|
|
|
ptrCall <dword ptr [edi].dsurf_pfnBankControl>,<edi,eax,JustifyTop>
|
|
;map in the bank
|
|
|
|
mov ecx,[edi].dsurf_pvBitmapStart
|
|
add pDst,ecx ;pointer to current position in screen
|
|
|
|
jmp bank_loop ;copy the next bank
|
|
|
|
;-----------------------------------------------------------------------;
|
|
; Loops for converting 1 or more scans in each of planes 0, 1, 2, and 3.
|
|
;-----------------------------------------------------------------------;
|
|
|
|
;-----------------------------------------------------------------------;
|
|
; Plane 0 DIB->VGA conversion code for a single scan line.
|
|
;-----------------------------------------------------------------------;
|
|
align 4
|
|
DIB4_to_VGA_plane0_copy::
|
|
|
|
;-----------------------------------------------------------------------;
|
|
; Set EBX to point to multiplexed DIB byte->planar byte conversion table
|
|
; for plane 0.
|
|
;
|
|
; Input: ECX with bits sets as described for ulCopyControlFlags, above
|
|
; ESI = DIB pointer to first two pixels
|
|
; EDI = VGA pointer to planar byte
|
|
; ulPlane0Scans = # of scan lines to copy to
|
|
; ulSrcDelta = offset from end of one source scan copied to start of next
|
|
; ulDstDelta = offset from end of one dest scan copied to start of next
|
|
; ulWholeDwordCount = # of whole, aligned dwords to copy
|
|
; ulLeftMask = mask for partial left edge, if any
|
|
; ulRightMask = mask for partial right edge, if any
|
|
; Plane 0 must be mapped in for writes
|
|
;-----------------------------------------------------------------------;
|
|
|
|
mov ebx,DIB4_to_VGA_plane0_table ;stays set for all bytes/words
|
|
|
|
DIB4_to_VGA_plane0_copy_loop::
|
|
|
|
;-----------------------------------------------------------------------;
|
|
; Code to convert 1-7 DIB4 pixels to a partial VGA plane 0 byte (8
|
|
; pixels in plane 0). Assumes that a full dword of DIB4 pixels (8
|
|
; pixels) is available, starting at ESI, although some of the pixels
|
|
; will be masked off. Assumes the DIB4 pixels (including masked-off
|
|
; pixels) start in the upper nibble of [ESI], and that the first
|
|
; (possibly masked-off) DIB4 pixel maps to bit 7 of the VGA at [EDI].
|
|
;
|
|
; Input: EBX = pointer to multiplexed DIB byte->planar byte conversion table
|
|
; (must start on a 256-byte boundary)
|
|
; ECX with bits sets as described for ulCopyControlFlags, above
|
|
; ESI = DIB pointer to first two pixels (possibly masked off)
|
|
; EDI = VGA pointer to planar byte
|
|
; Plane 0 must be mapped in for writes
|
|
;-----------------------------------------------------------------------;
|
|
|
|
test ecx,LEADING_PARTIAL ;handle a leading partial byte?
|
|
jz short DIB4_to_VGA_plane0_copy_lbyte ;no, go straight to whole
|
|
; byte
|
|
;yes, handle leading partial byte
|
|
mov edx,[esi] ;get 8 pixels to convert of DIB
|
|
and edx,11111111h ;keep only the plane 0 bits of DIB dword
|
|
; EDX = xxx6xxx7xxx4xxx5xxx2xxx3xxx0xxx1
|
|
shld eax,edx,16+2 ;put bits 7-4 of DIB dword in AX,
|
|
; shifted left 2 (x = zero bit)
|
|
; DX = xxx2xxx3xxx0xxx1
|
|
; AX = x6xxx7xxx4xxx5xx
|
|
or eax,edx ;put bits 7-0 of DIB dword 0 in AX:
|
|
; x6x2x7x3x4x0x5x1
|
|
mov bl,al ;BL = x4x0x5x1 of DIB dword 0
|
|
add ah,ah ;make AH 6x2x7x3x of DIB dword 0 (shl 1)
|
|
or bl,ah ;BL = 64207531 of DIB dword 0
|
|
add esi,4 ;point to next DIB dword
|
|
inc edi ;point to next VGA byte (placed here
|
|
; for 486 pipelining reasons)
|
|
mov cl,[ebx] ;CL = 76543210 of DIB dword 0
|
|
mov ch,[edi-1] ;get the VGA destination byte
|
|
and ecx,ulLeftMask ;mask off source and dest
|
|
or cl,ch ;combine masked source and dest
|
|
mov [edi-1],cl ;write the new pixels to the VGA
|
|
|
|
;-----------------------------------------------------------------------;
|
|
; Code to convert 8 DIB4 pixels to a single VGA plane 0 byte (8 pixels
|
|
; in plane 0). Assumes the DIB4 pixels start in the upper nibble of
|
|
; [ESI], and that the first DIB4 pixel maps to bit 7 of the VGA at
|
|
; [EDI].
|
|
;
|
|
; Input: EBX = pointer to multiplexed DIB byte->planar byte conversion table
|
|
; (must start on a 256-byte boundary)
|
|
; ECX with bits sets as described for ulCopyControlFlags, above
|
|
; ESI = DIB pointer to first two pixels
|
|
; EDI = VGA pointer to planar byte
|
|
; Plane 0 must be mapped in for writes
|
|
;-----------------------------------------------------------------------;
|
|
|
|
DIB4_to_VGA_plane0_copy_lbyte::
|
|
test ecx,LEADING_BYTE ;should we handle a leading byte?
|
|
jz short DIB4_to_VGA_plane0_copy_words ;no, go straight to words
|
|
;yes, handle leading byte
|
|
mov edx,[esi] ;get 8 pixels to convert of DIB
|
|
and edx,11111111h ;keep only the plane 0 bits of DIB dword
|
|
; EDX = xxx6xxx7xxx4xxx5xxx2xxx3xxx0xxx1
|
|
shld eax,edx,16+2 ;put bits 7-4 of DIB dword in AX,
|
|
; shifted left 2 (x = zero bit)
|
|
; DX = xxx2xxx3xxx0xxx1
|
|
; AX = x6xxx7xxx4xxx5xx
|
|
or eax,edx ;put bits 7-0 of DIB dword 0 in AX:
|
|
; x6x2x7x3x4x0x5x1
|
|
mov bl,al ;BL = x4x0x5x1 of DIB dword 0
|
|
add ah,ah ;make AH 6x2x7x3x of DIB dword 0 (shl 1)
|
|
or bl,ah ;BL = 64207531 of DIB dword 0
|
|
add esi,4 ;point to next DIB dword
|
|
inc edi ;point to next VGA byte (placed here
|
|
; for 486 pipelining reasons)
|
|
mov cl,[ebx] ;CL = 76543210 of DIB dword 0
|
|
mov [edi-1],cl ;write 8 bits from DIB dword to VGA
|
|
|
|
;-----------------------------------------------------------------------;
|
|
; Code to convert sets of 32 DIB4 pixels to 4 VGA plane 0 bytes (32
|
|
; pixels in plane 0). Assumes the VGA destination is word aligned.
|
|
; Assumes the DIB4 pixels start in the upper nibble of [ESI], and that
|
|
; the first DIB4 pixel maps to bit 7 of the VGA at [EDI].
|
|
;
|
|
; Input: EBX = pointer to multiplexed DIB byte->planar byte conversion table
|
|
; (must start on a 256-byte boundary)
|
|
; ECX with bits sets as described for ulCopyControlFlags, above
|
|
; ESI = DIB pointer to first two pixels
|
|
; EDI = VGA pointer to two planar bytes (must be word aligned)
|
|
; ulWholeDwordCount = # of VGA dwords to convert
|
|
; Plane 0 must be mapped in for writes
|
|
;
|
|
; Note: on entry at DIB4_to_VGA_plane0_word_odd, ESI must point to the
|
|
; desired source start minus 8, and EAX must be loaded as if the following
|
|
; instructions had been performed:
|
|
; mov edx,[esi+8]
|
|
; and edx,11111111h
|
|
; shld eax,edx,16+2
|
|
; or eax,edx
|
|
;
|
|
; Note: the code is so odd because of 486 pipeline optimization.
|
|
; DO NOT CHANGE THIS CODE UNLESS YOU KNOW EXACTLY WHAT YOU'RE DOING!!!
|
|
;
|
|
; Note: all 486 pipeline penalties are eliminated except for SHLD, which
|
|
; is losing 4 cycles total, and writing CX to memory (2 cycles), so far
|
|
; as I know.
|
|
;-----------------------------------------------------------------------;
|
|
|
|
DIB4_to_VGA_plane0_copy_words::
|
|
test ecx,ODD_WHOLE_WORD or WHOLE_WORDS ;any whole words to copy?
|
|
jz DIB4_to_VGA_plane0_copy_tbyte ;no, check for trailing whole
|
|
; bytes
|
|
;yes, copy the whole words
|
|
push ebp ;preserve stack frame pointer
|
|
mov ebp,ulWholeDwordCount ;# of VGA dwords to copy to
|
|
;even # of DIB dwords to copy? (flags still
|
|
; set from TEST)
|
|
.errnz ODD_WHOLE_WORD - 80000000h
|
|
jns short DIB4_to_VGA_plane0_word_loop ;yes, start copying
|
|
;no, there's an odd word; prepare to enter loop
|
|
; in middle
|
|
mov edx,[esi] ;get 8 pixels to convert of first DIB dword
|
|
and edx,11111111h ;keep only the plane 0 bits of DIB dword
|
|
; EDX = xxx6xxx7xxx4xxx5xxx2xxx3xxx0xxx1
|
|
shld eax,edx,16+2 ;put bits 7-4 of DIB dword in AX,
|
|
; shifted left 2
|
|
; DX = xxx2xxx3xxx0xxx1
|
|
; AX = x6xxx7xxx4xxx5xx
|
|
or eax,edx ;put bits 7-0 of DIB dword in AX:
|
|
sub esi,8 ;compensate source back for entering in middle
|
|
sub edi,2 ;compensate dest back for entering in middle
|
|
|
|
jmp short DIB4_to_VGA_plane0_word_odd
|
|
|
|
;-----------------------------------------------------------------------;
|
|
; Loop to copy a word at a time to VGA plane 0 (actually, unrolled once
|
|
; so copies dwords).
|
|
;-----------------------------------------------------------------------;
|
|
|
|
align 16
|
|
DIB4_to_VGA_plane0_word_loop::
|
|
mov edx,[esi] ;get 8 pixels to convert of DIB dword 0
|
|
and edx,11111111h ;keep only the plane 0 bits of DIB
|
|
; dword 0
|
|
; EDX = xxx6xxx7xxx4xxx5xxx2xxx3xxx0xxx1
|
|
shld eax,edx,16+2 ;put bits 7-4 of DIB dword 0 in AX,
|
|
; shifted left 2 (x = zero bit)
|
|
; DX = xxx2xxx3xxx0xxx1
|
|
; AX = x6xxx7xxx4xxx5xx
|
|
or eax,edx ;put bits 7-0 of DIB dword 0 in AX:
|
|
; x6x2x7x3x4x0x5x1
|
|
mov edx,[esi+4] ;get 8 pixels to convert of DIB dword 1
|
|
mov bl,al ;BL = x4x0x5x1 of DIB dword 0
|
|
add ah,ah ;make AH 6x2x7x3x of DIB dword 0 (shl 1)
|
|
or bl,ah ;BL = 64207531 of DIB dword 0
|
|
and edx,11111111h ;keep only the plane 0 bits of DIB
|
|
; dword 1
|
|
; EDX = xxx6xxx7xxx4xxx5xxx2xxx3xxx0xxx1
|
|
shld eax,edx,16+2 ;put bits 7-4 of DIB dword 1 in AX,
|
|
; shifted left 2
|
|
; DX = xxx2xxx3xxx0xxx1
|
|
; AX = x6xxx7xxx4xxx5xx
|
|
mov cl,[ebx] ;CL = 76543210 of DIB dword 0
|
|
or eax,edx ;put bits 7-0 of DIB dword 1 in AX:
|
|
; x6x2x7x3x4x0x5x1
|
|
mov bl,al ;BL = x4x0x5x1 of DIB dword 1
|
|
mov edx,[esi+8] ;get 8 pixels to convert of DIB dword 2
|
|
add ah,ah ;make AH 6x2x7x3x of DIB dword 1 (shl 1)
|
|
or bl,ah ;BL = 64207531 of DIB dword 1
|
|
and edx,11111111h ;keep only the plane 0 bits of DIB
|
|
; dword 2
|
|
; EDX = xxx6xxx7xxx4xxx5xxx2xxx3xxx0xxx1
|
|
shld eax,edx,16+2 ;put bits 7-4 of DIB dword 2 in AX,
|
|
; shifted left 2
|
|
; DX = xxx2xxx3xxx0xxx1
|
|
; AX = x6xxx7xxx4xxx5xx
|
|
mov ch,[ebx] ;CH = 76543210 of DIB dword 1
|
|
or eax,edx ;put bits 7-0 of DIB dword 2 in AX:
|
|
; x6x2x7x3x4x0x5x1
|
|
mov [edi],cx ;write 16 bits from DIB dwords 0 and 1
|
|
; to VGA
|
|
|
|
DIB4_to_VGA_plane0_word_odd::
|
|
mov edx,[esi+12] ;get 8 pixels to convert of DIB dword 3
|
|
mov bl,al ;BL = x4x0x5x1 of DIB dword 2
|
|
add ah,ah ;make AH 6x2x7x3x of DIB dword 2 (shl 1)
|
|
or bl,ah ;BL = 64207531 of DIB dword 2
|
|
and edx,11111111h ;keep only the plane 0 bits of DIB
|
|
; dword 3
|
|
; EDX = xxx6xxx7xxx4xxx5xxx2xxx3xxx0xxx1
|
|
shld eax,edx,16+2 ;put bits 7-4 of DIB dword 3 in AX,
|
|
; shifted left 2
|
|
; DX = xxx2xxx3xxx0xxx1
|
|
; AX = x6xxx7xxx4xxx5xx
|
|
mov cl,[ebx] ;CL = 76543210 of DIB dword 2
|
|
or eax,edx ;put bits 7-0 of DIB dword 3 in AX:
|
|
; x6x2x7x3x4x0x5x1
|
|
mov bl,al ;BL = x4x0x5x1 of DIB dword 3
|
|
add ah,ah ;make AH 6x2x7x3x of DIB dword 3 (shl 1)
|
|
or bl,ah ;BL = 64207531 of DIB dword 3
|
|
add esi,16 ;point to next set of 4 DIB dwords
|
|
add edi,4 ;point to next VGA dword
|
|
mov ch,[ebx] ;CH = 76543210 of dword 0
|
|
dec ebp ;count down VGA dwords
|
|
mov [edi-2],cx ;write 16 bits from DIB dwords 2 and 3
|
|
; to VGA
|
|
jnz DIB4_to_VGA_plane0_word_loop ;do next VGA dword, if any
|
|
|
|
pop ebp ;restore stack frame pointer
|
|
|
|
|
|
;-----------------------------------------------------------------------;
|
|
; Code to convert 8 DIB4 pixels to a single VGA plane 0 byte (8 pixels
|
|
; in plane 0). Assumes the DIB4 pixels start in the upper nibble of
|
|
; [ESI], and that the first DIB4 pixel maps to bit 7 of the VGA at
|
|
; [EDI].
|
|
;
|
|
; Input: EBX = pointer to multiplexed DIB byte->planar byte conversion table
|
|
; (must start on a 256-byte boundary)
|
|
; ECX with bits sets as described for ulCopyControlFlags, above
|
|
; ESI = DIB pointer to first two pixels
|
|
; EDI = VGA pointer to planar byte
|
|
; Plane 0 must be mapped in for writes
|
|
;
|
|
;-----------------------------------------------------------------------;
|
|
|
|
DIB4_to_VGA_plane0_copy_tbyte::
|
|
test ecx,TRAILING_BYTE ;should we handle a trailing byte?
|
|
jz short DIB4_to_VGA_plane0_copy_tpart ;no, check for trailing
|
|
; partial
|
|
;yes, handle trailing byte
|
|
mov edx,[esi] ;get 8 pixels to convert of DIB
|
|
and edx,11111111h ;keep only the plane 0 bits of DIB dword
|
|
; EDX = xxx6xxx7xxx4xxx5xxx2xxx3xxx0xxx1
|
|
shld eax,edx,16+2 ;put bits 7-4 of DIB dword in AX,
|
|
; shifted left 2 (x = zero bit)
|
|
; DX = xxx2xxx3xxx0xxx1
|
|
; AX = x6xxx7xxx4xxx5xx
|
|
or eax,edx ;put bits 7-0 of DIB dword 0 in AX:
|
|
; x6x2x7x3x4x0x5x1
|
|
mov bl,al ;BL = x4x0x5x1 of DIB dword 0
|
|
add ah,ah ;make AH 6x2x7x3x of DIB dword 0 (shl 1)
|
|
or bl,ah ;BL = 64207531 of DIB dword 0
|
|
add esi,4 ;point to next DIB dword
|
|
inc edi ;point to next VGA byte (placed here
|
|
; for 486 pipelining reasons)
|
|
mov cl,[ebx] ;CL = 76543210 of DIB dword 0
|
|
mov [edi-1],cl ;write 8 bits from DIB dword to VGA
|
|
|
|
;-----------------------------------------------------------------------;
|
|
; Code to convert 1-7 DIB4 pixels to a partial VGA plane 0 byte (8
|
|
; pixels in plane 0). Assumes that a full dword of DIB4 pixels (8
|
|
; pixels) is available, starting at ESI, although some of the pixels
|
|
; will be masked off. Assumes the DIB4 pixels (including masked-off
|
|
; pixels) start in the upper nibble of [ESI], and that the first
|
|
; (possibly masked-off) DIB4 pixel maps to bit 7 of the VGA at [EDI].
|
|
;
|
|
; Input: EBX = pointer to multiplexed DIB byte->planar byte conversion table
|
|
; (must start on a 256-byte boundary)
|
|
; ECX with bits sets as described for ulCopyControlFlags, above
|
|
; ESI = DIB pointer to first two pixels (possibly masked off)
|
|
; EDI = VGA pointer to planar byte
|
|
; Plane 0 must be mapped in for writes
|
|
;-----------------------------------------------------------------------;
|
|
|
|
DIB4_to_VGA_plane0_copy_tpart::
|
|
test ecx,TRAILING_PARTIAL ;handle a trailing partial byte?
|
|
jz short DIB4_to_VGA_plane0_copy_done ;no, done
|
|
;yes, handle trailing partial byte
|
|
mov edx,[esi] ;get 8 pixels to convert of DIB
|
|
and edx,11111111h ;keep only the plane 0 bits of DIB dword
|
|
; EDX = xxx6xxx7xxx4xxx5xxx2xxx3xxx0xxx1
|
|
shld eax,edx,16+2 ;put bits 7-4 of DIB dword in AX,
|
|
; shifted left 2 (x = zero bit)
|
|
; DX = xxx2xxx3xxx0xxx1
|
|
; AX = x6xxx7xxx4xxx5xx
|
|
or eax,edx ;put bits 7-0 of DIB dword 0 in AX:
|
|
; x6x2x7x3x4x0x5x1
|
|
mov bl,al ;BL = x4x0x5x1 of DIB dword 0
|
|
add ah,ah ;make AH 6x2x7x3x of DIB dword 0 (shl 1)
|
|
or bl,ah ;BL = 64207531 of DIB dword 0
|
|
add esi,4 ;point to next DIB dword
|
|
inc edi ;point to next VGA byte (placed here
|
|
; for 486 pipelining reasons)
|
|
mov cl,[ebx] ;CL = 76543210 of DIB dword 0
|
|
mov ch,[edi-1] ;get the VGA destination byte
|
|
and ecx,ulRightMask ;mask off source and dest
|
|
or cl,ch ;combine masked source and dest
|
|
mov [edi-1],cl ;write the new pixels to the VGA
|
|
|
|
DIB4_to_VGA_plane0_copy_done::
|
|
add esi,ulSrcDelta ;point to start of next DIB scan
|
|
add edi,ulDstDelta ;point to start of next VGA scan
|
|
dec ulPlane0Scans ;count down scans in this plane
|
|
jnz DIB4_to_VGA_plane0_copy_loop ;do next scan in this plane, if any
|
|
|
|
jmp copy_burst_plane0_done ;return to the top of the plane-copy
|
|
; loop
|
|
|
|
;-----------------------------------------------------------------------;
|
|
; Plane 1 DIB->VGA conversion code for a single scan line.
|
|
;
|
|
; Input: ECX with bits sets as described for ulCopyControlFlags, above
|
|
; bit 30 = 1 if there are whole words to be copied, = 0 if not
|
|
; bit 29 = 1 if leading byte should be copied, = 0 if not
|
|
; bit 28 = 1 if trailing byte should be copied, = 0 if not
|
|
; bit 27 = 1 if partial leading byte should be copied, = 0 if not
|
|
; bit 26 = 1 if partial trailing byte should be copied, = 0 if not
|
|
; ESI = DIB pointer to first two pixels
|
|
; EDI = VGA pointer to planar byte
|
|
; ulPlane1Scans = # of scan lines to copy to
|
|
; ulSrcDelta = offset from end of one source scan copied to start of next
|
|
; ulDstDelta = offset from end of one dest scan copied to start of next
|
|
; ulWholeDwordCount = # of whole, aligned dwords to copy
|
|
; ulLeftMask = mask for partial left edge, if any
|
|
; ulRightMask = mask for partial right edge, if any
|
|
; Plane 1 must be mapped in for writes
|
|
;-----------------------------------------------------------------------;
|
|
align 4
|
|
DIB4_to_VGA_plane1_copy::
|
|
|
|
;-----------------------------------------------------------------------;
|
|
; Set EBX to point to multiplexed DIB byte->planar byte conversion table
|
|
; for plane 1.
|
|
;-----------------------------------------------------------------------;
|
|
|
|
mov ebx,DIB4_to_VGA_plane1_table ;stays set for all bytes/words
|
|
|
|
DIB4_to_VGA_plane1_copy_loop::
|
|
|
|
;-----------------------------------------------------------------------;
|
|
; Code to convert 1-7 DIB4 pixels to a partial VGA plane 1 byte (8
|
|
; pixels in plane 1). Assumes that a full dword of DIB4 pixels (8
|
|
; pixels) is available, starting at ESI, although some of the pixels
|
|
; will be masked off. Assumes the DIB4 pixels (including masked-off
|
|
; pixels) start in the upper nibble of [ESI], and that the first
|
|
; (possibly masked-off) DIB4 pixel maps to bit 7 of the VGA at [EDI].
|
|
;
|
|
; Input: EBX = pointer to multiplexed DIB byte->planar byte conversion table
|
|
; (must start on a 256-byte boundary)
|
|
; ECX with bits sets as described for ulCopyControlFlags, above
|
|
; ESI = DIB pointer to first two pixels (possibly masked off)
|
|
; EDI = VGA pointer to planar byte
|
|
; plane 1 must be mapped in for writes
|
|
;-----------------------------------------------------------------------;
|
|
|
|
test ecx,LEADING_PARTIAL ;handle a leading partial byte?
|
|
jz short DIB4_to_VGA_plane1_copy_lbyte ;no, go straight to whole
|
|
; byte
|
|
;yes, handle leading partial byte
|
|
mov edx,[esi] ;get 8 pixels to convert of DIB
|
|
and edx,22222222h ;keep only the plane 1 bits of DIB
|
|
; dword 0
|
|
; EDX = xx6xxx7xxx4xxx5xxx2xxx3xxx0xxx1x
|
|
shld eax,edx,16+2 ;put bits 7-4 of DIB dword 0 in AX,
|
|
; shifted left 2 (x = zero bit)
|
|
; DX = xx2xxx3xxx0xxx1x
|
|
; AX = 6xxx7xxx4xxx5xxx
|
|
or eax,edx ;put bits 7-0 of DIB dword 0 in AX:
|
|
; 6x2x7x3x4x0x5x1x
|
|
mov bl,al ;BL = 4x0x5x1x of DIB dword 0
|
|
rol ah,7 ;make AH x6x2x7x3 of DIB dword 0 (shr 1)
|
|
or bl,ah ;BL = 46025713 of DIB dword 0
|
|
add esi,4 ;point to next DIB dword
|
|
inc edi ;point to next VGA byte (placed here
|
|
; for 486 pipelining reasons)
|
|
mov cl,[ebx] ;CL = 76543210 of DIB dword 0
|
|
mov ch,[edi-1] ;get the VGA destination byte
|
|
and ecx,ulLeftMask ;mask off source and dest
|
|
or cl,ch ;combine masked source and dest
|
|
mov [edi-1],cl ;write the new pixels to the VGA
|
|
|
|
;-----------------------------------------------------------------------;
|
|
; Code to convert 8 DIB4 pixels to a single VGA plane 1 byte (8 pixels
|
|
; in plane 1). Assumes the DIB4 pixels start in the upper nibble of
|
|
; [ESI], and that the first DIB4 pixel maps to bit 7 of the VGA at
|
|
; [EDI].
|
|
;
|
|
; Input: EBX = pointer to multiplexed DIB byte->planar byte conversion table
|
|
; (must start on a 256-byte boundary)
|
|
; ECX with bits sets as described for ulCopyControlFlags, above
|
|
; ESI = DIB pointer to first two pixels
|
|
; EDI = VGA pointer to planar byte
|
|
; plane 1 must be mapped in for writes
|
|
;-----------------------------------------------------------------------;
|
|
|
|
DIB4_to_VGA_plane1_copy_lbyte::
|
|
test ecx,LEADING_BYTE ;should we handle a leading byte?
|
|
jz short DIB4_to_VGA_plane1_copy_words ;no, go straight to words
|
|
;yes, handle leading byte
|
|
mov edx,[esi] ;get 8 pixels to convert of DIB
|
|
and edx,22222222h ;keep only the plane 1 bits of DIB
|
|
; dword 0
|
|
; EDX = xx6xxx7xxx4xxx5xxx2xxx3xxx0xxx1x
|
|
shld eax,edx,16+2 ;put bits 7-4 of DIB dword 0 in AX,
|
|
; shifted left 2 (x = zero bit)
|
|
; DX = xx2xxx3xxx0xxx1x
|
|
; AX = 6xxx7xxx4xxx5xxx
|
|
or eax,edx ;put bits 7-0 of DIB dword 0 in AX:
|
|
; 6x2x7x3x4x0x5x1x
|
|
mov bl,al ;BL = 4x0x5x1x of DIB dword 0
|
|
rol ah,7 ;make AH x6x2x7x3 of DIB dword 0 (shr 1)
|
|
or bl,ah ;BL = 46025713 of DIB dword 0
|
|
add esi,4 ;point to next DIB dword
|
|
inc edi ;point to next VGA byte (placed here
|
|
; for 486 pipelining reasons)
|
|
mov cl,[ebx] ;CL = 76543210 of DIB dword 0
|
|
mov [edi-1],cl ;write 8 bits from DIB dword to VGA
|
|
|
|
;-----------------------------------------------------------------------;
|
|
; Code for converting sets of 32 DIB4 pixels to 4 VGA plane 1 bytes (32
|
|
; pixels in plane 1). Assumes the VGA destination is word aligned.
|
|
; Assumes the DIB4 pixels start in the upper nibble of [ESI], and that
|
|
; the first DIB4 pixel maps to bit 7 of the VGA at [EDI].
|
|
;
|
|
; Input: EBX = pointer to multiplexed DIB byte->planar byte conversion table
|
|
; (must start on a 256-byte boundary)
|
|
; ECX with bits sets as described for ulCopyControlFlags, above
|
|
; ESI = DIB pointer to first two pixels
|
|
; EDI = VGA pointer to two planar bytes (must be word aligned)
|
|
; EBP = # of VGA dwords to convert
|
|
; ulWholeDwordCount = # of VGA dwords to convert
|
|
; Plane 1 must be mapped in for writes
|
|
;
|
|
; Note: on entry at DIB4_to_VGA_plane1_word_odd, ESI must point to the
|
|
; desired source start minus 8, and EAX must be loaded as if the following
|
|
; instructions had been performed:
|
|
; mov edx,[esi+8]
|
|
; and edx,22222222h
|
|
; shld eax,edx,16+2
|
|
; or eax,edx
|
|
;
|
|
; Note: ROL AH,7 is used instead of SHR AH,1 because the shift-by-1
|
|
; form is 1 cycle slower on a 486, and in this case the two forms are
|
|
; functionally identical.
|
|
;
|
|
; Note: the code is so odd because of 486 pipeline optimization.
|
|
; DO NOT CHANGE THIS CODE UNLESS YOU KNOW EXACTLY WHAT YOU'RE DOING!!!
|
|
;
|
|
; Note: all 486 pipeline penalties are eliminated except for SHLD, which
|
|
; is losing 4 cycles total, and writing CX to memory (2 cycles), so far
|
|
; as I know.
|
|
;-----------------------------------------------------------------------;
|
|
|
|
DIB4_to_VGA_plane1_copy_words::
|
|
test ecx,ODD_WHOLE_WORD or WHOLE_WORDS ;any whole words to copy?
|
|
jz DIB4_to_VGA_plane1_copy_tbyte ;no, check for trailing whole
|
|
; bytes
|
|
;yes, copy the whole words
|
|
push ebp ;preserve stack frame pointer
|
|
mov ebp,ulWholeDwordCount ;# of VGA dwords to copy to
|
|
;even # of DIB dwords to copy? (flags still
|
|
; set from TEST)
|
|
.errnz ODD_WHOLE_WORD - 80000000h
|
|
jns short DIB4_to_VGA_plane1_word_loop ;yes, start copying
|
|
;no, there's an odd word; prepare to enter loop
|
|
; in middle
|
|
mov edx,[esi] ;get 8 pixels to convert of first DIB dword
|
|
and edx,22222222h ;keep only the plane 1 bits of DIB dword
|
|
; EDX = xx6xxx7xxx4xxx5xxx2xxx3xxx0xxx1x
|
|
shld eax,edx,16+2 ;put bits 7-4 of DIB dword in AX,
|
|
; shifted left 2
|
|
; DX = xx2xxx3xxx0xxx1x
|
|
; AX = 6xxx7xxx4xxx5xxx
|
|
or eax,edx ;put bits 7-0 of DIB dword in AX:
|
|
; 6x2x7x3x4x0x5x1x
|
|
sub esi,8 ;compensate source back for entering in middle
|
|
sub edi,2 ;compensate dest back for entering in middle
|
|
|
|
jmp short DIB4_to_VGA_plane1_word_odd
|
|
|
|
;-----------------------------------------------------------------------;
|
|
; Loop to copy a word at a time to VGA plane 1 (actually, unrolled once
|
|
; so copies dwords).
|
|
;-----------------------------------------------------------------------;
|
|
|
|
align 16
|
|
DIB4_to_VGA_plane1_word_loop::
|
|
mov edx,[esi] ;get 8 pixels to convert of DIB dword 0
|
|
and edx,22222222h ;keep only the plane 1 bits of DIB
|
|
; dword 0
|
|
; EDX = xx6xxx7xxx4xxx5xxx2xxx3xxx0xxx1x
|
|
shld eax,edx,16+2 ;put bits 7-4 of DIB dword 0 in AX,
|
|
; shifted left 2 (x = zero bit)
|
|
; DX = xx2xxx3xxx0xxx1x
|
|
; AX = 6xxx7xxx4xxx5xxx
|
|
or eax,edx ;put bits 7-0 of DIB dword 0 in AX:
|
|
; 6x2x7x3x4x0x5x1x
|
|
mov edx,[esi+4] ;get 8 pixels to convert of DIB dword 1
|
|
mov bl,al ;BL = 4x0x5x1x of DIB dword 0
|
|
rol ah,7 ;make AH x6x2x7x3 of DIB dword 0 (shr 1)
|
|
or bl,ah ;BL = 46025713 of DIB dword 0
|
|
and edx,22222222h ;keep only the plane 1 bits of DIB
|
|
; dword 1
|
|
; EDX = xx6xxx7xxx4xxx5xxx2xxx3xxx0xxx1x
|
|
shld eax,edx,16+2 ;put bits 7-4 of DIB dword 1 in AX,
|
|
; shifted left 2
|
|
; DX = xx2xxx3xxx0xxx1x
|
|
; AX = 6xxx7xxx4xxx5xxx
|
|
mov cl,[ebx] ;CL = 76543210 of DIB dword 0
|
|
or eax,edx ;put bits 7-0 of DIB dword 1 in AX:
|
|
; 6x2x7x3x4x0x5x1x
|
|
mov bl,al ;BL = 4x0x5x1x of DIB dword 1
|
|
mov edx,[esi+8] ;get 8 pixels to convert of DIB dword 2
|
|
rol ah,7 ;make AH x6x2x7x3 of DIB dword 1 (shr 1)
|
|
or bl,ah ;BL = 46025713 of DIB dword 1
|
|
and edx,22222222h ;keep only the plane 1 bits of DIB
|
|
; dword 2
|
|
; EDX = xx6xxx7xxx4xxx5xxx2xxx3xxx0xxx1x
|
|
shld eax,edx,16+2 ;put bits 7-4 of DIB dword 2 in AX,
|
|
; shifted left 2
|
|
; DX = xx2xxx3xxx0xxx1x
|
|
; AX = 6xxx7xxx4xxx5xxx
|
|
mov ch,[ebx] ;CH = 76543210 of DIB dword 1
|
|
or eax,edx ;put bits 7-0 of DIB dword 2 in AX:
|
|
; 6x2x7x3x4x0x5x1x
|
|
mov [edi],cx ;write 16 bits from DIB dwords 0 and 1
|
|
; to VGA
|
|
DIB4_to_VGA_plane1_word_odd::
|
|
mov edx,[esi+12] ;get 8 pixels to convert of DIB dword 3
|
|
mov bl,al ;BL = 4x0x5x1x of DIB dword 2
|
|
rol ah,7 ;make AH x6x2x7x3 of DIB dword 2 (shr 1)
|
|
or bl,ah ;BL = 46025713 of DIB dword 2
|
|
and edx,22222222h ;keep only the plane 1 bits of DIB
|
|
; dword 3
|
|
; EDX = xx6xxx7xxx4xxx5xxx2xxx3xxx0xxx1x
|
|
shld eax,edx,16+2 ;put bits 7-4 of DIB dword 3 in AX,
|
|
; shifted left 2
|
|
; DX = xx2xxx3xxx0xxx1x
|
|
; AX = 6xxx7xxx4xxx5xxx
|
|
mov cl,[ebx] ;CL = 76543210 of DIB dword 2
|
|
or eax,edx ;put bits 7-0 of DIB dword 3 in AX:
|
|
; 6x2x7x3x4x0x5x1x
|
|
mov bl,al ;BL = 4x0x5x1x of DIB dword 3
|
|
rol ah,7 ;make AH x6x2x7x3 of DIB dword 3 (shr 1)
|
|
or bl,ah ;BL = 46025713 of DIB dword 3
|
|
add esi,16 ;point to next set of 4 DIB dwords
|
|
add edi,4 ;point to next VGA dword
|
|
mov ch,[ebx] ;CH = 76543210 of dword 0
|
|
dec ebp ;count down VGA dwords
|
|
mov [edi-2],cx ;write 16 bits from DIB dwords 2 and 3
|
|
; to VGA
|
|
jnz DIB4_to_VGA_plane1_word_loop ;do next VGA dword, if any
|
|
|
|
pop ebp ;restore stack frame pointer
|
|
|
|
;-----------------------------------------------------------------------;
|
|
; Code to convert 8 DIB4 pixels to a single VGA plane 1 byte (8 pixels
|
|
; in plane 1). Assumes the DIB4 pixels start in the upper nibble of
|
|
; [ESI], and that the first DIB4 pixel maps to bit 7 of the VGA at
|
|
; [EDI].
|
|
;
|
|
; Input: EBX = pointer to multiplexed DIB byte->planar byte conversion table
|
|
; (must start on a 256-byte boundary)
|
|
; ECX with bits sets as described for ulCopyControlFlags, above
|
|
; ESI = DIB pointer to first two pixels
|
|
; EDI = VGA pointer to planar byte
|
|
; Plane 1 must be mapped in for writes
|
|
;
|
|
;-----------------------------------------------------------------------;
|
|
|
|
DIB4_to_VGA_plane1_copy_tbyte::
|
|
test ecx,TRAILING_BYTE ;should we handle a trailing byte?
|
|
jz short DIB4_to_VGA_plane1_copy_tpart ;no, check for trailing
|
|
; partial
|
|
;yes, handle trailing byte
|
|
mov edx,[esi] ;get 8 pixels to convert of DIB
|
|
and edx,22222222h ;keep only the plane 1 bits of DIB
|
|
; dword 0
|
|
; EDX = xx6xxx7xxx4xxx5xxx2xxx3xxx0xxx1x
|
|
shld eax,edx,16+2 ;put bits 7-4 of DIB dword 0 in AX,
|
|
; shifted left 2 (x = zero bit)
|
|
; DX = xx2xxx3xxx0xxx1x
|
|
; AX = 6xxx7xxx4xxx5xxx
|
|
or eax,edx ;put bits 7-0 of DIB dword 0 in AX:
|
|
; 6x2x7x3x4x0x5x1x
|
|
mov bl,al ;BL = 4x0x5x1x of DIB dword 0
|
|
rol ah,7 ;make AH x6x2x7x3 of DIB dword 0 (shr 1)
|
|
or bl,ah ;BL = 46025713 of DIB dword 0
|
|
add esi,4 ;point to next DIB dword
|
|
inc edi ;point to next VGA byte (placed here
|
|
; for 486 pipelining reasons)
|
|
mov cl,[ebx] ;CL = 76543210 of DIB dword 0
|
|
mov [edi-1],cl ;write 8 bits from DIB dword to VGA
|
|
|
|
;-----------------------------------------------------------------------;
|
|
; Code to convert 1-7 DIB4 pixels to a partial VGA plane 1 byte (8
|
|
; pixels in plane 1). Assumes that a full dword of DIB4 pixels (8
|
|
; pixels) is available, starting at ESI, although some of the pixels
|
|
; will be masked off. Assumes the DIB4 pixels (including masked-off
|
|
; pixels) start in the upper nibble of [ESI], and that the first
|
|
; (possibly masked-off) DIB4 pixel maps to bit 7 of the VGA at [EDI].
|
|
;
|
|
; Input: EBX = pointer to multiplexed DIB byte->planar byte conversion table
|
|
; (must start on a 256-byte boundary)
|
|
; ECX with bits sets as described for ulCopyControlFlags, above
|
|
; ESI = DIB pointer to first two pixels (possibly masked off)
|
|
; EDI = VGA pointer to planar byte
|
|
; plane 1 must be mapped in for writes
|
|
;-----------------------------------------------------------------------;
|
|
|
|
DIB4_to_VGA_plane1_copy_tpart::
|
|
test ecx,TRAILING_PARTIAL ;handle a trailing partial byte?
|
|
jz short DIB4_to_VGA_plane1_copy_done ;no, done
|
|
;yes, handle trailing partial byte
|
|
mov edx,[esi] ;get 8 pixels to convert of DIB
|
|
and edx,22222222h ;keep only the plane 1 bits of DIB
|
|
; dword 0
|
|
; EDX = xx6xxx7xxx4xxx5xxx2xxx3xxx0xxx1x
|
|
shld eax,edx,16+2 ;put bits 7-4 of DIB dword 0 in AX,
|
|
; shifted left 2 (x = zero bit)
|
|
; DX = xx2xxx3xxx0xxx1x
|
|
; AX = 6xxx7xxx4xxx5xxx
|
|
or eax,edx ;put bits 7-0 of DIB dword 0 in AX:
|
|
; 6x2x7x3x4x0x5x1x
|
|
mov bl,al ;BL = 4x0x5x1x of DIB dword 0
|
|
rol ah,7 ;make AH x6x2x7x3 of DIB dword 0 (shr 1)
|
|
or bl,ah ;BL = 46025713 of DIB dword 0
|
|
add esi,4 ;point to next DIB dword
|
|
inc edi ;point to next VGA byte (placed here
|
|
; for 486 pipelining reasons)
|
|
mov cl,[ebx] ;CL = 76543210 of DIB dword 0
|
|
mov ch,[edi-1] ;get the VGA destination byte
|
|
and ecx,ulRightMask ;mask off source and dest
|
|
or cl,ch ;combine masked source and dest
|
|
mov [edi-1],cl ;write the new pixels to the VGA
|
|
|
|
DIB4_to_VGA_plane1_copy_done::
|
|
add esi,ulSrcDelta ;point to start of next DIB scan
|
|
add edi,ulDstDelta ;point to start of next VGA scan
|
|
dec ulPlane1Scans ;count down scans in this plane
|
|
jnz DIB4_to_VGA_plane1_copy_loop ;do next scan in this plane, if any
|
|
|
|
jmp copy_burst_plane1_done ;return to the top of the plane-copy
|
|
; loop
|
|
|
|
;-----------------------------------------------------------------------;
|
|
; Plane 2 DIB->VGA conversion code for a single scan line.
|
|
;
|
|
; Input: ECX with bits sets as described for ulCopyControlFlags, above
|
|
; bit 30 = 1 if there are whole words to be copied, = 0 if not
|
|
; bit 29 = 1 if leading byte should be copied, = 0 if not
|
|
; bit 28 = 1 if trailing byte should be copied, = 0 if not
|
|
; bit 27 = 1 if partial leading byte should be copied, = 0 if not
|
|
; bit 26 = 1 if partial trailing byte should be copied, = 0 if not
|
|
; ESI = DIB pointer to first two pixels
|
|
; EDI = VGA pointer to planar byte
|
|
; ulPlane2Scans = # of scan lines to copy to
|
|
; ulSrcDelta = offset from end of one source scan copied to start of next
|
|
; ulDstDelta = offset from end of one dest scan copied to start of next
|
|
; ulWholeDwordCount = # of whole, aligned dwords to copy
|
|
; ulLeftMask = mask for partial left edge, if any
|
|
; ulRightMask = mask for partial right edge, if any
|
|
; Plane 2 must be mapped in for writes
|
|
;-----------------------------------------------------------------------;
|
|
align 4
|
|
DIB4_to_VGA_plane2_copy::
|
|
|
|
;-----------------------------------------------------------------------;
|
|
; Set EBX to point to multiplexed DIB byte->planar byte conversion table
|
|
; for plane 2.
|
|
;-----------------------------------------------------------------------;
|
|
|
|
mov ebx,DIB4_to_VGA_plane2_table ;stays set for all bytes/words
|
|
|
|
DIB4_to_VGA_plane2_copy_loop::
|
|
|
|
;-----------------------------------------------------------------------;
|
|
; Code to convert 1-7 DIB4 pixels to a partial VGA plane 2 byte (8
|
|
; pixels in plane 2). Assumes that a full dword of DIB4 pixels (8
|
|
; pixels) is available, starting at ESI, although some of the pixels
|
|
; will be masked off. Assumes the DIB4 pixels (including masked-off
|
|
; pixels) start in the upper nibble of [ESI], and that the first
|
|
; (possibly masked-off) DIB4 pixel maps to bit 7 of the VGA at [EDI].
|
|
;
|
|
; Input: EBX = pointer to multiplexed DIB byte->planar byte conversion table
|
|
; (must start on a 256-byte boundary)
|
|
; ECX with bits sets as described for ulCopyControlFlags, above
|
|
; ESI = DIB pointer to first two pixels (possibly masked off)
|
|
; EDI = VGA pointer to planar byte
|
|
; plane 2 must be mapped in for writes
|
|
;-----------------------------------------------------------------------;
|
|
|
|
test ecx,LEADING_PARTIAL ;handle a leading partial byte?
|
|
jz short DIB4_to_VGA_plane2_copy_lbyte ;no, go straight to whole
|
|
; byte
|
|
;yes, handle leading partial byte
|
|
mov edx,[esi] ;get 8 pixels to convert of DIB
|
|
and edx,44444444h ;keep only the plane 2 bits of DIB
|
|
; dword 0
|
|
; EDX = x6xxx7xxx4xxx5xxx2xxx3xxx0xxx1xx
|
|
mov eax,edx ;put bits 7-4 of DIB dword 0 in AX,
|
|
shr eax,16+2 ; shifted right 2 (x = zero bit)
|
|
; DX = x2xxx3xxx0xxx1xx
|
|
; AX = xxx6xxx7xxx4xxx5
|
|
or eax,edx ;put bits 7-0 of DIB dword 0 in AX:
|
|
; x2x6x3x7x0x4x1x5
|
|
mov bl,al ;BL = x0x4x1x5 of DIB dword 0
|
|
add ah,ah ;make AH 2x6x3x7x of DIB dword 0 (shl 1)
|
|
or bl,ah ;BL = 20643175 of DIB dword 0
|
|
add esi,4 ;point to next DIB dword
|
|
inc edi ;point to next VGA byte (placed here
|
|
; for 486 pipelining reasons)
|
|
mov cl,[ebx] ;CL = 76543210 of DIB dword 0
|
|
mov ch,[edi-1] ;get the VGA destination byte
|
|
and ecx,ulLeftMask ;mask off source and dest
|
|
or cl,ch ;combine masked source and dest
|
|
mov [edi-1],cl ;write the new pixels to the VGA
|
|
|
|
;-----------------------------------------------------------------------;
|
|
; Code to convert 8 DIB4 pixels to a single VGA plane 2 byte (8 pixels
|
|
; in plane 2). Assumes the DIB4 pixels start in the upper nibble of
|
|
; [ESI], and that the first DIB4 pixel maps to bit 7 of the VGA at
|
|
; [EDI].
|
|
;
|
|
; Input: EBX = pointer to multiplexed DIB byte->planar byte conversion table
|
|
; (must start on a 256-byte boundary)
|
|
; ECX with bits sets as described for ulCopyControlFlags, above
|
|
; ESI = DIB pointer to first two pixels
|
|
; EDI = VGA pointer to planar byte
|
|
; plane 2 must be mapped in for writes
|
|
;-----------------------------------------------------------------------;
|
|
|
|
DIB4_to_VGA_plane2_copy_lbyte::
|
|
test ecx,LEADING_BYTE ;should we handle a leading byte?
|
|
jz short DIB4_to_VGA_plane2_copy_words ;no, go straight to words
|
|
;yes, handle leading byte
|
|
mov edx,[esi] ;get 8 pixels to convert of DIB
|
|
and edx,44444444h ;keep only the plane 2 bits of DIB
|
|
; dword 0
|
|
; EDX = x6xxx7xxx4xxx5xxx2xxx3xxx0xxx1xx
|
|
mov eax,edx ;put bits 7-4 of DIB dword 0 in AX,
|
|
shr eax,16+2 ; shifted right 2 (x = zero bit)
|
|
; DX = x2xxx3xxx0xxx1xx
|
|
; AX = xxx6xxx7xxx4xxx5
|
|
or eax,edx ;put bits 7-0 of DIB dword 0 in AX:
|
|
; x2x6x3x7x0x4x1x5
|
|
mov bl,al ;BL = x0x4x1x5 of DIB dword 0
|
|
add ah,ah ;make AH 2x6x3x7x of DIB dword 0 (shl 1)
|
|
or bl,ah ;BL = 20643175 of DIB dword 0
|
|
add esi,4 ;point to next DIB dword
|
|
inc edi ;point to next VGA byte (placed here
|
|
; for 486 pipelining reasons)
|
|
mov cl,[ebx] ;CL = 76543210 of DIB dword 0
|
|
mov [edi-1],cl ;write 8 bits from DIB dword to VGA
|
|
|
|
;-----------------------------------------------------------------------;
|
|
; Code for converting sets of 32 DIB4 pixels to 4 VGA plane 2 bytes (32
|
|
; pixels in plane 2). Assumes the VGA destination is word aligned.
|
|
; Assumes the DIB4 pixels start in the upper nibble of [ESI], and that
|
|
; the first DIB4 pixel maps to bit 7 of the VGA at [EDI].
|
|
;
|
|
; Input: EBX = pointer to multiplexed DIB byte->planar byte conversion table
|
|
; (must start on a 256-byte boundary)
|
|
; ECX with bits sets as described for ulCopyControlFlags, above
|
|
; ESI = DIB pointer to first two pixels
|
|
; EDI = VGA pointer to two planar bytes (must be word aligned)
|
|
; EBP = # of VGA dwords to convert
|
|
; ulWholeDwordCount = # of VGA dwords to convert
|
|
; Plane 2 must be mapped in for writes
|
|
;
|
|
; Note: on entry at DIB4_to_VGA_plane2_word_odd, ESI must point to the
|
|
; desired source start minus 8, and EAX must be loaded as if the following
|
|
; instructions had been performed:
|
|
; mov edx,[esi+8]
|
|
; and edx,44444444h
|
|
; mov eax,edx
|
|
; shr eax,16+2
|
|
; or eax,edx
|
|
;
|
|
; Note: the code is so odd because of 486 pipeline optimization.
|
|
; DO NOT CHANGE THIS CODE UNLESS YOU KNOW EXACTLY WHAT YOU'RE DOING!!!
|
|
;
|
|
; Note: all 486 pipeline penalties are eliminated except for writing CX
|
|
; to memory (2 cycles), so far as I know.
|
|
;-----------------------------------------------------------------------;
|
|
|
|
DIB4_to_VGA_plane2_copy_words::
|
|
test ecx,ODD_WHOLE_WORD or WHOLE_WORDS ;any whole words to copy?
|
|
jz DIB4_to_VGA_plane2_copy_tbyte ;no, check for trailing whole
|
|
; bytes
|
|
;yes, copy the whole words
|
|
push ebp ;preserve stack frame pointer
|
|
mov ebp,ulWholeDwordCount ;# of VGA dwords to copy to
|
|
;even # of DIB dwords to copy? (flags still
|
|
; set from TEST)
|
|
.errnz ODD_WHOLE_WORD - 80000000h
|
|
jns short DIB4_to_VGA_plane2_word_loop ;yes, start copying
|
|
;no, there's an odd word; prepare to enter loop
|
|
; in middle
|
|
mov edx,[esi] ;get 8 pixels to convert of first DIB dword
|
|
and edx,44444444h ;keep only the plane 2 bits of DIB dword
|
|
; EDX = x6xxx7xxx4xxx5xxx2xxx3xxx0xxx1xx
|
|
mov eax,edx ;put bits 7-4 of DIB dword in AX,
|
|
shr eax,16+2 ; shifted right 2 (x = zero bit)
|
|
; DX = x2xxx3xxx0xxx1xx
|
|
; AX = xxx6xxx7xxx4xxx5
|
|
or eax,edx ;put bits 7-0 of DIB dword in AX:
|
|
; 62xx73xx40xx51xx
|
|
sub esi,8 ;compensate source back for entering in middle
|
|
sub edi,2 ;compensate dest back for entering in middle
|
|
|
|
jmp short DIB4_to_VGA_plane2_word_odd
|
|
|
|
;-----------------------------------------------------------------------;
|
|
; Loop to copy a word at a time to VGA plane 2 (actually, unrolled once
|
|
; so copies dwords).
|
|
;-----------------------------------------------------------------------;
|
|
|
|
align 16
|
|
DIB4_to_VGA_plane2_word_loop::
|
|
mov edx,[esi] ;get 8 pixels to convert of DIB dword 0
|
|
and edx,44444444h ;keep only the plane 2 bits of DIB
|
|
; dword 0
|
|
; EDX = x6xxx7xxx4xxx5xxx2xxx3xxx0xxx1xx
|
|
mov eax,edx ;put bits 7-4 of DIB dword 0 in AX,
|
|
shr eax,16+2 ; shifted right 2 (x = zero bit)
|
|
; DX = x2xxx3xxx0xxx1xx
|
|
; AX = xxx6xxx7xxx4xxx5
|
|
or eax,edx ;put bits 7-0 of DIB dword 0 in AX:
|
|
; x2x6x3x7x0x4x1x5
|
|
mov edx,[esi+4] ;get 8 pixels to convert of DIB dword 1
|
|
mov bl,al ;BL = x0x4x1x5 of DIB dword 0
|
|
add ah,ah ;make AH 2x6x3x7x of DIB dword 0 (shl 1)
|
|
or bl,ah ;BL = 20643175 of DIB dword 0
|
|
and edx,44444444h ;keep only the plane 2 bits of DIB
|
|
; dword 1
|
|
; EDX = x6xxx7xxx4xxx5xxx2xxx3xxx0xxx1xx
|
|
mov eax,edx ;put bits 7-4 of DIB dword 1 in AX,
|
|
shr eax,16+2 ; shifted right 2 (x = zero bit)
|
|
; DX = x2xxx3xxx0xxx1xx
|
|
; AX = xxx6xxx7xxx4xxx5
|
|
mov cl,[ebx] ;CL = 76543210 of DIB dword 0
|
|
or eax,edx ;put bits 7-0 of DIB dword 1 in AX:
|
|
; 62xx73xx40xx51xx
|
|
mov bl,al ;BL = x0x4x1x5 of DIB dword 1
|
|
mov edx,[esi+8] ;get 8 pixels to convert of DIB dword 2
|
|
add ah,ah ;make AH 2x6x3x7x of DIB dword 1 (shl 1)
|
|
or bl,ah ;BL = 20643175 of DIB dword 1
|
|
and edx,44444444h ;keep only the plane 2 bits of DIB
|
|
; dword 2
|
|
; EDX = x6xxx7xxx4xxx5xxx2xxx3xxx0xxx1xx
|
|
mov eax,edx ;put bits 7-4 of DIB dword 2 in AX,
|
|
shr eax,16+2 ; shifted right 2 (x = zero bit)
|
|
; DX = x2xxx3xxx0xxx1xx
|
|
; AX = xxx6xxx7xxx4xxx5
|
|
mov ch,[ebx] ;CH = 76543210 of DIB dword 1
|
|
or eax,edx ;put bits 7-0 of DIB dword 2 in AX:
|
|
; 62xx73xx40xx51xx
|
|
mov [edi],cx ;write 16 bits from DIB dwords 0 and 1
|
|
; to VGA
|
|
DIB4_to_VGA_plane2_word_odd::
|
|
mov edx,[esi+12] ;get 8 pixels to convert of DIB dword 3
|
|
mov bl,al ;BL = x0x4x1x5 of DIB dword 2
|
|
add ah,ah ;make AH 2x6x3x7x of DIB dword 2 (shl 1)
|
|
or bl,ah ;BL = 20643175 of DIB dword 2
|
|
and edx,44444444h ;keep only the plane 2 bits of DIB
|
|
; dword 3
|
|
; EDX = x6xxx7xxx4xxx5xxx2xxx3xxx0xxx1xx
|
|
mov eax,edx ;put bits 7-4 of DIB dword 3 in AX,
|
|
shr eax,16+2 ; shifted right 2 (x = zero bit)
|
|
; DX = x2xxx3xxx0xxx1xx
|
|
; AX = xxx6xxx7xxx4xxx5
|
|
mov cl,[ebx] ;CL = 76543210 of DIB dword 2
|
|
or eax,edx ;put bits 7-0 of DIB dword 3 in AX:
|
|
; 62xx73xx40xx51xx
|
|
mov bl,al ;BL = x0x4x1x5 of DIB dword 3
|
|
add ah,ah ;make AH 2x6x3x7x of DIB dword 3 (shl 1)
|
|
or bl,ah ;BL = 20643175 of DIB dword 3
|
|
add esi,16 ;point to next set of 4 DIB dwords
|
|
add edi,4 ;point to next VGA dword
|
|
mov ch,[ebx] ;CH = 76543210 of dword 0
|
|
dec ebp ;count down VGA dwords
|
|
mov [edi-2],cx ;write 16 bits from DIB dwords 2 and 3
|
|
; to VGA
|
|
jnz DIB4_to_VGA_plane2_word_loop ;do next VGA dword, if any
|
|
|
|
pop ebp ;restore stack frame pointer
|
|
|
|
;-----------------------------------------------------------------------;
|
|
; Code to convert 8 DIB4 pixels to a single VGA plane 2 byte (8 pixels
|
|
; in plane 2). Assumes the DIB4 pixels start in the upper nibble of
|
|
; [ESI], and that the first DIB4 pixel maps to bit 7 of the VGA at
|
|
; [EDI].
|
|
;
|
|
; Input: EBX = pointer to multiplexed DIB byte->planar byte conversion table
|
|
; (must start on a 256-byte boundary)
|
|
; ECX with bits sets as described for ulCopyControlFlags, above
|
|
; ESI = DIB pointer to first two pixels
|
|
; EDI = VGA pointer to planar byte
|
|
; plane 2 must be mapped in for writes
|
|
;
|
|
;-----------------------------------------------------------------------;
|
|
|
|
DIB4_to_VGA_plane2_copy_tbyte::
|
|
test ecx,TRAILING_BYTE ;should we handle a trailing byte?
|
|
jz short DIB4_to_VGA_plane2_copy_tpart ;no, check for trailing
|
|
; partial
|
|
;yes, handle trailing byte
|
|
mov edx,[esi] ;get 8 pixels to convert of DIB
|
|
and edx,44444444h ;keep only the plane 2 bits of DIB
|
|
; dword 0
|
|
; EDX = x6xxx7xxx4xxx5xxx2xxx3xxx0xxx1xx
|
|
mov eax,edx ;put bits 7-4 of DIB dword 0 in AX,
|
|
shr eax,16+2 ; shifted right 2 (x = zero bit)
|
|
; DX = x2xxx3xxx0xxx1xx
|
|
; AX = xxx6xxx7xxx4xxx5
|
|
or eax,edx ;put bits 7-0 of DIB dword 0 in AX:
|
|
; x2x6x3x7x0x4x1x5
|
|
mov bl,al ;BL = x0x4x1x5 of DIB dword 0
|
|
add ah,ah ;make AH 2x6x3x7x of DIB dword 0 (shl 1)
|
|
or bl,ah ;BL = 20643175 of DIB dword 0
|
|
add esi,4 ;point to next DIB dword
|
|
inc edi ;point to next VGA byte (placed here
|
|
; for 486 pipelining reasons)
|
|
mov cl,[ebx] ;CL = 76543210 of DIB dword 0
|
|
mov [edi-1],cl ;write 8 bits from DIB dword to VGA
|
|
|
|
;-----------------------------------------------------------------------;
|
|
; Code to convert 1-7 DIB4 pixels to a partial VGA plane 2 byte (8
|
|
; pixels in plane 2). Assumes that a full dword of DIB4 pixels (8
|
|
; pixels) is available, starting at ESI, although some of the pixels
|
|
; will be masked off. Assumes the DIB4 pixels (including masked-off
|
|
; pixels) start in the upper nibble of [ESI], and that the first
|
|
; (possibly masked-off) DIB4 pixel maps to bit 7 of the VGA at [EDI].
|
|
;
|
|
; Input: EBX = pointer to multiplexed DIB byte->planar byte conversion table
|
|
; (must start on a 256-byte boundary)
|
|
; ECX with bits sets as described for ulCopyControlFlags, above
|
|
; ESI = DIB pointer to first two pixels (possibly masked off)
|
|
; EDI = VGA pointer to planar byte
|
|
; plane 2 must be mapped in for writes
|
|
;-----------------------------------------------------------------------;
|
|
|
|
DIB4_to_VGA_plane2_copy_tpart::
|
|
test ecx,TRAILING_PARTIAL ;handle a trailing partial byte?
|
|
jz short DIB4_to_VGA_plane2_copy_done ;no, done
|
|
;yes, handle trailing partial byte
|
|
mov edx,[esi] ;get 8 pixels to convert of DIB
|
|
and edx,44444444h ;keep only the plane 2 bits of DIB
|
|
; dword 0
|
|
; EDX = x6xxx7xxx4xxx5xxx2xxx3xxx0xxx1xx
|
|
mov eax,edx ;put bits 7-4 of DIB dword 0 in AX,
|
|
shr eax,16+2 ; shifted right 2 (x = zero bit)
|
|
; DX = x2xxx3xxx0xxx1xx
|
|
; AX = xxx6xxx7xxx4xxx5
|
|
or eax,edx ;put bits 7-0 of DIB dword 0 in AX:
|
|
; x2x6x3x7x0x4x1x5
|
|
mov bl,al ;BL = x0x4x1x5 of DIB dword 0
|
|
add ah,ah ;make AH 2x6x3x7x of DIB dword 0 (shl 1)
|
|
or bl,ah ;BL = 20643175 of DIB dword 0
|
|
add esi,4 ;point to next DIB dword
|
|
inc edi ;point to next VGA byte (placed here
|
|
; for 486 pipelining reasons)
|
|
mov cl,[ebx] ;CL = 76543210 of DIB dword 0
|
|
mov ch,[edi-1] ;get the VGA destination byte
|
|
and ecx,ulRightMask ;mask off source and dest
|
|
or cl,ch ;combine masked source and dest
|
|
mov [edi-1],cl ;write the new pixels to the VGA
|
|
|
|
DIB4_to_VGA_plane2_copy_done::
|
|
add esi,ulSrcDelta ;point to start of next DIB scan
|
|
add edi,ulDstDelta ;point to start of next VGA scan
|
|
dec ulPlane2Scans ;count down scans in this plane
|
|
jnz DIB4_to_VGA_plane2_copy_loop ;do next scan in this plane, if any
|
|
|
|
jmp copy_burst_plane2_done ;return to the top of the plane-copy
|
|
; loop
|
|
|
|
;-----------------------------------------------------------------------;
|
|
; Plane 3 DIB->VGA conversion code for a single scan line.
|
|
;
|
|
; Input: ECX with bits sets as described for ulCopyControlFlags, above
|
|
; ESI = DIB pointer to first two pixels
|
|
; EDI = VGA pointer to planar byte
|
|
; ulPlane3Scans = # of scan lines to copy to
|
|
; ulSrcDelta = offset from end of one source scan copied to start of next
|
|
; ulDstDelta = offset from end of one dest scan copied to start of next
|
|
; ulWholeDwordCount = # of whole, aligned dwords to copy
|
|
; ulLeftMask = mask for partial left edge, if any
|
|
; ulRightMask = mask for partial right edge, if any
|
|
; Plane 3 must be mapped in for writes
|
|
;-----------------------------------------------------------------------;
|
|
align 4
|
|
DIB4_to_VGA_plane3_copy::
|
|
|
|
;-----------------------------------------------------------------------;
|
|
; Set EBX to point to multiplexed DIB byte->planar byte conversion table
|
|
; for plane 3.
|
|
;-----------------------------------------------------------------------;
|
|
|
|
mov ebx,DIB4_to_VGA_plane3_table ;stays set for all bytes/words
|
|
|
|
DIB4_to_VGA_plane3_copy_loop::
|
|
|
|
;-----------------------------------------------------------------------;
|
|
; Code to convert 1-7 DIB4 pixels to a partial VGA plane 3 byte (8
|
|
; pixels in plane 3). Assumes that a full dword of DIB4 pixels (8
|
|
; pixels) is available, starting at ESI, although some of the pixels
|
|
; will be masked off. Assumes the DIB4 pixels (including masked-off
|
|
; pixels) start in the upper nibble of [ESI], and that the first
|
|
; (possibly masked-off) DIB4 pixel maps to bit 7 of the VGA at [EDI].
|
|
;
|
|
; Input: EBX = pointer to multiplexed DIB byte->planar byte conversion table
|
|
; (must start on a 256-byte boundary)
|
|
; ECX with bits sets as described for ulCopyControlFlags, above
|
|
; ESI = DIB pointer to first two pixels (possibly masked off)
|
|
; EDI = VGA pointer to planar byte
|
|
; plane 3 must be mapped in for writes
|
|
;-----------------------------------------------------------------------;
|
|
|
|
test ecx,LEADING_PARTIAL ;handle a leading partial byte?
|
|
jz short DIB4_to_VGA_plane3_copy_lbyte ;no, go straight to whole
|
|
; byte
|
|
;yes, handle leading partial byte
|
|
mov edx,[esi] ;get 8 pixels to convert of DIB dword 0
|
|
and edx,88888888h ;keep only the plane 3 bits of DIB
|
|
; dword 0
|
|
; EDX = 6xxx7xxx4xxx5xxx2xxx3xxx0xxx1xxx
|
|
mov eax,edx ;put bits 7-4 of DIB dword 0 in AX,
|
|
shr eax,16+2 ; shifted right 2 (x = zero bit)
|
|
; DX = 2xxx3xxx0xxx1xxx
|
|
; AX = xx6xxx7xxx4xxx5x
|
|
or eax,edx ;put bits 7-0 of DIB dword 0 in AX:
|
|
; 2x6x3x7x0x4x1x5x
|
|
mov bl,al ;BL = 0x4x1x5x of DIB dword 0
|
|
rol ah,7 ;make AH x2x6x3x7 of DIB dword 0 (shr 1)
|
|
or bl,ah ;BL = 02461357 of DIB dword 0
|
|
add esi,4 ;point to next DIB dword
|
|
inc edi ;point to next VGA byte (placed here
|
|
; for 486 pipelining reasons)
|
|
mov cl,[ebx] ;CL = 76543210 of DIB dword 0
|
|
mov ch,[edi-1] ;get the VGA destination byte
|
|
and ecx,ulLeftMask ;mask off source and dest
|
|
or cl,ch ;combine masked source and dest
|
|
mov [edi-1],cl ;write the new pixels to the VGA
|
|
|
|
;-----------------------------------------------------------------------;
|
|
; Code to convert 8 DIB4 pixels to a single VGA plane 3 byte (8 pixels
|
|
; in plane 3). Assumes the DIB4 pixels start in the upper nibble of
|
|
; [ESI], and that the first DIB4 pixel maps to bit 7 of the VGA at
|
|
; [EDI].
|
|
;
|
|
; Input: EBX = pointer to multiplexed DIB byte->planar byte conversion table
|
|
; (must start on a 256-byte boundary)
|
|
; ECX with bits sets as described for ulCopyControlFlags, above
|
|
; ESI = DIB pointer to first two pixels
|
|
; EDI = VGA pointer to planar byte
|
|
; plane 3 must be mapped in for writes
|
|
;-----------------------------------------------------------------------;
|
|
|
|
DIB4_to_VGA_plane3_copy_lbyte::
|
|
test ecx,LEADING_BYTE ;should we handle a leading byte?
|
|
jz short DIB4_to_VGA_plane3_copy_words ;no, go straight to words
|
|
;yes, handle leading byte
|
|
mov edx,[esi] ;get 8 pixels to convert of DIB dword 0
|
|
and edx,88888888h ;keep only the plane 3 bits of DIB
|
|
; dword 0
|
|
; EDX = 6xxx7xxx4xxx5xxx2xxx3xxx0xxx1xxx
|
|
mov eax,edx ;put bits 7-4 of DIB dword 0 in AX,
|
|
shr eax,16+2 ; shifted right 2 (x = zero bit)
|
|
; DX = 2xxx3xxx0xxx1xxx
|
|
; AX = xx6xxx7xxx4xxx5x
|
|
or eax,edx ;put bits 7-0 of DIB dword 0 in AX:
|
|
; 2x6x3x7x0x4x1x5x
|
|
mov bl,al ;BL = 0x4x1x5x of DIB dword 0
|
|
rol ah,7 ;make AH x2x6x3x7 of DIB dword 0 (shr 1)
|
|
or bl,ah ;BL = 02461357 of DIB dword 0
|
|
add esi,4 ;point to next DIB dword
|
|
inc edi ;point to next VGA byte (placed here
|
|
; for 486 pipelining reasons)
|
|
mov cl,[ebx] ;CL = 76543210 of DIB dword 0
|
|
mov [edi-1],cl ;write 8 bits from DIB dword to VGA
|
|
|
|
;-----------------------------------------------------------------------;
|
|
; Code for converting sets of 32 DIB4 pixels to 4 VGA plane 3 bytes (32
|
|
; pixels in plane 3). Assumes the VGA destination is word aligned.
|
|
; Assumes the DIB4 pixels start in the upper nibble of [ESI], and that
|
|
; the first DIB4 pixel maps to bit 7 of the VGA at [EDI].
|
|
;
|
|
; Input: EBX = pointer to multiplexed DIB byte->planar byte conversion table
|
|
; (must start on a 256-byte boundary)
|
|
; ECX with bits sets as described for ulCopyControlFlags, above
|
|
; ESI = DIB pointer to first two pixels
|
|
; EDI = VGA pointer to two planar bytes (must be word aligned)
|
|
; EBP = # of VGA dwords to convert
|
|
; ulWholeDwordCount = # of VGA dwords to convert
|
|
; plane 3 must be mapped in for writes
|
|
;
|
|
; Note: on entry at DIB4_to_VGA_plane3_word_odd, ESI must point to the
|
|
; desired source start minus 8, and EAX must be loaded as if the following
|
|
; instructions had been performed:
|
|
; mov edx,[esi+8]
|
|
; and edx,88888888h
|
|
; mov eax,edx
|
|
; shr eax,16+2
|
|
; or eax,edx
|
|
;
|
|
; Note: ROL AH,7 is used instead of SHR AH,1 because the shift-by-1
|
|
; form is 1 cycle slower on a 486, and in this case the two forms are
|
|
; functionally identical.
|
|
;
|
|
; Note: the code is so odd because of 486 pipeline optimization.
|
|
; DO NOT CHANGE THIS CODE UNLESS YOU KNOW EXACTLY WHAT YOU'RE DOING!!!
|
|
;
|
|
; Note: all 486 pipeline penalties are eliminated except for writing CX
|
|
; to memory (2 cycles), so far as I know.
|
|
;-----------------------------------------------------------------------;
|
|
|
|
DIB4_to_VGA_plane3_copy_words::
|
|
test ecx,ODD_WHOLE_WORD or WHOLE_WORDS ;any whole words to copy?
|
|
jz DIB4_to_VGA_plane3_copy_tbyte ;no, check for trailing whole
|
|
; bytes
|
|
;yes, copy the whole words
|
|
push ebp ;preserve stack frame pointer
|
|
mov ebp,ulWholeDwordCount ;# of VGA dwords to copy to
|
|
;even # of DIB dwords to copy? (flags still
|
|
; set from TEST)
|
|
.errnz ODD_WHOLE_WORD - 80000000h
|
|
jns short DIB4_to_VGA_plane3_word_loop ;yes, start copying
|
|
;no, there's an odd word; prepare to enter loop
|
|
; in middle
|
|
mov edx,[esi] ;get 8 pixels to convert of first DIB dword
|
|
and edx,88888888h ;keep only the plane 3 bits of DIB dword
|
|
; EDX = 6xxx7xxx4xxx5xxx2xxx3xxx0xxx1xxx
|
|
mov eax,edx ;put bits 7-4 of DIB dword in AX,
|
|
shr eax,16+2 ; shifted right 2 (x = zero bit)
|
|
; DX = 2xxx3xxx0xxx1xxx
|
|
; AX = xx6xxx7xxx4xxx5x
|
|
or eax,edx ;put bits 7-0 of DIB dword in AX:
|
|
; 2x6x3x7x0x4x1x5x
|
|
sub esi,8 ;compensate source back for entering in middle
|
|
sub edi,2 ;compensate dest back for entering in middle
|
|
|
|
jmp short DIB4_to_VGA_plane3_word_odd
|
|
|
|
;-----------------------------------------------------------------------;
|
|
; Loop to copy a word at a time to VGA plane 3 (actually, unrolled once
|
|
; so copies dwords).
|
|
;-----------------------------------------------------------------------;
|
|
|
|
align 16
|
|
DIB4_to_VGA_plane3_word_loop::
|
|
mov edx,[esi] ;get 8 pixels to convert of DIB dword 0
|
|
and edx,88888888h ;keep only the plane 3 bits of DIB
|
|
; dword 0
|
|
; EDX = 6xxx7xxx4xxx5xxx2xxx3xxx0xxx1xxx
|
|
mov eax,edx ;put bits 7-4 of DIB dword 0 in AX,
|
|
shr eax,16+2 ; shifted right 2 (x = zero bit)
|
|
; DX = 2xxx3xxx0xxx1xxx
|
|
; AX = xx6xxx7xxx4xxx5x
|
|
or eax,edx ;put bits 7-0 of DIB dword 0 in AX:
|
|
; 2x6x3x7x0x4x1x5x
|
|
mov edx,[esi+4] ;get 8 pixels to convert of DIB dword 1
|
|
mov bl,al ;BL = 0x4x1x5x of DIB dword 0
|
|
rol ah,7 ;make AH x2x6x3x7 of DIB dword 0 (shr 1)
|
|
or bl,ah ;BL = 02461357 of DIB dword 0
|
|
and edx,88888888h ;keep only the plane 3 bits of DIB
|
|
; dword 1
|
|
; EDX = 6xxx7xxx4xxx5xxx2xxx3xxx0xxx1xxx
|
|
mov eax,edx ;put bits 7-4 of DIB dword 1 in AX,
|
|
shr eax,16+2 ; shifted right 2 (x = zero bit)
|
|
; DX = 2xxx3xxx0xxx1xxx
|
|
; AX = xx6xxx7xxx4xxx5x
|
|
mov cl,[ebx] ;CL = 76543210 of DIB dword 0
|
|
or eax,edx ;put bits 7-0 of DIB dword 1 in AX:
|
|
; 2x6x3x7x0x4x1x5x
|
|
mov bl,al ;BL = 0x4x1x5x of DIB dword 1
|
|
mov edx,[esi+8] ;get 8 pixels to convert of DIB dword 2
|
|
rol ah,7 ;make AH x2x6x3x7 of DIB dword 1 (shr 1)
|
|
or bl,ah ;BL = 02461357 of DIB dword 1
|
|
and edx,88888888h ;keep only the plane 3 bits of DIB
|
|
; dword 2
|
|
; EDX = 6xxx7xxx4xxx5xxx2xxx3xxx0xxx1xxx
|
|
mov eax,edx ;put bits 7-4 of DIB dword 2 in AX,
|
|
shr eax,16+2 ; shifted right 2 (x = zero bit)
|
|
; DX = 2xxx3xxx0xxx1xxx
|
|
; AX = xx6xxx7xxx4xxx5x
|
|
mov ch,[ebx] ;CH = 76543210 of DIB dword 1
|
|
or eax,edx ;put bits 7-0 of DIB dword 2 in AX:
|
|
; 2x6x3x7x0x4x1x5x
|
|
mov [edi],cx ;write 16 bits from DIB dwords 0 and 1
|
|
; to VGA
|
|
DIB4_to_VGA_plane3_word_odd::
|
|
mov edx,[esi+12] ;get 8 pixels to convert of DIB dword 3
|
|
mov bl,al ;BL = 0x4x1x5x of DIB dword 2
|
|
rol ah,7 ;make AH x2x6x3x7 of DIB dword 2 (shr 1)
|
|
or bl,ah ;BL = 02461357 of DIB dword 2
|
|
and edx,88888888h ;keep only the plane 3 bits of DIB
|
|
; dword 3
|
|
; EDX = 6xxx7xxx4xxx5xxx2xxx3xxx0xxx1xxx
|
|
mov eax,edx ;put bits 7-4 of DIB dword 3 in AX,
|
|
shr eax,16+2 ; shifted right 2 (x = zero bit)
|
|
; DX = 2xxx3xxx0xxx1xxx
|
|
; AX = xx6xxx7xxx4xxx5x
|
|
mov cl,[ebx] ;CL = 76543210 of DIB dword 2
|
|
or eax,edx ;put bits 7-0 of DIB dword 3 in AX:
|
|
; 2x6x3x7x0x4x1x5x
|
|
mov bl,al ;BL = 0x4x1x5x of DIB dword 3
|
|
rol ah,7 ;make AH x2x6x3x7 of DIB dword 3 (shr 1)
|
|
or bl,ah ;BL = 02461357 of DIB dword 3
|
|
add esi,16 ;point to next set of 4 DIB dwords
|
|
add edi,4 ;point to next VGA dword
|
|
mov ch,[ebx] ;CH = 76543210 of dword 0
|
|
dec ebp ;count down VGA dwords
|
|
mov [edi-2],cx ;write 16 bits from DIB dwords 2 and 3
|
|
; to VGA
|
|
jnz DIB4_to_VGA_plane3_word_loop ;do next VGA dword, if any
|
|
|
|
pop ebp ;restore stack frame pointer
|
|
|
|
;-----------------------------------------------------------------------;
|
|
; Code to convert 8 DIB4 pixels to a single VGA plane 3 byte (8 pixels
|
|
; in plane 3). Assumes the DIB4 pixels start in the upper nibble of
|
|
; [ESI], and that the first DIB4 pixel maps to bit 7 of the VGA at
|
|
; [EDI].
|
|
;
|
|
; Input: EBX = pointer to multiplexed DIB byte->planar byte conversion table
|
|
; (must start on a 256-byte boundary)
|
|
; ECX with bits sets as described for ulCopyControlFlags, above
|
|
; ESI = DIB pointer to first two pixels
|
|
; EDI = VGA pointer to planar byte
|
|
; plane 3 must be mapped in for writes
|
|
;
|
|
;-----------------------------------------------------------------------;
|
|
|
|
DIB4_to_VGA_plane3_copy_tbyte::
|
|
test ecx,TRAILING_BYTE ;should we handle a trailing byte?
|
|
jz short DIB4_to_VGA_plane3_copy_tpart ;no, check for trailing
|
|
; partial
|
|
;yes, handle trailing byte
|
|
mov edx,[esi] ;get 8 pixels to convert of DIB dword 0
|
|
and edx,88888888h ;keep only the plane 3 bits of DIB
|
|
; dword 0
|
|
; EDX = 6xxx7xxx4xxx5xxx2xxx3xxx0xxx1xxx
|
|
mov eax,edx ;put bits 7-4 of DIB dword 0 in AX,
|
|
shr eax,16+2 ; shifted right 2 (x = zero bit)
|
|
; DX = 2xxx3xxx0xxx1xxx
|
|
; AX = xx6xxx7xxx4xxx5x
|
|
or eax,edx ;put bits 7-0 of DIB dword 0 in AX:
|
|
; 2x6x3x7x0x4x1x5x
|
|
mov bl,al ;BL = 0x4x1x5x of DIB dword 0
|
|
rol ah,7 ;make AH x2x6x3x7 of DIB dword 0 (shr 1)
|
|
or bl,ah ;BL = 02461357 of DIB dword 0
|
|
add esi,4 ;point to next DIB dword
|
|
inc edi ;point to next VGA byte (placed here
|
|
; for 486 pipelining reasons)
|
|
mov cl,[ebx] ;CL = 76543210 of DIB dword 0
|
|
mov [edi-1],cl ;write 8 bits from DIB dword to VGA
|
|
|
|
;-----------------------------------------------------------------------;
|
|
; Code to convert 1-7 DIB4 pixels to a partial VGA plane 3 byte (8
|
|
; pixels in plane 3). Assumes that a full dword of DIB4 pixels (8
|
|
; pixels) is available, starting at ESI, although some of the pixels
|
|
; will be masked off. Assumes the DIB4 pixels (including masked-off
|
|
; pixels) start in the upper nibble of [ESI], and that the first
|
|
; (possibly masked-off) DIB4 pixel maps to bit 7 of the VGA at [EDI].
|
|
;
|
|
; Input: EBX = pointer to multiplexed DIB byte->planar byte conversion table
|
|
; (must start on a 256-byte boundary)
|
|
; ECX with bits sets as described for ulCopyControlFlags, above
|
|
; ESI = DIB pointer to first two pixels (possibly masked off)
|
|
; EDI = VGA pointer to planar byte
|
|
; plane 3 must be mapped in for writes
|
|
;-----------------------------------------------------------------------;
|
|
|
|
DIB4_to_VGA_plane3_copy_tpart::
|
|
test ecx,TRAILING_PARTIAL ;handle a trailing partial byte?
|
|
jz short DIB4_to_VGA_plane3_copy_done ;no, done
|
|
;yes, handle trailing partial byte
|
|
mov edx,[esi] ;get 8 pixels to convert of DIB dword 0
|
|
and edx,88888888h ;keep only the plane 3 bits of DIB
|
|
; dword 0
|
|
; EDX = 6xxx7xxx4xxx5xxx2xxx3xxx0xxx1xxx
|
|
mov eax,edx ;put bits 7-4 of DIB dword 0 in AX,
|
|
shr eax,16+2 ; shifted right 2 (x = zero bit)
|
|
; DX = 2xxx3xxx0xxx1xxx
|
|
; AX = xx6xxx7xxx4xxx5x
|
|
or eax,edx ;put bits 7-0 of DIB dword 0 in AX:
|
|
; 2x6x3x7x0x4x1x5x
|
|
mov bl,al ;BL = 0x4x1x5x of DIB dword 0
|
|
rol ah,7 ;make AH x2x6x3x7 of DIB dword 0 (shr 1)
|
|
or bl,ah ;BL = 02461357 of DIB dword 0
|
|
add esi,4 ;point to next DIB dword
|
|
inc edi ;point to next VGA byte (placed here
|
|
; for 486 pipelining reasons)
|
|
mov cl,[ebx] ;CL = 76543210 of DIB dword 0
|
|
|
|
mov ch,[edi-1] ;get the VGA destination byte
|
|
mov ch,[edi-1] ;BUGFIX - do twice to fix very
|
|
; weird cirrus bug
|
|
|
|
and ecx,ulRightMask ;mask off source and dest
|
|
or cl,ch ;combine masked source and dest
|
|
mov [edi-1],cl ;write the new pixels to the VGA
|
|
|
|
DIB4_to_VGA_plane3_copy_done::
|
|
add esi,ulSrcDelta ;point to start of next DIB scan
|
|
add edi,ulDstDelta ;point to start of next VGA scan
|
|
dec ulPlane3Scans ;count down scans in this plane
|
|
jnz DIB4_to_VGA_plane3_copy_loop ;do next scan in this plane, if any
|
|
|
|
cmp fDfbTrg,0 ;if DbfTrg flag NOT set...
|
|
je @F ;skip DFB specific code
|
|
sub edi,ulBytesPerPlane ;remove the three scans just added
|
|
sub edi,ulBytesPerPlane
|
|
sub edi,ulBytesPerPlane
|
|
@@:
|
|
|
|
jmp copy_burst_plane3_done ;return to the top of the plane-copy
|
|
; loop
|
|
|
|
endProc vDIB2VGA
|
|
|
|
|
|
public jLeftMasks
|
|
public jRightMasks
|
|
public one_partial_only
|
|
public check_whole_bytes
|
|
public set_copy_control_flags
|
|
public set_shift_vec
|
|
public set_initial_banking
|
|
public map_init_bank
|
|
public init_bank_mapped
|
|
public bank_loop
|
|
public copy_burst_loop
|
|
public align_burst_rshift_486
|
|
public align_burst_lshift_486
|
|
public set_alignment_source
|
|
public proceed_with_copy
|
|
public copy_burst_plane0_done
|
|
public copy_burst_plane1_done
|
|
public copy_burst_plane2_done
|
|
public copy_burst_plane3_done
|
|
public next_bank
|
|
public DIB4_to_VGA_plane0_copy
|
|
public DIB4_to_VGA_plane0_copy_loop
|
|
public DIB4_to_VGA_plane0_copy_lbyte
|
|
public DIB4_to_VGA_plane0_copy_words
|
|
public DIB4_to_VGA_plane0_word_loop
|
|
public DIB4_to_VGA_plane0_word_odd
|
|
public DIB4_to_VGA_plane0_copy_tbyte
|
|
public DIB4_to_VGA_plane0_copy_tpart
|
|
public DIB4_to_VGA_plane0_copy_done
|
|
public DIB4_to_VGA_plane1_copy
|
|
public DIB4_to_VGA_plane1_copy_loop
|
|
public DIB4_to_VGA_plane1_copy_lbyte
|
|
public DIB4_to_VGA_plane1_copy_words
|
|
public DIB4_to_VGA_plane1_word_loop
|
|
public DIB4_to_VGA_plane1_word_odd
|
|
public DIB4_to_VGA_plane1_copy_tbyte
|
|
public DIB4_to_VGA_plane1_copy_tpart
|
|
public DIB4_to_VGA_plane1_copy_done
|
|
public DIB4_to_VGA_plane2_copy
|
|
public DIB4_to_VGA_plane2_copy_loop
|
|
public DIB4_to_VGA_plane2_copy_lbyte
|
|
public DIB4_to_VGA_plane2_copy_words
|
|
public DIB4_to_VGA_plane2_word_loop
|
|
public DIB4_to_VGA_plane2_word_odd
|
|
public DIB4_to_VGA_plane2_copy_tbyte
|
|
public DIB4_to_VGA_plane2_copy_tpart
|
|
public DIB4_to_VGA_plane2_copy_done
|
|
public DIB4_to_VGA_plane3_copy
|
|
public DIB4_to_VGA_plane3_copy_loop
|
|
public DIB4_to_VGA_plane3_copy_lbyte
|
|
public DIB4_to_VGA_plane3_copy_words
|
|
public DIB4_to_VGA_plane3_word_loop
|
|
public DIB4_to_VGA_plane3_word_odd
|
|
public DIB4_to_VGA_plane3_copy_tbyte
|
|
public DIB4_to_VGA_plane3_copy_tpart
|
|
public DIB4_to_VGA_plane3_copy_done
|
|
|
|
_TEXT$01 ends
|
|
|
|
end
|