; 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 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 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 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 inc esi cmp esi,10 jb bp_rack_pin mov bpHitMask3D,0 mov bpGutter3D,0 mov bpAccumulator3D,0 mov bpBallX3D,0 mov bpBallY3D,FP_1*225/10 ret BowlingPlayRack3D ENDP BowlingPlayLaunch3D PROC mov bpState3D,BP_RELEASE mov bpTime3D,0 mov bpAccumulator3D,0 mov eax,bpLockedPower3D imul eax,6*FP_1 cdq mov ecx,100 idiv ecx add eax,3*FP_1 imul eax,16 cdq mov ecx,1000 idiv ecx mov ecx,eax neg eax mov bpBallVY3D,eax mov eax,bpLockedAim3D imul ecx mov ecx,18*FP_1 idiv ecx mov bpBallVX3D,eax ret BowlingPlayLaunch3D ENDP BowlingPlayHit3D PROC uses esi pin:DWORD,vx:DWORD,vy:DWORD mov esi,pin mov ecx,esi mov eax,1 shl eax,cl test bpHitMask3D,eax jnz bp_hit_done or bpHitMask3D,eax mov eax,vx mov bpPinVX3D[esi*4],eax mov eax,vy mov bpPinVY3D[esi*4],eax bp_hit_done: ret BowlingPlayHit3D ENDP ; 16-ms fixed steps, lane-relative 16.16 discs. No random hit selection. BowlingPlayStep3D PROC uses ebx esi edi local deltaX:DWORD,deltaY:DWORD,impulseX:DWORD,rackMask:DWORD mov esi,bpLane3D mov eax,bwRack3D[esi*4] mov rackMask,eax mov eax,bpBallVX3D add bpBallX3D,eax mov eax,bpBallVY3D add bpBallY3D,eax mov eax,bpBallX3D cdq xor eax,edx sub eax,edx cmp eax,FP_1*74/100 jbe bp_step_pins mov bpGutter3D,1 mov eax,FP_1*87/100 cmp bpBallX3D,0 jge @F neg eax @@: mov bpBallX3D,eax mov bpBallVX3D,0 bp_step_pins: xor esi,esi bp_step_pin: mov ecx,esi mov ebx,1 shl ebx,cl test rackMask,ebx jz bp_step_next_pin test bpHitMask3D,ebx jnz bp_step_move_pin cmp bpGutter3D,0 jne bp_step_next_pin mov eax,bpPinX3D[esi*4] sub eax,bpBallX3D mov deltaX,eax sar eax,8 imul eax,eax mov edi,eax mov eax,bpPinY3D[esi*4] sub eax,bpBallY3D sar eax,8 imul eax,eax add eax,edi cmp eax,56*56 ja bp_step_next_pin mov eax,deltaX sar eax,3 add eax,bpBallVX3D mov impulseX,eax mov eax,bpBallVY3D imul eax,3 sar eax,2 invoke BowlingPlayHit3D,esi,impulseX,eax bp_step_move_pin: mov eax,bpPinVX3D[esi*4] add bpPinX3D[esi*4],eax imul eax,245 sar eax,8 mov bpPinVX3D[esi*4],eax mov eax,bpPinVY3D[esi*4] add bpPinY3D[esi*4],eax imul eax,245 sar eax,8 mov bpPinVY3D[esi*4],eax xor edi,edi bp_step_chain: mov ecx,edi mov ebx,1 shl ebx,cl test rackMask,ebx jz bp_step_chain_next test bpHitMask3D,ebx jnz bp_step_chain_next mov eax,bpPinX3D[edi*4] sub eax,bpPinX3D[esi*4] mov deltaX,eax sar eax,8 imul eax,eax mov ebx,eax mov eax,bpPinY3D[edi*4] sub eax,bpPinY3D[esi*4] mov deltaY,eax sar eax,8 imul eax,eax add eax,ebx cmp eax,49*49 ja bp_step_chain_next mov eax,deltaX sar eax,8 imul bpPinVX3D[esi*4] mov ebx,eax mov eax,deltaY sar eax,8 imul bpPinVY3D[esi*4] add eax,ebx jle bp_step_chain_next mov eax,bpPinVX3D[esi*4] sar eax,1 mov ebx,deltaX sar ebx,3 add eax,ebx mov impulseX,eax mov eax,bpPinVY3D[esi*4] sar eax,1 mov ebx,deltaY sar ebx,3 add eax,ebx invoke BowlingPlayHit3D,edi,impulseX,eax bp_step_chain_next: inc edi cmp edi,10 jb bp_step_chain bp_step_next_pin: inc esi cmp esi,10 jb bp_step_pin ret BowlingPlayStep3D ENDP 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 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: invoke BowlingRegisterRoll3D,bpLane3D,ecx 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 invoke Pressed3D,9 test eax,eax jz @F xor bpScoreOpen3D,1 @@: mov eax,mouseClick3D mov click,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 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_DIRECTION jne bp_handle_power 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,350 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 cmp bpBallY3D,3*FP_1 jl bp_handle_impact_done jmp bp_handle_fixed_step bp_handle_roll_end: cmp bpBallY3D,3*FP_1 jl bp_handle_impact_done cmp bpTime3D,12000 jb bp_handle_done bp_handle_impact_done: call BowlingPlayFinishRoll3D ret bp_handle_settle: cmp bpState3D,BP_SETTLE jne bp_handle_bot cmp bpTime3D,1800 jb bp_handle_done call BowlingPlayNext3D ret bp_handle_bot: 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: ret HandleBowlingPlay3D ENDP include src_graphics\bowling_play_render.inc