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.
1193 lines
26 KiB
PHP
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
|