; Elevator phases: shut, opening, open, closing, travelling. Movement stays manual. InitRoof3D PROC mov liftPhase3D,0 mov liftDoor3D,0 mov liftTrip3D,0 mov liftRideTime3D,0 mov liftAwayTime3D,0 mov roofSeat3D,0 mov roofLean3D,0 mov roofLeanTime3D,0 mov roofNight3D,0 mov roofAAValid3D,0 mov roofUpdateClock3D,-1 ret InitRoof3D ENDP LoadRoofAssets3D PROC invoke LoadAnimPack3D,OFFSET roofSkyArt3D,OFFSET roofSkyPath3D invoke LoadAnimPack3D,OFFSET roofMaterialArt3D,OFFSET roofMaterialPath3D invoke LoadAnimPack3D,OFFSET roofDetailArt3D,OFFSET roofDetailPath3D invoke LoadAnimPack3D,OFFSET roofCityArt3D,OFFSET roofCityPath3D invoke LoadAnimPack3D,OFFSET roofCityNightArt3D,OFFSET roofCityNightPath3D invoke LoadAnimPack3D,OFFSET roofHandsArt3D,OFFSET roofHandsPath3D invoke LoadAnimPack3D,OFFSET roofNightArt3D,OFFSET roofNightPath3D invoke LoadAnimPack3D,OFFSET roofLightingArt3D,OFFSET roofLightingPath3D ret LoadRoofAssets3D ENDP FreeRoofAssets3D PROC call FreeRoofHD3D invoke FreeAnimPack3D,OFFSET roofSkyArt3D invoke FreeAnimPack3D,OFFSET roofMaterialArt3D invoke FreeAnimPack3D,OFFSET roofDetailArt3D invoke FreeAnimPack3D,OFFSET roofCityArt3D invoke FreeAnimPack3D,OFFSET roofCityNightArt3D invoke FreeAnimPack3D,OFFSET roofHandsArt3D invoke FreeAnimPack3D,OFFSET roofNightArt3D invoke FreeAnimPack3D,OFFSET roofLightingArt3D ret FreeRoofAssets3D ENDP ResolveRoofSurface3D PROC material:DWORD mov eax,material sub eax,ROOF_FACADE cmp eax,21 ja roof_surface_furniture cmp roofCityArt3D.pixels,0 je roof_surface_missing shl eax,20 add eax,roofCityArt3D.pixels cmp roofNight3D,0 je roof_surface_city_ready cmp roofCityNightArt3D.pixels,0 je roof_surface_city_ready sub eax,roofCityArt3D.pixels add eax,roofCityNightArt3D.pixels roof_surface_city_ready: mov ecx,512 mov edx,512 ret roof_surface_furniture: mov eax,material cmp eax,ROOF_SOFA_FRONT jb @F sub eax,ROOF_SOFA_FRONT cmp eax,6 ja roof_surface_missing add eax,8 cmp roofDetailArt3D.pixels,0 je roof_surface_missing shl eax,18 add eax,roofDetailArt3D.pixels jmp roof_surface_size @@: cmp eax,ROOF_LIGHT jne @F mov eax,OFFSET roofIndicatorPixel3D mov ecx,1 mov edx,1 ret @@: cmp eax,ROOF_INDICATOR jne @F mov eax,OFFSET roofIndicatorPixels3D mov ecx,64 mov edx,64 ret @@: sub eax,ROOF_DECK cmp eax,7 ja roof_surface_detail cmp roofMaterialArt3D.pixels,0 je roof_surface_missing shl eax,18 add eax,roofMaterialArt3D.pixels jmp roof_surface_size roof_surface_detail: sub eax,8 cmp eax,7 ja roof_surface_missing cmp roofDetailArt3D.pixels,0 je roof_surface_missing shl eax,18 add eax,roofDetailArt3D.pixels roof_surface_size: mov ecx,256 mov edx,256 ret roof_surface_missing: xor eax,eax ret ResolveRoofSurface3D ENDP DrawRoofSky3D PROC uses ebx esi edi local row:DWORD,sourceRow:DWORD,offsetX:DWORD,pixels:DWORD cmp roofSkyArt3D.pixels,0 jne roof_sky_ready invoke DrawBox,0,0,320,240,00334C6Ah ret roof_sky_ready: mov eax,roofSkyArt3D.pixels cmp roofNight3D,0 je @F cmp roofNightArt3D.pixels,0 je @F mov eax,roofNightArt3D.pixels @@: mov pixels,eax mov eax,playerAngle shl eax,2 mov offsetX,eax mov row,0 lea edi,screenBuffer roof_sky_row: mov eax,row add eax,HALF_H sub eax,viewHorizon3D shl eax,9 xor edx,edx mov ecx,480 div ecx cmp eax,511 jbe @F mov eax,511 @@: shl eax,9 mov sourceRow,eax xor ebx,ebx roof_sky_pixel: mov eax,roofSkyColumns3D[ebx*4] add eax,offsetX and eax,2047 mov ecx,eax shr ecx,9 shl ecx,18 and eax,511 add eax,ecx add eax,sourceRow mov esi,pixels mov eax,[esi+eax*4] and eax,00FFFFFFh stosd inc ebx cmp ebx,640 jb roof_sky_pixel inc row cmp row,480 jb roof_sky_row ret DrawRoofSky3D ENDP StandFromRoofSeat3D PROC cmp roofSeat3D,0 je roof_stand_done mov eax,roofReturnX3D mov playerX,eax mov eax,roofReturnY3D mov playerY,eax mov eax,roofReturnAngle3D mov playerAngle,eax mov roofSeat3D,0 roof_stand_done: ret StandFromRoofSeat3D ENDP UpdateRoofEye3D PROC mov viewHorizon3D,HALF_H mov viewCeiling3D,FP_1*5/2 mov viewEye3D,ROOF_STANDING_EYE cmp roofLean3D,0 je @F mov eax,roofLeanTime3D imul eax,FP_1*28/100 xor edx,edx mov ecx,1100 div ecx sub viewEye3D,eax mov eax,roofLeanTime3D imul eax,84 xor edx,edx div ecx sub viewHorizon3D,eax ret @@: cmp roofSeat3D,0 je roof_eye_done mov viewEye3D,ROOF_SEATED_EYE mov eax,roofSeat3D dec eax cmp roofSeatKind3D[eax*4],2 jb roof_eye_done mov viewEye3D,ROOF_STANDING_EYE roof_eye_done: ret UpdateRoofEye3D ENDP UpdateRoof3D PROC uses ebx mov eax,animationClock3D cmp eax,roofUpdateClock3D je roof_update_done mov roofUpdateClock3D,eax cmp engineMode,MODE_WALK jne roof_update_done cmp hallLevel3D,0 je roof_update_lift cmp hallLevel3D,HALL_ROOF jne roof_update_done mov eax,deltaTime3D cmp eax,100 jbe @F mov eax,100 @@: invoke UpdateRoofGuests3D,eax cmp roofLean3D,0 je roof_update_seat call UpdateRoofLook3D mov ebx,deltaTime3D cmp ebx,100 jbe @F mov ebx,100 @@: cmp roofLean3D,3 je roof_lean_retract mov eax,ebx shr eax,2 inc eax cmp keys3D[41h],0 je @F sub playerAngle,eax @@: cmp keys3D[44h],0 je @F add playerAngle,eax @@: call UpdateRoofLook3D cmp keys3D[57h],0 jne roof_lean_release cmp keys3D[53h],0 jne roof_lean_release cmp keys3D[26h],0 jne roof_lean_release cmp keys3D[28h],0 jne roof_lean_release add roofLeanTime3D,ebx cmp roofLeanTime3D,1100 jb roof_update_lift mov roofLeanTime3D,1100 mov roofLean3D,2 jmp roof_update_lift roof_lean_release: mov roofLean3D,3 roof_lean_retract: shl ebx,1 sub roofLeanTime3D,ebx ja roof_update_lift mov roofLeanTime3D,0 mov roofLean3D,0 mov eax,roofReturnX3D mov playerX,eax mov eax,roofReturnY3D mov playerY,eax mov eax,roofReturnAngle3D mov playerAngle,eax call ClearKeys3D jmp roof_update_lift roof_update_seat: cmp roofSeat3D,0 je roof_update_lift cmp keys3D[57h],0 jne roof_update_stand cmp keys3D[53h],0 jne roof_update_stand cmp keys3D[26h],0 jne roof_update_stand cmp keys3D[28h],0 je roof_update_lift roof_update_stand: call StandFromRoofSeat3D roof_update_lift: cmp hallLevel3D,0 jne roof_update_lift_step cmp liftPhase3D,2 jne roof_update_lift_step cmp playerX,FP_1*236/10 jb roof_update_lift_step cmp playerX,FP_1*252/10 ja roof_update_lift_step cmp playerY,FP_1*31/10 ja roof_update_lift_step invoke Pressed3D,31h test eax,eax jz @F mov roofNight3D,0 @@: invoke Pressed3D,32h test eax,eax jz roof_update_lift_step mov roofNight3D,1 roof_update_lift_step: mov ebx,deltaTime3D cmp ebx,100 jbe @F mov ebx,100 @@: cmp liftPhase3D,1 je roof_lift_opening cmp liftPhase3D,2 je roof_lift_open cmp liftPhase3D,3 je roof_lift_closing cmp liftPhase3D,4 je roof_lift_ride ret roof_lift_opening: add liftDoor3D,ebx cmp liftDoor3D,1000 jb roof_update_done mov liftDoor3D,1000 mov liftPhase3D,2 mov liftAwayTime3D,0 ret roof_lift_open: cmp playerX,22*FP_1 jb roof_lift_away cmp playerX,27*FP_1 ja roof_lift_away cmp playerY,6*FP_1 ja roof_lift_away mov liftAwayTime3D,0 ret roof_lift_away: add liftAwayTime3D,ebx cmp liftAwayTime3D,2800 jb roof_update_done mov liftTrip3D,0 mov liftPhase3D,3 ret roof_lift_closing: ; An idle close reverses if the player re-enters the doorway. cmp liftTrip3D,0 jne roof_lift_close_step cmp playerX,23*FP_1 jb roof_lift_close_step cmp playerX,26*FP_1 ja roof_lift_close_step cmp playerY,5*FP_1 ja roof_lift_close_step mov liftPhase3D,1 ret roof_lift_close_step: sub liftDoor3D,ebx ja roof_update_done mov liftDoor3D,0 mov liftPhase3D,0 cmp liftTrip3D,0 je roof_update_done mov liftPhase3D,4 mov liftRideTime3D,0 ret roof_lift_ride: add liftRideTime3D,ebx cmp liftRideTime3D,3200 jb roof_update_done mov eax,liftDestination3D mov hallLevel3D,eax mov worldMap3D,OFFSET casinoMap mov floorTexture3D,100 test eax,eax jz @F mov worldMap3D,OFFSET roofMap3D mov floorTexture3D,ROOF_DECK invoke CopyString3D,OFFSET roofArrival3D,OFFSET flashMessage mov flashTimer,150 @@: mov liftTrip3D,0 mov liftPhase3D,1 mov liftAwayTime3D,0 mov interactTargetId,0 mov interactPromptPtr,0 call ClearKeys3D roof_update_done: ret UpdateRoof3D ENDP CheckRoofInteractions3D PROC uses esi cmp hallLevel3D,0 je roof_check_lift cmp hallLevel3D,HALL_ROOF jne roof_check_done mov interactTargetId,0 mov interactPromptPtr,0 cmp roofLean3D,0 je @F mov interactTargetId,INTERACT_ROOF_RAIL mov interactPromptPtr,OFFSET roofLeanLeave3D ret @@: cmp roofSeat3D,0 je @F mov interactTargetId,INTERACT_ROOF_SEAT mov interactPromptPtr,OFFSET roofStandPrompt3D ret @@: invoke HallTarget3D,15*FP_1,5*FP_1,INTERACT_BAR,OFFSET roofBarPrompt3D cmp interactTargetId,INTERACT_BAR je roof_check_lift xor esi,esi roof_check_seat: invoke HallTarget3D,roofSeatX3D[esi*4],roofSeatY3D[esi*4],INTERACT_ROOF_SEAT,OFFSET roofSeatPrompt3D cmp interactTargetId,INTERACT_ROOF_SEAT jne @F mov roofTargetSeat3D,esi jmp roof_check_lift @@: inc esi cmp esi,ROOF_SEAT_COUNT jb roof_check_seat call CheckRoofRail3D roof_check_lift: cmp liftPhase3D,3 jae roof_check_busy cmp playerX,FP_1*236/10 jb roof_check_call cmp playerX,FP_1*252/10 ja roof_check_call cmp playerY,FP_1*31/10 ja roof_check_call mov interactTargetId,INTERACT_LIFT_TRAVEL mov interactPromptPtr,OFFSET roofLiftUp3D cmp hallLevel3D,HALL_ROOF jne roof_check_done mov interactPromptPtr,OFFSET roofLiftDown3D ret roof_check_call: invoke HallTarget3D,FP_1*2555/100,LIFT_FRONT_Y,INTERACT_LIFT_CALL,OFFSET roofLiftCall3D ret roof_check_busy: cmp liftTrip3D,0 je roof_check_done mov interactTargetId,0 mov interactPromptPtr,OFFSET roofLiftBusy3D cmp liftDestination3D,0 jne roof_check_done mov interactPromptPtr,OFFSET roofLiftBusyDown3D roof_check_done: ret CheckRoofInteractions3D ENDP TryRoofInteraction3D PROC uses ebx cmp hallLevel3D,0 je roof_try_lift cmp hallLevel3D,HALL_ROOF jne roof_try_none cmp interactTargetId,INTERACT_ROOF_RAIL jne @F cmp roofLean3D,0 je roof_try_lean mov roofLean3D,3 jmp roof_try_handled roof_try_lean: call StartRoofLean3D jmp roof_try_handled @@: cmp interactTargetId,INTERACT_ROOF_SEAT jne roof_try_lift cmp roofSeat3D,0 je roof_try_sit call StandFromRoofSeat3D jmp roof_try_handled roof_try_sit: mov ebx,roofTargetSeat3D cmp ebx,ROOF_SEAT_COUNT jae roof_try_none mov eax,playerX mov roofReturnX3D,eax mov eax,playerY mov roofReturnY3D,eax mov eax,playerAngle mov roofReturnAngle3D,eax mov eax,roofSeatX3D[ebx*4] mov playerX,eax mov eax,roofSeatY3D[ebx*4] mov playerY,eax mov playerAngle,384 cmp roofSeatKind3D[ebx*4],3 jne @F mov playerAngle,256 @@: inc ebx mov roofSeat3D,ebx jmp roof_try_handled roof_try_lift: cmp interactTargetId,INTERACT_LIFT_CALL jne roof_try_travel cmp liftPhase3D,3 jae roof_try_none mov liftPhase3D,1 mov liftAwayTime3D,0 jmp roof_try_handled roof_try_travel: cmp interactTargetId,INTERACT_LIFT_TRAVEL jne roof_try_none cmp liftPhase3D,2 jne roof_try_none cmp playerX,FP_1*236/10 jb roof_try_none cmp playerX,FP_1*252/10 ja roof_try_none cmp playerY,FP_1*31/10 ja roof_try_none cmp playerY,FP_1*15/10 jb roof_try_none mov liftDestination3D,HALL_ROOF cmp hallLevel3D,0 je @F mov liftDestination3D,0 @@: mov liftTrip3D,1 mov liftPhase3D,3 mov liftRideTime3D,0 roof_try_handled: call ClearKeys3D mov eax,1 ret roof_try_none: xor eax,eax ret TryRoofInteraction3D ENDP LiftCanWalk3D PROC px:DWORD,py:DWORD cmp hallLevel3D,0 je @F cmp hallLevel3D,HALL_ROOF jne roof_lift_walk_clear @@: cmp py,FP_1*325/100 jb roof_lift_walk_inner cmp py,FP_1*375/100 ja roof_lift_walk_clear cmp px,FP_1*2225/100 jb roof_lift_walk_clear cmp px,FP_1*2655/100 ja roof_lift_walk_clear cmp px,FP_1*236/10 jb roof_lift_walk_block cmp px,FP_1*252/10 ja roof_lift_walk_block roof_lift_walk_inner: cmp px,FP_1*231/10 jb roof_lift_walk_clear cmp px,FP_1*257/10 ja roof_lift_walk_clear cmp py,FP_1*37/10 ja roof_lift_walk_clear cmp liftTrip3D,0 jne roof_lift_walk_block cmp px,FP_1*236/10 jb roof_lift_walk_block cmp px,FP_1*252/10 ja roof_lift_walk_block cmp py,FP_1*15/10 jb roof_lift_walk_block cmp py,FP_1*33/10 jb roof_lift_walk_clear cmp liftDoor3D,950 jb roof_lift_walk_block roof_lift_walk_clear: mov eax,1 ret roof_lift_walk_block: xor eax,eax ret LiftCanWalk3D ENDP RoofCanWalk3D PROC uses ebx esi px:DWORD,py:DWORD cmp roofLean3D,0 jne roof_walk_block cmp roofSeat3D,0 jne roof_walk_block invoke LiftCanWalk3D,px,py test eax,eax jz roof_walk_block cmp px,FP_1*112/10 jb roof_walk_block cmp px,FP_1*288/10 ja roof_walk_block cmp py,FP_1*12/10 jb roof_walk_block cmp py,FP_1*208/10 ja roof_walk_block cmp px,FP_1*117/10 jb roof_walk_furniture cmp px,FP_1*183/10 ja roof_walk_furniture cmp py,FP_1*51/10 jb roof_walk_block roof_walk_furniture: cmp px,FP_1*113/10 jb roof_walk_posts_start cmp px,FP_1*1255/100 ja roof_walk_posts_start cmp py,FP_1*113/10 jb roof_walk_posts_start cmp py,FP_1*167/10 jbe roof_walk_block roof_walk_posts_start: xor esi,esi roof_walk_post: mov eax,px sub eax,roofPostX3D[esi*4] test eax,eax jns @F neg eax @@: cmp eax,FP_1/4 ja roof_walk_post_next mov eax,py sub eax,roofPostY3D[esi*4] test eax,eax jns @F neg eax @@: cmp eax,FP_1/4 jbe roof_walk_block roof_walk_post_next: inc esi cmp esi,8 jb roof_walk_post xor esi,esi roof_walk_sofa: mov eax,px sub eax,roofSeatX3D[esi*4] test eax,eax jns @F neg eax @@: mov ebx,FP_1*17/10 cmp roofSeatKind3D[esi*4],0 je @F mov ebx,FP_1*7/10 cmp roofSeatKind3D[esi*4],2 jb @F mov ebx,FP_1*45/100 @@: cmp eax,ebx ja roof_walk_next mov eax,py sub eax,roofSeatY3D[esi*4] cmp roofSeatKind3D[esi*4],2 jb roof_walk_low_seat cmp eax,-FP_1*45/100 jl roof_walk_next cmp eax,FP_1*65/100 jle roof_walk_block jmp roof_walk_next roof_walk_low_seat: cmp eax,-FP_1/2 jl roof_walk_table cmp eax,FP_1*12/10 jle roof_walk_block roof_walk_table: mov ebx,FP_1*18/10 cmp roofSeatKind3D[esi*4],1 jne @F mov ebx,FP_1*14/10 @@: add eax,ebx cmp eax,-FP_1*6/10 jl roof_walk_next cmp eax,FP_1*6/10 jg roof_walk_next mov eax,px sub eax,roofSeatX3D[esi*4] test eax,eax jns @F neg eax @@: cmp eax,FP_1*8/10 jbe roof_walk_block roof_walk_next: inc esi cmp esi,ROOF_SEAT_COUNT jb roof_walk_sofa xor esi,esi roof_walk_tree: mov eax,px sub eax,roofTreeX3D[esi*4] test eax,eax jns @F neg eax @@: cmp eax,FP_1*5/10 ja roof_walk_tree_next mov eax,py sub eax,roofTreeY3D[esi*4] test eax,eax jns @F neg eax @@: cmp eax,FP_1*5/10 jbe roof_walk_block roof_walk_tree_next: inc esi cmp esi,ROOF_TREE_COUNT jb roof_walk_tree mov eax,1 ret roof_walk_block: xor eax,eax ret RoofCanWalk3D ENDP RenderLift3D PROC uses ebx esi local slide:DWORD call UpdateRoofIndicator3D ; The cabin is real geometry on both landings, never a screen transition. invoke DrawCityBoxSides3D,FP_1*2325/100,FP_1*2345/100,FP_1*12/10,LIFT_FRONT_Y,0,FP_1*24/10,ROOF_PLASTER invoke DrawCityBoxSides3D,FP_1*2535/100,FP_1*2555/100,FP_1*12/10,LIFT_FRONT_Y,0,FP_1*24/10,ROOF_PLASTER invoke DrawCityBoxSides3D,FP_1*2345/100,FP_1*2535/100,FP_1*12/10,FP_1*13/10,0,FP_1*24/10,ROOF_METAL invoke DrawCityHorizontal3D,FP_1*2345/100,FP_1*2535/100,FP_1*13/10,LIFT_FRONT_Y,FP_1*24/10,ROOF_PLASTER invoke DrawCityHorizontal3D,24*FP_1,FP_1*248/10,FP_1*17/10,FP_1*29/10,FP_1*238/100,ROOF_LIGHT invoke DrawCityHorizontal3D,FP_1*2345/100,FP_1*2535/100,FP_1*13/10,LIFT_FRONT_Y,FP_1/50,ROOF_STONE invoke DrawCityVertical3D,1,FP_1*134/100,FP_1*236/10,FP_1*252/10,FP_1*85/100,FP_1*9/10,ROOF_BRASS invoke DrawCityVertical3D,0,FP_1*235/10,FP_1*15/10,3*FP_1,FP_1*85/100,FP_1*9/10,ROOF_BRASS invoke DrawCityVertical3D,0,FP_1*253/10,FP_1*15/10,3*FP_1,FP_1*85/100,FP_1*9/10,ROOF_BRASS invoke DrawCityVertical3D,0,FP_1*2533/100,FP_1*20/10,FP_1*24/10,FP_1*9/10,FP_1*15/10,ROOF_BUTTON invoke DrawCityVertical3D,0,FP_1*2533/100,FP_1*19/10,FP_1*24/10,FP_1*17/10,FP_1*21/10,ROOF_INDICATOR ; Exterior call panel and a lit lintel. invoke DrawCityVertical3D,1,FP_1*358/100,FP_1*254/10,FP_1*258/10,FP_1*9/10,FP_1*15/10,ROOF_BUTTON invoke DrawCityBoxSides3D,FP_1*232/10,FP_1*256/10,FP_1*34/10,FP_1*35/10,FP_1*225/100,FP_1*24/10,ROOF_BRASS invoke DrawCityVertical3D,1,FP_1*357/100,FP_1*241/10,FP_1*247/10,FP_1*226/100,FP_1*24/10,ROOF_INDICATOR mov eax,liftDoor3D imul eax,FP_1*95/100 xor edx,edx mov ecx,1000 div ecx mov slide,eax mov ebx,LIFT_CENTRE_X-FP_1*95/100 sub ebx,eax mov esi,LIFT_CENTRE_X sub esi,eax invoke DrawCityVertical3D,1,LIFT_FRONT_Y,ebx,esi,0,FP_1*225/100,ROOF_DOOR mov eax,slide add eax,LIFT_CENTRE_X mov ebx,eax add eax,FP_1*95/100 invoke DrawCityVertical3D,1,LIFT_FRONT_Y,ebx,eax,0,FP_1*225/100,ROOF_DOOR ; These pockets occlude the translated leaves instead of squeezing their artwork. invoke DrawCityBoxSides3D,FP_1*224/10,FP_1*2345/100,FP_1*344/100,FP_1*356/100,0,FP_1*24/10,ROOF_PLASTER invoke DrawCityBoxSides3D,FP_1*2535/100,FP_1*264/10,FP_1*344/100,FP_1*356/100,0,FP_1*24/10,ROOF_PLASTER ret RenderLift3D ENDP UpdateRoofIndicator3D PROC uses ebx esi edi lea edi,roofIndicatorPixels3D mov eax,0FF101C24h mov ecx,4096 rep stosd mov eax,'1' cmp hallLevel3D,HALL_ROOF jne @F mov eax,'R' @@: cmp liftPhase3D,4 jne roof_indicator_glyph mov eax,liftRideTime3D shr eax,10 inc eax cmp liftDestination3D,0 jne @F neg eax add eax,5 @@: add eax,'0' roof_indicator_glyph: lea esi,font8x8[eax*8] xor ebx,ebx roof_indicator_row: movzx edx,BYTE PTR [esi+ebx] xor ecx,ecx roof_indicator_column: test edx,80h jz roof_indicator_next mov eax,ebx shl eax,2 add eax,16 shl eax,6 mov edi,ecx shl edi,2 add edi,16 add edi,eax lea edi,roofIndicatorPixels3D[edi*4] push ecx push edx mov edx,4 roof_indicator_block_row: mov eax,0FFFFDEA0h mov ecx,4 rep stosd add edi,(64-4)*4 dec edx jnz roof_indicator_block_row pop edx pop ecx roof_indicator_next: shl edx,1 inc ecx cmp ecx,8 jb roof_indicator_column inc ebx cmp ebx,8 jb roof_indicator_row ret UpdateRoofIndicator3D ENDP DrawRoofSofa3D PROC uses ebx esi centreX:DWORD,frontY:DWORD invoke DrawRoofUpholstery3D,centreX,frontY,0 ret DrawRoofSofa3D ENDP DrawRoofChair3D PROC uses ebx esi centreX:DWORD,frontY:DWORD,kind:DWORD invoke DrawRoofUpholstery3D,centreX,frontY,kind ret DrawRoofChair3D ENDP DrawRoofCoffee3D PROC uses ebx centreX:DWORD,centreY:DWORD local x0:DWORD,x1:DWORD,y0:DWORD,y1:DWORD mov eax,centreX sub eax,FP_1*6/10 mov x0,eax add eax,FP_1*12/10 mov x1,eax mov eax,centreY sub eax,FP_1*4/10 mov y0,eax add eax,FP_1*8/10 mov y1,eax invoke DrawCityBoxSides3D,x0,x1,y0,y1,FP_1*4/10,FP_1*45/100,ROOF_STONE invoke DrawCityHorizontal3D,x0,x1,y0,y1,FP_1*45/100,ROOF_MARBLE mov eax,centreX sub eax,FP_1*75/100 mov ebx,centreX add ebx,FP_1*75/100 invoke DrawCityVertical3D,1,centreY,eax,ebx,0,FP_1*9/10,ROOF_TABLE ret DrawRoofCoffee3D ENDP DrawRoofTree3D PROC uses ebx centreX:DWORD,centreY:DWORD,material:DWORD local loX:DWORD,hiX:DWORD,loY:DWORD,hiY:DWORD mov eax,centreX sub eax,FP_1 mov loX,eax add eax,2*FP_1 mov hiX,eax mov eax,centreY sub eax,FP_1 mov loY,eax add eax,2*FP_1 mov hiY,eax invoke DrawCityVertical3D,1,centreY,loX,hiX,0,FP_1*24/10,material invoke DrawCityVertical3D,0,centreX,loY,hiY,0,FP_1*24/10,material ret DrawRoofTree3D ENDP DrawRoofBulb3D PROC uses ebx wx:DWORD,wy:DWORD,wz:DWORD local endX:DWORD,endY:DWORD,endZ:DWORD mov eax,wx add eax,FP_1/12 mov endX,eax mov eax,wy add eax,FP_1/12 mov endY,eax mov eax,wz add eax,FP_1/10 mov endZ,eax mov eax,wx sub eax,FP_1/12 mov ebx,wx add ebx,FP_1/12 mov ecx,wz add ecx,FP_1/4 invoke DrawCityVertical3D,1,wy,eax,ebx,wz,ecx,ROOF_LANTERN ret DrawRoofBulb3D ENDP RenderRoof3D PROC uses ebx esi edi call UpdateRoofQuality3D call UpdateRoofLook3D call UpdateRoofEye3D ; Replace the prepass walls: roof boundaries are low physical rails, not DDA walls. cmp roofHDReady3D,1 jne roof_render_cpu_planes cmp engineMode,MODE_WALK jne roof_render_cpu_planes lea edi,screenBuffer xor eax,eax mov ecx,SCREEN_SIZE rep stosd jmp roof_render_planes_ready roof_render_cpu_planes: call RenderCeilingAndFloor roof_render_planes_ready: lea edi,cityDepthBuffer3D mov eax,ROOF_FAR_DEPTH mov ecx,SCREEN_SIZE rep stosd lea edi,zBuffer mov ecx,SCREEN_W rep stosd lea edi,roofCityMask3D mov eax,02020202h mov ecx,SCREEN_SIZE/4 rep stosd lea edi,roofGlowMask3D xor eax,eax mov ecx,SCREEN_SIZE/4 rep stosd call PrepareCityRays3D call PrepareRoofFloorDepth3D cmp roofHDReady3D,1 jne roof_render_software_city cmp engineMode,MODE_WALK je roof_render_city_ready roof_render_software_city: call PrepareRoofCityAA3D mov roofCityPass3D,1 call RenderRoofCityGround3D call RenderRoofDistrict3D call RenderRoofLandmarks3D call RenderRoofCityParks3D call RenderRoofCityLamps3D call RenderRoofTraffic3D call RenderRoofCityBloom3D call FinishRoofCityAA3D mov roofCityPass3D,0 call PrepareCityRays3D roof_render_city_ready: lea esi,screenBuffer lea edi,roofHDBackdrop3D mov ecx,SCREEN_SIZE rep movsd call RenderLift3D ; Long working bar, lit backbar and a genuine slatted pergola. invoke DrawCityBoxSides3D,12*FP_1,18*FP_1,4*FP_1,FP_1*48/10,0,FP_1*9/10,ROOF_STONE invoke DrawCityVertical3D,1,FP_1*481/100,12*FP_1,15*FP_1,0,FP_1*88/100,ROOF_BAR_FRONT invoke DrawCityVertical3D,1,FP_1*481/100,15*FP_1,18*FP_1,0,FP_1*88/100,ROOF_BAR_FRONT invoke DrawCityHorizontal3D,12*FP_1,18*FP_1,4*FP_1,5*FP_1,FP_1*9/10,ROOF_MARBLE invoke DrawCityBoxSides3D,12*FP_1,18*FP_1,FP_1*15/10,FP_1*17/10,0,FP_1*22/10,ROOF_STONE invoke DrawCityVertical3D,1,FP_1*171/100,12*FP_1,15*FP_1,FP_1*4/10,FP_1*22/10,ROOF_BOTTLES invoke DrawCityVertical3D,1,FP_1*171/100,15*FP_1,18*FP_1,FP_1*4/10,FP_1*22/10,ROOF_BOTTLES xor esi,esi roof_pergola_post: mov ebx,roofPostX3D[esi*4] mov ecx,roofPostY3D[esi*4] mov eax,ebx add eax,FP_1/8 mov edx,ecx add edx,FP_1/8 invoke DrawCityBoxSides3D,ebx,eax,ecx,edx,0,FP_1*28/10,ROOF_STONE inc esi cmp esi,8 jb roof_pergola_post xor esi,esi roof_pergola_slat: mov eax,esi imul eax,FP_1*6/10 add eax,12*FP_1 mov ebx,eax add ebx,FP_1/10 invoke DrawCityHorizontal3D,eax,ebx,FP_1*15/10,FP_1*63/10,FP_1*28/10,ROOF_STONE inc esi cmp esi,11 jb roof_pergola_slat mov eax,animationClock3D shr eax,8 and eax,1 cmp engineMode,MODE_BAR jne roof_tender_frame mov eax,barTime3D xor edx,edx mov ecx,375 div ecx cmp eax,7 jbe @F mov eax,7 @@: mov edx,barSelection3D shl edx,3 add eax,edx roof_tender_frame: mov roofTender3D.frame,eax invoke DrawCityObject3D,OFFSET roofTender3D,0 xor esi,esi roof_draw_sofas: cmp roofSeatKind3D[esi*4],0 jne roof_draw_chair invoke DrawRoofSofa3D,roofSeatX3D[esi*4],roofSeatY3D[esi*4] jmp roof_draw_seat_coffee roof_draw_chair: cmp engineMode,MODE_BAR jne @F cmp roofSeatKind3D[esi*4],2 jae roof_draw_next_seat @@: invoke DrawRoofChair3D,roofSeatX3D[esi*4],roofSeatY3D[esi*4],roofSeatKind3D[esi*4] roof_draw_seat_coffee: cmp roofSeatKind3D[esi*4],2 jae roof_draw_next_seat mov eax,roofSeatY3D[esi*4] sub eax,FP_1*18/10 cmp roofSeatKind3D[esi*4],1 jne @F add eax,FP_1*4/10 @@: invoke DrawRoofCoffee3D,roofSeatX3D[esi*4],eax roof_draw_next_seat: inc esi cmp esi,ROOF_SEAT_COUNT jb roof_draw_sofas ; Standing-height counter along the city rail, with three stools and lamps. invoke DrawCityBoxSides3D,FP_1*115/10,FP_1*122/10,FP_1*115/10,FP_1*165/10,FP_1,FP_1*106/100,ROOF_STONE invoke DrawCityHorizontal3D,FP_1*115/10,FP_1*122/10,FP_1*115/10,FP_1*165/10,FP_1*106/100,ROOF_MARBLE xor esi,esi roof_high_counter_leg: mov eax,esi imul eax,FP_1*23/10 add eax,FP_1*116/10 mov ebx,eax add ebx,FP_1/10 invoke DrawCityBoxSides3D,FP_1*117/10,FP_1*118/10,eax,ebx,0,FP_1,ROOF_METAL inc esi cmp esi,3 jb roof_high_counter_leg invoke DrawRoofBulb3D,FP_1*1185/100,FP_1*124/10,FP_1*107/100 invoke DrawRoofBulb3D,FP_1*1185/100,FP_1*146/10,FP_1*107/100 xor esi,esi roof_draw_trees: invoke DrawRoofTree3D,roofTreeX3D[esi*4],roofTreeY3D[esi*4],ROOF_TREE inc esi cmp esi,ROOF_TREE_COUNT jb roof_draw_trees invoke DrawRoofPlanter3D,12*FP_1,16*FP_1,FP_1*199/10,FP_1*205/10 invoke DrawRoofPlanter3D,23*FP_1,27*FP_1,FP_1*199/10,FP_1*205/10 xor esi,esi roof_rail_post: imul eax,esi,FP_1*25/10 add eax,FP_1*112/10 mov ebx,eax add ebx,FP_1/14 invoke DrawCityBoxSides3D,eax,ebx,FP_1*208/10,21*FP_1,0,ROOF_RAIL_HEIGHT,ROOF_METAL mov eax,esi imul eax,FP_1*25/10 add eax,FP_1*112/10 mov ebx,eax add ebx,FP_1/14 invoke DrawCityBoxSides3D,eax,ebx,FP_1,FP_1*12/10,0,ROOF_RAIL_HEIGHT,ROOF_METAL inc esi cmp esi,8 jb roof_rail_post invoke DrawRoofSolid3D,11*FP_1,29*FP_1,FP_1*2085/100,FP_1*2095/100,FP_1*98/100,ROOF_RAIL_HEIGHT,ROOF_METAL invoke DrawRoofSolid3D,11*FP_1,29*FP_1,FP_1*105/100,FP_1*115/100,FP_1*98/100,ROOF_RAIL_HEIGHT,ROOF_METAL invoke DrawRoofSolid3D,FP_1*1105/100,FP_1*1115/100,FP_1,21*FP_1,FP_1*98/100,ROOF_RAIL_HEIGHT,ROOF_METAL invoke DrawRoofSolid3D,FP_1*2885/100,FP_1*2895/100,FP_1,21*FP_1,FP_1*98/100,ROOF_RAIL_HEIGHT,ROOF_METAL xor esi,esi roof_rail_side_post: imul eax,esi,FP_1*25/10 add eax,FP_1*12/10 mov ebx,eax add ebx,FP_1/14 invoke DrawCityBoxSides3D,11*FP_1,FP_1*112/10,eax,ebx,0,ROOF_RAIL_HEIGHT,ROOF_METAL mov eax,esi imul eax,FP_1*25/10 add eax,FP_1*12/10 mov ebx,eax add ebx,FP_1/14 invoke DrawCityBoxSides3D,FP_1*288/10,29*FP_1,eax,ebx,0,ROOF_RAIL_HEIGHT,ROOF_METAL inc esi cmp esi,8 jb roof_rail_side_post ; Two suspended strings of small physical lamps, with edge supports. xor esi,esi roof_string_bulb: imul eax,esi,FP_1*13/10 add eax,12*FP_1 invoke DrawRoofBulb3D,eax,7*FP_1,FP_1*235/100 imul eax,esi,FP_1*13/10 add eax,12*FP_1 invoke DrawRoofBulb3D,eax,15*FP_1,FP_1*235/100 inc esi cmp esi,13 jb roof_string_bulb invoke DrawCityVertical3D,1,7*FP_1,12*FP_1,28*FP_1,FP_1*26/10,FP_1*261/100,ROOF_METAL invoke DrawCityVertical3D,1,15*FP_1,12*FP_1,28*FP_1,FP_1*26/10,FP_1*261/100,ROOF_METAL xor esi,esi roof_guest_draw: mov eax,roofGuestX3D[esi*4] mov roofActor3D.posX,eax mov eax,roofGuestY3D[esi*4] mov roofActor3D.posY,eax invoke ConfigureRoofVisitor3D,esi invoke DrawCityObject3D,OFFSET roofActor3D,0 inc esi cmp esi,ROOF_GUEST_COUNT jb roof_guest_draw call ShadeRoofNight3D call RenderRoofLean3D call RenderRoofQualityToast3D ret RenderRoof3D ENDP include src_graphics\rooftop_details.inc include src_graphics\rooftop_atmosphere.inc include src_graphics\rooftop_surfaces.inc include src_graphics\rooftop_city_life.inc include src_graphics\rooftop_gl.inc include src_graphics\rooftop_quality.inc