Add rooftop elevator, lounge, volumetric city, river and animated traffic. Prune invisible mesh faces, clip CPU surfaces, streamline compositing and add automatic/F8 roof quality profiles with renderer diagnostics. Include dartboard/reticle improvements, tracked fortune orb numerals and fate-session visuals, native regression tests, compatible jukebox IDs and updated shipping executables.
1496 lines
33 KiB
PHP
1496 lines
33 KiB
PHP
; Native ray/ellipsoid intersection supplies rounded cushions and copper domes.
|
|
DrawRoofEllipsoid3D PROC uses ebx esi edi centreX:DWORD,centreY:DWORD,centreZ:DWORD,radiusX:DWORD,radiusY:DWORD,radiusZ:DWORD,material:DWORD
|
|
local leftPx:DWORD,rightPx:DWORD,topPx:DWORD,bottomPx:DWORD,column:DWORD,row:DWORD
|
|
local centrePx:DWORD,centreDepth:DWORD,pixelDepth:DWORD,temp:DWORD,texU:DWORD,texV:DWORD
|
|
local texture:DWORD,texWidth:DWORD,texHeight:DWORD,shade:DWORD,color:DWORD
|
|
local ox:REAL4,oy:REAL4,oz:REAL4,rayX:REAL4,rayY:REAL4,rayZ:REAL4
|
|
local quadraticC:REAL4,quadraticA:REAL4,quadraticB:REAL4,discriminant:REAL4,hitTime:REAL4
|
|
invoke ResolveCitySurface3D,material
|
|
test eax,eax
|
|
jz roof_round_done
|
|
mov texture,eax
|
|
mov texWidth,ecx
|
|
mov texHeight,edx
|
|
invoke ProjectCityPoint3D,centreX,centreY
|
|
cmp edx,FP_1/8
|
|
jle roof_round_done
|
|
mov centrePx,eax
|
|
mov centreDepth,edx
|
|
mov eax,radiusX
|
|
add eax,radiusY
|
|
imul eax,SCREEN_H
|
|
cdq
|
|
idiv centreDepth
|
|
mov ecx,centrePx
|
|
sub ecx,eax
|
|
mov leftPx,ecx
|
|
add eax,centrePx
|
|
mov rightPx,eax
|
|
mov eax,viewEye3D
|
|
sub eax,centreZ
|
|
sub eax,radiusZ
|
|
imul eax,SCREEN_H
|
|
cdq
|
|
idiv centreDepth
|
|
add eax,viewHorizon3D
|
|
sub eax,4
|
|
mov topPx,eax
|
|
mov eax,viewEye3D
|
|
sub eax,centreZ
|
|
add eax,radiusZ
|
|
imul eax,SCREEN_H
|
|
cdq
|
|
idiv centreDepth
|
|
add eax,viewHorizon3D
|
|
add eax,4
|
|
mov bottomPx,eax
|
|
cmp leftPx,0
|
|
jge @F
|
|
mov leftPx,0
|
|
@@:
|
|
cmp rightPx,SCREEN_W-1
|
|
jle @F
|
|
mov rightPx,SCREEN_W-1
|
|
@@:
|
|
cmp topPx,0
|
|
jge @F
|
|
mov topPx,0
|
|
@@:
|
|
cmp bottomPx,SCREEN_H-1
|
|
jle @F
|
|
mov bottomPx,SCREEN_H-1
|
|
@@:
|
|
mov eax,leftPx
|
|
cmp eax,rightPx
|
|
jge roof_round_done
|
|
mov eax,topPx
|
|
cmp eax,bottomPx
|
|
jge roof_round_done
|
|
mov eax,playerX
|
|
sub eax,centreX
|
|
mov temp,eax
|
|
fild temp
|
|
fidiv radiusX
|
|
fstp ox
|
|
mov eax,playerY
|
|
sub eax,centreY
|
|
mov temp,eax
|
|
fild temp
|
|
fidiv radiusY
|
|
fstp oy
|
|
mov eax,viewEye3D
|
|
sub eax,centreZ
|
|
mov temp,eax
|
|
fild temp
|
|
fidiv radiusZ
|
|
fstp oz
|
|
fld ox
|
|
fmul st,st
|
|
fld oy
|
|
fmul st,st
|
|
faddp st(1),st
|
|
fld oz
|
|
fmul st,st
|
|
faddp st(1),st
|
|
fld1
|
|
fsubp st(1),st
|
|
fstp quadraticC
|
|
mov eax,topPx
|
|
mov row,eax
|
|
roof_round_row:
|
|
mov eax,viewHorizon3D
|
|
sub eax,row
|
|
mov temp,eax
|
|
fild temp
|
|
fmul roofFloatFP3D
|
|
fdiv roofFloat4803D
|
|
fidiv radiusZ
|
|
fstp rayZ
|
|
mov eax,row
|
|
imul eax,SCREEN_W*4
|
|
mov ebx,leftPx
|
|
lea edi,[eax+ebx*4]
|
|
mov column,ebx
|
|
roof_round_pixel:
|
|
mov ebx,column
|
|
fild cityRayX3D[ebx*4]
|
|
fidiv radiusX
|
|
fstp rayX
|
|
fild cityRayY3D[ebx*4]
|
|
fidiv radiusY
|
|
fstp rayY
|
|
fld rayX
|
|
fmul st,st
|
|
fld rayY
|
|
fmul st,st
|
|
faddp st(1),st
|
|
fld rayZ
|
|
fmul st,st
|
|
faddp st(1),st
|
|
fstp quadraticA
|
|
fld rayX
|
|
fmul ox
|
|
fld rayY
|
|
fmul oy
|
|
faddp st(1),st
|
|
fld rayZ
|
|
fmul oz
|
|
faddp st(1),st
|
|
fstp quadraticB
|
|
fld quadraticB
|
|
fmul st,st
|
|
fld quadraticA
|
|
fmul quadraticC
|
|
fsubp st(1),st
|
|
fst discriminant
|
|
ftst
|
|
fnstsw ax
|
|
sahf
|
|
fstp st(0)
|
|
jb roof_round_next
|
|
fld discriminant
|
|
fsqrt
|
|
fadd quadraticB
|
|
fchs
|
|
fdiv quadraticA
|
|
fst hitTime
|
|
fmul roofFloatFP3D
|
|
fistp pixelDepth
|
|
mov eax,pixelDepth
|
|
cmp eax,4096
|
|
jle roof_round_next
|
|
cmp eax,cityDepthBuffer3D[edi]
|
|
jae roof_round_next
|
|
fld hitTime
|
|
fmul rayX
|
|
fadd ox
|
|
fld1
|
|
faddp st(1),st
|
|
fmul roofFloatHalfTex3D
|
|
fistp texU
|
|
fld hitTime
|
|
fmul rayZ
|
|
fadd oz
|
|
fchs
|
|
fld1
|
|
faddp st(1),st
|
|
fmul roofFloatHalfTex3D
|
|
fistp texV
|
|
fld hitTime
|
|
fmul rayZ
|
|
fadd oz
|
|
fmul roofFloatShade3D
|
|
fadd roofFloatAmbient3D
|
|
fistp shade
|
|
mov eax,texV
|
|
and eax,255
|
|
mov ecx,texHeight
|
|
imul eax,ecx
|
|
shr eax,8
|
|
imul eax,texWidth
|
|
mov edx,texU
|
|
and edx,255
|
|
imul edx,texWidth
|
|
shr edx,8
|
|
add eax,edx
|
|
mov esi,texture
|
|
mov eax,[esi+eax*4]
|
|
mov color,eax
|
|
movzx eax,al
|
|
imul eax,shade
|
|
shr eax,8
|
|
mov ebx,eax
|
|
mov eax,color
|
|
shr eax,8
|
|
and eax,255
|
|
imul eax,shade
|
|
and eax,0FF00h
|
|
or ebx,eax
|
|
mov eax,color
|
|
shr eax,16
|
|
and eax,255
|
|
imul eax,shade
|
|
and eax,0FF00h
|
|
shl eax,8
|
|
or eax,ebx
|
|
cmp roofCityPass3D,0
|
|
je roof_round_color_ready
|
|
invoke ShadeRoofCityPixel3D,eax,pixelDepth,256,material
|
|
mov ecx,edi
|
|
shr ecx,2
|
|
mov edx,roofPixelGlow3D
|
|
mov roofGlowMask3D[ecx],dl
|
|
roof_round_color_ready:
|
|
mov screenBuffer[edi],eax
|
|
cmp hallLevel3D,HALL_ROOF
|
|
jne @F
|
|
mov ecx,edi
|
|
shr ecx,2
|
|
mov edx,roofCityPass3D
|
|
mov roofCityMask3D[ecx],dl
|
|
@@:
|
|
mov eax,pixelDepth
|
|
mov cityDepthBuffer3D[edi],eax
|
|
roof_round_next:
|
|
add edi,4
|
|
inc column
|
|
mov eax,column
|
|
cmp eax,rightPx
|
|
jbe roof_round_pixel
|
|
inc row
|
|
mov eax,row
|
|
cmp eax,bottomPx
|
|
jbe roof_round_row
|
|
roof_round_done:
|
|
ret
|
|
DrawRoofEllipsoid3D ENDP
|
|
|
|
; Closed furniture parts use material surfaces, never pictures of whole chairs.
|
|
DrawRoofSolid3D PROC uses ebx esi x0:DWORD,x1:DWORD,y0:DWORD,y1:DWORD,z0:DWORD,z1:DWORD,mat:DWORD
|
|
mov eax,x0
|
|
cmp playerX,eax
|
|
jge @F
|
|
invoke DrawCityVertical3D,0,x0,y0,y1,z0,z1,mat
|
|
@@:
|
|
mov eax,x1
|
|
cmp playerX,eax
|
|
jle @F
|
|
invoke DrawCityVertical3D,0,x1,y0,y1,z0,z1,mat
|
|
@@:
|
|
mov eax,y0
|
|
cmp playerY,eax
|
|
jge @F
|
|
invoke DrawCityVertical3D,1,y0,x0,x1,z0,z1,mat
|
|
@@:
|
|
mov eax,y1
|
|
cmp playerY,eax
|
|
jle @F
|
|
invoke DrawCityVertical3D,1,y1,x0,x1,z0,z1,mat
|
|
@@:
|
|
mov eax,z1
|
|
cmp viewEye3D,eax
|
|
jle @F
|
|
invoke DrawCityHorizontal3D,x0,x1,y0,y1,z1,mat
|
|
@@:
|
|
ret
|
|
DrawRoofSolid3D ENDP
|
|
|
|
DrawRoofPadding3D PROC uses ebx esi edi centreX:DWORD,centreY:DWORD,centreZ:DWORD,rx:DWORD,ry:DWORD,rz:DWORD,mat:DWORD
|
|
local x0:DWORD,x1:DWORD,y0:DWORD,y1:DWORD,z0:DWORD,z1:DWORD
|
|
local insetX0:DWORD,insetX1:DWORD,insetY0:DWORD,insetY1:DWORD,loZ:DWORD,hiZ:DWORD
|
|
mov eax,centreX
|
|
sub eax,rx
|
|
mov x0,eax
|
|
add eax,FP_1*35/1000
|
|
mov insetX0,eax
|
|
mov eax,centreX
|
|
add eax,rx
|
|
mov x1,eax
|
|
sub eax,FP_1*35/1000
|
|
mov insetX1,eax
|
|
mov eax,centreY
|
|
sub eax,ry
|
|
mov y0,eax
|
|
add eax,FP_1*35/1000
|
|
mov insetY0,eax
|
|
mov eax,centreY
|
|
add eax,ry
|
|
mov y1,eax
|
|
sub eax,FP_1*35/1000
|
|
mov insetY1,eax
|
|
mov eax,centreZ
|
|
sub eax,rz
|
|
mov z0,eax
|
|
add eax,FP_1*35/1000
|
|
mov loZ,eax
|
|
mov eax,centreZ
|
|
add eax,rz
|
|
mov z1,eax
|
|
sub eax,FP_1*35/1000
|
|
mov hiZ,eax
|
|
invoke DrawRoofSolid3D,insetX0,insetX1,insetY0,insetY1,z0,z1,mat
|
|
invoke DrawRoofSolid3D,x0,x1,insetY0,insetY1,loZ,hiZ,mat
|
|
invoke DrawRoofSolid3D,insetX0,insetX1,y0,y1,loZ,hiZ,mat
|
|
ret
|
|
DrawRoofPadding3D ENDP
|
|
|
|
DrawRoofUpholstery3D PROC uses ebx esi edi centreX:DWORD,frontY:DWORD,kind:DWORD
|
|
local x0:DWORD,x1:DWORD,y1:DWORD,halfWidth:DWORD,count:DWORD,seatZ:DWORD,backZ:DWORD
|
|
local xa:DWORD,xb:DWORD,ya:DWORD,yb:DWORD,za:DWORD,zb:DWORD
|
|
mov halfWidth,FP_1*120/100
|
|
mov count,3
|
|
mov seatZ,FP_1*45/100
|
|
mov backZ,FP_1*92/100
|
|
mov ecx,FP_1*90/100
|
|
cmp kind,0
|
|
je @F
|
|
mov halfWidth,FP_1*46/100
|
|
mov count,1
|
|
mov ecx,FP_1*86/100
|
|
cmp kind,2
|
|
jb @F
|
|
mov halfWidth,FP_1*27/100
|
|
mov seatZ,FP_1*78/100
|
|
mov backZ,FP_1*108/100
|
|
mov ecx,FP_1*48/100
|
|
@@:
|
|
mov eax,centreX
|
|
sub eax,halfWidth
|
|
mov x0,eax
|
|
mov eax,centreX
|
|
add eax,halfWidth
|
|
mov x1,eax
|
|
mov eax,frontY
|
|
add eax,ecx
|
|
mov y1,eax
|
|
; Four metal feet, solid armrests, a seat base and separate upholstered pads.
|
|
xor esi,esi
|
|
roof_furniture_foot:
|
|
mov eax,x0
|
|
add eax,FP_1*8/100
|
|
test esi,1
|
|
jz @F
|
|
mov eax,x1
|
|
sub eax,FP_1*12/100
|
|
@@:
|
|
mov xa,eax
|
|
add eax,FP_1*4/100
|
|
mov xb,eax
|
|
mov eax,frontY
|
|
add eax,FP_1*8/100
|
|
test esi,2
|
|
jz @F
|
|
mov eax,y1
|
|
sub eax,FP_1*12/100
|
|
@@:
|
|
mov ya,eax
|
|
add eax,FP_1*4/100
|
|
mov yb,eax
|
|
mov eax,seatZ
|
|
sub eax,FP_1*12/100
|
|
invoke DrawRoofSolid3D,xa,xb,ya,yb,0,eax,ROOF_METAL
|
|
inc esi
|
|
cmp esi,4
|
|
jb roof_furniture_foot
|
|
mov eax,seatZ
|
|
sub eax,FP_1*14/100
|
|
mov za,eax
|
|
add eax,FP_1*5/100
|
|
invoke DrawRoofSolid3D,x0,x1,frontY,y1,za,eax,ROOF_TEAL
|
|
mov eax,y1
|
|
sub eax,FP_1*14/100
|
|
mov ya,eax
|
|
invoke DrawRoofSolid3D,x0,x1,ya,y1,seatZ,backZ,ROOF_TEAL
|
|
mov eax,x0
|
|
add eax,FP_1*12/100
|
|
mov xa,eax
|
|
mov eax,x1
|
|
sub eax,FP_1*12/100
|
|
mov xb,eax
|
|
; Soft rectangular cushion edges are inset in three shallow bands.
|
|
xor esi,esi
|
|
roof_furniture_pad:
|
|
mov eax,xb
|
|
sub eax,xa
|
|
xor edx,edx
|
|
div count
|
|
mov edi,eax
|
|
imul eax,esi
|
|
add eax,xa
|
|
add eax,FP_1/100
|
|
mov ebx,eax
|
|
add ebx,edi
|
|
sub ebx,FP_1*2/100
|
|
mov ecx,frontY
|
|
add ecx,FP_1*5/100
|
|
mov edx,y1
|
|
sub edx,FP_1*16/100
|
|
mov za,eax
|
|
mov zb,ebx
|
|
mov ya,ecx
|
|
mov yb,edx
|
|
mov eax,seatZ
|
|
sub eax,FP_1*9/100
|
|
mov eax,za
|
|
add eax,zb
|
|
sar eax,1
|
|
mov ebx,zb
|
|
sub ebx,za
|
|
sar ebx,1
|
|
mov ecx,ya
|
|
add ecx,yb
|
|
sar ecx,1
|
|
mov edx,yb
|
|
sub edx,ya
|
|
sar edx,1
|
|
mov edi,seatZ
|
|
sub edi,FP_1*4/100
|
|
invoke DrawRoofPadding3D,eax,ecx,edi,ebx,edx,FP_1*8/100,ROOF_IVORY
|
|
mov eax,za
|
|
add eax,FP_1*2/100
|
|
mov ebx,zb
|
|
sub ebx,FP_1*2/100
|
|
mov ecx,ya
|
|
add ecx,FP_1*2/100
|
|
mov edx,yb
|
|
sub edx,FP_1*2/100
|
|
mov ya,ecx
|
|
mov yb,edx
|
|
mov ecx,seatZ
|
|
add ecx,FP_1*2/100
|
|
; Back cushions are real thin volumes, not alpha views pasted on each side.
|
|
mov eax,y1
|
|
sub eax,FP_1*22/100
|
|
mov ya,eax
|
|
add eax,FP_1*9/100
|
|
mov yb,eax
|
|
mov eax,seatZ
|
|
add eax,FP_1*2/100
|
|
mov ecx,backZ
|
|
sub ecx,FP_1*3/100
|
|
add eax,ecx
|
|
sar eax,1
|
|
mov edi,eax
|
|
mov eax,za
|
|
add eax,zb
|
|
sar eax,1
|
|
mov ebx,zb
|
|
sub ebx,za
|
|
sar ebx,1
|
|
mov ecx,ya
|
|
add ecx,yb
|
|
sar ecx,1
|
|
invoke DrawRoofPadding3D,eax,ecx,edi,ebx,FP_1*9/100,FP_1*23/100,ROOF_IVORY
|
|
inc esi
|
|
cmp esi,count
|
|
jb roof_furniture_pad
|
|
cmp kind,2
|
|
jae roof_furniture_done
|
|
mov eax,seatZ
|
|
add eax,FP_1*17/100
|
|
mov zb,eax
|
|
mov eax,x0
|
|
add eax,FP_1*11/100
|
|
invoke DrawRoofSolid3D,x0,eax,frontY,y1,seatZ,zb,ROOF_TEAL
|
|
mov eax,x1
|
|
sub eax,FP_1*11/100
|
|
invoke DrawRoofSolid3D,eax,x1,frontY,y1,seatZ,zb,ROOF_TEAL
|
|
roof_furniture_done:
|
|
ret
|
|
DrawRoofUpholstery3D ENDP
|
|
|
|
DrawRoofPlanter3D PROC uses ebx esi x0:DWORD,x1:DWORD,y0:DWORD,y1:DWORD
|
|
local xa:DWORD,xb:DWORD,ya:DWORD,yb:DWORD
|
|
invoke DrawRoofSolid3D,x0,x1,y0,y1,0,FP_1*42/100,ROOF_STONE
|
|
mov eax,x0
|
|
add eax,FP_1*4/100
|
|
mov xa,eax
|
|
mov eax,x1
|
|
sub eax,FP_1*4/100
|
|
mov xb,eax
|
|
mov eax,y0
|
|
add eax,FP_1*4/100
|
|
mov ya,eax
|
|
mov eax,y1
|
|
sub eax,FP_1*4/100
|
|
mov yb,eax
|
|
invoke DrawCityHorizontal3D,xa,xb,ya,yb,FP_1*425/1000,ROOF_EARTH
|
|
; Several separated foliage tufts give the bed depth from either end.
|
|
mov esi,xa
|
|
roof_planter_tuft:
|
|
mov ebx,esi
|
|
add ebx,FP_1*34/100
|
|
cmp ebx,xb
|
|
jae roof_planter_done
|
|
mov eax,ya
|
|
add eax,FP_1*10/100
|
|
invoke DrawCityVertical3D,1,eax,esi,ebx,FP_1*43/100,FP_1*85/100,ROOF_FOLIAGE
|
|
mov eax,yb
|
|
sub eax,FP_1*10/100
|
|
invoke DrawCityVertical3D,1,eax,esi,ebx,FP_1*43/100,FP_1*78/100,ROOF_FOLIAGE
|
|
mov eax,esi
|
|
add eax,FP_1*17/100
|
|
invoke DrawCityVertical3D,0,eax,ya,yb,FP_1*43/100,FP_1*85/100,ROOF_FOLIAGE
|
|
add esi,FP_1*38/100
|
|
jmp roof_planter_tuft
|
|
roof_planter_done:
|
|
ret
|
|
DrawRoofPlanter3D ENDP
|
|
|
|
UpdateRoofGuests3D PROC uses ebx esi edi milliseconds:DWORD
|
|
local px:DWORD,py:DWORD,stepSize:DWORD,savedSeat:DWORD,savedLean:DWORD
|
|
mov eax,milliseconds
|
|
add roofGuestClock3D,eax
|
|
imul eax,38
|
|
mov stepSize,eax
|
|
mov eax,roofSeat3D
|
|
mov savedSeat,eax
|
|
mov eax,roofLean3D
|
|
mov savedLean,eax
|
|
mov roofSeat3D,0
|
|
mov roofLean3D,0
|
|
xor esi,esi
|
|
roof_person_update:
|
|
mov roofGuestMoving3D[esi*4],0
|
|
mov eax,milliseconds
|
|
cmp roofGuestWait3D[esi*4],eax
|
|
jbe roof_person_step
|
|
sub roofGuestWait3D[esi*4],eax
|
|
jmp roof_person_next
|
|
roof_person_step:
|
|
mov roofGuestWait3D[esi*4],0
|
|
mov eax,roofGuestX3D[esi*4]
|
|
mov px,eax
|
|
mov eax,roofGuestY3D[esi*4]
|
|
mov py,eax
|
|
mov eax,roofGuestDir3D[esi*4]
|
|
mov ebx,stepSize
|
|
cmp eax,0
|
|
jne @F
|
|
add px,ebx
|
|
jmp roof_person_check
|
|
@@:
|
|
cmp eax,1
|
|
jne @F
|
|
sub px,ebx
|
|
jmp roof_person_check
|
|
@@:
|
|
cmp eax,2
|
|
jne @F
|
|
add py,ebx
|
|
jmp roof_person_check
|
|
@@:
|
|
sub py,ebx
|
|
roof_person_check:
|
|
invoke RoofCanWalk3D,px,py
|
|
test eax,eax
|
|
jz roof_person_turn
|
|
mov eax,px
|
|
sub eax,playerX
|
|
cdq
|
|
xor eax,edx
|
|
sub eax,edx
|
|
mov ebx,eax
|
|
mov eax,py
|
|
sub eax,playerY
|
|
cdq
|
|
xor eax,edx
|
|
sub eax,edx
|
|
add eax,ebx
|
|
cmp eax,FP_1*7/10
|
|
jb roof_person_turn
|
|
mov eax,px
|
|
mov roofGuestX3D[esi*4],eax
|
|
mov eax,py
|
|
mov roofGuestY3D[esi*4],eax
|
|
mov roofGuestMoving3D[esi*4],1
|
|
mov eax,stepSize
|
|
add roofGuestDistance3D[esi*4],eax
|
|
add roofGuestStep3D[esi*4],eax
|
|
cmp roofGuestStep3D[esi*4],FP_1*18/10
|
|
jb roof_person_next
|
|
roof_person_turn:
|
|
mov roofGuestStep3D[esi*4],0
|
|
mov roofGuestWait3D[esi*4],1700
|
|
inc roofGuestDir3D[esi*4]
|
|
and roofGuestDir3D[esi*4],3
|
|
roof_person_next:
|
|
inc esi
|
|
cmp esi,ROOF_GUEST_COUNT
|
|
jb roof_person_update
|
|
mov eax,savedSeat
|
|
mov roofSeat3D,eax
|
|
mov eax,savedLean
|
|
mov roofLean3D,eax
|
|
ret
|
|
UpdateRoofGuests3D ENDP
|
|
|
|
CheckRoofRail3D PROC
|
|
mov roofLeanSide3D,-1
|
|
cmp playerY,FP_1*191/10
|
|
jb @F
|
|
cmp playerAngle,64
|
|
jb @F
|
|
cmp playerAngle,192
|
|
ja @F
|
|
mov roofLeanSide3D,0
|
|
@@:
|
|
cmp playerX,FP_1*272/10
|
|
jb @F
|
|
mov eax,playerAngle
|
|
add eax,64
|
|
and eax,511
|
|
cmp eax,128
|
|
ja @F
|
|
mov roofLeanSide3D,1
|
|
@@:
|
|
cmp playerX,FP_1*128/10
|
|
ja @F
|
|
cmp playerAngle,192
|
|
jb @F
|
|
cmp playerAngle,320
|
|
ja @F
|
|
; The western drinks counter is not a handrail approach.
|
|
cmp playerY,11*FP_1
|
|
jb roof_check_west_rail
|
|
cmp playerY,17*FP_1
|
|
jbe @F
|
|
roof_check_west_rail:
|
|
mov roofLeanSide3D,2
|
|
@@:
|
|
cmp roofLeanSide3D,-1
|
|
je @F
|
|
mov interactTargetId,INTERACT_ROOF_RAIL
|
|
mov interactPromptPtr,OFFSET roofLeanPrompt3D
|
|
@@:
|
|
ret
|
|
CheckRoofRail3D ENDP
|
|
|
|
StartRoofLean3D PROC
|
|
mov eax,playerX
|
|
mov roofReturnX3D,eax
|
|
mov eax,playerY
|
|
mov roofReturnY3D,eax
|
|
mov eax,playerAngle
|
|
mov roofReturnAngle3D,eax
|
|
mov roofLeanAngle3D,128
|
|
mov eax,playerX
|
|
mov edx,FP_1*1975/100
|
|
cmp roofLeanSide3D,0
|
|
je roof_start_lean_check
|
|
mov eax,FP_1*2775/100
|
|
mov edx,playerY
|
|
mov roofLeanAngle3D,0
|
|
cmp roofLeanSide3D,1
|
|
je roof_start_lean_check
|
|
mov eax,FP_1*1225/100
|
|
mov roofLeanAngle3D,256
|
|
roof_start_lean_check:
|
|
push eax
|
|
push edx
|
|
invoke RoofCanWalk3D,eax,edx
|
|
mov ecx,eax
|
|
pop edx
|
|
pop eax
|
|
test ecx,ecx
|
|
jz roof_start_lean_done
|
|
mov playerX,eax
|
|
mov playerY,edx
|
|
mov eax,roofLeanAngle3D
|
|
mov playerAngle,eax
|
|
mov roofLean3D,1
|
|
mov roofLeanTime3D,0
|
|
call UpdateCamera3D
|
|
roof_start_lean_done:
|
|
ret
|
|
StartRoofLean3D ENDP
|
|
|
|
UpdateRoofLook3D PROC
|
|
cmp roofLean3D,0
|
|
je roof_look_done
|
|
mov eax,playerAngle
|
|
sub eax,roofLeanAngle3D
|
|
add eax,256
|
|
and eax,511
|
|
sub eax,256
|
|
cmp eax,104
|
|
jle @F
|
|
mov eax,104
|
|
@@:
|
|
cmp eax,-104
|
|
jge @F
|
|
mov eax,-104
|
|
@@:
|
|
add eax,roofLeanAngle3D
|
|
and eax,511
|
|
mov playerAngle,eax
|
|
call UpdateCamera3D
|
|
roof_look_done:
|
|
ret
|
|
UpdateRoofLook3D ENDP
|
|
|
|
RenderRoofLean3D PROC uses ebx esi
|
|
local anchorX:DWORD,anchorY:DWORD,depth:DWORD,left:DWORD,widthPx:DWORD,heightPx:DWORD
|
|
cmp roofLean3D,0
|
|
je roof_hands_done
|
|
cmp engineMode,MODE_WALK
|
|
jne roof_hands_done
|
|
mov eax,roofLeanTime3D
|
|
imul eax,31
|
|
xor edx,edx
|
|
mov ecx,1100
|
|
div ecx
|
|
mov esi,eax
|
|
; Project the fixed rail contact instead of rotating the hands with the head.
|
|
mov ebx,roofLeanAngle3D
|
|
and ebx,511
|
|
mov eax,tableCos[ebx*4]
|
|
mov ecx,FP_1*115/100
|
|
imul ecx
|
|
shrd eax,edx,16
|
|
add eax,playerX
|
|
mov anchorX,eax
|
|
mov eax,tableSin[ebx*4]
|
|
imul ecx
|
|
shrd eax,edx,16
|
|
add eax,playerY
|
|
mov anchorY,eax
|
|
invoke ProjectCityPoint3D,anchorX,anchorY
|
|
cmp edx,FP_1/5
|
|
jle roof_hands_done
|
|
mov depth,edx
|
|
mov left,eax
|
|
mov roofHandsContactX3D,eax
|
|
mov eax,640*FP_1*115/100
|
|
cdq
|
|
idiv depth
|
|
mov widthPx,eax
|
|
mov roofHandsWidth3D,eax
|
|
shr eax,1
|
|
sub left,eax
|
|
mov eax,widthPx
|
|
shr eax,1
|
|
mov heightPx,eax
|
|
mov eax,viewEye3D
|
|
sub eax,ROOF_RAIL_HEIGHT
|
|
imul eax,480
|
|
cdq
|
|
idiv depth
|
|
add eax,viewHorizon3D
|
|
mov ebx,eax
|
|
mov eax,widthPx
|
|
imul eax,166
|
|
xor edx,edx
|
|
mov ecx,640
|
|
div ecx
|
|
sub ebx,eax
|
|
invoke DrawRoofHandsPlane3D,esi,left,widthPx
|
|
roof_hands_done:
|
|
ret
|
|
RenderRoofLean3D ENDP
|
|
|
|
; Keep the forearms in the first-person view; shear their contact line onto the rail.
|
|
DrawRoofHandsPlane3D PROC uses ebx esi edi frame:DWORD,left:DWORD,scaleW:DWORD
|
|
local source:DWORD,col:DWORD,normalX:DWORD,normalY:DWORD,denom:DWORD
|
|
local depth:DWORD,srcX:DWORD,srcY:DWORD,stepY:DWORD,row:DWORD,lastRow:DWORD
|
|
local extension:DWORD,shiftDown:DWORD
|
|
cmp roofHandsArt3D.pixels,0
|
|
je roof_hands_plane_done
|
|
mov eax,frame
|
|
cmp eax,roofHandsArt3D.frames
|
|
jae roof_hands_plane_done
|
|
imul eax,640*320*4
|
|
add eax,roofHandsArt3D.pixels
|
|
mov source,eax
|
|
mov eax,roofLeanAngle3D
|
|
and eax,511
|
|
mov ecx,tableCos[eax*4]
|
|
mov normalX,ecx
|
|
mov ecx,tableSin[eax*4]
|
|
mov normalY,ecx
|
|
mov eax,FP_1*640
|
|
cdq
|
|
idiv scaleW
|
|
mov stepY,eax
|
|
mov col,0
|
|
roof_hands_plane_column:
|
|
cmp col,640
|
|
jge roof_hands_plane_done
|
|
mov esi,col
|
|
mov eax,cityRayX3D[esi*4]
|
|
imul normalX
|
|
shrd eax,edx,16
|
|
mov ebx,eax
|
|
mov eax,cityRayY3D[esi*4]
|
|
imul normalY
|
|
shrd eax,edx,16
|
|
add eax,ebx
|
|
cmp eax,FP_1/12
|
|
jle roof_hands_plane_next
|
|
mov denom,eax
|
|
mov eax,FP_1*115/100
|
|
mov ecx,FP_1
|
|
imul ecx
|
|
idiv denom
|
|
cmp eax,16*FP_1
|
|
jge roof_hands_plane_next
|
|
mov depth,eax
|
|
mov eax,col
|
|
sub eax,left
|
|
imul eax,640
|
|
cdq
|
|
idiv scaleW
|
|
mov extension,0
|
|
mov shiftDown,0
|
|
cmp eax,8
|
|
jge roof_hands_check_right_edge
|
|
mov eax,scaleW
|
|
xor edx,edx
|
|
mov ecx,80
|
|
div ecx
|
|
add eax,left
|
|
sub eax,col
|
|
mov shiftDown,eax
|
|
mov extension,1
|
|
mov eax,8
|
|
jmp roof_hands_source_column
|
|
roof_hands_check_right_edge:
|
|
cmp eax,632
|
|
jl roof_hands_source_column
|
|
mov eax,scaleW
|
|
imul eax,632
|
|
xor edx,edx
|
|
mov ecx,640
|
|
div ecx
|
|
add eax,left
|
|
mov ecx,col
|
|
sub ecx,eax
|
|
mov shiftDown,ecx
|
|
mov extension,1
|
|
mov eax,631
|
|
roof_hands_source_column:
|
|
mov srcX,eax
|
|
mov eax,viewEye3D
|
|
sub eax,ROOF_RAIL_HEIGHT
|
|
imul eax,480
|
|
cdq
|
|
idiv depth
|
|
add eax,viewHorizon3D
|
|
mov ebx,eax
|
|
mov eax,scaleW
|
|
imul eax,166
|
|
xor edx,edx
|
|
mov ecx,640
|
|
div ecx
|
|
sub ebx,eax
|
|
mov eax,shiftDown
|
|
add ebx,eax
|
|
mov denom,ebx
|
|
mov eax,ebx
|
|
test eax,eax
|
|
jns @F
|
|
xor eax,eax
|
|
@@:
|
|
cmp eax,480
|
|
jge roof_hands_plane_next
|
|
mov row,eax
|
|
mov eax,scaleW
|
|
shr eax,1
|
|
add eax,denom
|
|
cmp eax,480
|
|
jle @F
|
|
mov eax,480
|
|
@@:
|
|
mov lastRow,eax
|
|
cmp extension,0
|
|
je @F
|
|
mov lastRow,480
|
|
@@:
|
|
mov eax,row
|
|
sub eax,denom
|
|
imul eax,stepY
|
|
mov srcY,eax
|
|
mov eax,row
|
|
imul eax,640*4
|
|
mov edi,col
|
|
lea edi,[eax+edi*4]
|
|
mov ebx,srcX
|
|
shl ebx,2
|
|
add ebx,source
|
|
roof_hands_plane_pixel:
|
|
mov eax,row
|
|
cmp eax,lastRow
|
|
jge roof_hands_plane_next
|
|
mov edx,srcY
|
|
sar edx,16
|
|
cmp extension,0
|
|
je @F
|
|
cmp edx,314
|
|
jl @F
|
|
mov edx,313
|
|
@@:
|
|
cmp edx,320
|
|
jae roof_hands_plane_advance
|
|
imul edx,640*4
|
|
mov eax,[ebx+edx]
|
|
cmp eax,80000000h
|
|
jb roof_hands_plane_advance
|
|
and eax,00FFFFFFh
|
|
mov screenBuffer[edi],eax
|
|
mov eax,edi
|
|
shr eax,2
|
|
mov roofCityMask3D[eax],0
|
|
roof_hands_plane_advance:
|
|
mov eax,stepY
|
|
add srcY,eax
|
|
add edi,640*4
|
|
inc row
|
|
jmp roof_hands_plane_pixel
|
|
roof_hands_plane_next:
|
|
inc col
|
|
cmp col,640
|
|
jb roof_hands_plane_column
|
|
roof_hands_plane_done:
|
|
ret
|
|
DrawRoofHandsPlane3D ENDP
|
|
|
|
ShadeRoofNight3D PROC uses ebx esi edi
|
|
cmp roofNight3D,0
|
|
je roof_night_done
|
|
; Sky is already night artwork. Only shade actual depth-tested world pixels.
|
|
xor edi,edi
|
|
roof_night_pixel:
|
|
mov eax,edi
|
|
shr eax,2
|
|
cmp roofCityMask3D[eax],0
|
|
jne roof_night_next
|
|
cmp cityDepthBuffer3D[edi],ROOF_FAR_DEPTH
|
|
jae roof_night_next
|
|
mov eax,screenBuffer[edi]
|
|
mov edx,eax
|
|
and edx,000000FFh
|
|
cmp edx,90
|
|
ja @F
|
|
mov edx,eax
|
|
shr edx,16
|
|
cmp edx,110
|
|
ja roof_night_next
|
|
@@:
|
|
and eax,00FCFCFCh
|
|
shr eax,2
|
|
add eax,00070D1Dh
|
|
mov screenBuffer[edi],eax
|
|
roof_night_next:
|
|
add edi,4
|
|
cmp edi,SCREEN_SIZE*4
|
|
jb roof_night_pixel
|
|
roof_night_done:
|
|
ret
|
|
ShadeRoofNight3D ENDP
|
|
|
|
PrepareRoofFloorDepth3D PROC uses ebx esi edi
|
|
local row:DWORD,depth:DWORD,px:DWORD,py:DWORD,deltaX:DWORD,deltaY:DWORD
|
|
mov eax,viewHorizon3D
|
|
inc eax
|
|
mov row,eax
|
|
roof_floor_depth_row:
|
|
mov ecx,row
|
|
sub ecx,viewHorizon3D
|
|
mov eax,viewEye3D
|
|
imul eax,SCREEN_H
|
|
cdq
|
|
idiv ecx
|
|
mov depth,eax
|
|
imul cityRayX3D[0]
|
|
shrd eax,edx,16
|
|
add eax,playerX
|
|
mov px,eax
|
|
mov eax,depth
|
|
imul cityRayY3D[0]
|
|
shrd eax,edx,16
|
|
add eax,playerY
|
|
mov py,eax
|
|
mov eax,depth
|
|
imul playerPlaneX
|
|
shrd eax,edx,16
|
|
shl eax,1
|
|
cdq
|
|
mov ecx,SCREEN_W
|
|
idiv ecx
|
|
mov deltaX,eax
|
|
mov eax,depth
|
|
imul playerPlaneY
|
|
shrd eax,edx,16
|
|
shl eax,1
|
|
cdq
|
|
idiv ecx
|
|
mov deltaY,eax
|
|
mov eax,row
|
|
imul eax,SCREEN_W*4
|
|
mov edi,eax
|
|
xor ebx,ebx
|
|
roof_floor_depth_pixel:
|
|
cmp px,FP_1*109/10
|
|
jl roof_floor_depth_next
|
|
cmp px,FP_1*291/10
|
|
jge roof_floor_depth_next
|
|
cmp py,FP_1*9/10
|
|
jl roof_floor_depth_next
|
|
cmp py,FP_1*211/10
|
|
jge roof_floor_depth_next
|
|
mov eax,depth
|
|
mov cityDepthBuffer3D[edi],eax
|
|
mov eax,edi
|
|
shr eax,2
|
|
mov roofCityMask3D[eax],0
|
|
cmp roofHDReady3D,1
|
|
jne roof_floor_depth_next
|
|
cmp engineMode,MODE_WALK
|
|
jne roof_floor_depth_next
|
|
mov roofCityMask3D[eax],3
|
|
roof_floor_depth_next:
|
|
mov eax,deltaX
|
|
add px,eax
|
|
mov eax,deltaY
|
|
add py,eax
|
|
add edi,4
|
|
inc ebx
|
|
cmp ebx,SCREEN_W
|
|
jb roof_floor_depth_pixel
|
|
inc row
|
|
cmp row,SCREEN_H
|
|
jb roof_floor_depth_row
|
|
ret
|
|
PrepareRoofFloorDepth3D ENDP
|
|
|
|
RenderRoofDistrict3D PROC uses ebx esi edi
|
|
local x0:DWORD,x1:DWORD,y0:DWORD,y1:DWORD,z:DWORD,mat:DWORD,roofZ:DWORD
|
|
local screenX:DWORD,centreDepth:DWORD,middle:DWORD,ridgeZ:DWORD
|
|
xor esi,esi
|
|
roof_district_building:
|
|
imul edi,esi,28
|
|
mov eax,roofDistrict3D[edi]
|
|
mov x0,eax
|
|
mov eax,roofDistrict3D[edi+4]
|
|
mov x1,eax
|
|
add eax,x0
|
|
sar eax,1
|
|
mov ebx,roofDistrict3D[edi+8]
|
|
mov y0,ebx
|
|
mov ecx,roofDistrict3D[edi+12]
|
|
mov y1,ecx
|
|
add ebx,ecx
|
|
sar ebx,1
|
|
invoke ProjectCityPoint3D,eax,ebx
|
|
cmp edx,-12*FP_1
|
|
jle roof_district_next
|
|
mov centreDepth,edx
|
|
mov screenX,eax
|
|
cmp edx,12*FP_1
|
|
jle roof_district_visible
|
|
mov eax,x1
|
|
sub eax,x0
|
|
add eax,y1
|
|
sub eax,y0
|
|
imul eax,SCREEN_H
|
|
cdq
|
|
idiv centreDepth
|
|
mov edx,screenX
|
|
add edx,eax
|
|
cmp edx,0
|
|
jl roof_district_next
|
|
neg eax
|
|
add eax,screenX
|
|
cmp eax,SCREEN_W
|
|
jg roof_district_next
|
|
roof_district_visible:
|
|
mov eax,roofDistrict3D[edi+16]
|
|
mov z,eax
|
|
mov eax,roofDistrict3D[edi+20]
|
|
mov mat,eax
|
|
invoke DrawCityBoxSides3D,x0,x1,y0,y1,ROOF_CITY_STREET_Z,z,mat
|
|
mov eax,z
|
|
add eax,FP_1/6
|
|
mov roofZ,eax
|
|
invoke DrawRoofSolid3D,x0,x1,y0,y1,z,eax,ROOF_PLASTER
|
|
cmp mat,ROOF_MODERN_FACADE
|
|
jae roof_city_flat_roof
|
|
cmp centreDepth,100*FP_1
|
|
jle @F
|
|
roof_city_flat_roof:
|
|
mov eax,roofZ
|
|
add eax,FP_1/20
|
|
invoke DrawCityHorizontal3D,x0,x1,y0,y1,eax,ROOF_CITY_ROOF
|
|
jmp roof_district_next
|
|
@@:
|
|
; Stepped low mansards, dormers and chimneys give the skyline real parallax.
|
|
mov ebx,x0
|
|
add ebx,FP_1*6/10
|
|
mov ecx,x1
|
|
sub ecx,FP_1*6/10
|
|
mov edx,y0
|
|
add edx,FP_1*6/10
|
|
mov eax,y1
|
|
sub eax,FP_1*6/10
|
|
mov x0,ebx
|
|
mov x1,ecx
|
|
mov y0,edx
|
|
mov y1,eax
|
|
mov eax,roofZ
|
|
add eax,FP_1*24/10
|
|
mov ridgeZ,eax
|
|
mov eax,x1
|
|
sub eax,x0
|
|
mov edx,y1
|
|
sub edx,y0
|
|
cmp eax,edx
|
|
ja roof_mansard_ridge_x
|
|
mov eax,x0
|
|
add eax,x1
|
|
sar eax,1
|
|
mov middle,eax
|
|
invoke DrawRoofSlope3D,0,x0,middle,y0,y1,roofZ,FP_1*24/10,ROOF_CITY_ROOF
|
|
invoke DrawRoofSlope3D,0,middle,x1,y0,y1,ridgeZ,-FP_1*24/10,ROOF_CITY_ROOF
|
|
jmp roof_mansard_chimney
|
|
roof_mansard_ridge_x:
|
|
mov eax,y0
|
|
add eax,y1
|
|
sar eax,1
|
|
mov middle,eax
|
|
invoke DrawRoofSlope3D,1,x0,x1,y0,middle,roofZ,FP_1*24/10,ROOF_CITY_ROOF
|
|
invoke DrawRoofSlope3D,1,x0,x1,middle,y1,ridgeZ,-FP_1*24/10,ROOF_CITY_ROOF
|
|
roof_mansard_chimney:
|
|
mov eax,ridgeZ
|
|
mov roofZ,eax
|
|
mov eax,x0
|
|
add eax,FP_1/2
|
|
mov ebx,y0
|
|
add ebx,FP_1/2
|
|
mov ecx,z
|
|
add ecx,FP_1*24/10
|
|
invoke DrawRoofSolid3D,x0,eax,y0,ebx,roofZ,ecx,ROOF_STONE
|
|
roof_district_next:
|
|
inc esi
|
|
cmp esi,ROOF_BUILDING_COUNT
|
|
jb roof_district_building
|
|
ret
|
|
RenderRoofDistrict3D ENDP
|
|
|
|
RenderRoofCityGround3D PROC uses ebx esi edi
|
|
local row:DWORD,depth:DWORD,px:DWORD,py:DWORD,deltaX:DWORD,deltaY:DWORD
|
|
local road:DWORD,stone:DWORD,water:DWORD,tex:DWORD,ix:DWORD,iy:DWORD
|
|
local sampleDepth:DWORD,planeHeight:DWORD,waterHeight:DWORD
|
|
mov eax,viewEye3D
|
|
sub eax,ROOF_CITY_STREET_Z
|
|
mov planeHeight,eax
|
|
add eax,2*FP_1
|
|
mov waterHeight,eax
|
|
invoke ResolveRoofSurface3D,ROOF_CITY_ROAD
|
|
mov road,eax
|
|
invoke ResolveRoofSurface3D,ROOF_CITY_WATER
|
|
mov water,eax
|
|
invoke ResolveRoofSurface3D,ROOF_STONE
|
|
mov stone,eax
|
|
cmp road,0
|
|
jne @F
|
|
mov road,0FFFFFFFFh
|
|
@@:
|
|
cmp water,0
|
|
jne @F
|
|
mov water,0FFFFFFFDh
|
|
@@:
|
|
cmp stone,0
|
|
jne @F
|
|
mov stone,0FFFFFFFEh
|
|
@@:
|
|
mov roofGroundRoadPixels3D,0
|
|
mov roofGroundWaterPixels3D,0
|
|
mov eax,viewHorizon3D
|
|
inc eax
|
|
mov row,eax
|
|
roof_city_ground_row:
|
|
mov ecx,row
|
|
sub ecx,viewHorizon3D
|
|
mov eax,viewEye3D
|
|
sub eax,ROOF_CITY_STREET_Z
|
|
imul eax,SCREEN_H
|
|
cdq
|
|
idiv ecx
|
|
cmp eax,ROOF_FAR_DEPTH
|
|
jae roof_city_ground_next_row
|
|
mov depth,eax
|
|
imul cityRayX3D[0]
|
|
shrd eax,edx,16
|
|
add eax,playerX
|
|
mov px,eax
|
|
mov eax,depth
|
|
imul cityRayY3D[0]
|
|
shrd eax,edx,16
|
|
add eax,playerY
|
|
mov py,eax
|
|
mov eax,depth
|
|
imul playerPlaneX
|
|
shrd eax,edx,16
|
|
shl eax,1
|
|
cdq
|
|
mov ecx,SCREEN_W
|
|
idiv ecx
|
|
mov deltaX,eax
|
|
mov eax,depth
|
|
imul playerPlaneY
|
|
shrd eax,edx,16
|
|
shl eax,1
|
|
cdq
|
|
idiv ecx
|
|
mov deltaY,eax
|
|
mov eax,row
|
|
imul eax,SCREEN_W*4
|
|
mov edi,eax
|
|
xor ebx,ebx
|
|
roof_city_ground_pixel:
|
|
mov eax,depth
|
|
mov sampleDepth,eax
|
|
cmp px,-600*FP_1
|
|
jl roof_city_ground_advance
|
|
cmp px,600*FP_1
|
|
jg roof_city_ground_advance
|
|
cmp py,-600*FP_1
|
|
jl roof_city_ground_advance
|
|
cmp py,600*FP_1
|
|
jg roof_city_ground_advance
|
|
mov eax,depth
|
|
cmp eax,cityDepthBuffer3D[edi]
|
|
jae roof_city_ground_advance
|
|
mov eax,px
|
|
sar eax,16
|
|
sub eax,20
|
|
cdq
|
|
mov ecx,36
|
|
idiv ecx
|
|
test edx,edx
|
|
jns @F
|
|
add edx,36
|
|
@@:
|
|
mov ix,edx
|
|
mov eax,py
|
|
sar eax,16
|
|
sub eax,11
|
|
cdq
|
|
idiv ecx
|
|
test edx,edx
|
|
jns @F
|
|
add edx,36
|
|
@@:
|
|
mov iy,edx
|
|
mov eax,road
|
|
mov tex,eax
|
|
; Narrow stone pavements border the connected eight-metre carriageways.
|
|
cmp ix,13
|
|
jb roof_city_ground_y_street
|
|
cmp ix,23
|
|
ja roof_city_ground_y_street
|
|
cmp ix,14
|
|
jb roof_city_ground_pavement
|
|
cmp ix,22
|
|
ja roof_city_ground_pavement
|
|
jmp roof_city_ground_canal
|
|
roof_city_ground_y_street:
|
|
cmp iy,13
|
|
jb roof_city_ground_pavement
|
|
cmp iy,23
|
|
ja roof_city_ground_pavement
|
|
cmp iy,14
|
|
jb roof_city_ground_pavement
|
|
cmp iy,22
|
|
jbe roof_city_ground_canal
|
|
roof_city_ground_pavement:
|
|
mov eax,stone
|
|
mov tex,eax
|
|
roof_city_ground_canal:
|
|
cmp py,29*FP_1
|
|
jl roof_city_ground_sample
|
|
cmp py,76*FP_1
|
|
jg roof_city_ground_sample
|
|
cmp py,60*FP_1
|
|
jge roof_city_old_channel
|
|
cmp px,70*FP_1
|
|
jl roof_city_ground_sample
|
|
jmp roof_city_new_bridges
|
|
roof_city_old_channel:
|
|
mov eax,px
|
|
add eax,34*FP_1
|
|
add eax,3*FP_1
|
|
cmp eax,6*FP_1
|
|
jbe roof_city_ground_sample
|
|
mov eax,px
|
|
sub eax,38*FP_1-3*FP_1
|
|
cmp eax,6*FP_1
|
|
jbe roof_city_ground_sample
|
|
roof_city_new_bridges:
|
|
mov eax,px
|
|
sub eax,110*FP_1-3*FP_1
|
|
cmp eax,6*FP_1
|
|
jbe roof_city_ground_sample
|
|
mov eax,px
|
|
sub eax,254*FP_1-3*FP_1
|
|
cmp eax,6*FP_1
|
|
jbe roof_city_ground_sample
|
|
mov eax,px
|
|
sub eax,398*FP_1-3*FP_1
|
|
cmp eax,6*FP_1
|
|
jbe roof_city_ground_sample
|
|
roof_city_ground_water:
|
|
mov eax,water
|
|
mov tex,eax
|
|
mov eax,depth
|
|
imul waterHeight
|
|
idiv planeHeight
|
|
mov sampleDepth,eax
|
|
roof_city_ground_sample:
|
|
mov eax,py
|
|
sar eax,9
|
|
and eax,511
|
|
shl eax,9
|
|
mov edx,px
|
|
sar edx,9
|
|
and edx,511
|
|
add eax,edx
|
|
mov esi,tex
|
|
cmp esi,stone
|
|
jne @F
|
|
shr eax,2
|
|
and eax,65535
|
|
@@:
|
|
cmp esi,0FFFFFFFDh
|
|
jb roof_city_ground_texel
|
|
mov eax,00343B42h
|
|
cmp esi,0FFFFFFFFh
|
|
je roof_city_ground_texel_ready
|
|
mov eax,0063686Ah
|
|
cmp esi,0FFFFFFFEh
|
|
je roof_city_ground_texel_ready
|
|
mov eax,00183848h
|
|
jmp roof_city_ground_texel_ready
|
|
roof_city_ground_texel:
|
|
mov eax,[esi+eax*4]
|
|
roof_city_ground_texel_ready:
|
|
and eax,00FFFFFFh
|
|
cmp esi,road
|
|
jne @F
|
|
inc roofGroundRoadPixels3D
|
|
@@:
|
|
cmp esi,water
|
|
jne roof_city_ground_lighting
|
|
inc roofGroundWaterPixels3D
|
|
cmp roofNight3D,0
|
|
je @F
|
|
mov eax,006E6E6Eh
|
|
jmp roof_city_ground_lighting
|
|
@@:
|
|
mov edx,px
|
|
sar edx,11
|
|
add edx,animationClock3D
|
|
shr edx,4
|
|
and edx,31
|
|
cmp edx,3
|
|
ja roof_city_ground_lighting
|
|
add eax,0020160Ch
|
|
roof_city_ground_lighting:
|
|
invoke SampleRoofGroundLight3D,eax,px,py
|
|
invoke ShadeRoofCityPixel3D,eax,sampleDepth,225,ROOF_CITY_ROAD
|
|
mov screenBuffer[edi],eax
|
|
mov eax,edi
|
|
shr eax,2
|
|
mov roofCityMask3D[eax],1
|
|
mov eax,sampleDepth
|
|
mov cityDepthBuffer3D[edi],eax
|
|
roof_city_ground_advance:
|
|
mov eax,deltaX
|
|
add px,eax
|
|
mov eax,deltaY
|
|
add py,eax
|
|
add edi,4
|
|
inc ebx
|
|
cmp ebx,SCREEN_W
|
|
jb roof_city_ground_pixel
|
|
roof_city_ground_next_row:
|
|
inc row
|
|
cmp row,SCREEN_H
|
|
jb roof_city_ground_row
|
|
; Continuous stone quays and three traversing bridge decks.
|
|
invoke DrawCityBoxSides3D,-190*FP_1,230*FP_1,59*FP_1,60*FP_1,ROOF_CITY_STREET_Z-2*FP_1,ROOF_CITY_STREET_Z,ROOF_STONE
|
|
invoke DrawCityBoxSides3D,-190*FP_1,230*FP_1,76*FP_1,77*FP_1,ROOF_CITY_STREET_Z-2*FP_1,ROOF_CITY_STREET_Z,ROOF_STONE
|
|
mov esi,-34*FP_1
|
|
mov ebx,3
|
|
roof_city_bridge:
|
|
mov eax,esi
|
|
sub eax,3*FP_1
|
|
mov edx,esi
|
|
add edx,3*FP_1
|
|
invoke DrawCityHorizontal3D,eax,edx,59*FP_1,77*FP_1,ROOF_CITY_STREET_Z,ROOF_CITY_ROAD
|
|
add esi,72*FP_1
|
|
dec ebx
|
|
jnz roof_city_bridge
|
|
roof_city_ground_done:
|
|
ret
|
|
RenderRoofCityGround3D ENDP
|
|
|
|
RenderRoofLandmarks3D PROC uses ebx esi edi
|
|
mov roofLandmarkLight3D,1
|
|
lea esi,roofLandmarkParts3D
|
|
mov ebx,ROOF_LANDMARK_PARTS
|
|
roof_landmark_piece:
|
|
cmp DWORD PTR [esi],0
|
|
jne roof_landmark_round
|
|
invoke DrawRoofSolid3D,[esi+4],[esi+8],[esi+12],[esi+16],[esi+20],[esi+24],[esi+28]
|
|
jmp roof_landmark_next
|
|
roof_landmark_round:
|
|
cmp DWORD PTR [esi],2
|
|
jne @F
|
|
invoke DrawRoofPyramid3D,[esi+4],[esi+8],[esi+12],[esi+16],[esi+20],[esi+24],[esi+28]
|
|
jmp roof_landmark_next
|
|
@@:
|
|
invoke DrawRoofEllipsoid3D,[esi+4],[esi+8],[esi+12],[esi+16],[esi+20],[esi+24],[esi+28]
|
|
roof_landmark_next:
|
|
add esi,32
|
|
dec ebx
|
|
jnz roof_landmark_piece
|
|
mov roofLandmarkLight3D,0
|
|
ret
|
|
RenderRoofLandmarks3D ENDP
|
|
|
|
RenderRoofCityParks3D PROC uses ebx esi edi
|
|
local px:DWORD,py:DWORD,x0:DWORD,x1:DWORD,y0:DWORD,y1:DWORD,treeX:DWORD,treeY:DWORD
|
|
xor esi,esi
|
|
roof_city_park:
|
|
mov eax,roofCityParks3D[esi*8]
|
|
mov px,eax
|
|
sub eax,12*FP_1
|
|
mov x0,eax
|
|
add eax,24*FP_1
|
|
mov x1,eax
|
|
mov eax,roofCityParks3D[esi*8+4]
|
|
mov py,eax
|
|
sub eax,12*FP_1
|
|
mov y0,eax
|
|
add eax,24*FP_1
|
|
mov y1,eax
|
|
invoke DrawCityHorizontal3D,x0,x1,y0,y1,ROOF_CITY_STREET_Z+FP_1/20,ROOF_CITY_LAWN
|
|
mov eax,px
|
|
sub eax,FP_1
|
|
mov edx,px
|
|
add edx,FP_1
|
|
invoke DrawCityHorizontal3D,eax,edx,y0,y1,ROOF_CITY_STREET_Z+FP_1/10,ROOF_STONE
|
|
xor ebx,ebx
|
|
roof_city_park_tree:
|
|
mov eax,px
|
|
sub eax,8*FP_1
|
|
test ebx,1
|
|
jz @F
|
|
add eax,16*FP_1
|
|
@@:
|
|
mov treeX,eax
|
|
mov eax,ebx
|
|
shr eax,1
|
|
imul eax,8*FP_1
|
|
add eax,py
|
|
sub eax,8*FP_1
|
|
mov treeY,eax
|
|
mov eax,treeX
|
|
sub eax,FP_1/8
|
|
mov edx,treeX
|
|
add edx,FP_1/8
|
|
mov ecx,treeY
|
|
sub ecx,FP_1/8
|
|
mov edi,treeY
|
|
add edi,FP_1/8
|
|
invoke DrawRoofSolid3D,eax,edx,ecx,edi,ROOF_CITY_STREET_Z,ROOF_CITY_STREET_Z+3*FP_1,ROOF_STONE
|
|
invoke DrawRoofEllipsoid3D,treeX,treeY,ROOF_CITY_STREET_Z+4*FP_1,FP_1*18/10,FP_1*18/10,FP_1*22/10,ROOF_CITY_LAWN
|
|
inc ebx
|
|
cmp ebx,6
|
|
jb roof_city_park_tree
|
|
inc esi
|
|
cmp esi,ROOF_PARK_COUNT
|
|
jb roof_city_park
|
|
ret
|
|
RenderRoofCityParks3D ENDP
|