; Q16.16 simulation, velocities in cloth pixels per 2 ms fixed step. PoolSqrt3D PROC squared:DWORD local result:DWORD fild squared fsqrt fistp result mov eax, result ret PoolSqrt3D ENDP InitPool3D PROC uses ebx esi edi lea edi, poolVX3D xor eax, eax mov ecx, 32 rep stosd xor esi, esi pool_init_balls: mov poolActive3D[esi*4], 1 mov poolPocket3D[esi*4], -1 mov poolSinkTime3D[esi*4], 0 inc esi cmp esi, 16 jb pool_init_balls mov poolX3D, 82*FP_1 mov poolY3D, 115*FP_1 xor esi, esi xor ebx, ebx pool_rack_row: xor edi, edi pool_rack_ball: mov ecx, poolRackOrder3D[esi*4] imul eax, ebx, FP_1*9 add eax, 202*FP_1 mov poolX3D[ecx*4], eax imul eax, edi, 10*FP_1 imul edx, ebx, 5*FP_1 sub eax, edx add eax, 115*FP_1 mov poolY3D[ecx*4], eax inc esi inc edi cmp edi, ebx jbe pool_rack_ball inc ebx cmp ebx, 5 jb pool_rack_row mov poolState3D, POOL_AIM mov poolPlayer3D, 0 mov poolGroups3D, 0 mov poolGroups3D[4], 0 mov poolAngle3D, 0 mov poolPower3D, 80000 mov poolBreak3D, 1 mov poolAccumulator3D, 0 mov poolCharge3D, 0 mov poolTime3D, 0 mov poolFoul3D, 0 mov poolPotted3D, 0 mov poolStill3D, 1 mov poolCalled3D, 1 mov poolCalledPocket3D, 0 ret InitPool3D ENDP ; Symmetric equal-mass impulse plus separation; opening contacts never gain energy. PoolCollide3D PROC uses ebx esi edi a:DWORD,b:DWORD local deltaX:DWORD,deltaY:DWORD,length8:DWORD,nx:DWORD,ny:DWORD,impulse:DWORD,correction:DWORD mov esi, a mov edi, b cmp poolActive3D[esi*4], 0 je pool_pair_done cmp poolActive3D[edi*4], 0 je pool_pair_done mov eax, poolX3D[edi*4] sub eax, poolX3D[esi*4] cmp eax, 10*FP_1 jg pool_pair_done cmp eax, -10*FP_1 jl pool_pair_done mov deltaX, eax mov eax, poolY3D[edi*4] sub eax, poolY3D[esi*4] cmp eax, 10*FP_1 jg pool_pair_done cmp eax, -10*FP_1 jl pool_pair_done mov deltaY, eax sar eax, 8 imul eax, eax mov ebx, deltaX sar ebx, 8 imul ebx, ebx add eax, ebx cmp eax, 100*256*256 jg pool_pair_done test eax, eax jnz @F mov deltaX, 256 mov eax, 1 @@: invoke PoolSqrt3D, eax cmp eax, 1 jge @F mov eax, 1 @@: mov length8, eax mov eax, deltaX imul eax, 256 cdq idiv length8 mov nx, eax mov eax, deltaY imul eax, 256 cdq idiv length8 mov ny, eax mov eax, poolVX3D[edi*4] sub eax, poolVX3D[esi*4] imul nx shrd eax, edx, 16 mov ebx, eax mov eax, poolVY3D[edi*4] sub eax, poolVY3D[esi*4] imul ny shrd eax, edx, 16 add eax, ebx test eax, eax jns pool_pair_separate imul eax, 99 cdq mov ecx, 100 idiv ecx mov impulse, eax imul nx shrd eax, edx, 16 add poolVX3D[esi*4], eax sub poolVX3D[edi*4], eax mov eax, impulse imul ny shrd eax, edx, 16 add poolVY3D[esi*4], eax sub poolVY3D[edi*4], eax test esi, esi jnz pool_pair_separate cmp poolFirst3D, -1 jne pool_pair_separate mov poolFirst3D, edi pool_pair_separate: mov eax, length8 shl eax, 8 neg eax add eax, 10*FP_1 sar eax, 1 mov correction, eax imul nx shrd eax, edx, 16 sub poolX3D[esi*4], eax add poolX3D[edi*4], eax mov eax, correction imul ny shrd eax, edx, 16 sub poolY3D[esi*4], eax add poolY3D[edi*4], eax pool_pair_done: ret PoolCollide3D ENDP PoolPocketBall3D PROC uses ebx esi ball:DWORD mov esi, ball xor ebx, ebx pool_pocket_test: mov eax, poolX3D[esi*4] sub eax, poolPocketX3D[ebx*4] sar eax, 8 imul eax, eax mov ecx, eax mov eax, poolY3D[esi*4] sub eax, poolPocketY3D[ebx*4] sar eax, 8 imul eax, eax add eax, ecx ; The visible 8px mouth is the capture boundary, not a 12px invisible halo. cmp eax, 64*256*256 ja pool_pocket_next pool_pocket_capture: mov poolActive3D[esi*4], 0 mov poolVX3D[esi*4], 0 mov poolVY3D[esi*4], 0 mov poolPocket3D[esi*4], ebx mov poolSinkTime3D[esi*4], 220 bts poolPotted3D, esi ret pool_pocket_next: inc ebx cmp ebx, 6 jb pool_pocket_test ret PoolPocketBall3D ENDP PoolRailContact3D PROC ball:DWORD mov ecx, ball bts poolBreakRails3D, ecx cmp poolFirst3D, -1 je @F mov poolRail3D, 1 @@: ret PoolRailContact3D ENDP PoolJawContact3D PROC uses ebx esi edi ball:DWORD local deltaX:DWORD,deltaY:DWORD,distance:DWORD,normX:DWORD,normY:DWORD,impulse:DWORD mov esi, ball xor edi, edi pool_jaw_test: mov eax, poolX3D[esi*4] sub eax, poolJawX3D[edi*4] cmp eax, 7*FP_1 jg pool_jaw_next cmp eax, -7*FP_1 jl pool_jaw_next mov deltaX, eax mov eax, poolY3D[esi*4] sub eax, poolJawY3D[edi*4] cmp eax, 7*FP_1 jg pool_jaw_next cmp eax, -7*FP_1 jl pool_jaw_next mov deltaY, eax sar eax, 8 imul eax, eax mov ebx, deltaX sar ebx, 8 imul ebx, ebx add eax, ebx cmp eax, 49*256*256 ja pool_jaw_next test eax, eax jnz @F mov deltaX, 256 mov eax, 1 @@: invoke PoolSqrt3D,eax cmp eax, 1 jge @F mov eax, 1 @@: mov distance, eax mov eax, deltaX imul eax, 256 cdq idiv distance mov normX, eax mov eax, deltaY imul eax, 256 cdq idiv distance mov normY, eax mov eax, poolVX3D[esi*4] imul normX shrd eax, edx, 16 mov ebx, eax mov eax, poolVY3D[esi*4] imul normY shrd eax, edx, 16 add eax, ebx test eax, eax jns pool_jaw_separate imul eax, 187 cdq mov ecx, 100 idiv ecx mov impulse, eax imul normX shrd eax, edx, 16 sub poolVX3D[esi*4], eax mov eax, impulse imul normY shrd eax, edx, 16 sub poolVY3D[esi*4], eax invoke PoolRailContact3D,esi pool_jaw_separate: mov eax, distance shl eax, 8 neg eax add eax, 7*FP_1 mov impulse, eax imul normX shrd eax, edx, 16 add poolX3D[esi*4], eax mov eax, impulse imul normY shrd eax, edx, 16 add poolY3D[esi*4], eax pool_jaw_next: inc edi cmp edi, 12 jb pool_jaw_test ret PoolJawContact3D ENDP PoolStep3D PROC uses ebx esi edi xor esi, esi pool_step_ball: cmp poolActive3D[esi*4], 0 je pool_step_next mov eax, poolVX3D[esi*4] add poolX3D[esi*4], eax mov eax, poolVY3D[esi*4] add poolY3D[esi*4], eax invoke PoolPocketBall3D, esi cmp poolActive3D[esi*4], 0 je pool_step_next invoke PoolJawContact3D,esi ; Leave the corner throats open. Solid cushions stop at their jaws. mov ebx, 38*FP_1 mov edi, 282*FP_1 cmp poolY3D[esi*4], 64*FP_1 jle pool_rail_corner_x cmp poolY3D[esi*4], 166*FP_1 jl pool_rail_test_x pool_rail_corner_x: mov ebx, 32*FP_1 mov edi, 288*FP_1 pool_rail_test_x: cmp poolX3D[esi*4], ebx jge pool_rail_right mov poolX3D[esi*4], ebx mov eax, poolVX3D[esi*4] test eax, eax jns pool_rail_y jmp pool_rail_bounce_x pool_rail_right: cmp poolX3D[esi*4], edi jle pool_rail_y mov poolX3D[esi*4], edi mov eax, poolVX3D[esi*4] test eax, eax jle pool_rail_y pool_rail_bounce_x: imul eax, -87 cdq mov ecx, 100 idiv ecx mov poolVX3D[esi*4], eax invoke PoolRailContact3D, esi pool_rail_y: mov ebx, 58*FP_1 mov edi, 172*FP_1 cmp poolX3D[esi*4], 44*FP_1 jle pool_rail_throat_y cmp poolX3D[esi*4], 276*FP_1 jge pool_rail_throat_y cmp poolX3D[esi*4], 153*FP_1 jl pool_rail_test_y cmp poolX3D[esi*4], 167*FP_1 jg pool_rail_test_y pool_rail_throat_y: mov ebx, 52*FP_1 mov edi, 178*FP_1 pool_rail_test_y: cmp poolY3D[esi*4], ebx jge pool_rail_bottom mov poolY3D[esi*4], ebx mov eax, poolVY3D[esi*4] test eax, eax jns pool_step_next jmp pool_rail_bounce_y pool_rail_bottom: cmp poolY3D[esi*4], edi jle pool_step_next mov poolY3D[esi*4], edi mov eax, poolVY3D[esi*4] test eax, eax jle pool_step_next pool_rail_bounce_y: imul eax, -87 cdq mov ecx, 100 idiv ecx mov poolVY3D[esi*4], eax invoke PoolRailContact3D, esi pool_step_next: inc esi cmp esi, 16 jb pool_step_ball ; Two contact passes stabilize the triangular break rack. mov ebx, 2 pool_contact_pass: xor esi, esi pool_contact_outer: lea edi, [esi+1] pool_contact_inner: invoke PoolCollide3D, esi,edi inc edi cmp edi, 16 jb pool_contact_inner inc esi cmp esi, 15 jb pool_contact_outer dec ebx jnz pool_contact_pass xor esi, esi mov poolStill3D, 1 pool_friction_ball: mov eax, poolVX3D[esi*4] sar eax, 8 imul eax, eax mov ecx, poolVY3D[esi*4] sar ecx, 8 imul ecx, ecx add eax, ecx cmp eax, 4 jbe pool_sleep_ball invoke PoolSqrt3D, eax shl eax, 8 cmp eax, 512 jbe pool_sleep_ball mov ecx, eax sub eax, 64 xor edx, edx shld edx, eax, 16 shl eax, 16 div ecx mov ecx, eax mov eax, poolVX3D[esi*4] imul ecx shrd eax, edx, 16 mov poolVX3D[esi*4], eax mov eax, poolVY3D[esi*4] imul ecx shrd eax, edx, 16 mov poolVY3D[esi*4], eax mov poolStill3D, 0 jmp pool_friction_next pool_sleep_ball: mov poolVX3D[esi*4], 0 mov poolVY3D[esi*4], 0 pool_friction_next: inc esi cmp esi, 16 jb pool_friction_ball ret PoolStep3D ENDP PoolBallLegal3D PROC uses ebx ball:DWORD mov ecx, poolPlayer3D mov ebx, poolGroups3D[ecx*4] mov ecx, ball xor eax, eax test ebx, ebx jz pool_legal_open cmp poolAtStart3D, 0 jne pool_legal_group cmp ecx, 8 sete al ret pool_legal_group: cmp ebx, 1 jne pool_legal_stripe cmp ecx, 1 jb pool_legal_done cmp ecx, 7 seta al xor eax, 1 ret pool_legal_stripe: cmp ecx, 9 jb pool_legal_done cmp ecx, 15 seta al xor eax, 1 ret pool_legal_open: test ecx, ecx jle pool_legal_done cmp ecx, 8 je pool_legal_done cmp ecx, 15 seta al xor eax, 1 pool_legal_done: ret PoolBallLegal3D ENDP PoolCountGroup3D PROC uses ebx esi mov poolAtStart3D, 0 mov ecx, poolPlayer3D mov ebx, poolGroups3D[ecx*4] test ebx, ebx jz pool_count_done mov esi, 1 pool_count_ball: cmp esi, 8 je pool_count_next mov eax, 1 cmp esi, 8 jb @F mov eax, 2 @@: cmp eax, ebx jne pool_count_next mov eax, poolActive3D[esi*4] add poolAtStart3D, eax pool_count_next: inc esi cmp esi, 16 jb pool_count_ball pool_count_done: ret PoolCountGroup3D ENDP PoolShoot3D PROC cmp poolState3D, POOL_AIM jne pool_shoot_done call PoolCountGroup3D mov poolFirst3D, -1 mov poolRail3D, 0 mov poolBreakRails3D, 0 mov poolPotted3D, 0 mov poolFoul3D, 0 mov poolCharge3D, 0 mov poolAccumulator3D, 0 mov poolTime3D, 0 mov poolState3D, POOL_STRIKE pool_shoot_done: ret PoolShoot3D ENDP PoolPlaceCue3D PROC uses ebx esi px:DWORD,py:DWORD cmp px, 39*FP_1 jl pool_place_fail cmp px, 281*FP_1 jg pool_place_fail cmp py, 59*FP_1 jl pool_place_fail cmp py, 171*FP_1 jg pool_place_fail mov esi, 1 pool_place_ball: cmp poolActive3D[esi*4], 0 je pool_place_next mov eax, px sub eax, poolX3D[esi*4] sar eax, 8 imul eax, eax mov ebx, eax mov eax, py sub eax, poolY3D[esi*4] sar eax, 8 imul eax, eax add eax, ebx cmp eax, 100*256*256 jbe pool_place_fail pool_place_next: inc esi cmp esi, 16 jb pool_place_ball mov eax, px mov poolX3D, eax mov eax, py mov poolY3D, eax mov poolActive3D, 1 mov poolPocket3D, -1 mov poolSinkTime3D, 0 mov poolVX3D, 0 mov poolVY3D, 0 mov eax, 1 ret pool_place_fail: xor eax, eax ret PoolPlaceCue3D ENDP PoolFinishShot3D PROC uses ebx esi mov poolFoul3D, 0 cmp poolActive3D, 0 je pool_finish_foul cmp poolFirst3D, -1 je pool_finish_foul cmp poolBreak3D, 0 jne pool_finish_break invoke PoolBallLegal3D,poolFirst3D test eax, eax jz pool_finish_foul cmp poolRail3D, 0 jne pool_finish_eight cmp poolPotted3D, 0 jne pool_finish_eight jmp pool_finish_foul pool_finish_break: mov eax, poolPotted3D and eax, 0FFFEh jnz pool_finish_eight mov eax, poolBreakRails3D and eax, 0FFFEh xor ecx, ecx pool_count_break_rails: test eax, eax jz @F lea edx, [eax-1] and eax, edx inc ecx jmp pool_count_break_rails @@: cmp ecx, 4 jae pool_finish_eight pool_finish_foul: mov poolFoul3D, 1 pool_finish_eight: cmp poolActive3D[8*4], 0 jne pool_finish_continue cmp poolBreak3D, 0 je pool_finish_eight_result ; A break eight is re-spotted along the foot spot without overlapping survivors. mov ebx, 220*FP_1 pool_spot_eight_try: mov esi, 1 pool_spot_eight_scan: cmp esi, 8 je pool_spot_eight_next cmp poolActive3D[esi*4], 0 je pool_spot_eight_next mov eax, poolX3D[esi*4] sub eax, ebx sar eax, 8 imul eax, eax mov ecx, eax mov eax, poolY3D[esi*4] sub eax, 115*FP_1 sar eax, 8 imul eax, eax add eax, ecx cmp eax, 100*256*256 jbe pool_spot_eight_advance pool_spot_eight_next: inc esi cmp esi, 16 jb pool_spot_eight_scan mov poolX3D[8*4], ebx mov poolY3D[8*4], 115*FP_1 mov poolActive3D[8*4], 1 mov poolPocket3D[8*4], -1 jmp pool_finish_continue pool_spot_eight_advance: sub ebx, 11*FP_1 cmp ebx, 39*FP_1 jge pool_spot_eight_try call InitPool3D ret pool_finish_eight_result: mov eax, poolPlayer3D cmp poolFoul3D, 0 jne pool_eight_lost cmp poolAtStart3D, 0 jne pool_eight_lost mov ecx, poolGroups3D[eax*4] test ecx, ecx jz pool_eight_lost cmp poolCalled3D, 8 jne pool_eight_lost mov ecx, poolCalledPocket3D cmp ecx, poolPocket3D[8*4] je pool_eight_end pool_eight_lost: xor eax, 1 pool_eight_end: mov poolWinner3D, eax mov poolState3D, POOL_RESULT ret pool_finish_continue: mov eax, poolBreak3D mov poolBreak3D, 0 cmp poolFoul3D, 0 jne pool_change_foul test eax, eax jz pool_finish_called cmp poolPotted3D, 0 jne pool_new_aim jmp pool_change_player pool_finish_called: mov ebx, poolCalled3D cmp ebx, 1 jb pool_change_player cmp ebx, 15 ja pool_change_player bt poolPotted3D, ebx jnc pool_change_player mov eax, poolCalledPocket3D cmp eax, poolPocket3D[ebx*4] jne pool_change_player invoke PoolBallLegal3D,ebx test eax, eax jz pool_change_player mov ecx, poolPlayer3D cmp poolGroups3D[ecx*4], 0 jne pool_new_aim mov eax, 1 cmp ebx, 8 jb @F mov eax, 2 @@: mov poolGroups3D[ecx*4], eax xor ecx, 1 xor eax, 3 mov poolGroups3D[ecx*4], eax jmp pool_new_aim pool_change_foul: xor poolPlayer3D, 1 mov poolState3D, POOL_HAND mov poolTime3D, 0 ret pool_change_player: xor poolPlayer3D, 1 pool_new_aim: mov poolState3D, POOL_AIM mov poolTime3D, 0 ret PoolFinishShot3D ENDP PoolAimPoint3D PROC uses ebx esi edi px:DWORD,py:DWORD local deltaX:DWORD,deltaY:DWORD,best:DWORD,angle:DWORD mov eax, px sub eax, poolX3D sar eax, 8 mov deltaX, eax mov eax, py sub eax, poolY3D sar eax, 8 mov deltaY, eax mov best, 80000000h xor esi, esi pool_aim_direction: mov eax, tableCos[esi*4] sar eax, 8 imul eax, deltaX mov ebx, eax mov eax, tableSin[esi*4] sar eax, 8 imul eax, deltaY add eax, ebx cmp eax, best jle @F mov best, eax mov angle, esi @@: inc esi cmp esi, 512 jb pool_aim_direction mov eax, angle mov poolAngle3D, eax ret PoolAimPoint3D ENDP ; AI selects an actual legal ball and aims a ghost-ball contact towards a pocket. PoolChooseAI3D PROC uses ebx esi edi local deltaX:DWORD,deltaY:DWORD,dist:DWORD,targetX:DWORD,targetY:DWORD call PoolCountGroup3D mov esi, 1 pool_ai_target: cmp poolActive3D[esi*4], 0 je pool_ai_next invoke PoolBallLegal3D,esi test eax, eax jz pool_ai_next mov poolCalled3D, esi xor edi, edi mov dist, 7FFFFFFFh pool_ai_pocket: mov eax, poolPocketX3D[edi*4] sub eax, poolX3D[esi*4] sar eax, 8 imul eax, eax mov ebx, eax mov eax, poolPocketY3D[edi*4] sub eax, poolY3D[esi*4] sar eax, 8 imul eax, eax add eax, ebx cmp eax, dist jge @F mov dist, eax mov poolCalledPocket3D, edi @@: inc edi cmp edi, 6 jb pool_ai_pocket mov edi, poolCalledPocket3D mov eax, poolPocketX3D[edi*4] sub eax, poolX3D[esi*4] mov deltaX, eax mov eax, poolPocketY3D[edi*4] sub eax, poolY3D[esi*4] mov deltaY, eax invoke PoolSqrt3D,dist test eax, eax jnz @F mov eax, 1 @@: mov dist, eax mov eax, deltaX imul eax, 10*256 cdq idiv dist mov ebx, poolX3D[esi*4] sub ebx, eax mov targetX, ebx mov eax, deltaY imul eax, 10*256 cdq idiv dist mov ebx, poolY3D[esi*4] sub ebx, eax mov targetY, ebx invoke PoolAimPoint3D,targetX,targetY mov poolPower3D, 65000 ret pool_ai_next: inc esi cmp esi, 16 jb pool_ai_target mov poolAngle3D, 0 mov poolPower3D, 30000 ret PoolChooseAI3D ENDP HandlePool3D PROC uses ebx esi edi xor esi, esi pool_sink_tick: mov eax, deltaTime3D sub poolSinkTime3D[esi*4], eax jnc @F mov poolSinkTime3D[esi*4], 0 @@: inc esi cmp esi, 16 jb pool_sink_tick mov eax, deltaTime3D add poolTime3D, eax cmp poolState3D, POOL_MOVING jne pool_check_strike add poolAccumulator3D, eax pool_simulate: cmp poolAccumulator3D, 2 jb pool_handle_done sub poolAccumulator3D, 2 call PoolStep3D cmp poolStill3D, 0 je pool_simulate call PoolFinishShot3D ret pool_check_strike: cmp poolState3D, POOL_STRIKE jne pool_check_result cmp poolTime3D, 240 jb pool_handle_done mov ecx, poolAngle3D mov eax, tableCos[ecx*4] imul poolPower3D shrd eax, edx, 16 mov poolVX3D, eax mov eax, tableSin[ecx*4] imul poolPower3D shrd eax, edx, 16 mov poolVY3D, eax mov poolState3D, POOL_MOVING mov poolAccumulator3D, 0 ret pool_check_result: cmp poolState3D, POOL_RESULT jne pool_input invoke Pressed3D,20h test eax, eax jz pool_handle_done call InitPool3D ret pool_input: cmp poolPlayer3D, 1 jne pool_human cmp poolAI3D, 0 je pool_human cmp poolTime3D, 850 jb pool_handle_done cmp poolState3D, POOL_HAND jne pool_ai_shot mov esi, 55 pool_ai_place: mov eax, esi shl eax, 16 invoke PoolPlaceCue3D,eax,115*FP_1 test eax, eax jnz @F add esi, 8 cmp esi, 280 jb pool_ai_place ret @@: mov poolState3D, POOL_AIM pool_ai_shot: call PoolChooseAI3D call PoolShoot3D ret pool_human: cmp mouseClick3D, 0 je pool_key_input cmp mouseY3D, 50 jb pool_mouse_buttons cmp mouseY3D, 180 ja pool_mouse_buttons mov eax, mouseX3D shl eax, 16 mov ebx, mouseY3D shl ebx, 16 cmp poolState3D, POOL_HAND jne pool_mouse_aim invoke PoolPlaceCue3D,eax,ebx test eax, eax jz pool_handle_done mov poolState3D, POOL_AIM ret pool_mouse_aim: invoke PoolAimPoint3D,eax,ebx jmp pool_key_input pool_mouse_buttons: cmp mouseY3D, 193 jb pool_key_input cmp mouseY3D, 209 ja pool_mouse_commands cmp mouseX3D, 202 jb pool_key_input cmp mouseX3D, 308 ja pool_key_input mov eax, mouseX3D sub eax, 202 imul eax, 82000 xor edx, edx mov ecx, 106 div ecx add eax, 8000 mov poolPower3D, eax ret pool_mouse_commands: cmp mouseY3D, 211 jb pool_key_input cmp mouseY3D, 229 ja pool_key_input cmp mouseX3D, 90 jb pool_cycle_ball cmp mouseX3D, 200 jb pool_cycle_pocket call PoolShoot3D ret pool_key_input: cmp poolState3D, POOL_AIM jne pool_handle_done cmp keys3D[25h], 0 je @F sub poolAngle3D, 1 @@: cmp keys3D[27h], 0 je @F add poolAngle3D, 1 @@: and poolAngle3D, 511 mov eax, deltaTime3D imul eax, 100 cmp keys3D[26h], 0 je @F add poolPower3D, eax @@: cmp keys3D[28h], 0 je @F sub poolPower3D, eax @@: cmp poolPower3D, 8000 jge @F mov poolPower3D, 8000 @@: cmp poolPower3D, 90000 jle @F mov poolPower3D, 90000 @@: invoke Pressed3D,42h test eax, eax jnz pool_cycle_ball invoke Pressed3D,50h test eax, eax jnz pool_cycle_pocket invoke Pressed3D,20h test eax, eax jz pool_handle_done call PoolShoot3D ret pool_cycle_ball: inc poolCalled3D cmp poolCalled3D, 15 jbe pool_handle_done mov poolCalled3D, 1 ret pool_cycle_pocket: inc poolCalledPocket3D cmp poolCalledPocket3D, 6 jb pool_handle_done mov poolCalledPocket3D, 0 pool_handle_done: ret HandlePool3D ENDP RenderPool3D PROC uses ebx esi edi local x:DWORD,y:DWORD,angle:DWORD invoke DrawBox,0,0,320,240,00191E1Bh invoke DrawBoxBorder,19,39,282,153,00573D26h,00AC8A4Dh,3 invoke DrawBoxBorder,25,45,270,141,00254432h,009D9161h,2 invoke DrawBox,30,50,260,130,0029744Eh xor esi, esi pool_render_pockets: mov ebx, poolPocketX3D[esi*4] sar ebx, 16 mov edi, poolPocketY3D[esi*4] sar edi, 16 invoke DrawCircle,ebx,edi,8,000E1511h cmp esi, poolCalledPocket3D jne @F invoke DrawCircle,ebx,edi,2,00D7BC6Ah @@: inc esi cmp esi, 6 jb pool_render_pockets xor esi, esi pool_render_balls: cmp poolActive3D[esi*4], 0 je pool_render_sunk_ball mov ebx, poolX3D[esi*4] sar ebx, 16 mov edi, poolY3D[esi*4] sar edi, 16 invoke DrawCircle,ebx,edi,6,001D3024h invoke DrawCircle,ebx,edi,5,poolColors3D[esi*4] cmp esi, 9 jb @F lea eax, [ebx-3] lea edx, [edi-2] invoke DrawBox,eax,edx,7,3,00E9E3CFh @@: lea eax, [ebx-1] lea edx, [edi-1] invoke DrawPixel,eax,edx,00FFFFFFh cmp esi, poolCalled3D jne pool_render_next_ball lea eax, [ebx-3] lea edx, [edi-9] invoke DrawNumber,eax,edx,esi,00F5E7BAh jmp pool_render_next_ball pool_render_sunk_ball: cmp poolSinkTime3D[esi*4], 0 je pool_render_tray_ball mov ecx, poolPocket3D[esi*4] mov ebx, poolPocketX3D[ecx*4] sar ebx, 16 mov edi, poolPocketY3D[ecx*4] sar edi, 16 mov eax, poolSinkTime3D[esi*4] imul eax, 5 xor edx, edx mov ecx, 220 div ecx inc eax invoke DrawCircle,ebx,edi,eax,poolColors3D[esi*4] jmp pool_render_next_ball pool_render_tray_ball: ; Scratched cue is retained on the rack until ball-in-hand placement. imul ebx, esi, 10 add ebx, 20 invoke DrawCircle,ebx,195,4,poolColors3D[esi*4] pool_render_next_ball: inc esi cmp esi, 16 jb pool_render_balls cmp poolState3D, POOL_AIM je pool_render_cue cmp poolState3D, POOL_STRIKE jne pool_render_header pool_render_cue: mov ecx, poolAngle3D mov angle, ecx mov esi, 8 mov eax, poolPower3D shr eax, 12 add esi, eax cmp poolState3D, POOL_STRIKE jne pool_cue_line mov eax, poolTime3D shr eax, 3 sub esi, eax cmp esi, 5 jge pool_cue_line mov esi, 5 pool_cue_line: mov edi, 40 pool_render_cue_pixel: mov ecx, angle mov eax, tableCos[ecx*4] imul esi neg eax add eax, poolX3D sar eax, 16 mov ebx, eax mov eax, tableSin[ecx*4] imul esi neg eax add eax, poolY3D sar eax, 16 invoke DrawCircle,ebx,eax,1,00CFA872h inc esi dec edi jnz pool_render_cue_pixel cmp poolState3D, POOL_AIM jne pool_render_header mov esi, 16 pool_aim_guide_pixel: mov ecx, angle mov eax, tableCos[ecx*4] imul esi add eax, poolX3D sar eax, 16 mov ebx, eax mov eax, tableSin[ecx*4] imul esi add eax, poolY3D sar eax, 16 invoke DrawCircle,ebx,eax,1,008BCB87h add esi, 4 cmp esi, 76 jb pool_aim_guide_pixel pool_render_header: invoke DrawString8x8,12,12,OFFSET poolTitle3D,00E6D09Dh mov ebx, OFFSET poolPlayerText3D mov eax, poolPlayer3D cmp poolState3D, POOL_RESULT jne @F mov eax, poolWinner3D @@: test eax, eax je @F mov ebx, OFFSET poolDealerText3D @@: invoke DrawString8x8,100,12,ebx,00F1ECE0h mov eax, poolPlayer3D mov eax, poolGroups3D[eax*4] invoke DrawString8x8,184,12,poolGroupTexts3D[eax*4],00CCBE94h invoke DrawBoxBorder,12,211,74,18,0039412Fh,00AC9862h,1 invoke DrawString8x8,18,216,OFFSET poolBallText3D,00FFFFFFh invoke DrawNumber,62,216,poolCalled3D,00EAD19Bh invoke DrawBoxBorder,92,211,104,18,0039412Fh,00AC9862h,1 invoke DrawString8x8,98,216,OFFSET poolPocketText3D,00FFFFFFh mov eax, poolCalledPocket3D inc eax invoke DrawNumber,167,216,eax,00EAD19Bh invoke DrawBoxBorder,202,211,106,18,00425232h,00BBA76Fh,1 mov ebx, OFFSET poolShotText3D cmp poolState3D, POOL_RESULT jne @F mov ebx, OFFSET poolRackText3D @@: invoke DrawString8x8,226,216,ebx,00FFFFFFh invoke DrawString8x8,202,187,OFFSET poolPowerText3D,00CCBE94h mov eax, poolPower3D xor edx, edx mov ecx, 900 div ecx invoke DrawNumber,254,187,eax,00FFFFFFh mov eax, poolPower3D sub eax, 8000 imul eax, 106 xor edx, edx mov ecx, 82000 div ecx mov x, eax invoke DrawBox,202,201,106,5,00363D36h invoke DrawBox,202,201,x,5,00D5BB73h mov eax, x add eax, 201 invoke DrawBox,eax,199,2,9,00F4F0DDh cmp poolState3D, POOL_HAND jne @F invoke DrawString8x8,84,30,OFFSET poolPlaceText3D,00E8B9A1h @@: cmp poolState3D, POOL_RESULT jne pool_render_done invoke DrawBoxBorder,102,91,116,39,00192720h,00D6B971h,2 invoke DrawString8x8,130,103,OFFSET poolWinText3D,00FFFFFFh pool_render_done: ret RenderPool3D ENDP