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.
 
 
 
 
 
 

378 lines
13 KiB

.486p
.model flat
include offsets.asm
.data
one DWORD 3f800000h
a1 dd 0.47 ; Constants to compute inverse square root
a2 dd 1.47
v255 dd 65280.0 ; 255*256
v1_256 dd 0.00390625 ; 1/255
.code
PUBLIC _Directional2P5S ; Pentium optimized, specular, unit scale
PUBLIC _Directional2P5 ; Pentium optimized, no specular, unit scale
;-------------------------------------------------------------------------
; Jim Blinn's method is used to compute inverse square root s = 1/sqrt(x):
; ONE_AS_INTEGER = 0x3F800000
; float y;
; int tmp = ((ONE_AS_INTEGER << 1 + ONE_AS_INTEGER) - *(long*)&x) >> 1;
; y = *(float*)&tmp;
; s = y*(1.47f - 0.47f*x*y*y);
; Input:
; st(0) = vector length
; y, len = should be defined as DWORD PTR
; a1, a2 = 0.27 and 1.47
; Output:
; st(0) = 1/sqrt(vector length)
;
COMPUTE_ISQRT MACRO
mov eax, 07F000000h+03F800000h ; (ONE_AS_INTEGER<<1) + ONE_AS_INTEGER
fst len ; Vector length (x = len)
sub eax, len
sar eax, 1
mov y, eax ; y
fmul a1 ; len*0.47 x y z
fld y ; y len*0.47 x y z
fld st(0) ; y y len*0.47 x y z
fmul st(0), st(1) ; y*y y len*0.47 x y z
fld a2 ; 1.47 y*y y len*0.47 x y z
fxch st(3) ; len*0.47 y*y y 1.47 x y z
fmulp st(1), st(0) ; len*0.47*y*y y 1.47 x y z
fsubp st(2), st(0) ; y aaa x y z
fmulp st(1), st(0) ; 1/sqrt(len) x y z
ENDM
;-------------------------------------------------------------------------
; Exit from the function
;
EXIT_FUNC MACRO
pop edx
pop ebx
pop ecx
mov esp, ebp
pop ebp
ret
ENDM
;-------------------------------------------------------------------------
; void Directional2P5S(LPD3DFE_PROCESSVERTICES pv,
; D3DI_LIGHT *light,
; D3DLIGHTINGELEMENT *vertex)
; Limitations:
; Transformation matrix should not have a scale
; Specular is always computed
; Optimized for Pentium
;
; Input:
; [esp + 4] - pv
; [esp + 8] - light
; [esp + 12] - vertex
; Output:
; pv.lighting.diffuse and pv.lighting.specular are updated
; pv.lighting.specularComputed is set to 1, if there is specular component
;
pv equ DWORD PTR [ebp + 8]
light equ DWORD PTR [ebp + 12]
vertex equ DWORD PTR [ebp + 16]
dot equ DWORD PTR [ebp - 4]
y equ DWORD PTR [ebp - 8] ; temporary variable to compute
; inverse square root
len equ DWORD PTR [ebp - 12] ; vector length
_Directional2P5S PROC NEAR
push ebp
mov ebp, esp
sub esp, 12
push ecx
mov ecx, light
push ebx
mov ebx, vertex
; dot = VecDot(light->model_direction, in->dvNormal)
fld DWORD PTR [ecx + D3DI_LIGHT_model_direction + _X_]
fmul DWORD PTR [ebx + D3DLIGHTINGELEMENT_dvNormal + _X_]
fld DWORD PTR [ecx + D3DI_LIGHT_model_direction + _Y_]
fmul DWORD PTR [ebx + D3DLIGHTINGELEMENT_dvNormal + _Y_]
fld DWORD PTR [ecx + D3DI_LIGHT_model_direction + _Z_]
fmul DWORD PTR [ebx + D3DLIGHTINGELEMENT_dvNormal + _Z_] ; z y x
fxch st(2) ; x y z
faddp st(1), st ; x+y z
push edx
faddp st(1), st ; dot
mov edx, pv
fst dot
cmp dot, 0
jle exit1
; ldrv.diffuse.r += light->local_diffR * dot;
; ldrv.diffuse.g += light->local_diffG * dot;
; ldrv.diffuse.b += light->local_diffB * dot;
fld DWORD PTR [ecx + D3DI_LIGHT_local_diffR]
fmul st(0), st(1)
fld DWORD PTR [ecx + D3DI_LIGHT_local_diffG]
fmul st(0), st(2)
fld DWORD PTR [ecx + D3DI_LIGHT_local_diffB]
fmulp st(3), st(0) ; g r b
fxch st(1) ; r g b
fadd DWORD PTR [edx + PV_LIGHT_diffuse + _R_]
fxch st(1) ; g r b
fadd DWORD PTR [edx + PV_LIGHT_diffuse + _G_]
fxch st(2) ; b r g
fadd DWORD PTR [edx + PV_LIGHT_diffuse + _B_]
fxch st(1) ; r b g
fstp DWORD PTR [edx + PV_LIGHT_diffuse + _R_]
fstp DWORD PTR [edx + PV_LIGHT_diffuse + _B_]
fstp DWORD PTR [edx + PV_LIGHT_diffuse + _G_]
; if (light->flags & D3DLIGHTI_COMPUTE_SPECULAR)
; test DWORD PTR [ecx + D3DI_LIGHT_flags], D3DLIGHTI_COMPUTE_SPECULAR
; jz exit
; VecSub(in->dvPosition, light->model_eye, eye);
fld DWORD PTR [ebx + D3DLIGHTINGELEMENT_dvPosition + _X_]
fsub DWORD PTR [ecx + D3DI_LIGHT_model_eye + _X_]
fld DWORD PTR [ebx + D3DLIGHTINGELEMENT_dvPosition + _Y_]
fsub DWORD PTR [ecx + D3DI_LIGHT_model_eye + _Y_]
fld DWORD PTR [ebx + D3DLIGHTINGELEMENT_dvPosition + _Z_]
fsub DWORD PTR [ecx + D3DI_LIGHT_model_eye + _Z_] ; z y x
fxch st(2) ; x y z
; VecNormalizeFast(eye);
;
; Compute vector length. Leave vector on the FPU stack, because we will use it
;
fld st(1) ; x x y z
fmul st(0), st(0) ; x*x x y z
fld st(2)
fmul st(0), st(0) ; y*y x*x x y z
fld st(4)
fmul st(0), st(0) ; z*z y*y x*x x y z
fxch st(2) ; x y z
faddp st(1), st ; x + y, z
faddp st(1), st ; len x y z
COMPUTE_ISQRT ; st(0) will be 1/sqrt(len)
; Start normalizing the eye vector
fmul st(1), st(0)
fmul st(2), st(0)
fmulp st(3), st(0) ; x y z Normalized "eye" vector
; Calc halfway vector
; VecSub(light->model_direction, eye, h);
;
fsubr DWORD PTR [ecx + D3DI_LIGHT_model_direction + _X_]
fxch st(1) ; y x z
fsubr DWORD PTR [ecx + D3DI_LIGHT_model_direction + _Y_]
fxch st(2) ; z x y
fsubr DWORD PTR [ecx + D3DI_LIGHT_model_direction + _Z_]
fxch st(1) ; x z y
; dot = VecDot(h, in->dvNormal);
fld st(0)
fmul DWORD PTR [ebx + D3DLIGHTINGELEMENT_dvNormal + _X_]
fld st(3)
fmul DWORD PTR [ebx + D3DLIGHTINGELEMENT_dvNormal + _Y_]
fld st(3) ; z*Nz y*Ny x*Nx x z y
fmul DWORD PTR [ebx + D3DLIGHTINGELEMENT_dvNormal + _Z_]
fxch st(2)
faddp st(1), st(0)
faddp st(1), st(0) ; dot x z y
fstp dot ; x z y
; if (FLOAT_GTZ(dot))
cmp dot, 0
jle exit2
; dot *= ISQRTF(VecLenSq(h));
;
fmul st(0), st(0) ; x*x y z
fxch st(1) ; y x*x z
fmul st(0), st(0) ; y*y x*x z
fxch st(2)
fmul st(0), st(0) ; z*z y*y x*x
fxch st(2) ;
faddp st(1), st ; x + y, z
faddp st(1), st ; len
COMPUTE_ISQRT ; st(0) will be 1/sqrt(len)
fmul dot ; dot
mov eax, [edx + PV_LIGHT_specThreshold]
fst dot
; if (FLOAT_CMP_POS(dot, >=, ldrv.specThreshold))
cmp dot, eax
jle exit1
; power = COMPUTE_DOT_POW(&ldrv, dot);
; int indx;
; float v;
; dot *= 255.0f;
; indx = (int)dot;
; dot -= indx;
; ldrv->specularComputed = TRUE;
; v = ldrv->currentSpecTable[indx];
; return v + (ldrv->currentSpecTable[indx+1] - v)*dot;
;
fmul v255 ; dot*255*256
push ebx
fistp dot ; indx << 8. 8 bits used to compute dot fraction
mov ebx, dot ;
and dot, 0FFh ; fractional part of dot
shr ebx, 8 ; Table index
mov eax, [edx + PV_LIGHT_currentSpecTable]
lea eax, [eax + ebx*4]
fild dot ; fractional part of dot
fmul v1_256 ; dot*1/256 -> integer fraction to floating point
fld DWORD PTR [eax + 4] ; currentSpecTable[indx+1]
fsub DWORD PTR [eax] ; currentSpecTable[indx]
fmulp st(1), st(0) ; dot*(v2-v1)
mov DWORD PTR [edx + PV_LIGHT_specularComputed], 1
pop ebx
fadd DWORD PTR [eax]
; power = COMPUTE_DOT_POW(&ldrv, dot);
; This is an alternative method to compute x power y.
; Jim Blinn's method is used:
; int tmp = (int)(power*(*(long*)&dot - ONE_AS_INTEGER)) + ONE_AS_INTEGER;
; dot ^ power = *(float*)&tmp;
;
; sub dot, 03F800000h
; fstp st(0) ; Remove dot
; fld DWORD PTR [edx + PV_LIGHT_material_power]
; fimul dot
; fistp dot
; mov DWORD PTR [edx + PV_LIGHT_specularComputed], 1
; add dot, 03F800000h
; fld dot
; ldrv.specular.r += light->local_specR * power;
; ldrv.specular.g += light->local_specG * power;
; ldrv.specular.b += light->local_specB * power;
;
fld DWORD PTR [ecx + D3DI_LIGHT_local_specR]
fmul st(0), st(1)
fld DWORD PTR [ecx + D3DI_LIGHT_local_specG]
fmul st(0), st(2)
fld DWORD PTR [ecx + D3DI_LIGHT_local_specB]
fmulp st(3), st(0) ; g r b
fxch st(1) ; r g b
fadd DWORD PTR [edx + PV_LIGHT_specular + _R_]
fxch st(1) ; g r b
fadd DWORD PTR [edx + PV_LIGHT_specular + _G_]
fxch st(2) ; b r g
fadd DWORD PTR [edx + PV_LIGHT_specular + _G_]
fxch st(1) ; r b g
fstp DWORD PTR [edx + PV_LIGHT_specular + _R_]
fstp DWORD PTR [edx + PV_LIGHT_specular + _B_]
fstp DWORD PTR [edx + PV_LIGHT_specular + _G_]
exit:
EXIT_FUNC
exit1:
fstp st(0)
EXIT_FUNC
exit2:
fstp st(0)
fstp st(0)
fstp st(0)
EXIT_FUNC
_Directional2P5S ENDP
;-------------------------------------------------------------------------
; void Directional2P5(LPD3DFE_PROCESSVERTICES pv,
; D3DI_LIGHT *light,
; D3DLIGHTINGELEMENT *vertex)
; Limitations:
; Transformation matrix should not have a scale
; Only diffuse component is computed
; Optimized for Pentium
;
; Input:
; [esp + 4] - pv
; [esp + 8] - light
; [esp + 12] - vertex
; Output:
; pv.lighting.diffuse is updated
;
pv equ DWORD PTR [ebp + 8]
light equ DWORD PTR [ebp + 12]
vertex equ DWORD PTR [ebp + 16]
dot equ DWORD PTR [ebp - 4]
y equ DWORD PTR [ebp - 8] ; temporary variable to compute
; inverse square root
len equ DWORD PTR [ebp - 12] ; vector length
_Directional2P5 PROC NEAR
push ebp
mov ebp, esp
sub esp, 12
push ecx
mov ecx, light
push ebx
mov ebx, vertex
; dot = VecDot(light->model_direction, in->dvNormal)
fld DWORD PTR [ecx + D3DI_LIGHT_model_direction + _X_]
fmul DWORD PTR [ebx + D3DLIGHTINGELEMENT_dvNormal + _X_]
fld DWORD PTR [ecx + D3DI_LIGHT_model_direction + _Y_]
fmul DWORD PTR [ebx + D3DLIGHTINGELEMENT_dvNormal + _Y_]
fld DWORD PTR [ecx + D3DI_LIGHT_model_direction + _Z_]
fmul DWORD PTR [ebx + D3DLIGHTINGELEMENT_dvNormal + _Z_] ; z y x
fxch st(2) ; x y z
faddp st(1), st ; x+y z
push edx
faddp st(1), st ; dot
mov edx, pv
fst dot
cmp dot, 0
jle exit3
; ldrv.diffuse.r += light->local_diffR * dot;
; ldrv.diffuse.g += light->local_diffG * dot;
; ldrv.diffuse.b += light->local_diffB * dot;
fld DWORD PTR [ecx + D3DI_LIGHT_local_diffR]
fmul st(0), st(1)
fld DWORD PTR [ecx + D3DI_LIGHT_local_diffG]
fmul st(0), st(2)
fld DWORD PTR [ecx + D3DI_LIGHT_local_diffB]
fmulp st(3), st(0) ; g r b
fxch st(1) ; r g b
fadd DWORD PTR [edx + PV_LIGHT_diffuse + _R_]
fxch st(1) ; g r b
fadd DWORD PTR [edx + PV_LIGHT_diffuse + _G_]
fxch st(2) ; b r g
fadd DWORD PTR [edx + PV_LIGHT_diffuse + _B_]
fxch st(1) ; r b g
fstp DWORD PTR [edx + PV_LIGHT_diffuse + _R_]
fstp DWORD PTR [edx + PV_LIGHT_diffuse + _B_]
fstp DWORD PTR [edx + PV_LIGHT_diffuse + _G_]
EXIT_FUNC
exit3:
fstp st(0)
EXIT_FUNC
_Directional2P5 ENDP
end