; Two timing gates commit one immutable launch; the same solver serves both players. BeginBowlingPlay3D PROC uses esi lane:DWORD cmp bpActive3D,0 jne bp_begin_no mov esi,lane cmp esi,BW_LANES jae bp_begin_no cmp bwBusy3D[esi*4],0 jne bp_begin_no mov eax,playerX mov bpHomeX3D,eax mov eax,playerY mov bpHomeY3D,eax mov eax,playerAngle mov bpHomeAngle3D,eax mov bpLane3D,esi imul eax,esi,BW_LANE_STEP add eax,3*FP_1 mov bpCentre3D,eax mov bpActive3D,1 mov bwBusy3D[esi*4],2 mov engineMode,MODE_BOWLING mov paused3D,0 mov bwSeat3D,0 call ResetBowlingPlay3D mov bpState3D,BP_SELECT_BALL call BowlingAudioOpen3D mov eax,1 ret bp_begin_no: xor eax,eax ret BeginBowlingPlay3D ENDP ResetBowlingPlay3D PROC uses ebx esi edi mov esi,bpLane3D lea ebx,[esi*8] mov bwFrames3D[ebx],0 mov bwFrames3D[ebx+4],0 mov bwRollCount3D[ebx],0 mov bwRollCount3D[ebx+4],0 mov bwScores3D[ebx],0 mov bwScores3D[ebx+4],0 imul eax,esi,192 lea edi,bwRolls3D[eax] xor eax,eax mov ecx,48 rep stosd mov bwTurn3D[esi*4],0 mov bwBall3D[esi*4],0 mov bwRack3D[esi*4],1023 mov bwState3D[esi*4],0 mov bwHit3D[esi*4],0 mov bwTime3D[esi*4],0 mov bpState3D,BP_DIRECTION mov bpTime3D,0 call BowlingPlayStartAim3D mov bpScoreOpen3D,0 mov bpLast3D,0 mov bpLastKind3D,0 mov bpReactionTime3D,0 mov bpAfterReturn3D,BP_DIRECTION call BowlingPlayRack3D call ClearKeys3D mov mouseClick3D,0 ret ResetBowlingPlay3D ENDP ; Randomize only the visible starting phase, never the committed trajectory. BowlingPlayStartAim3D PROC mov eax,bwRng3D imul eax,1664525 add eax,1013904223 mov bwRng3D,eax shr eax,16 and eax,2047 mov bpClock3D,eax ret BowlingPlayStartAim3D ENDP LeaveBowlingPlay3D PROC uses esi cmp bpActive3D,0 je bp_leave_done call BowlingAudioClose3D mov esi,bpLane3D mov bwBusy3D[esi*4],0 mov bwRack3D[esi*4],1023 mov bwHit3D[esi*4],0 mov bwState3D[esi*4],0 mov bpActive3D,0 mov bpScoreOpen3D,0 mov eax,bpHomeX3D mov playerX,eax mov eax,bpHomeY3D mov playerY,eax mov eax,bpHomeAngle3D mov playerAngle,eax mov engineMode,MODE_WALK call BowlingEye3D call UpdateCamera3D call ClearKeys3D mov mouseClick3D,0 mov bwMonitorClock3D,-1 bp_leave_done: ret LeaveBowlingPlay3D ENDP BowlingPlayRack3D PROC uses esi xor esi,esi bp_rack_pin: mov eax,bwPinX3D[esi*4] mov bpPinX3D[esi*4],eax mov eax,bwPinY3D[esi*4] mov bpPinY3D[esi*4],eax mov bpPinVX3D[esi*4],0 mov bpPinVY3D[esi*4],0 mov bpPinTilt3D[esi*4],0 mov bpPinTiltV3D[esi*4],0 mov bpPinAxisX3D[esi*4],0 mov bpPinAxisY3D[esi*4],-FP_1 mov bpPinSpin3D[esi*4],0 mov bpPinContactTick3D[esi*4],0 mov bpRadius3D[esi*4],24 inc esi cmp esi,10 jb bp_rack_pin mov bpHitMask3D,0 mov bpGutter3D,0 mov bpAccumulator3D,0 mov bpPhysicsTicks3D,0 mov bpEndTicks3D,0 mov bpImpactEnergy3D,0 mov bpImpactCooldown3D,0 mov bpAudioReleased3D,0 mov bpBallX3D,FP_1/2 mov bpBallY3D,24*FP_1 ret BowlingPlayRack3D ENDP BowlingPlayLaunch3D PROC local speed:DWORD,aimX:DWORD,aimLength:REAL8 mov bpState3D,BP_RELEASE mov bpTime3D,0 mov bpAccumulator3D,0 call BowlingApplyBallMass3D mov eax,bpLockedPower3D imul eax,6*FP_1 cdq mov ecx,100 idiv ecx add eax,3*FP_1 mov speed,eax ; The gauge fixes launch work, calibrated to the existing six-kilogram ball. ; v = v_reference * sqrt(m_reference / m); no mass-dependent aim noise. fild bpReferenceKg3D fidiv bpShotWeightKg3D fsqrt fimul speed fist bpLaunchSpeed3D fimul bpTickMs3D fidiv bpSecondMs3D fistp speed mov eax,bpLockedAim3D sub eax,bpBallX3D mov aimX,eax fild aimX fmul st,st fild bpLaneDistance3D fmul st,st faddp st(1),st fsqrt fstp aimLength fild aimX fdiv aimLength fimul speed fistp bpBallVX3D fild bpLaneDistance3D fdiv aimLength fimul speed fchs fistp bpBallVY3D ret BowlingPlayLaunch3D ENDP include src_graphics\bowling_physics.inc include src_graphics\bowling_audio.inc include src_graphics\bowling_return.inc include src_graphics\bowling_weight.inc BowlingPlayFinishRoll3D PROC uses esi mov eax,bpHitMask3D xor ecx,ecx bp_finish_count: test eax,eax jz bp_finish_register lea edx,[eax-1] and eax,edx inc ecx jmp bp_finish_count bp_finish_register: mov bpLast3D,ecx mov bpReaction3D,CAST_TALK cmp ecx,7 jb @F mov bpReaction3D,CAST_CHEER @@: mov bpReactionTime3D,6500 mov bpLastKind3D,0 mov esi,bpLane3D cmp bwBall3D[esi*4],1 jne bp_finish_strike mov eax,bwFirstHit3D[esi*4] cmp eax,10 je bp_finish_strike add eax,ecx cmp eax,10 jne bp_finish_register_score mov bpLastKind3D,2 jmp bp_finish_register_score bp_finish_strike: cmp ecx,10 jne bp_finish_register_score mov bpLastKind3D,1 bp_finish_register_score: cmp bpLastKind3D,0 je @F mov bpReaction3D,CAST_CHEER @@: cmp bpReaction3D,CAST_CHEER jne @F cmp bpAudioReady3D,0 je @F invoke mciSendStringA,OFFSET bpClapPlay,0,0,0 @@: invoke BowlingRegisterRoll3D,bpLane3D,bpLast3D mov bpState3D,BP_SETTLE mov bpTime3D,0 mov bwMonitorClock3D,-1 ret BowlingPlayFinishRoll3D ENDP BowlingPlayNext3D PROC uses ebx esi mov esi,bpLane3D mov eax,bpHitMask3D not eax and bwRack3D[esi*4],eax cmp bwNewRack3D[esi*4],0 je @F mov bwRack3D[esi*4],1023 @@: cmp bwFrameDone3D[esi*4],0 je bp_next_ready xor bwTurn3D[esi*4],1 lea ebx,[esi*2] add ebx,bwTurn3D[esi*4] cmp bwFrames3D[ebx*4],10 jb bp_next_ready xor bwTurn3D[esi*4],1 lea ebx,[esi*2] add ebx,bwTurn3D[esi*4] cmp bwFrames3D[ebx*4],10 jb bp_next_ready mov bpState3D,BP_FINISHED ret bp_next_ready: call BowlingPlayRack3D call BowlingPlayStartAim3D mov bpTime3D,0 mov bpState3D,BP_DIRECTION cmp bwTurn3D[esi*4],0 je @F mov bpState3D,BP_BOT @@: ret BowlingPlayNext3D ENDP HandleBowlingPlay3D PROC uses ebx esi local click:DWORD,elapsed:DWORD,mousePress:DWORD mov eax,deltaTime3D sub bpImpactCooldown3D,eax jns @F mov bpImpactCooldown3D,0 @@: sub bpReactionTime3D,eax jns @F mov bpReactionTime3D,0 @@: invoke Pressed3D,9 test eax,eax jz @F xor bpScoreOpen3D,1 @@: mov eax,mouseClick3D mov click,eax mov mousePress,eax mov mouseClick3D,0 cmp click,0 je @F cmp mouseY3D,224 jb @F cmp mouseX3D,265 jb @F call LeaveBowlingPlay3D ret @@: invoke Pressed3D,20h or click,eax cmp bpScoreOpen3D,0 jne bp_handle_done cmp bpState3D,BP_FINISHED jne bp_handle_clock cmp click,0 je bp_handle_done call ResetBowlingPlay3D mov bpState3D,BP_SELECT_BALL ret bp_handle_clock: mov eax,deltaTime3D cmp eax,250 jbe @F mov eax,250 @@: mov elapsed,eax add bpClock3D,eax add bpTime3D,eax cmp bpState3D,BP_SELECT_BALL jne @F cmp mousePress,0 jne bp_handle_rack_mouse cmp click,0 je bp_handle_rack_mouse mov bpState3D,BP_DIRECTION ret bp_handle_rack_mouse: invoke HandleBowlingWeight3D,mousePress jmp bp_handle_done @@: cmp bpState3D,BP_DIRECTION jne bp_handle_power invoke HandleBowlingWeight3D,mousePress test eax,eax jnz bp_handle_done mov eax,bpClock3D xor edx,edx mov ecx,4 div ecx and eax,511 mov eax,tableSin[eax*4] imul eax,6 cdq mov ecx,5 idiv ecx mov bpAim3D,eax cmp click,0 je bp_handle_done mov bpLockedAim3D,eax mov bpState3D,BP_POWER mov bpClock3D,0 mov bpTime3D,0 ret bp_handle_power: cmp bpState3D,BP_POWER jne bp_handle_release mov eax,bpClock3D xor edx,edx mov ecx,1600 div ecx mov eax,edx cmp eax,800 jbe @F neg eax add eax,1600 @@: shr eax,3 mov bpPower3D,eax cmp click,0 je bp_handle_done mov bpLockedPower3D,eax call BowlingPlayLaunch3D ret bp_handle_release: cmp bpState3D,BP_RELEASE jne bp_handle_roll mov esi,bpLane3D mov ecx,BP_RELEASE_MS cmp bwTurn3D[esi*4],0 je @F mov ecx,2400 @@: cmp bpTime3D,ecx jb bp_handle_done mov bpState3D,BP_ROLL mov bpTime3D,0 ret bp_handle_roll: cmp bpState3D,BP_ROLL jne bp_handle_settle mov eax,elapsed add bpAccumulator3D,eax bp_handle_fixed_step: cmp bpAccumulator3D,16 jb bp_handle_roll_end sub bpAccumulator3D,16 call BowlingPlayStep3D call BowlingPlayReady3D test eax,eax jnz bp_handle_impact_done jmp bp_handle_fixed_step bp_handle_roll_end: jmp bp_handle_done bp_handle_impact_done: call BowlingPlayFinishRoll3D ret bp_handle_settle: cmp bpState3D,BP_SETTLE jne bp_handle_reset cmp bpTime3D,1600 jb bp_handle_done cmp bpHitMask3D,0 jne @F mov esi,bpLane3D cmp bwNewRack3D[esi*4],0 jne @F call CompleteBowlingRoll3D ret @@: mov bpState3D,BP_RESET mov bpTime3D,0 cmp bpAudioReady3D,0 je bp_handle_done invoke mciSendStringA,OFFSET bpResetPlay,0,0,0 jmp bp_handle_done bp_handle_reset: cmp bpState3D,BP_RESET jne bp_handle_bot cmp bpTime3D,BP_RESET_MS jb bp_handle_done call CompleteBowlingRoll3D ret bp_handle_bot: cmp bpState3D,BP_RETURN jne bp_handle_bot_ready cmp bpTime3D,BP_RETURN_MS jb bp_handle_done mov eax,bpAfterReturn3D mov bpState3D,eax mov bpTime3D,0 call ClearKeys3D jmp bp_handle_done bp_handle_bot_ready: cmp bpState3D,BP_BOT jne bp_handle_done cmp bpTime3D,1100 jb bp_handle_done mov eax,bwRng3D imul eax,1664525 add eax,1013904223 mov bwRng3D,eax shr eax,16 xor edx,edx mov ecx,101 div ecx sub edx,50 imul eax,edx,FP_1 cdq mov ecx,100 idiv ecx mov bpLockedAim3D,eax mov eax,bwRng3D shr eax,24 and eax,31 add eax,60 mov bpLockedPower3D,eax call BowlingPlayLaunch3D bp_handle_done: call BowlingAudioUpdate3D ret HandleBowlingPlay3D ENDP include src_graphics\bowling_play_render.inc