KAZIK/src_graphics/scene_animation.inc
Игорь Федосеев ca62db53e9 feat: implement native billiards, scratch tickets, first-person dice, and city wake scene
- Billiards: add native Russian Pyramid & American Eight-Ball pool with physics prediction, controls, and regression tests
- Scratch Tickets: add dedicated counter, mat presentation, elliptical coin scraping, 4 ticket types, and payout effects
- First-Person Dice: add native dice scene, hand anchor frames, throwing animation, and table perspective
- City Wake & Weather: add arrival cutscene, alley geometry, weather/rain effects, and lighter/rocker animation
- World Dressing: add hall paintings, furniture packs, hall lighting, and scene regression tests
- Build & Tooling: update build.bat for modern MSVC toolchain, update launcher hash, and refresh shipping binaries
2026-10-16 12:37:40 +03:00

467 lines
12 KiB
PHP

LoadAnimPack3D PROC uses ebx esi edi pack:DWORD,path:DWORD
local io:DWORD,heap:DWORD,allocation:DWORD
mov esi, pack
cmp [esi].AnimPack3D.pixels, 0
jne anim_load_success
invoke CreateFileA, path, 80000000h, 1, 0, 3, 80h, 0
cmp eax, -1
je anim_load_failure
mov ebx, eax
invoke ReadFile, ebx, esi, 20, ADDR io, 0
test eax, eax
jz anim_close_failure
cmp io, 20
jne anim_close_failure
cmp [esi].AnimPack3D.magic, 314D4E41h
jne anim_close_failure
mov eax, [esi].AnimPack3D.imageWidth
test eax, eax
jz anim_close_failure
cmp eax, 640
ja anim_close_failure
mov ecx, [esi].AnimPack3D.height
test ecx, ecx
jz anim_close_failure
cmp ecx, 1024
ja anim_close_failure
imul eax, ecx
shl eax, 2
mov ecx, [esi].AnimPack3D.frames
test ecx, ecx
jz anim_close_failure
cmp ecx, 64
ja anim_close_failure
imul eax, ecx
cmp eax, 32*1024*1024
ja anim_close_failure
cmp eax, [esi].AnimPack3D.bytes
jne anim_close_failure
invoke GetFileSize, ebx, 0
mov ecx, [esi].AnimPack3D.bytes
add ecx, 20
cmp eax, ecx
jne anim_close_failure
invoke GetProcessHeap
mov heap, eax
invoke HeapAlloc, eax, 0, [esi].AnimPack3D.bytes
test eax, eax
jz anim_close_failure
mov allocation, eax
invoke ReadFile, ebx, allocation, [esi].AnimPack3D.bytes, ADDR io, 0
test eax, eax
jz anim_free_failure
mov eax, io
cmp eax, [esi].AnimPack3D.bytes
jne anim_free_failure
invoke CloseHandle, ebx
mov eax, allocation
mov [esi].AnimPack3D.pixels, eax
anim_load_success:
mov eax, 1
ret
anim_free_failure:
invoke HeapFree, heap, 0, allocation
anim_close_failure:
invoke CloseHandle, ebx
anim_load_failure:
; A parsed header is not a loaded asset. Leave no misleading frame count.
mov edi, esi
xor eax, eax
mov ecx, SIZEOF AnimPack3D/4
rep stosd
xor eax, eax
ret
LoadAnimPack3D ENDP
FreeAnimPack3D PROC uses esi pack:DWORD
mov esi, pack
cmp [esi].AnimPack3D.pixels, 0
je @F
invoke GetProcessHeap
invoke HeapFree, eax, 0, [esi].AnimPack3D.pixels
mov [esi].AnimPack3D.pixels, 0
@@:
ret
FreeAnimPack3D ENDP
; Physical framebuffer coordinates. Clip before sampling; fractional alpha is preserved.
DrawAnimSprite3D PROC uses ebx esi edi pack:DWORD,frame:DWORD,x:DWORD,y:DWORD,w:DWORD,h:DWORD
local columnPx:DWORD,rowPx:DWORD,sx:DWORD,sy:DWORD,xStep:DWORD,yStep:DWORD
local xFirst:DWORD,xLast:DWORD,yLast:DWORD,sourceRow:DWORD,pixel:DWORD
local alpha:DWORD,inverse:DWORD,result:DWORD
mov esi, pack
cmp [esi].AnimPack3D.pixels, 0
je anim_draw_done
cmp w, 0
jle anim_draw_done
cmp h, 0
jle anim_draw_done
cmp w, 4096
ja anim_draw_done
cmp h, 4096
ja anim_draw_done
mov eax, frame
cmp eax, [esi].AnimPack3D.frames
jae anim_draw_done
imul eax, [esi].AnimPack3D.imageWidth
imul eax, [esi].AnimPack3D.height
shl eax, 2
add eax, [esi].AnimPack3D.pixels
mov sourceRow, eax
mov eax, [esi].AnimPack3D.imageWidth
shl eax, 16
xor edx, edx
div w
mov xStep, eax
mov eax, [esi].AnimPack3D.height
shl eax, 16
xor edx, edx
div h
mov yStep, eax
mov eax, x
add eax, w
cmp eax, 640
jle @F
mov eax, 640
@@:
mov xLast, eax
mov eax, x
test eax, eax
jns @F
xor eax, eax
@@:
mov xFirst, eax
cmp eax, xLast
jge anim_draw_done
mov eax, y
add eax, h
cmp eax, 480
jle @F
mov eax, 480
@@:
mov yLast, eax
mov eax, y
test eax, eax
jns @F
xor eax, eax
@@:
mov rowPx, eax
sub eax, y
imul eax, yStep
mov sy, eax
anim_draw_row:
mov eax, rowPx
cmp eax, yLast
jge anim_draw_done
imul eax, 640*4
add eax, OFFSET screenBuffer
mov ecx, xFirst
lea edi, [eax+ecx*4]
mov eax, sy
shr eax, 16
imul eax, [esi].AnimPack3D.imageWidth
shl eax, 2
add eax, sourceRow
mov ebx, eax
mov columnPx, ecx
sub ecx, x
imul ecx, xStep
mov sx, ecx
anim_draw_column:
mov eax, sx
shr eax, 16
mov eax, [ebx+eax*4]
mov pixel, eax
shr eax, 24
test eax, eax
jz anim_draw_next
cmp animOpacity3D, 255
je @F
imul eax, animOpacity3D
mov edx, eax
shr edx, 8
add eax, edx
inc eax
shr eax, 8
test eax, eax
jz anim_draw_next
@@:
cmp eax, 250
jb anim_blend
mov eax, pixel
and eax, 00FFFFFFh
mov [edi], eax
jmp anim_draw_next
anim_blend:
mov alpha, eax
mov ecx, 255
sub ecx, eax
mov inverse, ecx
mov result, 0
push ebx
xor ebx, ebx
anim_blend_channel:
mov ecx, ebx
mov eax, pixel
shr eax, cl
and eax, 255
imul eax, alpha
mov edx, [edi]
shr edx, cl
and edx, 255
imul edx, inverse
add eax, edx
; Exact rounded /255 for the bounded 0..65025 channel sum.
add eax, 128
mov edx, eax
shr edx, 8
add eax, edx
shr eax, 8
mov ecx, ebx
shl eax, cl
or result, eax
add ebx, 8
cmp ebx, 24
jb anim_blend_channel
pop ebx
mov eax, result
mov [edi], eax
anim_draw_next:
add edi, 4
mov eax, xStep
add sx, eax
inc columnPx
mov eax, columnPx
cmp eax, xLast
jl anim_draw_column
mov eax, yStep
add sy, eax
inc rowPx
jmp anim_draw_row
anim_draw_done:
ret
DrawAnimSprite3D ENDP
LoadArrivalAssets3D PROC
invoke LoadAnimPack3D, OFFSET guardPack3D, OFFSET guardPath3D
invoke LoadAnimPack3D, OFFSET merchantPack3D, OFFSET merchantPath3D
invoke LoadAnimPack3D, OFFSET propsPack3D, OFFSET propsPath3D
invoke LoadAnimPack3D, OFFSET backsPack3D, OFFSET backsPath3D
invoke LoadAnimPack3D, OFFSET handsPack3D, OFFSET handsPath3D
invoke LoadAnimPack3D, OFFSET activeTablePack3D, OFFSET activeTablePath3D
call InstallHallProps3D
call LoadHallAssets3D
ret
LoadArrivalAssets3D ENDP
InstallHallProps3D PROC uses ebx esi edi
; Keep the user's existing interior materials; the exterior has separate slots.
hall_install_props:
cmp propsPack3D.pixels, 0
je @F
cmp propsPack3D.imageWidth, 128
jne @F
cmp propsPack3D.height, 128
jne @F
cmp propsPack3D.frames, 9
jne @F
mov esi, propsPack3D.pixels
mov edi, OFFSET texturesBuffer+(48*128*128*4)
mov ecx, 9*128*128
props_copy_pixel:
lodsd
cmp eax, 80000000h
jae props_copy_opaque
mov eax, CHROMA_KEY
jmp props_copy_store
props_copy_opaque:
and eax, 00FFFFFFh
props_copy_store:
stosd
loop props_copy_pixel
mov casinoSprites[3*SIZEOF SpriteObject].baseTexId, 48
mov casinoSprites[4*SIZEOF SpriteObject].baseTexId, 50
mov casinoSprites[5*SIZEOF SpriteObject].baseTexId, 49
mov casinoSprites[9*SIZEOF SpriteObject].baseTexId, 51
mov casinoSprites[12*SIZEOF SpriteObject].baseTexId, 54
mov casinoSprites[14*SIZEOF SpriteObject].baseTexId, 52
mov casinoSprites[17*SIZEOF SpriteObject].baseTexId, 55
mov casinoSprites[18*SIZEOF SpriteObject].baseTexId, 53
mov casinoSprites[19*SIZEOF SpriteObject].baseTexId, 55
@@:
ret
InstallHallProps3D ENDP
FreeArrivalAssets3D PROC
call FreeScratchArt3D
call FreeNativeDiceArt3D
call FreeHallAssets3D
invoke FreeAnimPack3D, OFFSET streetPack3D
invoke FreeAnimPack3D, OFFSET guardPack3D
invoke FreeAnimPack3D, OFFSET merchantPack3D
invoke FreeAnimPack3D, OFFSET propsPack3D
invoke FreeAnimPack3D, OFFSET backsPack3D
invoke FreeAnimPack3D, OFFSET handsPack3D
invoke FreeAnimPack3D, OFFSET materialsPack3D
invoke FreeAnimPack3D, OFFSET activeTablePack3D
invoke FreeAnimPack3D, OFFSET cityTilesPack3D
invoke FreeAnimPack3D, OFFSET cityHandsPack3D
invoke FreeAnimPack3D, OFFSET cityPropsPack3D
invoke FreeAnimPack3D, OFFSET citySmokePack3D
invoke FreeAnimPack3D, OFFSET cityCarsPack3D
invoke FreeAnimPack3D, OFFSET cityBinPack3D
invoke FreeAnimPack3D, OFFSET cityCloudPack3D
invoke FreeAnimPack3D, OFFSET cityWakePack3D
invoke FreeAnimPack3D, OFFSET citySleevePack3D
invoke FreeAnimPack3D, OFFSET cityDecorPack3D
invoke FreeAnimPack3D, OFFSET cityLighterPack3D
invoke FreeAnimPack3D, OFFSET cityKneesPack3D
ret
FreeArrivalAssets3D ENDP
QueueTableHand3D PROC x:DWORD,y:DWORD,timeMs:DWORD,kind:DWORD
mov eax, timeMs
cmp eax, TABLE_FLIGHT_MS
jae @F
mov tableHandTime3D, eax
mov eax, x
mov tableHandX3D, eax
mov eax, y
mov tableHandY3D, eax
mov eax, kind
mov tableHandKind3D, eax
mov tableHandQueued3D, 1
@@:
ret
QueueTableHand3D ENDP
DrawQueuedTableHand3D PROC uses ebx esi edi
local drawX:DWORD,drawY:DWORD
cmp tableHandQueued3D, 0
je table_hand_done
cmp handsPack3D.pixels, 0
je table_hand_done
cmp handsPack3D.imageWidth, 144
jne table_hand_done
cmp handsPack3D.height, 192
jne table_hand_done
cmp handsPack3D.frames, 8
jne table_hand_done
mov eax, tableHandTime3D
mov ebx, 0
cmp eax, 60
jb table_hand_frame
inc ebx
cmp eax, 120
jb table_hand_frame
inc ebx
cmp eax, 260
jb table_hand_frame
inc ebx
cmp eax, 300
jb table_hand_frame
inc ebx
cmp eax, 340
jb table_hand_frame
inc ebx
table_hand_frame:
cmp tableHandKind3D, 1
jne @F
mov ebx, 6
cmp tableHandTime3D, 250
jb @F
inc ebx
@@:
mov eax, tableHandX3D
shl eax, 1
add eax, 24
sub eax, tableHandAnchorX3D[ebx*4]
mov drawX, eax
mov eax, tableHandY3D
shl eax, 1
add eax, 12
sub eax, tableHandAnchorY3D[ebx*4]
mov drawY, eax
cmp ebx, 4
jb table_hand_draw
cmp ebx, 6
jae table_hand_draw
mov eax, tableHandTime3D
sub eax, 300
shr eax, 1
sub drawY, eax
table_hand_draw:
; Composite above the actual cards, preserving the header and action buttons.
lea esi, screenBuffer
lea edi, tableProtectedRows3D
mov ecx, 640*88
rep movsd
lea esi, screenBuffer[640*444*4]
mov ecx, 640*36
rep movsd
cmp ebx, 6
jae table_hand_player
invoke DrawDealerArm3D, ebx, drawX, drawY
jmp table_hand_restore
table_hand_player:
invoke DrawAnimSprite3D, OFFSET handsPack3D, ebx, drawX, drawY, 144, 192
table_hand_restore:
lea esi, tableProtectedRows3D
lea edi, screenBuffer
mov ecx, 640*88
rep movsd
lea edi, screenBuffer[640*444*4]
mov ecx, 640*36
rep movsd
table_hand_done:
ret
DrawQueuedTableHand3D ENDP
; A non-owning view keeps the hand undistorted while the sleeve reaches from the shoulder.
DrawDealerArm3D PROC uses ebx esi edi frame:DWORD,x:DWORD,y:DWORD
local framePtr:DWORD,endY:DWORD,row:DWORD,span:DWORD,part:AnimPack3D
mov part.imageWidth, 144
mov part.height, 124
mov part.frames, 1
mov eax, frame
imul eax, 144*192*4
add eax, handsPack3D.pixels
mov framePtr, eax
add eax, 68*144*4
mov part.pixels, eax
mov eax, y
add eax, 68
mov endY, eax
invoke DrawAnimSprite3D, ADDR part, 0, x, endY, 144, 124
cmp endY, 64
jle dealer_arm_done
mov eax, endY
sub eax, 64
mov span, eax
mov part.height, 1
mov row, 64
dealer_arm_row:
mov eax, row
sub eax, 64
imul eax, 68
xor edx, edx
div span
imul eax, 144*4
add eax, framePtr
mov part.pixels, eax
mov eax, x
sub eax, 310
mov ecx, row
sub ecx, 64
imul eax, ecx
cdq
idiv span
add eax, 310
invoke DrawAnimSprite3D, ADDR part, 0, eax, row, 144, 1
inc row
mov eax, row
cmp eax, endY
jl dealer_arm_row
dealer_arm_done:
ret
DrawDealerArm3D ENDP