Decouple gameplay from presentation and preserve signed movement fractions. Separate cinematic camera ownership with safe body handoff and transactional current-room restarts. Resample input latches on focus regain, discard modal timing debt, and attach cinematic lighting to the view to match editor preview. Verify editor 137/137 and ASM 288/288, cinematic traces, RGB bake and IPC framebuffer parity without changing project assets.
835 lines
17 KiB
PHP
835 lines
17 KiB
PHP
; Versioned authored lighting, RGB shading and exact occlusion traversal.
|
|
.code
|
|
InitLightingSystem PROTO
|
|
BakeMapLighting PROTO
|
|
UpdateDynamicLights PROTO
|
|
AddLightSource PROTO :DWORD,:DWORD,:DWORD,:DWORD,:DWORD,:DWORD,:DWORD
|
|
SpawnExplosionLight PROTO :DWORD,:DWORD
|
|
SpawnMuzzleFlashLight PROTO :DWORD,:DWORD
|
|
CastLightRay PROTO :DWORD,:DWORD,:DWORD,:DWORD
|
|
ComputeWallLightLevel PROTO :DWORD,:DWORD,:DWORD,:DWORD,:DWORD,:DWORD,:DWORD,:DWORD,:DWORD,:DWORD,:DWORD
|
|
ComputeSpriteLight PROTO :DWORD,:DWORD,:DWORD
|
|
SamplePointLighting PROTO :DWORD,:DWORD,:DWORD,:DWORD
|
|
LightCellFree PROTO :DWORD,:DWORD
|
|
RefreshLightGrid PROTO
|
|
|
|
ValidateLightingData PROC uses ebx ecx edx esi, settings:DWORD,sources:DWORD,count:DWORD
|
|
mov esi,settings
|
|
cmp DWORD PTR [esi],2
|
|
ja vl_invalid
|
|
cmp DWORD PTR [esi+4],255
|
|
ja vl_invalid
|
|
cmp DWORD PTR [esi+8],1
|
|
ja vl_invalid
|
|
cmp DWORD PTR [esi+12],32
|
|
jb vl_invalid
|
|
cmp DWORD PTR [esi+12],2048
|
|
ja vl_invalid
|
|
cmp DWORD PTR [esi+16],255
|
|
ja vl_invalid
|
|
cmp DWORD PTR [esi+20],1
|
|
jb vl_invalid
|
|
cmp DWORD PTR [esi+20],96
|
|
ja vl_invalid
|
|
cmp DWORD PTR [esi+24],1
|
|
jne vl_invalid
|
|
cmp DWORD PTR [esi+28],0
|
|
jne vl_invalid
|
|
cmp count,13
|
|
ja vl_invalid
|
|
mov ecx,count
|
|
mov esi,sources
|
|
vl_source:
|
|
test ecx,ecx
|
|
jz vl_valid
|
|
cmp [esi].LightSource.x,2048
|
|
jae vl_invalid
|
|
cmp [esi].LightSource.y,2048
|
|
jae vl_invalid
|
|
cmp [esi].LightSource.radius,1
|
|
jb vl_invalid
|
|
cmp [esi].LightSource.radius,2048
|
|
ja vl_invalid
|
|
cmp [esi].LightSource.intensity,255
|
|
ja vl_invalid
|
|
cmp [esi].LightSource.curIntensity,255
|
|
ja vl_invalid
|
|
cmp [esi].LightSource.lightType,1
|
|
jbe vl_type_ok
|
|
cmp [esi].LightSource.lightType,4
|
|
jne vl_invalid
|
|
vl_type_ok:
|
|
mov eax,[esi].LightSource.flags
|
|
and eax,0FFFFFFF8h
|
|
jnz vl_invalid
|
|
test [esi].LightSource.color,0FF000000h
|
|
jnz vl_invalid
|
|
add esi,40
|
|
dec ecx
|
|
jmp vl_source
|
|
vl_valid:
|
|
mov eax,1
|
|
ret
|
|
vl_invalid:
|
|
xor eax,eax
|
|
ret
|
|
ValidateLightingData ENDP
|
|
|
|
InitLightingSystem PROC uses eax ecx edi
|
|
mov lightingMode,0
|
|
mov ambientLightLevel,40
|
|
mov isFlashlightOn,1
|
|
mov flashlightRadius,384
|
|
mov flashlightIntensity,240
|
|
mov flashlightConeAngle,45
|
|
mov authoredLightCount,0
|
|
mov lightingTick,0
|
|
mov edi,OFFSET lightSources
|
|
mov ecx,MAX_LIGHTS*10
|
|
xor eax,eax
|
|
rep stosd
|
|
mov edi,OFFSET lightGridRGB
|
|
mov ecx,MAP_SIZE
|
|
mov eax,00282828h
|
|
rep stosd
|
|
call RefreshLightGrid
|
|
ret
|
|
InitLightingSystem ENDP
|
|
|
|
CommitLightingData PROC uses eax ecx esi edi,settings:DWORD,sources:DWORD,count:DWORD,rgb:DWORD
|
|
call InitLightingSystem
|
|
mov esi,settings
|
|
lodsd
|
|
mov lightingMode,eax
|
|
lodsd
|
|
mov ambientLightLevel,eax
|
|
lodsd
|
|
mov isFlashlightOn,eax
|
|
lodsd
|
|
mov flashlightRadius,eax
|
|
lodsd
|
|
mov flashlightIntensity,eax
|
|
lodsd
|
|
mov flashlightConeAngle,eax
|
|
mov esi,sources
|
|
mov edi,OFFSET lightSources+40
|
|
mov ecx,count
|
|
mov authoredLightCount,ecx
|
|
imul ecx,10
|
|
rep movsd
|
|
mov esi,rgb
|
|
mov edi,OFFSET lightGridRGB
|
|
mov ecx,MAP_SIZE
|
|
rep movsd
|
|
call RefreshLightGrid
|
|
ret
|
|
CommitLightingData ENDP
|
|
|
|
LightCellFree PROC uses edx,x:DWORD,y:DWORD
|
|
cmp x,32
|
|
jae lcf_no
|
|
cmp y,32
|
|
jae lcf_no
|
|
mov eax,y
|
|
shl eax,5
|
|
add eax,x
|
|
movzx eax,BYTE PTR [gameMap+eax]
|
|
cmp eax,0
|
|
je lcf_yes
|
|
cmp eax,6
|
|
je lcf_yes
|
|
cmp eax,10
|
|
je lcf_yes
|
|
lcf_no:
|
|
xor eax,eax
|
|
ret
|
|
lcf_yes:
|
|
mov eax,1
|
|
ret
|
|
LightCellFree ENDP
|
|
|
|
; Supercover traversal: test both sides when crossing an exact grid corner.
|
|
CastLightRay PROC uses ebx ecx edx esi edi,x1:DWORD,y1:DWORD,x2:DWORD,y2:DWORD
|
|
LOCAL cellX:DWORD,cellY:DWORD,ex:DWORD,ey:DWORD,deltaX:DWORD,deltaY:DWORD,sx:DWORD,sy:DWORD,nx:DWORD,ny:DWORD,axv:DWORD
|
|
mov eax,x1
|
|
or eax,y1
|
|
or eax,x2
|
|
or eax,y2
|
|
test eax,0FFFFF800h
|
|
jnz lr_blocked
|
|
mov eax,x1
|
|
shr eax,6
|
|
mov cellX,eax
|
|
mov eax,y1
|
|
shr eax,6
|
|
mov cellY,eax
|
|
mov eax,x2
|
|
shr eax,6
|
|
mov ex,eax
|
|
mov eax,y2
|
|
shr eax,6
|
|
mov ey,eax
|
|
mov sx,1
|
|
mov eax,x2
|
|
sub eax,x1
|
|
jns lr_dx
|
|
neg eax
|
|
mov sx,-1
|
|
lr_dx:
|
|
mov deltaX,eax
|
|
mov sy,1
|
|
mov eax,y2
|
|
sub eax,y1
|
|
jns lr_dy
|
|
neg eax
|
|
mov sy,-1
|
|
lr_dy:
|
|
mov deltaY,eax
|
|
mov eax,cellX
|
|
shl eax,6
|
|
cmp sx,1
|
|
jne lr_nx_neg
|
|
add eax,64
|
|
sub eax,x1
|
|
jmp lr_nx
|
|
lr_nx_neg:
|
|
neg eax
|
|
add eax,x1
|
|
lr_nx:
|
|
mov nx,eax
|
|
mov eax,cellY
|
|
shl eax,6
|
|
cmp sy,1
|
|
jne lr_ny_neg
|
|
add eax,64
|
|
sub eax,y1
|
|
jmp lr_ny
|
|
lr_ny_neg:
|
|
neg eax
|
|
add eax,y1
|
|
lr_ny:
|
|
mov ny,eax
|
|
mov edi,65
|
|
lr_step:
|
|
mov eax,cellX
|
|
cmp eax,ex
|
|
jne lr_cross
|
|
mov eax,cellY
|
|
cmp eax,ey
|
|
je lr_end
|
|
lr_cross:
|
|
mov eax,3FFFFFFFh
|
|
cmp deltaX,0
|
|
je lr_a
|
|
mov eax,nx
|
|
imul eax,deltaY
|
|
lr_a:
|
|
mov axv,eax
|
|
mov eax,3FFFFFFFh
|
|
cmp deltaY,0
|
|
je lr_b
|
|
mov eax,ny
|
|
imul eax,deltaX
|
|
lr_b:
|
|
cmp axv,eax
|
|
jb lr_x
|
|
ja lr_y
|
|
mov eax,cellX
|
|
add eax,sx
|
|
invoke LightCellFree,eax,cellY
|
|
test eax,eax
|
|
jz lr_blocked
|
|
mov eax,cellY
|
|
add eax,sy
|
|
invoke LightCellFree,cellX,eax
|
|
test eax,eax
|
|
jz lr_blocked
|
|
mov eax,sx
|
|
add cellX,eax
|
|
add nx,64
|
|
lr_y:
|
|
mov eax,sy
|
|
add cellY,eax
|
|
add ny,64
|
|
jmp lr_test
|
|
lr_x:
|
|
mov eax,sx
|
|
add cellX,eax
|
|
add nx,64
|
|
lr_test:
|
|
invoke LightCellFree,cellX,cellY
|
|
test eax,eax
|
|
jz lr_blocked
|
|
dec edi
|
|
jnz lr_step
|
|
lr_blocked:
|
|
xor eax,eax
|
|
ret
|
|
lr_end:
|
|
invoke LightCellFree,cellX,cellY
|
|
ret
|
|
CastLightRay ENDP
|
|
|
|
LightDistance PROC uses ebx edx,deltaX:DWORD,deltaY:DWORD
|
|
mov eax,deltaX
|
|
cdq
|
|
xor eax,edx
|
|
sub eax,edx
|
|
mov ebx,eax
|
|
mov eax,deltaY
|
|
cdq
|
|
xor eax,edx
|
|
sub eax,edx
|
|
cmp eax,ebx
|
|
jae ld_max
|
|
xchg eax,ebx
|
|
ld_max:
|
|
lea ebx,[ebx+ebx*2]
|
|
shr ebx,3
|
|
add eax,ebx
|
|
ret
|
|
LightDistance ENDP
|
|
|
|
AddLightColor PROC uses eax ebx ecx edx,color:DWORD,amount:DWORD
|
|
mov ebx,255
|
|
mov eax,color
|
|
and eax,255
|
|
imul eax,amount
|
|
xor edx,edx
|
|
div ebx
|
|
add lightAccumB,eax
|
|
mov eax,color
|
|
shr eax,8
|
|
and eax,255
|
|
imul eax,amount
|
|
xor edx,edx
|
|
div ebx
|
|
add lightAccumG,eax
|
|
mov eax,color
|
|
shr eax,16
|
|
and eax,255
|
|
imul eax,amount
|
|
xor edx,edx
|
|
div ebx
|
|
add lightAccumR,eax
|
|
ret
|
|
AddLightColor ENDP
|
|
|
|
PointLightAmount PROC uses ebx ecx edx esi,source:DWORD,x:DWORD,y:DWORD
|
|
LOCAL distance:DWORD
|
|
mov esi,source
|
|
mov eax,x
|
|
sub eax,[esi].LightSource.x
|
|
mov ecx,y
|
|
sub ecx,[esi].LightSource.y
|
|
invoke LightDistance,eax,ecx
|
|
mov distance,eax
|
|
cmp eax,[esi].LightSource.radius
|
|
jae pla_zero
|
|
test [esi].LightSource.flags,LIGHT_FLAG_SHADOWS
|
|
jz pla_visible
|
|
invoke CastLightRay,[esi].LightSource.x,[esi].LightSource.y,x,y
|
|
test eax,eax
|
|
jz pla_zero
|
|
pla_visible:
|
|
mov eax,[esi].LightSource.radius
|
|
sub eax,distance
|
|
imul eax,[esi].LightSource.curIntensity
|
|
xor edx,edx
|
|
div [esi].LightSource.radius
|
|
ret
|
|
pla_zero:
|
|
xor eax,eax
|
|
ret
|
|
PointLightAmount ENDP
|
|
|
|
RefreshLightGrid PROC uses eax ebx ecx edx esi edi
|
|
mov esi,OFFSET lightGridRGB
|
|
mov edi,OFFSET lightGrid
|
|
mov ecx,MAP_SIZE
|
|
rlg_loop:
|
|
lodsd
|
|
mov edx,eax
|
|
and eax,255
|
|
mov ebx,edx
|
|
shr ebx,8
|
|
and ebx,255
|
|
add eax,ebx
|
|
shr edx,16
|
|
and edx,255
|
|
add eax,edx
|
|
xor edx,edx
|
|
mov ebx,3
|
|
div ebx
|
|
stosb
|
|
loop rlg_loop
|
|
ret
|
|
RefreshLightGrid ENDP
|
|
|
|
PackBakedRGB PROC uses ebx edx
|
|
mov eax,lightAccumR
|
|
cmp eax,255
|
|
jbe @F
|
|
mov eax,255
|
|
@@:
|
|
shl eax,16
|
|
mov ebx,eax
|
|
mov eax,lightAccumG
|
|
cmp eax,255
|
|
jbe @F
|
|
mov eax,255
|
|
@@:
|
|
shl eax,8
|
|
or ebx,eax
|
|
mov eax,lightAccumB
|
|
cmp eax,255
|
|
jbe @F
|
|
mov eax,255
|
|
@@:
|
|
or eax,ebx
|
|
ret
|
|
PackBakedRGB ENDP
|
|
|
|
AccumulateBakedCell PROC uses eax ebx ecx edx,x:DWORD,y:DWORD,weight:DWORD
|
|
invoke LightCellFree,x,y
|
|
test eax,eax
|
|
jz abc_done
|
|
mov eax,y
|
|
shl eax,5
|
|
add eax,x
|
|
mov edx,[lightGridRGB+eax*4]
|
|
mov eax,edx
|
|
and eax,255
|
|
imul eax,weight
|
|
add lightAccumB,eax
|
|
mov eax,edx
|
|
shr eax,8
|
|
and eax,255
|
|
imul eax,weight
|
|
add lightAccumG,eax
|
|
shr edx,16
|
|
imul edx,weight
|
|
add lightAccumR,edx
|
|
mov eax,weight
|
|
add lightWeight,eax
|
|
abc_done:
|
|
ret
|
|
AccumulateBakedCell ENDP
|
|
|
|
BakeMapLighting PROC uses ebx ecx edx esi edi
|
|
LOCAL index:DWORD,x:DWORD,y:DWORD
|
|
mov index,0
|
|
bl_cell:
|
|
mov eax,index
|
|
and eax,31
|
|
mov x,eax
|
|
mov eax,index
|
|
shr eax,5
|
|
mov y,eax
|
|
mov eax,ambientLightLevel
|
|
mov lightAccumR,eax
|
|
mov lightAccumG,eax
|
|
mov lightAccumB,eax
|
|
invoke LightCellFree,x,y
|
|
test eax,eax
|
|
jz bl_store
|
|
mov eax,x
|
|
shl eax,6
|
|
add eax,32
|
|
mov x,eax
|
|
mov eax,y
|
|
shl eax,6
|
|
add eax,32
|
|
mov y,eax
|
|
mov esi,OFFSET lightSources+40
|
|
mov edi,13
|
|
bl_source:
|
|
test [esi].LightSource.flags,LIGHT_FLAG_ACTIVE
|
|
jz bl_next_source
|
|
cmp [esi].LightSource.lightType,LIGHT_TYPE_STATIC
|
|
jne bl_next_source
|
|
mov eax,[esi].LightSource.intensity
|
|
push [esi].LightSource.curIntensity
|
|
mov [esi].LightSource.curIntensity,eax
|
|
invoke PointLightAmount,esi,x,y
|
|
pop [esi].LightSource.curIntensity
|
|
invoke AddLightColor,[esi].LightSource.color,eax
|
|
bl_next_source:
|
|
add esi,40
|
|
dec edi
|
|
jnz bl_source
|
|
bl_store:
|
|
call PackBakedRGB
|
|
mov ebx,index
|
|
mov [lightGridRGB+ebx*4],eax
|
|
inc index
|
|
cmp index,MAP_SIZE
|
|
jb bl_cell
|
|
; Smooth out of place, without averaging through wall cells.
|
|
mov index,0
|
|
bl_smooth:
|
|
mov ebx,index
|
|
mov eax,[lightGridRGB+ebx*4]
|
|
mov [lightSmoothRGB+ebx*4],eax
|
|
mov eax,ebx
|
|
and eax,31
|
|
mov x,eax
|
|
shr ebx,5
|
|
mov y,ebx
|
|
invoke LightCellFree,x,y
|
|
test eax,eax
|
|
jz bl_next_smooth
|
|
mov lightAccumR,0
|
|
mov lightAccumG,0
|
|
mov lightAccumB,0
|
|
mov lightWeight,0
|
|
invoke AccumulateBakedCell,x,y,2
|
|
mov eax,x
|
|
dec eax
|
|
invoke AccumulateBakedCell,eax,y,1
|
|
mov eax,x
|
|
inc eax
|
|
invoke AccumulateBakedCell,eax,y,1
|
|
mov eax,y
|
|
dec eax
|
|
invoke AccumulateBakedCell,x,eax,1
|
|
mov eax,y
|
|
inc eax
|
|
invoke AccumulateBakedCell,x,eax,1
|
|
mov eax,lightAccumR
|
|
xor edx,edx
|
|
div lightWeight
|
|
mov lightAccumR,eax
|
|
mov eax,lightAccumG
|
|
xor edx,edx
|
|
div lightWeight
|
|
mov lightAccumG,eax
|
|
mov eax,lightAccumB
|
|
xor edx,edx
|
|
div lightWeight
|
|
mov lightAccumB,eax
|
|
call PackBakedRGB
|
|
mov ebx,index
|
|
mov [lightSmoothRGB+ebx*4],eax
|
|
bl_next_smooth:
|
|
inc index
|
|
cmp index,MAP_SIZE
|
|
jb bl_smooth
|
|
mov esi,OFFSET lightSmoothRGB
|
|
mov edi,OFFSET lightGridRGB
|
|
mov ecx,MAP_SIZE
|
|
rep movsd
|
|
call RefreshLightGrid
|
|
ret
|
|
BakeMapLighting ENDP
|
|
|
|
UpdateDynamicLights PROC uses eax ebx ecx edx esi
|
|
inc lightingTick
|
|
mov esi,OFFSET lightSources+40
|
|
mov ecx,1
|
|
udl_next:
|
|
test [esi].LightSource.flags,LIGHT_FLAG_ACTIVE
|
|
jz udl_skip
|
|
cmp [esi].LightSource.lightType,LIGHT_TYPE_BURST
|
|
je udl_burst
|
|
mov eax,[esi].LightSource.intensity
|
|
cmp [esi].LightSource.lightType,LIGHT_TYPE_STATIC
|
|
je udl_store
|
|
cmp [esi].LightSource.lightType,LIGHT_TYPE_PULSE
|
|
jne udl_flicker
|
|
mov edx,lightingTick
|
|
shl edx,2
|
|
add edx,ecx
|
|
and edx,511
|
|
mov ebx,[tableSin+edx*4]
|
|
sar ebx,1
|
|
add ebx,98304
|
|
imul eax,ebx
|
|
sar eax,17
|
|
udl_flicker:
|
|
test [esi].LightSource.flags,LIGHT_FLAG_FLICKER
|
|
jz udl_store
|
|
mov edx,lightingTick
|
|
shr edx,2
|
|
imul edx,1103515245
|
|
imul ebx,ecx,12345
|
|
add edx,ebx
|
|
shr edx,16
|
|
and edx,15
|
|
sub edx,7
|
|
add eax,edx
|
|
cmp eax,0
|
|
jge @F
|
|
xor eax,eax
|
|
@@:
|
|
cmp eax,255
|
|
jle udl_store
|
|
mov eax,255
|
|
jmp udl_store
|
|
udl_burst:
|
|
mov eax,[esi].LightSource.curIntensity
|
|
sub eax,[esi].LightSource.decaySpeed
|
|
jg udl_store
|
|
xor eax,eax
|
|
mov [esi].LightSource.flags,0
|
|
udl_store:
|
|
mov [esi].LightSource.curIntensity,eax
|
|
udl_skip:
|
|
add esi,40
|
|
inc ecx
|
|
cmp ecx,16
|
|
jb udl_next
|
|
ret
|
|
UpdateDynamicLights ENDP
|
|
|
|
SamplePointLighting PROC uses ebx ecx edx esi edi,x:DWORD,y:DWORD,distance:DWORD,side:DWORD
|
|
LOCAL forward:DWORD,lateral:DWORD,beam:DWORD,atten:DWORD,fog:DWORD
|
|
LOCAL originX:DWORD,originY:DWORD,originAngle:DWORD
|
|
; Camera-attached flashlight. Cinematics never move the gameplay body, but
|
|
; use the same lighting origin as the editor's camera-only preview packet.
|
|
mov eax,playerX
|
|
mov originX,eax
|
|
mov eax,playerY
|
|
mov originY,eax
|
|
mov eax,playerAngle
|
|
mov originAngle,eax
|
|
cmp isCutsceneActive,0
|
|
je spl_origin_ready
|
|
mov eax,csCameraX
|
|
mov originX,eax
|
|
mov eax,csCameraY
|
|
mov originY,eax
|
|
mov eax,csCameraAngle
|
|
mov originAngle,eax
|
|
spl_origin_ready:
|
|
mov eax,256
|
|
mov lightRed,eax
|
|
mov lightGreen,eax
|
|
mov lightBlue,eax
|
|
cmp lightingMode,0
|
|
je spl_done
|
|
mov eax,x
|
|
sar eax,6
|
|
and eax,31
|
|
mov edx,y
|
|
sar edx,6
|
|
and edx,31
|
|
shl edx,5
|
|
add eax,edx
|
|
mov eax,[lightGridRGB+eax*4]
|
|
mov edx,eax
|
|
and eax,255
|
|
mov lightAccumB,eax
|
|
mov eax,edx
|
|
shr eax,8
|
|
and eax,255
|
|
mov lightAccumG,eax
|
|
shr edx,16
|
|
mov lightAccumR,edx
|
|
cmp lightingMode,2
|
|
jne spl_fog
|
|
mov esi,OFFSET lightSources+40
|
|
mov edi,15
|
|
spl_source:
|
|
test [esi].LightSource.flags,LIGHT_FLAG_ACTIVE
|
|
jz spl_next
|
|
cmp [esi].LightSource.lightType,LIGHT_TYPE_STATIC
|
|
je spl_next
|
|
cmp [esi].LightSource.radius,0
|
|
jle spl_next
|
|
invoke PointLightAmount,esi,x,y
|
|
invoke AddLightColor,[esi].LightSource.color,eax
|
|
spl_next:
|
|
add esi,40
|
|
dec edi
|
|
jnz spl_source
|
|
cmp isFlashlightOn,0
|
|
je spl_fog
|
|
mov eax,x
|
|
sub eax,originX
|
|
mov ebx,y
|
|
sub ebx,originY
|
|
invoke LightDistance,eax,ebx
|
|
cmp eax,flashlightRadius
|
|
jae spl_fog
|
|
mov edx,flashlightRadius
|
|
sub edx,eax
|
|
mov eax,edx
|
|
imul eax,flashlightIntensity
|
|
xor edx,edx
|
|
div flashlightRadius
|
|
mov atten,eax
|
|
mov ecx,originAngle
|
|
and ecx,511
|
|
mov eax,x
|
|
sub eax,originX
|
|
imul [tableCos+ecx*4]
|
|
shrd eax,edx,16
|
|
mov forward,eax
|
|
mov eax,y
|
|
sub eax,originY
|
|
imul [tableSin+ecx*4]
|
|
shrd eax,edx,16
|
|
add forward,eax
|
|
cmp forward,0
|
|
jle spl_fog
|
|
mov eax,y
|
|
sub eax,originY
|
|
imul [tableCos+ecx*4]
|
|
shrd eax,edx,16
|
|
mov lateral,eax
|
|
mov eax,x
|
|
sub eax,originX
|
|
imul [tableSin+ecx*4]
|
|
shrd eax,edx,16
|
|
sub lateral,eax
|
|
mov ecx,flashlightConeAngle
|
|
mov eax,forward
|
|
imul [tableSin+ecx*4]
|
|
idiv DWORD PTR [tableCos+ecx*4]
|
|
mov beam,eax
|
|
test eax,eax
|
|
jle spl_fog
|
|
mov eax,lateral
|
|
cdq
|
|
xor eax,edx
|
|
sub eax,edx
|
|
cmp eax,beam
|
|
jae spl_fog
|
|
mov ebx,beam
|
|
sub ebx,eax
|
|
mov eax,ebx
|
|
imul eax,atten
|
|
xor edx,edx
|
|
div beam
|
|
mov atten,eax
|
|
invoke CastLightRay,originX,originY,x,y
|
|
test eax,eax
|
|
jz spl_fog
|
|
invoke AddLightColor,00FFFFFFh,atten
|
|
spl_fog:
|
|
mov fog,256
|
|
mov eax,distance
|
|
cmp eax,280
|
|
jle spl_side
|
|
cmp eax,720
|
|
jb spl_partial
|
|
mov fog,32
|
|
jmp spl_side
|
|
spl_partial:
|
|
sub eax,280
|
|
imul eax,224
|
|
xor edx,edx
|
|
mov ebx,440
|
|
div ebx
|
|
sub fog,eax
|
|
spl_side:
|
|
cmp side,1
|
|
jne spl_coeff
|
|
mov eax,fog
|
|
imul eax,192
|
|
shr eax,8
|
|
mov fog,eax
|
|
spl_coeff:
|
|
mov eax,lightAccumR
|
|
cmp eax,256
|
|
jbe @F
|
|
mov eax,256
|
|
@@:
|
|
imul eax,fog
|
|
shr eax,8
|
|
mov lightRed,eax
|
|
mov eax,lightAccumG
|
|
cmp eax,256
|
|
jbe @F
|
|
mov eax,256
|
|
@@:
|
|
imul eax,fog
|
|
shr eax,8
|
|
mov lightGreen,eax
|
|
mov eax,lightAccumB
|
|
cmp eax,256
|
|
jbe @F
|
|
mov eax,256
|
|
@@:
|
|
imul eax,fog
|
|
shr eax,8
|
|
mov lightBlue,eax
|
|
spl_done:
|
|
mov eax,lightRed
|
|
cmp eax,lightGreen
|
|
jae @F
|
|
mov eax,lightGreen
|
|
@@:
|
|
cmp eax,lightBlue
|
|
jae @F
|
|
mov eax,lightBlue
|
|
@@:
|
|
ret
|
|
SamplePointLighting ENDP
|
|
|
|
ComputeWallLightLevel PROC uses ebx ecx edx,screenX:DWORD,mapX:DWORD,mapY:DWORD,sideHit:DWORD,stepX:DWORD,stepY:DWORD,rawDist:DWORD,perpWallDist:DWORD,rayAngle:DWORD,rayDirX:DWORD,rayDirY:DWORD
|
|
LOCAL x:DWORD,y:DWORD
|
|
mov eax,rawDist
|
|
imul rayDirX
|
|
shrd eax,edx,24
|
|
add eax,viewX
|
|
mov x,eax
|
|
mov eax,rawDist
|
|
imul rayDirY
|
|
shrd eax,edx,24
|
|
add eax,viewY
|
|
mov y,eax
|
|
cmp sideHit,0
|
|
jne cwl_y
|
|
mov eax,mapX
|
|
shl eax,6
|
|
cmp stepX,0
|
|
jg @F
|
|
add eax,64
|
|
@@:
|
|
sub eax,stepX
|
|
mov x,eax
|
|
jmp cwl_ready
|
|
cwl_y:
|
|
mov eax,mapY
|
|
shl eax,6
|
|
cmp stepY,0
|
|
jg @F
|
|
add eax,64
|
|
@@:
|
|
sub eax,stepY
|
|
mov y,eax
|
|
cwl_ready:
|
|
invoke SamplePointLighting,x,y,perpWallDist,sideHit
|
|
ret
|
|
ComputeWallLightLevel ENDP
|
|
|
|
ComputeSpriteLight PROC sprX:DWORD,sprY:DWORD,sprDist:DWORD
|
|
invoke SamplePointLighting,sprX,sprY,sprDist,0
|
|
ret
|
|
ComputeSpriteLight ENDP
|
|
|
|
ShadeLightPixel PROC uses eax ebx
|
|
mov eax,edx
|
|
and eax,255
|
|
imul eax,lightBlue
|
|
shr eax,8
|
|
mov ebx,eax
|
|
mov eax,edx
|
|
shr eax,8
|
|
and eax,255
|
|
imul eax,lightGreen
|
|
shr eax,8
|
|
shl eax,8
|
|
or ebx,eax
|
|
mov eax,edx
|
|
shr eax,16
|
|
and eax,255
|
|
imul eax,lightRed
|
|
shr eax,8
|
|
shl eax,16
|
|
or eax,ebx
|
|
mov edx,eax
|
|
ret
|
|
ShadeLightPixel ENDP
|