InitBowlingSetterSurface3D PROC uses ebx esi edi lea edi,bpSetterSurface3D xor esi,esi bp_setter_surface_row: xor ebx,ebx bp_setter_surface_pixel: mov eax,esi and eax,15 mov edx,002C363Dh test eax,eax jnz @F mov edx,00141B20h @@: cmp eax,1 jne @F mov edx,00414C54h @@: mov eax,ebx and eax,3 imul eax,00010101h add eax,edx or eax,0FF000000h stosd inc ebx cmp ebx,64 jb bp_setter_surface_pixel inc esi cmp esi,64 jb bp_setter_surface_row ret InitBowlingSetterSurface3D ENDP ; Smooth motor travel, clamped at both mechanical stops. BowlingPinsetterEase3D PROC ticks:DWORD,duration:DWORD local phase:DWORD mov eax,ticks test eax,eax jle bp_ease_zero cmp eax,duration jae bp_ease_full imul eax,FP_1 cdq idiv duration mov phase,eax imul eax shrd eax,edx,16 mov ecx,3*FP_1 sub ecx,phase sub ecx,phase imul ecx shrd eax,edx,16 ret bp_ease_zero: xor eax,eax ret bp_ease_full: mov eax,FP_1 ret BowlingPinsetterEase3D ENDP ; Strings stay invisible; the guard closes before the hoist starts. BowlingPinsetterGate3D PROC cmp bpState3D,BP_RESET jne bp_gate_open mov eax,bpTime3D cmp eax,4400 jae bp_gate_open cmp eax,400 jb bp_gate_closing sub eax,4000 invoke BowlingPinsetterEase3D,eax,400 mov ecx,FP_1*87/100 imul ecx shrd eax,edx,16 add eax,FP_1*13/100 ret bp_gate_closing: invoke BowlingPinsetterEase3D,eax,400 mov ecx,FP_1*87/100 imul ecx shrd eax,edx,16 neg eax add eax,FP_1 ret bp_gate_open: mov eax,FP_1 ret BowlingPinsetterGate3D ENDP ; All physical pins remain present aloft, including the knocked-down ones. BowlingPinsetterPose3D PROC uses ebx esi edi pin:DWORD local progress:DWORD mov esi,pin mov edi,bpLane3D mov ebx,bwRack3D[edi*4] mov eax,bpPinX3D[esi*4] mov bpVisualPinX3D,eax mov eax,bpPinY3D[esi*4] mov bpVisualPinY3D,eax mov eax,bpPinTilt3D[esi*4] mov bpVisualPinTilt3D,eax mov bpVisualPinLift3D,0 cmp bpState3D,BP_RESET jne bp_setter_mask cmp bwNewRack3D[edi*4],0 je @F mov ebx,1023 @@: mov eax,bpTime3D cmp eax,2200 jae bp_setter_lower sub eax,400 invoke BowlingPinsetterEase3D,eax,1300 mov progress,eax mov ecx,FP_1*11/10 imul ecx shrd eax,edx,16 mov bpVisualPinLift3D,eax mov eax,bwPinX3D[esi*4] sub eax,bpVisualPinX3D imul progress shrd eax,edx,16 add bpVisualPinX3D,eax mov eax,bwPinY3D[esi*4] sub eax,bpVisualPinY3D imul progress shrd eax,edx,16 add bpVisualPinY3D,eax mov eax,FP_1 sub eax,progress imul bpVisualPinTilt3D shrd eax,edx,16 mov bpVisualPinTilt3D,eax jmp bp_setter_mask bp_setter_lower: cmp bwNewRack3D[edi*4],0 jne bp_setter_new_pose bt bpHitMask3D,esi jnc bp_setter_new_pose mov bpVisualPinLift3D,FP_1*11/10 mov bpVisualPinTilt3D,0 mov eax,bwPinX3D[esi*4] mov bpVisualPinX3D,eax mov eax,bwPinY3D[esi*4] mov bpVisualPinY3D,eax jmp bp_setter_mask bp_setter_new_pose: mov eax,bwPinX3D[esi*4] mov bpVisualPinX3D,eax mov eax,bwPinY3D[esi*4] mov bpVisualPinY3D,eax mov bpVisualPinTilt3D,0 mov eax,bpTime3D sub eax,2200 invoke BowlingPinsetterEase3D,eax,1500 neg eax add eax,FP_1 mov ecx,FP_1*11/10 imul ecx shrd eax,edx,16 mov bpVisualPinLift3D,eax bp_setter_mask: bt ebx,esi setc al movzx eax,al ret BowlingPinsetterPose3D ENDP RenderBowlingPinsetter3D PROC uses ebx esi local lo:DWORD,hi:DWORD,light:DWORD,gate:DWORD,top:DWORD mov eax,bpCentre3D sub eax,FP_1*82/100 mov lo,eax add eax,FP_1*164/100 mov hi,eax invoke DrawRoofSolid3D,lo,hi,FP_1*28/10,FP_1*52/10,FP_1,FP_1*16/10,254 mov eax,lo add eax,FP_1*6/100 invoke DrawRoofSolid3D,lo,eax,FP_1*52/10,FP_1*53/10,0,FP_1*16/10,238 mov eax,hi sub eax,FP_1*6/100 invoke DrawRoofSolid3D,eax,hi,FP_1*52/10,FP_1*53/10,0,FP_1*16/10,238 call BowlingPinsetterGate3D mov gate,eax add eax,FP_1*9/10 mov top,eax invoke DrawRoofSolid3D,lo,hi,FP_1*53/10,FP_1*534/100,gate,top,254 mov eax,gate add eax,FP_1*4/100 invoke DrawCityVertical3D,1,FP_1*535/100,lo,hi,gate,eax,238 mov light,242 cmp bpState3D,BP_RESET jne @F test bpTime3D,100h jz @F mov light,243 @@: mov eax,bpCentre3D sub eax,FP_1/10 mov ebx,bpCentre3D add ebx,FP_1/10 invoke DrawCityVertical3D,1,FP_1*536/100,eax,ebx,FP_1*12/10,FP_1*124/100,light ret RenderBowlingPinsetter3D ENDP