2025-04-27 07:49:33 -04:00

774 lines
26 KiB
NASM

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