KAZIK/tools/tests/arrival_test.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

635 lines
19 KiB
PHP

.data
arrivalFixtureDir3D db "build\arrival\fixtures",0
arrivalFixtureValid3D db "build\arrival\fixtures\valid.dat",0
arrivalFixtureZero3D db "build\arrival\fixtures\zero.dat",0
arrivalFixtureTamper3D db "build\arrival\fixtures\tampered.dat",0
arrivalFixtureMagic3D db "build\arrival\fixtures\wrong-magic.dat",0
arrivalFixtureShort3D db "build\arrival\fixtures\truncated.dat",0
arrivalFixtureName3D db "zero.dat",0
arrivalFreshName3D db "FreshPlayer",0
arrivalTestStage3D dd 40
arrivalFixtureBroken3D db "build\arrival\fixtures\broken-animation.bin",0
arrivalBrokenPack3D AnimPack3D <>
arrivalStreetSnapshot3D db "build\actions\arrival-street.bmp",0
arrivalStopSnapshot3D db "build\actions\arrival-stop.bmp",0
arrivalProfileSnapshot3D db "build\actions\arrival-profile.bmp",0
arrivalAdmitSnapshot3D db "build\actions\arrival-admit.bmp",0
arrivalNameSnapshot3D db "build\actions\arrival-name.bmp",0
merchantIdleSnapshot3D db "build\actions\merchant-idle.bmp",0
merchantGestureSnapshot3D db "build\actions\merchant-gesture.bmp",0
arrivalHallSnapshot3D db "build\actions\arrival-hall.bmp",0
cityEyeSnapshot3D db "build\actions\city-eyes.bmp",0
cityUpwardSnapshot3D db "build\actions\city-upward.bmp",0
citySmokeSnapshot3D db "build\actions\city-smoke.bmp",0
cityTossSnapshot3D db "build\actions\city-toss.bmp",0
cityAlleySnapshot3D db "build\actions\city-alley.bmp",0
cityStreetSnapshot3D db "build\actions\city-street.bmp",0
citySkylineSnapshot3D db "build\actions\city-skyline.bmp",0
cityBlackSnapshot3D db "build\actions\city-black.bmp",0
cityTossFormat3D db "build\actions\city-toss-%02u.bmp",0
cityTrafficFormat3D db "build\actions\city-traffic-%02u.bmp",0
arrivalSequenceFormat3D db "build\actions\guard-admit-%02u.bmp",0
merchantSequenceFormat3D db "build\actions\merchant-talk-%02u.bmp",0
arrivalSequenceName3D db 128 dup(0)
cityAlphaPixels3D dd 00FFFFFFh,80FF0000h,0FF00FF00h,40FFFFFFh
cityAlphaPack3D AnimPack3D <314D4E41h,2,2,1,16,OFFSET cityAlphaPixels3D>
cityPerformancePath3D db "build\actions\city-performance.json",0
cityPerformanceFormat3D db '{"alley_ms":%u,"street_ms":%u,"sky_ms":%u,"frames_each":20}',0
.code
TestCityCigarette3D PROC uses ebx esi
; A held cigarette must be a connected, shaded object, not spaced sample dots.
invoke DrawBox, 0, 0, 100, 100, 0
invoke DrawCityCigarette3D, 100, 100, 256, 4
mov esi, 46
city_test_cigarette_run:
cmp screenBuffer[(100*SCREEN_W)*4+esi*4], 0
je city_test_cigarette_fail
inc esi
cmp esi, 106
jb city_test_cigarette_run
mov ebx, screenBuffer[(100*SCREEN_W+50)*4]
cmp ebx, screenBuffer[(100*SCREEN_W+80)*4]
je city_test_cigarette_fail
mov ebx, screenBuffer[(100*SCREEN_W+80)*4]
cmp ebx, screenBuffer[(100*SCREEN_W+104)*4]
je city_test_cigarette_fail
cmp screenBuffer[(94*SCREEN_W+80)*4], 0
jne city_test_cigarette_fail
mov eax, 1
ret
city_test_cigarette_fail:
xor eax, eax
ret
TestCityCigarette3D ENDP
TestCitySmokeAnchors3D PROC uses ebx esi
xor esi, esi
city_test_smoke_anchor:
mov eax, citySmokeRootX3D[esi*4]
cmp eax, 96
jae city_test_smoke_fail
mov ebx, eax
mov eax, citySmokeRootY3D[esi*4]
cmp eax, 128
jae city_test_smoke_fail
imul eax, 96
add eax, ebx
shl eax, 2
mov ebx, esi
imul ebx, 96*128*4
add eax, ebx
add eax, citySmokePack3D.pixels
cmp BYTE PTR [eax+3], 32
jb city_test_smoke_fail
inc esi
cmp esi, 4
jb city_test_smoke_anchor
mov eax, 1
ret
city_test_smoke_fail:
xor eax, eax
ret
TestCitySmokeAnchors3D ENDP
TestCityAlpha3D PROC
mov animOpacity3D, 255
mov screenBuffer, 00102030h
mov screenBuffer[4], 00102030h
mov screenBuffer[640*4], 00102030h
mov screenBuffer[640*4+4], 00102030h
invoke DrawAnimSprite3D, OFFSET cityAlphaPack3D, 0, 0, 0, 2, 2
cmp screenBuffer, 00102030h
jne city_alpha_fail
cmp screenBuffer[4], 00881018h
jne city_alpha_fail
cmp screenBuffer[640*4], 0000FF00h
jne city_alpha_fail
cmp screenBuffer[640*4+4], 004C5864h
jne city_alpha_fail
mov screenBuffer[4], 00102030h
mov animOpacity3D, 64
invoke DrawAnimSprite3D, OFFSET cityAlphaPack3D, 0, 0, 0, 2, 2
mov animOpacity3D, 255
cmp screenBuffer[4], 002E1C2Ah
jne city_alpha_fail
mov eax, 1
ret
city_alpha_fail:
mov animOpacity3D, 255
xor eax, eax
ret
TestCityAlpha3D ENDP
MeasureCityFrame3D PROC uses ebx esi
invoke GetTickCount
mov ebx, eax
mov esi, 20
city_measure_frame:
call RenderCityArrival3D
dec esi
jnz city_measure_frame
invoke GetTickCount
sub eax, ebx
xor edx, edx
mov ecx, 20
div ecx
ret
MeasureCityFrame3D ENDP
WriteCityPerformance3D PROC uses ebx
local alley:DWORD,street:DWORD,sky:DWORD,count:DWORD,bytesOut:DWORD
mov arrivalState3D, ARRIVAL_WALK
mov cityPhase3D, CITY_SMOKE
mov cityTime3D, 700
call MeasureCityFrame3D
mov alley, eax
mov cityPhase3D, CITY_STREET
mov cityTime3D, 1800
call MeasureCityFrame3D
mov street, eax
mov cityPhase3D, CITY_WAKE
mov cityTime3D, 700
call MeasureCityFrame3D
mov sky, eax
invoke wsprintfA, OFFSET arrivalSequenceName3D, OFFSET cityPerformanceFormat3D, alley,street,sky
mov bytesOut, eax
invoke CreateFileA, OFFSET cityPerformancePath3D,40000000h,0,0,2,80h,0
cmp eax, -1
je city_performance_done
mov ebx, eax
invoke WriteFile, ebx,OFFSET arrivalSequenceName3D,bytesOut,ADDR count,0
invoke CloseHandle, ebx
city_performance_done:
ret
WriteCityPerformance3D ENDP
RunArrivalTest3D PROC uses ebx esi edi
local oldBank:DWORD,oldBack:DWORD,oldRng:DWORD,oldX:DWORD,oldY:DWORD,oldAngle:DWORD
local phase:DWORD,sample:DWORD,ticks:DWORD,phasesSeen:DWORD
local previousX:DWORD,previousY:DWORD,previousAngle:DWORD,previousHorizon:DWORD
call InitHall3D
call TestCityAlpha3D
test eax, eax
jz arrival_test_fail
call TestCityCigarette3D
test eax, eax
jz arrival_test_fail
invoke ValidateGraphicProfile3D, OFFSET arrivalFixtureValid3D
cmp eax, 1
jne arrival_test_fail
invoke ValidateGraphicProfile3D, OFFSET arrivalFixtureTamper3D
test eax, eax
jnz arrival_test_fail
invoke ValidateGraphicProfile3D, OFFSET arrivalFixtureMagic3D
test eax, eax
jnz arrival_test_fail
invoke ValidateGraphicProfile3D, OFFSET arrivalFixtureShort3D
test eax, eax
jnz arrival_test_fail
invoke LoadAnimPack3D, OFFSET arrivalBrokenPack3D, OFFSET arrivalFixtureBroken3D
test eax, eax
jnz arrival_test_fail
cmp arrivalBrokenPack3D.pixels, 0
jne arrival_test_fail
call BeginStartup3D
mov startupElapsed3D, 6990
mov deltaTime3D, 16
call HandleStartupInput3D
cmp engineMode, MODE_ARRIVAL
jne arrival_test_fail
cmp cityPhase3D, CITY_BLACK
jne arrival_test_fail
call BeginArrival3D
cmp engineMode, MODE_ARRIVAL
jne arrival_test_fail
cmp guardPack3D.frames, 32
jne arrival_test_fail
cmp merchantPack3D.frames, 24
jne arrival_test_fail
cmp backsPack3D.frames, 13
jne arrival_test_fail
cmp cityTilesPack3D.frames, 16
jne arrival_test_fail
cmp cityHandsPack3D.frames, 16
jne arrival_test_fail
cmp cityPropsPack3D.frames, 6
jne arrival_test_fail
cmp citySmokePack3D.frames, 4
jne arrival_test_fail
cmp cityCarsPack3D.frames, 16
jne arrival_test_fail
cmp cityBinPack3D.frames, 4
jne arrival_test_fail
cmp cityCloudPack3D.frames, 4
jne arrival_test_fail
call TestCitySmokeAnchors3D
test eax, eax
jz arrival_test_fail
cmp cityPhase3D, CITY_BLACK
jne arrival_test_fail
call RenderArrival3D
invoke WriteActionSnapshot3D, OFFSET cityBlackSnapshot3D
mov cityPhase3D, CITY_WAKE
mov cityTime3D, 700
mov cityClock3D, 1400
call RenderArrival3D
invoke WriteActionSnapshot3D, OFFSET cityEyeSnapshot3D
mov cityTime3D, 2480
call RenderArrival3D
invoke WriteActionSnapshot3D, OFFSET cityUpwardSnapshot3D
mov cityPhase3D, CITY_SMOKE
mov cityTime3D, 700
mov cityClock3D, 3600
call RenderArrival3D
invoke WriteActionSnapshot3D, OFFSET citySmokeSnapshot3D
mov cityPhase3D, CITY_TOSS
xor edi, edi
arrival_toss_sequence:
mov eax, edi
imul eax, 75
mov cityTime3D, eax
call RenderArrival3D
invoke wsprintfA, OFFSET arrivalSequenceName3D, OFFSET cityTossFormat3D, edi
invoke WriteActionSnapshot3D, OFFSET arrivalSequenceName3D
inc edi
cmp edi, 20
jb arrival_toss_sequence
mov cityTime3D, 500
call RenderArrival3D
invoke WriteActionSnapshot3D, OFFSET cityTossSnapshot3D
mov cityPhase3D, CITY_ALLEY
mov cityTime3D, 2500
mov cityClock3D, 10000
call RenderArrival3D
invoke WriteActionSnapshot3D, OFFSET cityAlleySnapshot3D
mov cityPhase3D, CITY_STREET
mov cityTime3D, 1200
mov cityClock3D, 13000
call RenderArrival3D
invoke WriteActionSnapshot3D, OFFSET cityStreetSnapshot3D
mov cityTime3D, 6200
call RenderArrival3D
invoke WriteActionSnapshot3D, OFFSET citySkylineSnapshot3D
cmp zBuffer[HALF_W*4], 7FFFFFFFh
jne arrival_test_fail
mov cityTime3D, 3750
call RenderArrival3D
invoke WriteActionSnapshot3D, OFFSET arrivalStreetSnapshot3D
xor edi, edi
arrival_traffic_sequence:
mov cityPhase3D, CITY_STREET
mov cityTime3D, 1800
mov eax, edi
imul eax, 200
add eax, 13000
mov cityClock3D, eax
call RenderArrival3D
invoke wsprintfA, OFFSET arrivalSequenceName3D, OFFSET cityTrafficFormat3D, edi
invoke WriteActionSnapshot3D, OFFSET arrivalSequenceName3D
inc edi
cmp edi, 16
jb arrival_traffic_sequence
call WriteCityPerformance3D
mov cityPhase3D, CITY_STREET
mov cityTime3D, 1800
mov arrivalTestStage3D, 41
; Every camera waypoint is on an open exterior cell, and draws restore hall state.
mov eax, playerX
mov oldX, eax
mov eax, playerY
mov oldY, eax
mov eax, playerAngle
mov oldAngle, eax
mov eax, rngSeed3D
mov oldRng, eax
mov cityPhase3D, CITY_BLACK
mov cityTime3D, 0
call PositionCityCamera3D
mov eax, playerX
mov previousX, eax
mov eax, playerY
mov previousY, eax
mov eax, playerAngle
mov previousAngle, eax
mov eax, viewHorizon3D
mov previousHorizon, eax
mov phase, 0
arrival_continuity_phase:
mov eax, phase
mov cityPhase3D, eax
mov cityTime3D, 0
arrival_continuity_sample:
call PositionCityCamera3D
mov eax, playerX
sub eax, previousX
test eax, eax
jns @F
neg eax
@@:
cmp eax, 4000
ja arrival_test_fail
mov eax, playerY
sub eax, previousY
test eax, eax
jns @F
neg eax
@@:
cmp eax, 4000
ja arrival_test_fail
mov eax, playerAngle
sub eax, previousAngle
add eax, 256
and eax, 511
sub eax, 256
test eax, eax
jns @F
neg eax
@@:
cmp eax, 6
ja arrival_test_fail
; The wake phase intentionally starts looking upward from the black screen.
cmp phase, CITY_WAKE
jne arrival_continuity_store
cmp cityTime3D, 0
je arrival_continuity_store
mov eax, viewHorizon3D
sub eax, previousHorizon
test eax, eax
jns @F
neg eax
@@:
cmp eax, 40
ja arrival_test_fail
arrival_continuity_store:
mov eax, playerX
mov previousX, eax
mov eax, playerY
mov previousY, eax
mov eax, playerAngle
mov previousAngle, eax
mov eax, viewHorizon3D
mov previousHorizon, eax
mov eax, phase
mov ecx, cityDurations3D[eax*4]
cmp cityTime3D, ecx
jae arrival_continuity_next
add cityTime3D, 16
cmp cityTime3D, ecx
jbe arrival_continuity_sample
mov cityTime3D, ecx
jmp arrival_continuity_sample
arrival_continuity_next:
inc phase
cmp phase, CITY_DOOR+1
jb arrival_continuity_phase
mov phase, 0
arrival_camera_phase:
mov eax, phase
mov cityPhase3D, eax
mov sample, 0
arrival_camera_sample:
mov ecx, phase
mov eax, cityDurations3D[ecx*4]
imul eax, sample
shr eax, 3
mov cityTime3D, eax
call PositionCityCamera3D
mov eax, playerY
shr eax, 16
shl eax, 5
mov edx, playerX
shr edx, 16
add eax, edx
cmp BYTE PTR cityMap3D[eax], 0
jne arrival_test_fail
inc sample
cmp sample, 9
jb arrival_camera_sample
inc phase
cmp phase, CITY_DOOR+1
jb arrival_camera_phase
mov eax, oldX
mov playerX, eax
mov eax, oldY
mov playerY, eax
mov eax, oldAngle
mov playerAngle, eax
mov viewHorizon3D, HALF_H
call RenderArrival3D
mov arrivalTestStage3D, 42
mov eax, oldX
cmp playerX, eax
jne arrival_test_fail
mov eax, oldY
cmp playerY, eax
jne arrival_test_fail
cmp worldMap3D, OFFSET casinoMap
jne arrival_test_fail
cmp outdoorRender3D, 0
jne arrival_test_fail
cmp cityBackdrop3D, 0
jne arrival_test_fail
cmp viewEye3D, FP_1*17/20
jne arrival_test_fail
cmp animOpacity3D, 255
jne arrival_test_fail
cmp floorTexture3D, 100
jne arrival_test_fail
cmp viewHorizon3D, HALF_H
jne arrival_test_fail
mov eax, oldRng
cmp rngSeed3D, eax
jne arrival_test_fail
call BeginArrival3D
mov arrivalTestStage3D, 43
cmp cityPhase3D, CITY_BLACK
jne arrival_test_fail
mov deltaTime3D, 16
mov ticks, 0
mov phasesSeen, 0
arrival_full_cinematic:
mov eax, cityPhase3D
bts phasesSeen, eax
call HandleArrival3D
cmp arrivalState3D, ARRIVAL_PROFILE
je arrival_full_cinematic_done
inc ticks
cmp ticks, 2400
jae arrival_test_fail
jmp arrival_full_cinematic
arrival_full_cinematic_done:
cmp phasesSeen, 3FFh
jne arrival_test_fail
mov arrivalTestStage3D, 44
mov arrivalState3D, ARRIVAL_STOP
mov arrivalTime3D, 400
call RenderArrival3D
invoke WriteActionSnapshot3D, OFFSET arrivalStopSnapshot3D
mov arrivalState3D, ARRIVAL_PROFILE
mov arrivalTime3D, 0
call RenderArrival3D
invoke WriteActionSnapshot3D, OFFSET arrivalProfileSnapshot3D
mov arrivalState3D, ARRIVAL_NAME
mov arrivalNameLength3D, 0
mov arrivalName3D, 0
invoke ArrivalChar3D, 'A'
invoke ArrivalChar3D, '/'
invoke ArrivalChar3D, '\'
invoke ArrivalChar3D, '.'
invoke ArrivalChar3D, 'B'
cmp arrivalNameLength3D, 2
jne arrival_test_fail
invoke ArrivalChar3D, 8
cmp arrivalNameLength3D, 1
jne arrival_test_fail
invoke CopyCString, OFFSET arrivalName3D, OFFSET arrivalFreshName3D
mov arrivalNameLength3D, 11
call RenderArrival3D
invoke WriteActionSnapshot3D, OFFSET arrivalNameSnapshot3D
call ArrivalEscape3D
cmp arrivalState3D, ARRIVAL_PROFILE
jne arrival_test_fail
; The preview button also needs the complete guard gesture and threshold transition.
mov arrivalSelected3D, 0
mov pressedKeys3D[0Dh], 1
mov pressedKeys3D[45h], 1
mov deltaTime3D, 16
call HandleArrival3D
cmp arrivalState3D, ARRIVAL_ADMIT
jne arrival_test_fail
cmp pressedKeys3D[45h], 0
jne arrival_test_fail
cmp arrivalConfirmed3D, 1
jne arrival_test_fail
mov arrivalTime3D, 640
call RenderArrival3D
invoke WriteActionSnapshot3D, OFFSET arrivalAdmitSnapshot3D
xor edi, edi
arrival_admit_sequence:
mov eax, edi
imul eax, 100
mov arrivalTime3D, eax
call RenderArrival3D
invoke wsprintfA, OFFSET arrivalSequenceName3D, OFFSET arrivalSequenceFormat3D, edi
invoke WriteActionSnapshot3D, OFFSET arrivalSequenceName3D
inc edi
cmp edi, 12
jb arrival_admit_sequence
mov arrivalTime3D, 1200
call HandleArrival3D
cmp arrivalState3D, ARRIVAL_ENTER
jne arrival_test_fail
mov arrivalTime3D, 1400
call HandleArrival3D
cmp engineMode, MODE_WALK
jne arrival_test_fail
cmp playerY, (27*FP_1+FP_HALF)
jne arrival_test_fail
invoke CanWalk3D, playerX, playerY
test eax, eax
jz arrival_test_fail
; Load zero-bank accounts faithfully, without the legacy automatic $10,000 refill.
mov nativeProfilesDirPtr3D, OFFSET arrivalFixtureDir3D
mov entryAccountCount3D, 1
invoke CopyCString, OFFSET entryAccountNames3D, OFFSET arrivalFixtureName3D
invoke CopyCString, OFFSET entryAccountPaths3D, OFFSET arrivalFixtureZero3D
invoke SelectGraphicProfile3D, 0
cmp eax, 1
jne arrival_test_fail
cmp bankroll, 0
jne arrival_test_fail
mov entryAccountCount3D, 0
call CreateGraphicProfile3D
cmp eax, 1
jne arrival_test_fail
cmp bankroll, 10000
jne arrival_test_fail
call CreateGraphicProfile3D
test eax, eax
jnz arrival_test_fail
mov nativeProfileActive3D, 0
mov nativeProfilesDirPtr3D, OFFSET nativeProfilesDir3D
mov bankroll, 50000
mov ownedBacks3D, 1
mov selectedBack3D, 0
invoke BuyMerchantBack3D, 5
cmp bankroll, 35000
jne arrival_test_fail
cmp selectedBack3D, 5
jne arrival_test_fail
invoke BuyMerchantBack3D, 5
cmp bankroll, 35000
jne arrival_test_fail
mov bankroll, 1
invoke BuyMerchantBack3D, 12
cmp bankroll, 1
jne arrival_test_fail
cmp selectedBack3D, 5
jne arrival_test_fail
mov bankroll, 35000
call BeginMerchant3D
mov merchantSelected3D, 5
mov merchantReaction3D, 1280
mov eax, bankroll
mov oldBank, eax
mov eax, selectedBack3D
mov oldBack, eax
mov eax, rngSeed3D
mov oldRng, eax
call RenderMerchant3D
invoke WriteActionSnapshot3D, OFFSET merchantIdleSnapshot3D
mov merchantReaction3D, 640
mov merchantReactionKind3D, 2
call RenderMerchant3D
invoke WriteActionSnapshot3D, OFFSET merchantGestureSnapshot3D
mov eax, oldBank
cmp bankroll, eax
jne arrival_test_fail
mov eax, oldBack
cmp selectedBack3D, eax
jne arrival_test_fail
mov eax, oldRng
cmp rngSeed3D, eax
jne arrival_test_fail
mov merchantReactionKind3D, 1
xor edi, edi
merchant_talk_sequence:
mov eax, edi
imul eax, 100
mov merchantReaction3D, eax
call RenderMerchant3D
invoke wsprintfA, OFFSET arrivalSequenceName3D, OFFSET merchantSequenceFormat3D, edi
invoke WriteActionSnapshot3D, OFFSET arrivalSequenceName3D
inc edi
cmp edi, 12
jb merchant_talk_sequence
; Invalid frames and completely clipped sprites must be safe no-ops.
invoke DrawAnimSprite3D, OFFSET guardPack3D, 999, 0, 0, 192, 256
invoke DrawAnimSprite3D, OFFSET guardPack3D, 0, -400, -400, 192, 256
call LoadTextures3D
call InstallHallProps3D
mov playerX, (16*FP_1+FP_HALF)
mov playerY, (18*FP_1+FP_HALF)
mov playerAngle, 384
call UpdateCamera3D
call RenderCeilingAndFloor
call RenderWalls
call PrepareCityDepth3D
; Init3DEngine's placements are not used by this hidden test window.
mov casinoSprites[3*SIZEOF SpriteObject].posX, (12*FP_1+FP_HALF)
mov casinoSprites[3*SIZEOF SpriteObject].posY, (8*FP_1)
mov casinoSprites[3*SIZEOF SpriteObject].frameCount, 1
mov casinoSprites[4*SIZEOF SpriteObject].posX, (16*FP_1+FP_HALF)
mov casinoSprites[4*SIZEOF SpriteObject].posY, (10*FP_1)
mov casinoSprites[4*SIZEOF SpriteObject].frameCount, 1
mov casinoSprites[5*SIZEOF SpriteObject].posX, (20*FP_1+FP_HALF)
mov casinoSprites[5*SIZEOF SpriteObject].posY, (8*FP_1)
mov casinoSprites[5*SIZEOF SpriteObject].frameCount, 1
call RenderSprites
invoke WriteActionSnapshot3D, OFFSET arrivalHallSnapshot3D
xor eax, eax
ret
arrival_test_fail:
mov eax, arrivalTestStage3D
ret
RunArrivalTest3D ENDP