KAZIK/src_graphics/billiards.inc
Artvasil09 3ad5bf4c9d Develop assembly-only casino scenes and native games
Add native Durak, poker, blackjack, roulette, Buckshot and billiards scenes with animation assets and regression tests. Improve arrival, city, hall, profiles, shops, audio and exit handling; remove the portable C game core and refresh shipping executables.
2026-10-08 22:39:19 +03:00

1193 lines
26 KiB
PHP

; 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