page ,132 title Dib Conversions ;---------------------------Module-Header------------------------------; ; Module Name: dibs.asm ; ; Copyright (c) 1992 Microsoft Corporation ;-----------------------------------------------------------------------; .386 ifndef DOS_PLATFORM .model small,c else ifdef STD_CALL .model small,c else .model small,pascal endif; STD_CALL endif; DOS_PLATFORM .xlist include stdcall.inc ;calling convention cmacros include i386\cmacFLAT.inc ; FLATland cmacros include i386\display.inc ; Display specific structures include i386\ppc.inc ; Pack pel conversion structure include i386\bitblt.inc ; General definitions include i386\egavga.inc .list assume ds:FLAT,es:FLAT,ss:FLAT assume fs:nothing,gs:nothing EXTRNP comp_byte_interval ; General equates CJ_PLANE equ (cj_max_scan+1) ;Extra byte makes algorithm easier .data ; Define the buffer for packed-pel to planer conversion. !!! when we do ; conversion to planer bitmaps, this will have to come from the extra scan ; we'll allocate in our planer color bitmaps !!! public ajConvertBuffer ajConvertBuffer db (CJ_PLANE * 4) dup (0) .code _TEXT$03 SEGMENT DWORD USE32 PUBLIC 'CODE' ASSUME DS:FLAT, ES:FLAT, SS:NOTHING, FS:NOTHING, GS:NOTHING ; Define the default pixel mapping table. This table will be used when ; converting from 4bpp to planer with no color translation. align 4 public aulDefBitMapping aulDefBitMapping label dword dd 00000000000000000000000000000000b ;0000 dd 00000000000000000000000000000001b ;0001 dd 00000000000000000000000100000000b ;0010 dd 00000000000000000000000100000001b ;0011 dd 00000000000000010000000000000000b ;0100 dd 00000000000000010000000000000001b ;0101 dd 00000000000000010000000100000000b ;0110 dd 00000000000000010000000100000001b ;0111 dd 00000001000000000000000000000000b ;1000 dd 00000001000000000000000000000001b ;1001 dd 00000001000000000000000100000000b ;1010 dd 00000001000000000000000100000001b ;1011 dd 00000001000000010000000000000000b ;1100 dd 00000001000000010000000000000001b ;1101 dd 00000001000000010000000100000000b ;1110 dd 00000001000000010000000100000001b ;1111 ;-----------------------------------------------------------------------; ; vDIB4n8ToPlaner ; ; Converts a scan of a 4bpp or 8bpp DIB into planer format for bitblt ; ; Entry: ; EBP --> ppc structure ; Exit: ; ESI --> plane 0 of scan data ; Registers Destroyed: ; EAX,EBX,EDX,EBP ; Registers Preserved: ; ECX,EDI ;-----------------------------------------------------------------------; ppc equ [ebp] vDIB4n8ToPlaner proc push ecx push edi ; Load up the parameters for the blt mov esi,ppc.pSrc ;Source pointer mov eax,ppc.iNextScan ;Index to next scan add eax,esi mov ppc.pSrc,eax ;Save next source pointer xor eax,eax ;Creating a four bit index in eax ; pulXlate must be zero for 4bpp conversion since we will be using ; ebx for creating an index. No problem since we don't need the ; translation by the time we're in this code. mov ebx,ppc.pulXlate ;Color translation or zero lea edi,ajConvertBuffer ;Where to store results ; Handle a partial first byte and all full bytes mov ecx,ppc.cLeftMiddle ;Get loop count for middle and left jecxz vDIB4n8DoneFirst ;No first/inner push ebp push offset FLAT:VDIB4n8FinishFirst ;Set return address push ppc.pfnLeftMiddle ;Set proc for left partial byte mov ebp,ppc.pulConvert ;Base address of conversion table xor edx,edx ;Init accumulated bits ret ;To ppc.pfnLeftMiddle VDIB4n8FinishFirst: ;It returns here pop ebp vDIB4n8DoneFirst: mov ecx,ppc.pfnRight jecxz short vDIB4n8DoneRightSide ;No left side and edx,01010101h ;Carryover from a partial 4bpp byte push ebp push offset FLAT:VDIB4n8FinishLast ;Set return address push ecx ;Set function address mov ecx,1 ;No looping mov ebp,ppc.pulConvert ;Base address of conversion table ret ;To ppc.pfnRight VDIB4n8FinishLast: ;It returns here pop ebp mov cl,ppc.cLeftShift ;Must align right side pels shl edx,cl mov [edi][CJ_PLANE*0][-1],dl mov [edi][CJ_PLANE*1][-1],dh shr edx,16 mov [edi][CJ_PLANE*2][-1],dl mov [edi][CJ_PLANE*3][-1],dh ; Load up the source pointer and exit vDIB4n8DoneRightSide: pop edi pop ecx mov esi,ppc.pjConverted ret vDIB4n8ToPlaner endp ppc equ <> ;-----------------------------------------------------------------------; ; vDIB4Convert* ; ; Converts the specified number of source 4 bpp bits into the ; buffer. These are support routines for vDIB4Planer, where a ; source byte converts into two aligned bits ; ; Entry: ; EAX 31:8 = 0 ; EBP --> Bit conversion table ; ESI --> Source bitmap ; EDI --> Planer destination ; ECX = Loop count ; Exit: ; EBP --> Bit conversion table ; ESI --> Next source byte ; EDI --> Next planer destination ; EDX = Last planer byte accumulated ; Registers Destroyed: ; EAX,ECX,EDX ; Registers Preserved: ;-----------------------------------------------------------------------; vDIB4Convert8:: lodsb mov ebx,eax shr eax,4 and ebx,00001111b mov edx,[ebp][eax*4] shl edx,1 or edx,[ebp][ebx*4] vDIB4Convert6:: lodsb shl edx,1 mov ebx,eax shr eax,4 and ebx,00001111b or edx,[ebp][eax*4] shl edx,1 or edx,[ebp][ebx*4] vDIB4Convert4:: lodsb shl edx,1 mov ebx,eax shr eax,4 and ebx,00001111b or edx,[ebp][eax*4] shl edx,1 or edx,[ebp][ebx*4] vDIB4Convert2:: lodsb shl edx,1 mov ebx,eax shr eax,4 and ebx,00001111b or edx,[ebp][eax*4] shl edx,1 or edx,[ebp][ebx*4] mov [edi][CJ_PLANE*0],dl mov [edi][CJ_PLANE*1],dh ror edx,16 mov [edi][CJ_PLANE*2],dl mov [edi][CJ_PLANE*3],dh inc edi dec ecx jnz vDIB4Convert8 rol edx,16 ;Incase alignment of last byte ret ;-----------------------------------------------------------------------; ; vDIB4NAConvert* ; ; Converts the specified number of source 4 bpp bits into the ; buffer. These are support routines for vDIB4Planer, where a ; source byte converts into two non-aligned bytes (we have to carry ; a bit over into the next destination byte). ; ; Entry: ; EAX 31:8 = 0 ; EBP --> Bit conversion table ; ESI --> Source bitmap ; EDI --> Planer destination ; ECX = Loop count ; Exit: ; EBP --> Bit conversion table ; ESI --> Next source byte ; EDI --> Next planer destination ; EDX = first pel of next destination ; Registers Destroyed: ; EAX,ECX,EDX ; Registers Preserved: ;-----------------------------------------------------------------------; vDIB4NAConvert7:: lodsb shl edx,1 ;Carry over bit from last fetch mov ebx,eax shr eax,4 and ebx,00001111b or edx,[ebp][eax*4] shl edx,1 or edx,[ebp][ebx*4] vDIB4NAConvert5:: lodsb shl edx,1 mov ebx,eax shr eax,4 and ebx,00001111b or edx,[ebp][eax*4] shl edx,1 or edx,[ebp][ebx*4] vDIB4NAConvert3:: lodsb shl edx,1 mov ebx,eax shr eax,4 and ebx,00001111b or edx,[ebp][eax*4] shl edx,1 or edx,[ebp][ebx*4] vDIB4NAConvert1:: lodsb shl edx,1 mov ebx,eax shr eax,4 and ebx,00001111b or edx,[ebp][eax*4] mov [edi][CJ_PLANE*0],dl mov [edi][CJ_PLANE*1],dh shr edx,16 mov [edi][CJ_PLANE*2],dl mov [edi][CJ_PLANE*3],dh inc edi mov edx,[ebp][ebx*4] ;Start of next destination byte dec ecx jnz vDIB4NAConvert7 ret ;-----------------------------------------------------------------------; ; vDIB4NAConvert0 ; ; Last byte code for the 4bpp non-aligned case where the data already ; exists in EDX, but we have to increment the destination pointer since ; vDIB4n8ToPlaner assumes we stored the data and incremented the pointer ; ; Entry: ; EDI --> destination ; Exit: ; EDI = EDI + 1 ; Registers Destroyed: ; None ; Registers Preserved: ; All but EDI ;-----------------------------------------------------------------------; vDIB4NAConvert0 proc inc edi vNOP:: ret vDIB4NAConvert0 endp ;-----------------------------------------------------------------------; ; The following table is indexed into to get the address of where to ; enter the 4bpp conversion loops ;-----------------------------------------------------------------------; apfn4bppConvert label dword dd offset FLAT:vDIB4Convert8 dd offset FLAT:vDIB4NAConvert7 dd offset FLAT:vDIB4Convert6 dd offset FLAT:vDIB4NAConvert5 dd offset FLAT:vDIB4Convert4 dd offset FLAT:vDIB4NAConvert3 dd offset FLAT:vDIB4Convert2 dd offset FLAT:vDIB4NAConvert1 ;-----------------------------------------------------------------------; ; The following table is indexed into to get the address of where to ; enter the 4bpp conversion loops for a partial right hand side byte ;-----------------------------------------------------------------------; apfn4bppConvertRHS label dword dd offset FLAT:vNOP ;Should never be called dd offset FLAT:vDIB4Convert6 ;Convert three more source bytes dd offset FLAT:vDIB4Convert6 ;Convert three source bytes dd offset FLAT:vDIB4Convert4 ;Convert two more source bytes dd offset FLAT:vDIB4Convert4 ;Convert two source bytes dd offset FLAT:vDIB4Convert2 ;Convert one more source byte dd offset FLAT:vDIB4Convert2 ;Convert one source byte dd offset FLAT:vDIB4NAConvert0 ;Non-aligned, data in EDX already ;-----------------------------------------------------------------------; ; vDIB8Convert* ; ; Converts the specified number of source 8 bpp bits into the ; buffer. These are support routines for vDIB8Planer. ; ; Entry: ; EAX 31:8 = 0 ; EBP --> Bit conversion table ; EBX --> Color translation table ; ESI --> Source bitmap ; EDI --> Planer destination ; ECX = Loop count ; Exit: ; EBP --> Bit conversion table ; EBX --> Color translation table ; ESI --> Next source byte ; EDI --> Next planer destination ; Registers Destroyed: ; EAX,ECX,EDX ; Registers Preserved: ; None ;-----------------------------------------------------------------------; vDIB8Convert8:: lodsb ;Get pel 1 mov al,[ebx][eax*4] ;Color translation into 4 bits mov edx,[ebp][eax*4] vDIB8Convert7:: lodsb ;Get pel 2 shl edx,1 mov al,[ebx][eax*4] or edx,[ebp][eax*4] vDIB8Convert6:: lodsb ;Get pel 2 shl edx,1 mov al,[ebx][eax*4] or edx,[ebp][eax*4] vDIB8Convert5:: lodsb ;Get pel 2 shl edx,1 mov al,[ebx][eax*4] or edx,[ebp][eax*4] vDIB8Convert4:: lodsb ;Get pel 2 shl edx,1 mov al,[ebx][eax*4] or edx,[ebp][eax*4] vDIB8Convert3:: lodsb ;Get pel 2 shl edx,1 mov al,[ebx][eax*4] or edx,[ebp][eax*4] vDIB8Convert2:: lodsb ;Get pel 2 shl edx,1 mov al,[ebx][eax*4] or edx,[ebp][eax*4] vDIB8Convert1:: lodsb ;Get pel 7 shl edx,1 mov al,[ebx][eax*4] or edx,[ebp][eax*4] mov [edi][CJ_PLANE*0],dl mov [edi][CJ_PLANE*1],dh ror edx,16 mov [edi][CJ_PLANE*2],dl mov [edi][CJ_PLANE*3],dh inc edi dec ecx jnz vDIB8Convert8 rol edx,16 ;Incase alignment of last byte ret ;-----------------------------------------------------------------------; ; The following table is indexed into to get the address of where to ; enter the 8bpp conversion loop ;-----------------------------------------------------------------------; apfn8bppConvert label dword dd offset FLAT:vDIB8Convert8 dd offset FLAT:vDIB8Convert7 dd offset FLAT:vDIB8Convert6 dd offset FLAT:vDIB8Convert5 dd offset FLAT:vDIB8Convert4 dd offset FLAT:vDIB8Convert3 dd offset FLAT:vDIB8Convert2 dd offset FLAT:vDIB8Convert1 ;-----------------------------------------------------------------------; ; vDIB8Preprocess() ; ; Performs whatever processing is necessary to prepare for a blt from ; a 8bpp DIB to a planer format bitmap. ; ; Entry: ; EBP --> Bitblt frame structure ; Exit: ; None ; Registers Destroyed: ; EAX,EBX,ECX,EDX,ESI,EDI ; Registers Preserved: ; EBP,EBX ;-----------------------------------------------------------------------; fr equ [ebp] cProc vDIB8Preprocess push ebx mov fr.ppcBlt.pulConvert,offset FLAT:aulDefBitMapping ; Align the blt so that the blt's phase will become 0. Both origins are ; guaranteed to be positive and < 16 bits !!! movzx eax,fr.DestxOrg ;Align source and dest X origins mov edx,eax mov ax,fr.SrcxOrg mov fr.SrcxOrg,dx ;D31:16 is zero for both add eax,fr.src.lp_bits mov fr.ppcBlt.pSrc,eax ;Save address of first source pel and edx,7 ;Always start in first byte of buffer push edx ;Save for computing loop entry movzx ebx,fr.xExt ;Compute exclusive right hand side (rhs) add ebx,edx push ebx ;Save rhs for shift count computation ; comp_byte_interval returns: ; ; EDI = offset to first byte to be altered in the scan ; ESI = inner loop count (possibly 0) ; AL = first byte mask (possibly 0) ; AH = last byte mask (possibly 0) cCall comp_byte_interval pop ebx ;Exclusive rhs pop edx ;Inclusive lhs ; If only a partial destination byte will be altered, the mask will have ; been returned in AL with AH and ESI 0. or ah,ah ;See if only a first byte jnz short @f ;More than one byte to alter or esi,esi jnz @F ;More than a partial byte ; There will only be a partial byte. The normal flow-o-control falls apart ; so we have to special case it. mov fr.ppcBlt.cLeftMiddle,esi ;No first/inner loop mov eax,8 sub eax,ebx mov fr.ppcBlt.cLeftShift,al ;Set shift count to align last byte mov eax,8 sub ebx,edx ;EBX = # pels needed (<8) sub eax,ebx mov eax,apfn8bppConvert[eax*4] jmp short v8bpp_have_last @@: ; More than a single byte will be written for the destination. Compute entry ; into the convert loop based on the destination X origin. If the X dest ; origin was zero, the first byte will have been combined into the inner loop ; count cmp al,1 ;If partial first byte we need to bump cmc ; the loop count by 1 adc esi,0 mov edx,apfn8bppConvert[edx*4] mov al,ah ;Set last byte mask mov fr.ppcBlt.pfnLeftMiddle,edx v8bpp_have_first_inner: mov fr.ppcBlt.cLeftMiddle,esi ;Save innerloop count (possibly 0) ; Compute the function and shift count for the last byte (if one exists) movzx eax,al or eax,eax jz short v8bpp_have_last ;No last byte, set pfn = 0 mov al,8 ;D31:8 set to 0 with above movzx sub eax,ebx and eax,00000111b mov fr.ppcBlt.cLeftShift,al ;Set shift count to align last byte mov eax,apfn8bppConvert[eax*4] v8bpp_have_last: mov fr.ppcBlt.pfnRight,eax ; Set the address of routine which will be called from the compiled blt mov fr.ppcBlt.pfnConvert,offset FLAT:vDIB4n8ToPlaner mov fr.ppcBlt.pjConverted,offset FLAT:ajConvertBuffer pop ebx cRet vDIB8Preprocess endProc vDIB8Preprocess ;-----------------------------------------------------------------------; ; vDIB4Preprocess() ; ; Performs whatever processing is necessary to prepare for a blt from ; a 4bpp DIB to a planer format bitmap. ; ; Entry: ; EBP --> Bitblt frame structure ; Exit: ; None ; Registers Destroyed: ; EAX,EBX,ECX,EDX,ESI,EDI ; Registers Preserved: ; EBP,EBX ;-----------------------------------------------------------------------; fr equ [ebp] cProc vDIB4Preprocess push ebx ; If a color translation vector was given, generate the new bit ; conversion array mov eax,offset FLAT:aulDefBitMapping cld mov esi,fr.ppcBlt.pulXlate or esi,esi jz vDIB4_have_mapping_array lea edi,fr.aulMap mov ecx,16 create_next_bit_mapping: lodsd mov eax,aulDefBitMapping[eax*4] stosd dec ecx jnz create_next_bit_mapping lea eax,[edi][-16*4] vDIB4_have_mapping_array: mov fr.ppcBlt.pulConvert,eax ; Align the blt so that the blt's phase will become 0. Both origins are ; guaranteed to be positive and < 16 bits !!! movzx eax,fr.DestxOrg ;Align source and dest X origins mov edx,eax ;Save for later calculations mov ax,fr.SrcxOrg ;D31:16 is zero for both mov fr.SrcxOrg,dx ; We never want to process a partial source byte. We will move the source ; left if necessary, and adjust the extent if necessary. Note that if any ; adjustments are made, we won't fetch past the end of the source nor ; will we write beyond the end of our buffer (since we made it big enough ; in the first place). ; We don't worry about adjusting the source origin before we save it ; since we will be shifting it right later to round it to a byte address mov ecx,eax shr ecx,1 add ecx,fr.src.lp_bits mov fr.ppcBlt.pSrc,ecx ;Save address of first pel and eax,1 ;EAX = 1 if source is odd pel movzx ebx,fr.xExt sub edx,eax ;Move dest left if necessary add ebx,eax ;Also bump extent if moved and edx,7 ;Start dest in first byte of buffer inc ebx ;Round extent to a multiple of 2 and bl,11111110b add ebx,edx ;Exclusive right hand side ; A problem: When moving the source left a pel, we can encounter a situation ; wherein the first pel written is in bit position 0. However, it should be ; noted that this pel is not part of the blt, so we have to skip over the ; byte containing it to get to the correct first pel (which will be bit 7 ; of the next byte). cmp dl,7 je @F xor ax,ax @@: add eax,offset FLAT:ajConvertBuffer mov fr.ppcBlt.pjConverted,eax ; comp_byte_interval returns: ; ; EDI = offset to first byte to be altered in the scan ; ESI = inner loop count (possibly 0) ; AL = first byte mask (possibly 0) ; AH = last byte mask (possibly 0) push edx ;Save for computing loop entry push ebx ;Save rhs for shift count computation cCall comp_byte_interval pop ebx ;Exclusive rhs pop edx ;Inclusive lhs ; If only a partial destination byte will be altered, the mask will have ; been returned in AL with AH and ESI 0. or ah,ah ;See if only a first byte jnz short @f ;More than one byte to alter or esi,esi jnz short @f ;More than one byte ; There will only be a partial byte. The normal flow-o-control falls apart ; so we have to special case it. mov fr.ppcBlt.cLeftMiddle,esi ;No first/inner loop mov eax,8 sub eax,ebx mov fr.ppcBlt.cLeftShift,al ;Set shift count to align last byte mov eax,8 sub ebx,edx ;EBX = # pels needed (<8) sub eax,ebx mov eax,apfn4bppConvertRHS[eax*4] jmp short v4bpp_have_last @@: ; More than a single byte will be written for the destination. Compute entry ; into the convert loop based on the destination X origin. If the X dest ; origin was zero, the first byte will have been combined into the inner loop ; count cmp al,1 ;If partial first byte we need to bump cmc ; the loop count by 1 adc esi,0 mov ecx,apfn4bppConvert[edx*4] mov al,ah ;Set last byte mask mov fr.ppcBlt.pfnLeftMiddle,ecx v4bpp_have_first_inner: mov fr.ppcBlt.cLeftMiddle,esi ;Save innerloop count (possibly 0) ; Compute the function and shift count for the last byte (if one exists) movzx eax,al or eax,eax jz short v4bpp_have_last ;No last byte, set pfn = 0 mov al,8 ;D31:8 set to 0 with above movzx sub eax,ebx and eax,00000111b mov fr.ppcBlt.cLeftShift,al ;Set shift count to align last byte mov eax,apfn4bppConvertRHS[eax*4] v4bpp_have_last: mov fr.ppcBlt.pfnRight,eax ; Set the address of the routine which will be called from the compiled blt mov fr.ppcBlt.pfnConvert,offset FLAT:vDIB4n8ToPlaner pop ebx cRet vDIB4Preprocess endProc vDIB4Preprocess ;----------------------------Private-Routine----------------------------; ; packed_pel_comp_y ; ; Compute y-related parameters. ; ; The parameters related to the Y coordinate and BLT direction ; are computed. The parameters include: ; ; a) Index to next scan line ; b) Starting Y address calculation ; d) Index to next plane ; ; Entry: ; EBP --> Blt frame ; AX = Y coordinate ; ECX = BLT direction ; 0000 = Y+ ; FFFF = Y- ; BX = inclusive Y extent ; Returns: ; None ; Registers Preserved: ; EBP,ECX,EBX,EDX ; Registers Destroyed: ; EAX,ESI,EDI,flags ; Calls: ; None ; History: ;-----------------------------------------------------------------------; fr equ [ebp] cProc packed_pel_comp_y push edx mov fr.src.next_plane,CJ_PLANE ;Index to next plane of data movsx esi,fr.src.width_b ;Need bmWidthBytes couple-o-times movzx eax,ax mul esi ;Compute Y address add fr.ppcBlt.pSrc,eax ;Add to base address xor esi,ecx ;1's complement if Y- sub esi,ecx ;2's complement if Y- mov fr.ppcBlt.iNextScan,esi ;Set index to next scan line pop edx cRet packed_pel_comp_y endProc packed_pel_comp_y _TEXT$03 ends end