KAZIK/tools/tests/casino_actions_test.inc
Artvasil09 4f8ae0893b Implement native slots, coin toss, European roulette and hall furniture
Add native assembly scenes and assets for Slots (777), Coin flip, and European Roulette; add 3D hall furniture packs and prompts; improve Russian UI strings in CP1251; update launcher hash and rebuild shipping binaries.
2026-10-10 14:43:30 +03:00

582 lines
16 KiB
PHP

; Compiled only with /DCASINO_ACTION_TEST. Uses the actual game renderer and handlers.
.data
actionBmpHeader db 42h,4Dh
dd 1228854
dw 0,0
dd 54,40,640,-480
dw 1,32
dd 0,1228800,0,0,0,0
actionReportPath db "build\actions\test-report.txt",0
actionReportText db "PASS: fullscreen/startup/audio/dice/2000 roulette rounds; 9021 exact poker rankings, 500 poker hands, 500 blackjack hands; entrance/profiles/merchant; ",13,10
db "hall/basement/bar; multi-bet roulette; billiards impulses/rails/jaws/pockets/fixed timestep/8-ball outcomes; render invariants",13,10
db "Buckshot: 250 complete rounds, trigger timing, items/turns/payouts/death/recovery; 30 native scene snapshots",13,10
db "World: complete camera/car route; staff/front bar access; cabaret collision; six pocket throats; 100 varied-force breaks; 3 distinct drinks",13,10
db "Cards: exit/cancel from every active phase, frozen hand, mouse/keyboard, no refunds/double payouts; street lamp/window lightmap",13,10
db "Durak: 500 native complete games, 5184 beat pairs, transfers/takes/refill/trump, 36-card conservation, paging, exit in every phase",13,10
db "777: 8000 stop combinations, 500 complete spins at four rates, monotonic reels, payouts, safe queued exit, native framebuffer snapshots",13,10
db "Coin: 500 paid flips at four rates, safe exit in all phases, 1701 continuous poses, payouts, controls, missing art, 10 native frames",13,10
db "Coin detail: owned window, monitor bounds, restoration, F11, no quit/focus stealing; five private-buffer captures",13,10
actionReportSize equ ($-actionReportText)
actionDiceTimes dd 0,200,500,800,1200,1600
actionDice0 db "build\actions\dice-0.bmp",0
actionDice1 db "build\actions\dice-200.bmp",0
actionDice2 db "build\actions\dice-500.bmp",0
actionDice3 db "build\actions\dice-800.bmp",0
actionDice4 db "build\actions\dice-1200.bmp",0
actionDice5 db "build\actions\dice-1600.bmp",0
actionDicePaths dd OFFSET actionDice0,OFFSET actionDice1,OFFSET actionDice2
dd OFFSET actionDice3,OFFSET actionDice4,OFFSET actionDice5
actionRRTimes dd 0,900,1600,700,500,30,200,0,900,2400
actionRRStates dd RR_LOAD,RR_LOAD,RR_LOAD,RR_SPIN,RR_RAISE,RR_FIRE,RR_GLITCH,RR_GMAN,RR_GMAN,RR_GMAN
actionRR0 db "build\actions\rr-load-0.bmp",0
actionRR1 db "build\actions\rr-load-900.bmp",0
actionRR2 db "build\actions\rr-load-1600.bmp",0
actionRR3 db "build\actions\rr-spin.bmp",0
actionRR4 db "build\actions\rr-raise.bmp",0
actionRR5 db "build\actions\rr-fire.bmp",0
actionRR6 db "build\actions\rr-glitch.bmp",0
actionRR7 db "build\actions\rr-gman-0.bmp",0
actionRR8 db "build\actions\rr-gman-900.bmp",0
actionRR9 db "build\actions\rr-gman-2400.bmp",0
actionLoadingHand db "build\actions\rr-loading-hand.bmp",0
actionRRPaths dd OFFSET actionRR0,OFFSET actionRR1,OFFSET actionRR2,OFFSET actionRR3,OFFSET actionRR4
dd OFFSET actionRR5,OFFSET actionRR6,OFFSET actionRR7,OFFSET actionRR8,OFFSET actionRR9
actionStartupTimes dd 0,240,700,1300,2500,6500
actionStartup0 db "build\actions\intro-0.bmp",0
actionStartup1 db "build\actions\intro-240.bmp",0
actionStartup2 db "build\actions\intro-700.bmp",0
actionStartup3 db "build\actions\intro-1300.bmp",0
actionStartup4 db "build\actions\intro-2500.bmp",0
actionStartup5 db "build\actions\intro-6500.bmp",0
actionStartupFallback db "build\actions\intro-fallback.bmp",0
actionStartupPaths dd OFFSET actionStartup0,OFFSET actionStartup1,OFFSET actionStartup2
dd OFFSET actionStartup3,OFFSET actionStartup4,OFFSET actionStartup5
actionStudio0 db "build\actions\studio-0.bmp",0
actionStudio1 db "build\actions\studio-240.bmp",0
actionStudio2 db "build\actions\studio-700.bmp",0
actionStudio3 db "build\actions\studio-1300.bmp",0
actionStudio4 db "build\actions\studio-2500.bmp",0
actionStudio5 db "build\actions\studio-6500.bmp",0
actionStudioPaths dd OFFSET actionStudio0,OFFSET actionStudio1,OFFSET actionStudio2
dd OFFSET actionStudio3,OFFSET actionStudio4,OFFSET actionStudio5
.code
WriteActionSnapshot3D PROC uses ebx path:DWORD
local count:DWORD
invoke CreateFileA, path, 40000000h, 0, 0, 2, 80h, 0
cmp eax, -1
je snapshot_failed
mov ebx, eax
invoke WriteFile, ebx, OFFSET actionBmpHeader, 54, ADDR count, 0
test eax, eax
jz snapshot_close_failed
invoke WriteFile, ebx, OFFSET screenBuffer, 1228800, ADDR count, 0
test eax, eax
jz snapshot_close_failed
cmp count, 1228800
jne snapshot_close_failed
invoke CloseHandle, ebx
mov eax, 1
ret
snapshot_close_failed:
invoke CloseHandle, ebx
snapshot_failed:
xor eax, eax
ret
WriteActionSnapshot3D ENDP
include tools\tests\card_tables_test.inc
include tools\tests\arrival_test.inc
include tools\tests\hall_test.inc
include tools\tests\buckshot_test.inc
include tools\tests\unavailable_test.inc
include tools\tests\card_exit_test.inc
include tools\tests\city_lighting_test.inc
include tools\tests\durak_test.inc
include tools\tests\slots_test.inc
include tools\tests\coin_detail_test.inc
include tools\tests\coin_test.inc
RunCasinoActionsTest3D PROC uses ebx esi edi
local savedSeed:DWORD,iterations:DWORD,chamberMask:DWORD,value1:DWORD,value2:DWORD,count:DWORD
local testExecutable[260]:BYTE
invoke GetModuleFileNameA, 0, ADDR testExecutable, 260
cmp eax, 20
jb @F
lea edx, testExecutable
sub eax, 20
add eax, edx
invoke lstrcmpiA, eax, OFFSET bsPreviewName3D
test eax, eax
jnz @F
call RunBuckshotPreview3D
ret
@@:
; The actual creation path must be fullscreen before it ever becomes visible.
call Create3DWindow
test eax, eax
jz action_fail_14
cmp fullscreen3D, 1
jne action_fail_14
invoke GetWindowLongA, h3DWnd, -16
test eax, 10000000h
jnz action_fail_14
invoke GetWindowRect, h3DWnd, OFFSET clientRect3D
lea esi, clientRect3D
lea edi, monitor3D[4]
mov ecx, 4
repe cmpsd
jne action_fail_14
call ToggleFullscreen3D
cmp fullscreen3D, 0
jne action_fail_14
invoke GetWindowRect, h3DWnd, OFFSET clientRect3D
lea esi, clientRect3D
lea edi, savedRect3D
mov ecx, 4
repe cmpsd
jne action_fail_14
call ToggleFullscreen3D
cmp fullscreen3D, 1
jne action_fail_14
call RunCoinDetailWindowTest3D
test eax,eax
jz @F
ret
@@:
invoke ReleaseDC, h3DWnd, h3DDC
mov h3DDC, 0
invoke DestroyWindow, h3DWnd
mov h3DWnd, 0
; Dirty state cannot bypass the studio screen or turn an Enter into a shot.
mov rngSeed3D, 12345678h
mov savedSeed, 12345678h
mov engineMode, MODE_RUSSIAN
mov paused3D, 1
mov interactTargetId, INTERACT_RUSSIAN_ROULETTE
mov keys3D[45h], 1
call BeginStartup3D
cmp engineMode, MODE_INTRO
jne action_fail_15
cmp paused3D, 0
jne action_fail_15
cmp interactTargetId, 0
jne action_fail_15
cmp keys3D[45h], 0
jne action_fail_15
cmp startupPixels3D, 0
je action_fail_15
cmp startupSequence3D, 0
je action_fail_15
cmp startupSequenceHeader3D[12], 100
jne action_fail_15
cmp startupSequenceHeader3D[16], 36
jne action_fail_15
mov startupElapsed3D, 1619
call ResolveStartupFrame3D
cmp eax, 35
jne action_fail_15
mov startupElapsed3D, 1620
call ResolveStartupFrame3D
cmp eax, 36
jne action_fail_15
mov startupElapsed3D, 4499
call ResolveStartupFrame3D
cmp eax, 99
jne action_fail_15
mov startupElapsed3D, 4500
call ResolveStartupFrame3D
cmp eax, 36
jne action_fail_15
xor esi, esi
action_startup_snapshots:
mov eax, actionStartupTimes[esi*4]
mov startupElapsed3D, eax
call RenderStartup3D
mov eax, savedSeed
cmp eax, rngSeed3D
jne action_fail_15
invoke WriteActionSnapshot3D, actionStartupPaths[esi*4]
test eax, eax
jz action_fail_15
inc esi
cmp esi, 6
jb action_startup_snapshots
mov deltaTime3D, 16
mov pressedKeys3D[71h], 1
call HandleStartupInput3D
cmp startupVariant3D, 1
jne action_fail_15
xor esi, esi
action_studio_snapshots:
mov eax, actionStartupTimes[esi*4]
mov startupElapsed3D, eax
call RenderStartup3D
invoke WriteActionSnapshot3D, actionStudioPaths[esi*4]
test eax, eax
jz action_fail_15
inc esi
cmp esi, 6
jb action_studio_snapshots
mov deltaTime3D, 16
mov pressedKeys3D[0Dh], 1
mov keys3D[57h], 1
mov pressedKeys3D[45h], 1
call HandleStartupInput3D
cmp engineMode, MODE_ARRIVAL
jne action_fail_15
cmp keys3D[57h], 0
jne action_fail_15
cmp pressedKeys3D[45h], 0
jne action_fail_15
cmp startupPixels3D, 0
jne action_fail_15
cmp startupSequence3D, 0
jne action_fail_15
; Missing intro art remains a playable branded screen, not a crash/dialog loop.
mov startupPath3D, '_'
mov startupSequencePath3D, '_'
call BeginStartup3D
mov startupPath3D, 'a'
mov startupSequencePath3D, 'a'
cmp startupPixels3D, 0
jne action_fail_15
mov startupElapsed3D, 2000
call RenderStartup3D
invoke WriteActionSnapshot3D, OFFSET actionStartupFallback
test eax, eax
jz action_fail_15
mov pressedKeys3D[20h], 1
call HandleStartupInput3D
cmp engineMode, MODE_ARRIVAL
jne action_fail_15
cmp rngSeed3D, 12345678h
jne action_fail_15
invoke PlayCasinoSound3D, OFFSET soundClick, 0, 1
cmp lastSoundPath3D, OFFSET soundClick
jne action_fail_13
cmp lastSoundFlags3D, 20013h
jne action_fail_13
mov bankroll, 10000
mov targetBank, 300000
invoke PlayCasinoSound3D, OFFSET soundRoundWin, 0, 1
cmp lastSoundPath3D, OFFSET soundRoundWin
jne action_fail_13
mov bankroll, 300000
invoke PlayCasinoSound3D, OFFSET soundVictory, 0, 1
cmp lastSoundPath3D, OFFSET soundVictory
jne action_fail_13
mov bankroll, 50
invoke PlayCasinoSound3D, OFFSET soundLose, 0, 1
cmp lastSoundPath3D, OFFSET soundRoundLose
jne action_fail_13
mov bankroll, 0
invoke PlayCasinoSound3D, OFFSET soundLose, 0, 1
cmp lastSoundPath3D, OFFSET soundLose
jne action_fail_13
invoke PlayCasinoSound3D, OFFSET rrDrySound3D, 0, 1
cmp lastSoundPath3D, OFFSET rrDrySound3D
jne action_fail_13
cmp lastSoundFlags3D, 20003h
jne action_fail_13
mov bankroll, 10000
mov dice3d_bet, 50
mov dice3d_choice, 1
call InitDiceGame
mov pressedKeys3D[20h], 1
call HandleDiceInput
cmp lastSoundPath3D, OFFSET soundDiceRoll
jne action_fail_13
cmp bankroll, 9950
jne action_fail_1
cmp dice3d_state, 1
jne action_fail_1
mov eax, rngSeed3D
mov savedSeed, eax
mov eax, dice3d_val1
mov value1, eax
mov eax, dice3d_val2
mov value2, eax
mov deltaTime3D, 16
mov esi, 100
action_dice_updates:
call HandleDiceInput
dec esi
jnz action_dice_updates
cmp dice3d_state, 2
jne action_fail_2
mov eax, savedSeed
cmp eax, rngSeed3D
jne action_fail_2
mov eax, value1
cmp eax, dice3d_val1
jne action_fail_2
add eax, value2
cmp eax, dice3d_sum
jne action_fail_2
mov ebx, 9950
test eax, 1
jnz @F
add ebx, 100
@@:
cmp ebx, bankroll
jne action_fail_3
mov deltaTime3D, 50
call HandleDiceInput
cmp ebx, bankroll
jne action_fail_3
mov dice3d_state, 1
mov dice3d_val1, 4
mov dice3d_val2, 6
xor esi, esi
action_dice_snapshots:
mov dice3d_sum, 10
mov dice3d_win, 100
mov eax, actionDiceTimes[esi*4]
mov dice3d_timer, eax
cmp eax, 1600
jne @F
mov dice3d_state, 2
@@:
call RenderDiceGame
mov eax, savedSeed
cmp eax, rngSeed3D
jne action_fail_4
invoke WriteActionSnapshot3D, actionDicePaths[esi*4]
test eax, eax
jz action_fail_4
inc esi
cmp esi, 6
jb action_dice_snapshots
mov engineMode, MODE_RUSSIAN
call InitRussianGame3D
test eax, eax
jz action_fail_5
mov rr3d_bullets, 3
mov rr3d_mask, 25h
mov rr3d_shot, 1
xor esi, esi
action_rr_snapshots:
mov eax, actionRRStates[esi*4]
mov rr3d_state, eax
mov eax, actionRRTimes[esi*4]
mov rr3d_timer, eax
call RenderRussianGame3D
mov eax, savedSeed
cmp eax, rngSeed3D
jne action_fail_6
invoke WriteActionSnapshot3D, actionRRPaths[esi*4]
test eax, eax
jz action_fail_6
inc esi
cmp esi, 10
jb action_rr_snapshots
mov rr3d_state, RR_LOAD
mov rr3d_timer, 270
call RenderRussianGame3D
invoke WriteActionSnapshot3D, OFFSET actionLoadingHand
test eax, eax
jz action_fail_6
; Fixed empty chamber, then live dealer chamber. No cylinder reroll between turns.
mov rr3d_mask, 2
mov rr3d_chamber, 0
mov rr3d_turn, 0
mov rr3d_state, RR_RAISE
mov rr3d_bet, 50
mov bankroll, 9950
call AdvanceRussianScene3D
cmp rr3d_shot, 0
jne action_fail_7
call AdvanceRussianScene3D
cmp rr3d_state, RR_DRY
jne action_fail_7
call AdvanceRussianScene3D
cmp rr3d_turn, 1
jne action_fail_7
cmp rr3d_chamber, 1
jne action_fail_7
call AdvanceRussianScene3D
cmp rr3d_shot, 1
jne action_fail_7
call AdvanceRussianScene3D
cmp rr3d_state, RR_WIN
jne action_fail_8
cmp bankroll, 10050
jne action_fail_8
call AdvanceRussianScene3D
cmp bankroll, 10050
jne action_fail_8
; Many starting chambers, bullet counts, update rates and first players.
mov iterations, 2000
action_round_loop:
mov bankroll, 10000
mov rr3d_state, RR_READY
mov rr3d_bet, 50
mov eax, iterations
xor edx, edx
mov ecx, 3
div ecx
inc edx
mov rr3d_bullets, edx
call StartRussianRound3D
cmp bankroll, 9950
jne action_fail_9
mov eax, rr3d_mask
mov chamberMask, eax
xor ecx, ecx
mov ebx, eax
action_count_bits:
shr ebx, 1
adc ecx, 0
test ebx, ebx
jnz action_count_bits
cmp ecx, rr3d_bullets
jne action_fail_9
mov eax, iterations
and eax, 1
imul eax, 34
add eax, 16
mov deltaTime3D, eax
mov ebx, 0
action_round_tick:
mov pressedKeys3D[20h], 1
call HandleRussianInput3D
mov eax, chamberMask
cmp eax, rr3d_mask
jne action_fail_10
inc ebx
cmp ebx, 1800
ja action_fail_10
cmp engineMode, MODE_WALK
je action_lost
cmp rr3d_state, RR_WIN
jne action_round_tick
cmp bankroll, 10050
jne action_fail_11
jmp action_round_done
action_lost:
cmp bankroll, 9950
jne action_fail_11
cmp rr3d_state, RR_READY
jne action_fail_11
action_round_done:
mov engineMode, MODE_RUSSIAN
mov pressedKeys3D[20h], 0
dec iterations
jnz action_round_loop
; A failed stake must not start a scene or create money.
mov bankroll, 0
mov rr3d_state, RR_READY
call StartRussianRound3D
cmp rr3d_state, RR_READY
jne action_fail_12
cmp bankroll, 0
jne action_fail_12
call RunUnavailableTest3D
test eax,eax
jz @F
ret
@@:
call RunCardTablesTest3D
test eax, eax
jz @F
ret
@@:
call RunArrivalTest3D
test eax, eax
jz @F
ret
@@:
call RunCardExitTest3D
test eax, eax
jz @F
ret
@@:
call RunCityLightingTest3D
test eax, eax
jz @F
ret
@@:
call RunDurakTest3D
test eax, eax
jz @F
ret
@@:
call RunBuckshotTest3D
test eax, eax
jz @F
ret
@@:
call RunSlotsTest3D
test eax,eax
jz @F
ret
@@:
call RunCoinTest3D
test eax,eax
jz @F
ret
@@:
call RunHallTest3D
test eax, eax
jz @F
ret
@@:
invoke CreateFileA, OFFSET actionReportPath, 40000000h, 0, 0, 2, 80h, 0
cmp eax, -1
je action_fail_12
mov ebx, eax
invoke WriteFile, ebx, OFFSET actionReportText, actionReportSize, ADDR count, 0
invoke CloseHandle, ebx
call FreeRussianAssets3D
call FreeArrivalAssets3D
invoke PlaySoundA, 0, 0, 0
xor eax, eax
ret
action_fail_1:
mov eax, 1
ret
action_fail_2:
mov eax, 2
ret
action_fail_3:
mov eax, 3
ret
action_fail_4:
mov eax, 4
ret
action_fail_5:
mov eax, 5
ret
action_fail_6:
mov eax, 6
ret
action_fail_7:
mov eax, 7
ret
action_fail_8:
mov eax, 8
ret
action_fail_9:
mov eax, 9
ret
action_fail_10:
mov eax, 10
ret
action_fail_11:
mov eax, 11
ret
action_fail_12:
mov eax, 12
ret
action_fail_13:
mov eax, 13
ret
action_fail_14:
mov eax, 14
ret
action_fail_15:
mov eax, 15
ret
RunCasinoActionsTest3D ENDP