Leaked source code of windows server 2003
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

701 lines
20 KiB

; Names are read LSB to MSB, so B5G6R5 means five bits of blue starting
; at the LSB, then six bits of green, then five bits of red.
dnl
dnl Texture read routine have texture address passed as edi. The offset into that
dnl is passed as eax. Output is mm1 in 8.8 for each color channel. For border
dnl mm0 is used to pass sign information of iU and iV. Each word contains a
dnl UV pair so that all 4 values for bilinear can be stored in mm0.
dnl
dnl The only free registers are MM1 and MM2. EAX is free after texture is read and
dnl edx is free after DoBorder macro. Any other register useage will cause problems
dnl and even exceptions.
dnl
dnl
define(`texreadVars', `
EXTERN MaskRed565to888:MMWORD
EXTERN MaskGreen565to888:MMWORD
EXTERN MaskBlue565to888:MMWORD
EXTERN MaskRed555to888:MMWORD
EXTERN MaskGreen555to888:MMWORD
EXTERN MaskBlue555to888:MMWORD
EXTERN MaskAlpha1555to8888:MMWORD
EXTERN MaskRed1555to8888:MMWORD
EXTERN MaskGreen1555to8888:MMWORD
EXTERN MaskBlue1555to8888:MMWORD
; TBD. I think that I want to do 0xffff instead of 0xff. This will
; have to be checked. There is a value very similiar to this in
; buf write.
EXTERN SetAlphato0xffff:MMWORD
EXTERN SetAlphato0xff:MMWORD
; TODO This equate are identical to the ones in texread.mas. Maybe they should be in a common .inc file.
RedShift565to888 equ 8
GreenShift565to888 equ 5
BlueShift565to888 equ 3
RedShift555to888 equ 9
GreenShift555to888 equ 6
BlueShift555to888 equ 3
AlphaShift1555to8888 equ 16
RedShift1555to8888 equ 9
GreenShift1555to8888 equ 6
BlueShift1555to8888 equ 3
EXTERN Zero:MMWORD
')
dnl
dnl d_DoTex
dnl
dnl Calls the macro in $1 with all options to generate differentiated texture
dnl read functions. Specifies that all of these are Not Monolithic.
dnl Monolithic cases will need to call routines by themselves and specify border and colorkey options.
dnl
define(`d_DoTex', `d_Null($1(NoBorder, NoColorKey, NotMonolithic))
d_Null($1(NoBorder, ColorKey, NotMonolithic))
d_Null($1(Border, NoColorKey, NotMonolithic))
d_Null($1(Border, ColorKey, NotMonolithic))')dnl
dnl
dnl d_DoBorder
dnl
dnl Inserts conditional border code
dnl
define(`d_DoBorder', `ifelse(`$1', `NoBorder', `
; Generate Border Mask to always be true in non border case.
;pcmpeqd mm5, mm5
', `
; Generate Border Mask based on if statement.
;if ((iU < 0) || (iV < 0))
;{
; Are branches bad enough to do all of this code?
; Address ends up negative when were supposed to set the border color.
; Generate mask based on sign bit.
movq mm5, mm0
psrlq mm0, 16 ; Shift iu iv values for next border case. This is only useful in bilinear
pand mm5, MMWORD PTR CheckLowTwo8BitSignbits
pcmpeqd mm5, MMWORD PTR Zero
movd edx, mm5
and eax, edx
;return pTex->BorderColor;
;}
')
')dnl
dnl
dnl d_DoBorderMix
dnl
dnl Inserts conditional border code
dnl
define(`d_DoBorderMix', `ifelse(`$1', `NoBorder', `
; Generate Border Mask to always be true.
;pcmpeqd mm5, mm5
', `
movd mm2, XpTex(BorderColor)
pand mm1, mm5
pandn mm5, mm2
por mm1, mm5
')
')dnl
dnl
dnl d_DoColorKey
dnl
dnl Inserts conditional color key code
dnl $1 the function type, $2 is the thing to test against the Transparent color,
dnl and $3 is its type.
dnl
define(`d_DoColorKey', `ifelse(`$1', `ColorKey', `
; Generate another mask based on TransparentColor
; Should be able to do pcmpeq to generate mask.
; Need Palettized and non Palettized code both use eax for the original Texel.
; if (ColorOriTexel == (int32)pTex->TransparentColor)
; {
; Color &= 0xffffff;
; }
movq mm2, mm1
movd mm1, eax
pcmpeqd mm1, XpTex(TransparentColor)
; if they are equal then mm1 = 0xffffffff else mm1 = 0
pslld mm1, 24 ; mm1 = 0xffffffff << 24 = 0xff000000 or mm2 = 0 << 24 = 0.
pandn mm1, mm2 ; mask off alpha if color is transparent color.
')')dnl
dnl
dnl
dnl d_DoReturn
dnl
dnl Inserts conditional return. Return in general case and dont in monolith case.
dnl
define(`d_DoReturn', `ifelse(`$1', `NotMonolithic', `
;return Color;
ret
', `
; No call or return in monolith case.
')
')dnl
define(`d_Palette8', ``
; This code needs to be cleaned up quite a bit.
;D3DCOLOR TexRead_Palette8_$1_$2(INT32 iU, INT32 iV, INT32 iShiftU, PUINT8 pBits, PD3DI_SPANTEX pTex)
;{
ifelse(`$3', `Monolithic', `', `
PUBLIC _MMX_TexRead_Palette8_$1_$2
_MMX_TexRead_Palette8_$1_$2:
')
; Start this line now to give pmadd moretime to finish
; INT32 iTexel = pBits[iU | (iV << iShiftU)];
; Save mm3 for now
; TBD look to see if need to save it or if it will change.
d_DoBorder(`$1')
movzx eax, byte ptr [edi + eax] ; get index
mov edx, eax
shl edx, 2 ; convert to DWORD offset
;D3DCOLOR Color = pTex->pPalette[iTexel];
add edx, XpTex(pPalette) ; add index to get palette address
movd mm1, dword ptr[edx]
movq mm2, mm1 ; 0000?BGR = mm2
punpcklwd mm1, mm1 ; ?B?BGRGR = mm1
psrlq mm2, 16 ; 000000?B
pand mm2, MMWORD PTR Val0x00ff00ff ; 0000000B
pand mm1, MMWORD PTR Val0xffff00 ; 00000RG0
por mm1, mm2 ; 00000RGB
; RL palette is BGR - flip the channels into RGB
;Color = RGBA_MAKE((Color & 0xff),
; (Color >> 8) & 0xff,
; (Color >> 16) & 0xff,
; 0xff);
; result should be in mm1 for color key and border masking.
por mm1, dword ptr SetAlphaTo0xFF
d_DoColorKey(`$2')
d_DoBorderMix($1)
; Need to unpack color for bilinear 16 bit multiplications
punpcklbw mm1, MMWORD PTR Zero
d_DoReturn($3)
;}'')dnl
define(`d_Palette4', ``
;D3DCOLOR TexRead_Palette4_$1_$2(INT32 iU, INT32 iV, INT32 iShiftU, PUINT8 pBits, PD3DI_SPANTEX pTex)
;{
ifelse(`$3', `Monolithic', `', `
PUBLIC _MMX_TexRead_Palette4_$1_$2
_MMX_TexRead_Palette4_$1_$2:
')
d_DoBorder(`$1')
;INT32 iIndex = iU | (iV << iShiftU);
; Need ecx to shift with. Save it off since it will be needed later.
mov edx, ecx
mov ecx, eax
and ecx, 1
;INT32 iTexel = pBits[iIndex>>1];
shr eax, 1
movzx eax, byte ptr [edi + eax] ; get index
;if ((iIndex & 1) == 0)
;{
; iTexel &= 0xf;
;}
;else
;{
; iTexel >>= 4;
;}
shl ecx, 2 ; This will make ecx 0 or 4. This gets lookup value in correct place without branching.
shr eax, cl ; Shift by 0 or 4 now.
and eax, 0fh
mov ecx, eax
shl ecx, 2 ; convert to DWORD offset
;D3DCOLOR Color = pTex->pPalette[iTexel];
add ecx, XpTex(pPalette) ; add index to get palette address
movd mm1, dword ptr[ecx]
; RL palette is BGR - flip the channels into RGB
;Color = RGBA_MAKE((Color & 0xff),
; (Color >> 8) & 0xff,
; (Color >> 16) & 0xff,
; 0xff);
movq mm2, mm1 ; 0000?BGR = mm2
punpcklwd mm1, mm1 ; ?B?BGRGR = mm1
psrlq mm2, 16 ; 000000?B
pand mm2, MMWORD PTR Val0x00ff00ff ; 0000000B
pand mm1, MMWORD PTR Val0xffff00 ; 00000RG0
por mm1, mm2 ; 00000RGB
por mm1, dword ptr SetAlphaTo0xFF
d_DoColorKey(`$2')
d_DoBorderMix($1)
punpcklbw mm1, MMWORD PTR Zero
; Revive ecx.
mov ecx, edx
d_DoReturn($3)
;}'')dnl
define(`d_Palette8A', ``
; This code needs to be cleaned up quite a bit.
;D3DCOLOR TexRead_Palette8A_$1_$2(INT32 iU, INT32 iV, INT32 iShiftU, PUINT8 pBits, PD3DI_SPANTEX pTex)
;{
ifelse(`$3', `Monolithic', `', `
PUBLIC _MMX_TexRead_Palette8A_$1_$2
_MMX_TexRead_Palette8A_$1_$2:
')
; Start this line now to give pmadd moretime to finish
; INT32 iTexel = pBits[iU | (iV << iShiftU)];
; Save mm3 for now
; TBD look to see if need to save it or if it will change.
d_DoBorder(`$1')
movzx eax, byte ptr [edi + eax] ; get index
mov edx, eax
shl edx, 2 ; convert to DWORD offset
;D3DCOLOR Color = pTex->pPalette[iTexel];
add edx, XpTex(pPalette) ; add index to get palette address
movd mm1, dword ptr[edx]
movq mm2, mm1 ; 0000ABGR = mm2
pand mm1, MMWORD PTR Val0xff00ff00 ; 0000A0G0 = mm1
pand mm2, MMWORD PTR Val0x00ff00ff ; 00000B0R = mm2
psllq mm2, 16 ; 000B0R00 = mm2
por mm1, mm2 ; 000BARG0 = mm1
psrlq mm2, 32 ; 0000000B = mm2
por mm1, mm2 ; 000BARBG = mm1
; RL palette is BGR - flip the channels into RGB
;Color = RGBA_MAKE((Color & 0xff),
; (Color >> 8) & 0xff,
; (Color >> 16) & 0xff,
; (Color >> 24) & 0xff);
d_DoColorKey(`$2')
d_DoBorderMix($1)
; Need to unpack color for bilinear 16 bit multiplications
punpcklbw mm1, MMWORD PTR Zero
d_DoReturn($3)
;}'')dnl
define(`d_Palette4A', ``
;D3DCOLOR TexRead_Palette4A_$1_$2(INT32 iU, INT32 iV, INT32 iShiftU, PUINT8 pBits, PD3DI_SPANTEX pTex)
;{
ifelse(`$3', `Monolithic', `', `
PUBLIC _MMX_TexRead_Palette4A_$1_$2
_MMX_TexRead_Palette4A_$1_$2:
')
d_DoBorder(`$1')
;INT32 iIndex = iU | (iV << iShiftU);
; Need ecx to shift with. Save it off since it will be needed later.
mov edx, ecx
mov ecx, eax
and ecx, 1
;INT32 iTexel = pBits[iIndex>>1];
shr eax, 1
movzx eax, byte ptr [edi + eax] ; get index
;if ((iIndex & 1) == 0)
;{
; iTexel &= 0xf;
;}
;else
;{
; iTexel >>= 4;
;}
shl ecx, 2 ; This will make ecx 0 or 4. This gets lookup value in correct place without branching.
shr eax, cl ; Shift by 0 or 4 now.
and eax, 0fh
mov ecx, eax
shl ecx, 2 ; convert to DWORD offset
;D3DCOLOR Color = pTex->pPalette[iTexel];
add ecx, XpTex(pPalette) ; add index to get palette address
movd mm1, dword ptr[ecx]
; RL palette is BGR - flip the channels into RGB
;Color = RGBA_MAKE((Color & 0xff),
; (Color >> 8) & 0xff,
; (Color >> 16) & 0xff,
; (Color >> 24) & 0xff);
movq mm2, mm1 ; 0000ABGR = mm2
pand mm1, MMWORD PTR Val0xff00ff00 ; 0000A0G0 = mm1
pand mm2, MMWORD PTR Val0x00ff00ff ; 00000B0R = mm2
psllq mm2, 16 ; 000B0R00 = mm2
por mm1, mm2 ; 000BARG0 = mm1
psrlq mm2, 32 ; 0000000B = mm2
por mm1, mm2 ; 000BARBG = mm1
d_DoColorKey(`$2')
d_DoBorderMix($1)
punpcklbw mm1, MMWORD PTR Zero
; Revive ecx.
mov ecx, edx
d_DoReturn($3)
;}'')dnl
define(`d_B8G8R8', ``
;D3DCOLOR TexRead_B8G8R8_$1_$2(INT32 iU, INT32 iV, INT32 iShiftU, PUINT8 pBits, PD3DI_SPANTEX pTex)
;{
ifelse(`$3', `Monolithic', `', `
PUBLIC _MMX_TexRead_B8G8R8_$1_$2
_MMX_TexRead_B8G8R8_$1_$2:
')
d_DoBorder(`$1')
;D3DCOLOR Color = (((D3DCOLOR*)pBits)[iU | (iV << iShiftU)]) | 0xff000000;
; Save mm3 for now
; TBD look to see if need to save it or if it will change.
mov eax, dword ptr [edi+4*eax]
movd mm1, eax ; save copy of original texel
por mm1, dword ptr SetAlphaTo0xFF
d_DoColorKey(`$2')
d_DoBorderMix($1)
; Need to unpack color for bilinear 16 bit multiplications
punpcklbw mm1, MMWORD PTR Zero
d_DoReturn($3)
;}'')dnl
define(`d_B8G8R8A8', ``
;D3DCOLOR TexRead_B8G8R8A8_$1_$2(INT32 iU, INT32 iV, INT32 iShiftU, PUINT8 pBits, PD3DI_SPANTEX pTex)
;{
ifelse(`$3', `Monolithic', `', `
PUBLIC _MMX_TexRead_B8G8R8A8_$1_$2
_MMX_TexRead_B8G8R8A8_$1_$2:
')
d_DoBorder(`$1')
;D3DCOLOR Color = ((D3DCOLOR*)pBits)[iU | (iV << iShiftU)];
mov eax, dword ptr [edi+4*eax] ; This should be aligned
movd mm1, eax ; save copy of original texel
d_DoColorKey(`$2')
d_DoBorderMix($1)
punpcklbw mm1, MMWORD PTR Zero
d_DoReturn($3)
;}'')dnl
define(`d_B5G6R5', ``
;D3DCOLOR TexRead_B5G6R5_$1_$2(INT32 iU, INT32 iV, INT32 iShiftU, PUINT8 pBits, PD3DI_SPANTEX pTex)
;{
ifelse(`$3', `Monolithic', `', `
PUBLIC _MMX_TexRead_B5G6R5_$1_$2
_MMX_TexRead_B5G6R5_$1_$2:
')
d_DoBorder(`$1')
movzx eax, word ptr [edi+2*eax]
;UINT16 uTexel = ((UINT16*)pBits)[iU | (iV << iShiftU)];
;D3DCOLOR Color = RGBA_MAKE(( uTexel >> 8 ) & 0xf8,
; (( uTexel >> 3) & 0xfc ),
; (( uTexel << 3) & 0xf8 ),
; 0xff);
movd mm1, eax ; Make three more copies of input color
mov edx, eax
movq mm2, mm1
pand mm1, dword ptr MaskGreen565to888 ; MaskGreen565to888 is in memory
psllq mm2, RedShift565to888 ; RedShift should be an immediate
pand mm2, dword ptr MaskRed565to888 ; MaskRed565to888 in memory.
psllq mm1, GreenShift565to888
shl edx, BlueShift565to888
por mm1, mm2
and edx, dword ptr MaskBlue565to888
movd mm2, edx
por mm1, dword ptr SetAlphaTo0xFF
por mm1, mm2
d_DoColorKey(`$2')
d_DoBorderMix($1)
; Dont need to unpack here since I shift to correct location.
; BUG BUG this will cause a problem with the border color.
; Could do different shifts if border is on or not.
; For now, just unpack and dont shift as much.
punpcklbw mm1, MMWORD PTR Zero
d_DoReturn($3)
;}'')dnl
define(`d_B5G5R5', ``
;D3DCOLOR TexRead_B5G5R5_$1_$2(INT32 iU, INT32 iV, INT32 iShiftU, PUINT8 pBits, PD3DI_SPANTEX pTex)
;{
ifelse(`$3', `Monolithic', `', `
PUBLIC _MMX_TexRead_B5G5R5_$1_$2
_MMX_TexRead_B5G5R5_$1_$2:
')
d_DoBorder(`$1')
;UINT16 uTexel = ((UINT16*)pBits)[iU | (iV << iShiftU)];
movzx eax, word ptr [edi+2*eax]
;D3DCOLOR Color = RGBA_MAKE(( uTexel >> 7 ) & 0xf8,
; (( uTexel >> 2) & 0xf8 ),
; (( uTexel << 3) & 0xf8 ),
; 0xff);
movd mm1, eax ; Make three more copies of input color
mov edx, eax
movq mm2, mm1
pand mm1, dword ptr MaskGreen555to888 ; MaskGreen555to888 is in memory
psllq mm2, RedShift555to888 ; RedShift should be an immediate
pand mm2, dword ptr MaskRed555to888 ; MaskRed555to888 in memory.
psllq mm1, GreenShift555to888
shl edx, BlueShift555to888
por mm1, mm2
and edx, dword ptr MaskBlue555to888
movd mm2, edx
por mm1, dword ptr SetAlphaTo0xFF
por mm1, mm2
por mm1, dword ptr SetAlphaTo0xFF
d_DoColorKey(`$2')
d_DoBorderMix($1)
punpcklbw mm1, MMWORD PTR Zero
d_DoReturn($3)
;}'')dnl
define(`d_B5G5R5A1', ``
;D3DCOLOR TexRead_B5G5R5A1_$1_$2(INT32 iU, INT32 iV, INT32 iShiftU, PUINT8 pBits, PD3DI_SPANTEX pTex)
;{
ifelse(`$3', `Monolithic', `', `
PUBLIC _MMX_TexRead_B5G5R5A1_$1_$2
_MMX_TexRead_B5G5R5A1_$1_$2:
')
d_DoBorder(`$1')
;INT16 iTexel = ((INT16*)pBits)[iU | (iV << iShiftU)];
movzx eax, word ptr [edi+2*eax]
;D3DCOLOR Color = RGBA_MAKE(( iTexel >> 7 ) & 0xf8,
; (( iTexel >> 2) & 0xf8 ),
; (( iTexel << 3) & 0xf8 ),
; (iTexel >> 15) & 0xff);
movd mm1, eax ; Make two more copies of input color
movq mm2, mm1
mov edx, eax
pand mm1, dword ptr MaskAlpha1555to8888 ; MaskAlpha1555to8888 is in memory
psllq mm2, RedShift1555to8888 ; RedShift should be an immediate
pand mm2, dword ptr MaskRed1555to8888 ; MaskRed1555to8888 in memory.
psllq mm1, AlphaShift1555to8888 ; shift bit to top of dword
psrad mm1, 7 ; copy bit to upper 8 bits.
por mm1, mm2
movd mm2, eax
pslld mm2, BlueShift1555to8888
shl edx, GreenShift1555to8888
pand mm2, MMWORD PTR MaskBlue1555to8888
por mm1, mm2
and edx, dword ptr MaskGreen1555to8888
movd mm2, edx
por mm1, mm2
d_DoColorKey(`$2')
d_DoBorderMix($1)
punpcklbw mm1, MMWORD PTR Zero
d_DoReturn($3)
;}'')dnl
define(`d_B4G4R4', ``
;D3DCOLOR TexRead_B4G4R4_$1_$2(INT32 iU, INT32 iV, INT32 iShiftU, PUINT8 pBits, PD3DI_SPANTEX pTex)
;{
ifelse(`$3', `Monolithic', `', `
PUBLIC _MMX_TexRead_B4G4R4_$1_$2
_MMX_TexRead_B4G4R4_$1_$2:
')
d_DoBorder(`$1')
movzx eax, word ptr [edi+2*eax]
;D3DCOLOR Color = RGBA_MAKE((( iTexel >> 4 ) & 0xf0),
; (( iTexel >> 0) & 0xf0 ),
; (( iTexel << 4) & 0xf0 ),
; 0xff);
movd mm1, eax
pand mm1, MMWORD ptr MaskGreen444to888
psrld mm1, 4
movd mm2, eax
pand mm2, MMWORD PTR MaskRedBlue444to888
punpcklbw mm1, mm2 ; interleave red green and blue.
; Duplicate 4 bits to make 8 bits. Also allows colors to reach full intensity and linear.
movq mm2, mm1
psrld mm2, 4
por mm1, mm2
por mm1, dword ptr SetAlphaTo0xFF ; make alpha value one.
d_DoColorKey(`$2')
d_DoBorderMix($1)
; Need to unpack color for bilinear 16 bit multiplications
punpcklbw mm1, MMWORD PTR Zero
d_DoReturn($3)
;}'')dnl
define(`d_B4G4R4A4', ``
;D3DCOLOR TexRead_B4G4R4A4_$1_$2(INT32 iU, INT32 iV, INT32 iShiftU, PUINT8 pBits, PD3DI_SPANTEX pTex)
;{
ifelse(`$3', `Monolithic', `', `
PUBLIC _MMX_TexRead_B4G4R4A4_$1_$2
_MMX_TexRead_B4G4R4A4_$1_$2:
')
d_DoBorder(`$1')
movzx eax, word ptr [edi+2*eax]
;INT16 iAlpha = ( iTexel >> 12 ) & 0xf;
; Kents Idea:
; An alpha of 0xf becomes 0xff, 0x0 becomes 0x0, and it is monotonic.
; May want to apply this operation to all color channels
; Great Idea.
;D3DCOLOR Color = RGBA_MAKE((( iTexel >> 4 ) & 0xf0),
; (( iTexel >> 0) & 0xf0 ),
; (( iTexel << 4) & 0xf0 ),
; (iAlpha << 4) | iAlpha );
movd mm1, eax
pand mm1, MMWORD PTR MaskAlphaGreen4444to8888
psrld mm1, 4
movd mm2, eax
pand mm2, MMWORD PTR MaskRedBlue4444to8888
punpcklbw mm2, mm1 ; interleave red green and blue.
; Duplicate 4 bits to make 8 bits. Also allows colors to reach full intensity and linear.
movq mm1, mm2
pslld mm2, 4
por mm1, mm2
d_DoColorKey(`$2')
d_DoBorderMix($1)
; BUG BUG border needs to be unpacked.
punpcklbw mm1, MMWORD PTR Zero
d_DoReturn($3)
;}'')dnl
define(`d_L8', ``
;D3DCOLOR TexRead_L8_$1_$2(INT32 iU, INT32 iV, INT32 iShiftU, PUINT8 pBits, PD3DI_SPANTEX pTex)
;{
ifelse(`$2', `Monolithic', `', `
PUBLIC _MMX_TexRead_L8_$1_$2
_MMX_TexRead_L8_$1_$2:
')
d_DoBorder(`$1')
;UINT8 iTexel = pBits[iU | (iV << iShiftU)];
;D3DCOLOR Color = RGBA_MAKE(iTexel,
; iTexel,
; iTexel,
; 0xff );
movzx eax, byte ptr [edi+eax]
movd mm1, eax
punpcklbw mm1,mm1
punpcklwd mm1,mm1
por mm1, dword ptr SetAlphaTo0xFF
d_DoColorKey(`$2')
d_DoBorderMix($1)
; BUG BUG border needs to be unpacked.
punpcklbw mm1, MMWORD PTR Zero
d_DoReturn($3)
;}'')dnl
define(`d_L8A8', ``
;D3DCOLOR TexRead_L8A8_$1_$2(INT32 iU, INT32 iV, INT32 iShiftU, PUINT8 pBits, PD3DI_SPANTEX pTex)
;{
ifelse(`$2', `Monolithic', `', `
PUBLIC _MMX_TexRead_L8A8_$1_$2
_MMX_TexRead_L8A8_$1_$2:
')
d_DoBorder(`$1')
;INT16 iTexel = ((INT16*)pBits)[iU | (iV << iShiftU)];
;INT16 iAlpha = ( iTexel >> 8 ) & 0xff;
;D3DCOLOR Color = RGBA_MAKE(iTexel,
; iTexel,
; iTexel,
; iAlpha );
movzx eax, word ptr [edi+2*eax]
movd mm1, eax
pslld mm1, 16
and eax, dword ptr MaskL8A8ALPHA
movd mm2, eax
por mm1, mm2
pslld mm2, 8
por mm1, mm2
d_DoColorKey(`$2')
d_DoBorderMix($1)
; BUG BUG border needs to be unpacked.
punpcklbw mm1, MMWORD PTR Zero
d_DoReturn($3)
;}'')dnl