;---------------------------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 , 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 , ;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