KAZIK/src_graphics/native_slots.inc
Игорь Федосеев eaac8b861e feat: rework artifacts and tower relics
Extend profiles from 280 to 312 bytes with legacy compatibility.
Keep tower relics run-local and share the profile bankroll.
2026-10-30 23:22:19 +03:00

634 lines
16 KiB
PHP

FreeNativeSlots3D PROC
invoke FreeAnimPack3D, OFFSET slotCabinetPack3D
invoke FreeAnimPack3D, OFFSET slotSymbolsPack3D
ret
FreeNativeSlots3D ENDP
InitNativeSlots3D PROC
invoke LoadAnimPack3D, OFFSET slotCabinetPack3D, OFFSET slotCabinetPath3D
test eax,eax
jz slot_init_fail
cmp slotCabinetPack3D.imageWidth,640
jne slot_init_fail
cmp slotCabinetPack3D.height,480
jne slot_init_fail
cmp slotCabinetPack3D.frames,1
jne slot_init_fail
invoke LoadAnimPack3D, OFFSET slotSymbolsPack3D, OFFSET slotSymbolsPath3D
test eax,eax
jz slot_init_fail
cmp slotSymbolsPack3D.imageWidth,64
jne slot_init_fail
cmp slotSymbolsPack3D.height,64
jne slot_init_fail
cmp slotSymbolsPack3D.frames,8
jne slot_init_fail
mov slotSpinState,SLOT_READY
mov slotSpinTimer,0
mov slotWinAmount,0
mov slotStake3D,0
mov slotLeaveAfter3D,0
mov slotPaytable3D,0
mov slotError3D,0
mov slotEffects3D,0
mov slotBetIndex3D,1
mov slotBet,50
mov cardExitActive3D,0
mov paused3D,0
call ClearKeys3D
mov eax,1
ret
slot_init_fail:
call FreeNativeSlots3D
xor eax,eax
ret
InitNativeSlots3D ENDP
; Results are sampled once at stake debit. Rendering never consumes RNG or pays.
StartNativeSlots3D PROC uses ebx esi
cmp slotSpinState,SLOT_SPIN
je slot_start_done
cmp slotPaytable3D,0
jne slot_start_done
cmp slotCabinetPack3D.pixels,0
je slot_start_done
cmp slotSymbolsPack3D.pixels,0
je slot_start_done
mov eax,slotBet
test eax,eax
jz slot_start_done
cmp eax,10000
ja slot_start_done
cmp eax,bankroll
ja slot_start_money
sub bankroll,eax
mov slotStake3D,eax
mov slotSpinState,SLOT_SPIN
mov slotSpinTimer,0
mov slotWinAmount,0
mov slotLeaveAfter3D,0
mov slotError3D,0
mov slotEffects3D,0
xor esi,esi
slot_start_reel:
mov eax,slotStops3D[esi*4]
mov slotStartStops3D[esi*4],eax
invoke RandomRange3D,20
mov slotTargets3D[esi*4],eax
mov edx,slotStrip3D[eax*4]
mov slotReel1[esi*4],edx
sub eax,slotStartStops3D[esi*4]
jns @F
add eax,20
@@:
add eax,slotCycles3D[esi*4]
shl eax,6
mov slotTravel3D[esi*4],eax
inc esi
cmp esi,3
jb slot_start_reel
call SaveProgress3D
invoke PlayCasinoSound3D, OFFSET soundSlotSpin,0,1
ret
slot_start_money:
mov slotError3D,1
slot_start_done:
ret
StartNativeSlots3D ENDP
; Gross multipliers. A cherry pair pays 2x, any other pair returns the stake.
SlotMultiplier3D PROC first:DWORD,second:DWORD,third:DWORD
mov eax,first
cmp eax,7
ja slot_multiplier_zero
cmp second,7
ja slot_multiplier_zero
cmp third,7
ja slot_multiplier_zero
cmp eax,second
jne slot_multiplier_other_pair
cmp eax,third
jne slot_multiplier_pair
mov eax,slotTriple3D[eax*4]
ret
slot_multiplier_other_pair:
cmp eax,third
je slot_multiplier_pair
mov eax,second
cmp eax,third
jne slot_multiplier_zero
slot_multiplier_pair:
cmp eax,1
jne @F
mov eax,2
ret
@@:
mov eax,1
ret
slot_multiplier_zero:
xor eax,eax
ret
SlotMultiplier3D ENDP
SettleNativeSlots3D PROC uses esi
cmp slotSpinState,SLOT_SPIN
jne slot_settle_done
invoke SlotMultiplier3D,slotReel1,slotReel2,slotReel3
mul slotStake3D
mov ecx,1000000000
sub ecx,bankroll
cmp eax,ecx
jbe @F
mov eax,ecx
@@:
mov slotWinAmount,eax
add bankroll,eax
jc slot_settle_cap
cmp bankroll,1000000000
jbe @F
slot_settle_cap:
mov bankroll,1000000000
@@:
xor esi,esi
slot_settle_stops:
mov eax,slotTargets3D[esi*4]
mov slotStops3D[esi*4],eax
inc esi
cmp esi,3
jb slot_settle_stops
mov slotSpinTimer,3000
mov slotSpinState,SLOT_RESULT
mov slotEffects3D,0
xor eax,eax
mov ecx,slotWinAmount
cmp ecx,slotStake3D
seta al
invoke NpcRecordRound3D,4,eax
call SaveProgress3D
mov eax,slotWinAmount
cmp eax,slotStake3D
jb slot_settle_loss
jne @F
invoke PlayCasinoSound3D,0,0,0
jmp slot_settle_exit
@@:
invoke PlayCasinoSound3D,OFFSET soundRoundWin,0,1
mov eax,slotWinAmount
sub eax,slotStake3D
invoke TriggerCharmWinBonus,eax
jmp slot_settle_exit
slot_settle_loss:
mov eax,slotStake3D
sub eax,slotWinAmount
invoke TriggerCharmLossProtection,eax
test eax, eax
jnz slot_settle_exit
invoke PlayCasinoSound3D,OFFSET soundRoundLose,0,1
slot_settle_exit:
cmp slotLeaveAfter3D,0
je slot_settle_done
call SlotEscape3D
slot_settle_done:
ret
SettleNativeSlots3D ENDP
; Escape queues a safe exit during a paid spin; it never opens the pause menu.
SlotEscape3D PROC
mov paused3D,0
cmp slotPaytable3D,0
je @F
mov slotPaytable3D,0
call ClearKeys3D
ret
@@:
cmp slotSpinState,SLOT_SPIN
jne slot_exit_hall
mov slotLeaveAfter3D,1
call ClearKeys3D
ret
slot_exit_hall:
mov slotLeaveAfter3D,0
mov paused3D,0
mov engineMode,MODE_WALK
call ClearKeys3D
invoke PlayCasinoSound3D,0,0,0
ret
SlotEscape3D ENDP
; A monotonic quadratic ease-out maps elapsed milliseconds to strip pixels.
SlotReelPosition3D PROC uses ebx index:DWORD
mov ebx,index
cmp ebx,2
ja slot_position_zero
mov eax,slotStops3D[ebx*4]
shl eax,6
cmp slotSpinState,SLOT_SPIN
jne slot_position_done
mov eax,slotSpinTimer
cmp eax,slotDurations3D[ebx*4]
jae slot_position_end
shl eax,10
xor edx,edx
div slotDurations3D[ebx*4]
mov ecx,2048
sub ecx,eax
imul eax,ecx
mul slotTravel3D[ebx*4]
shrd eax,edx,20
mov edx,slotStartStops3D[ebx*4]
shl edx,6
add eax,edx
ret
slot_position_end:
mov eax,slotStartStops3D[ebx*4]
shl eax,6
add eax,slotTravel3D[ebx*4]
slot_position_done:
ret
slot_position_zero:
xor eax,eax
ret
SlotReelPosition3D ENDP
SlotExitMouse3D PROC
cmp mouseClick3D,0
je slot_exit_mouse_done
mov mouseClick3D,0
cmp mouseY3D,3
jb slot_exit_mouse_done
cmp mouseY3D,17
jae slot_exit_mouse_done
cmp mouseX3D,252
jb slot_exit_mouse_done
cmp mouseX3D,312
jae slot_exit_mouse_done
call SlotEscape3D
slot_exit_mouse_done:
ret
SlotExitMouse3D ENDP
HandleNativeSlots3D PROC uses ebx
cmp slotSpinState,SLOT_SPIN
jne slot_handle_idle
; Process the header before settlement so the final spin tick cannot eat it.
call SlotExitMouse3D
mov eax,deltaTime3D
cmp eax,250
jbe @F
mov eax,250
@@:
add slotSpinTimer,eax
cmp slotSpinTimer,3000
jb slot_handle_exit_mouse
call SettleNativeSlots3D
ret
slot_handle_idle:
mov eax,deltaTime3D
add slotEffects3D,eax
cmp slotEffects3D,2000
jbe @F
mov slotEffects3D,2000
@@:
cmp slotPaytable3D,0
je slot_handle_controls
invoke Pressed3D,0Dh
test eax,eax
jnz slot_close_paytable
invoke Pressed3D,20h
test eax,eax
jnz slot_close_paytable
invoke Pressed3D,50h
test eax,eax
jnz slot_close_paytable
cmp mouseClick3D,0
je slot_handle_done
mov mouseClick3D,0
cmp mouseY3D,202
jb slot_handle_done
cmp mouseY3D,220
jae slot_handle_done
cmp mouseX3D,112
jb slot_handle_done
cmp mouseX3D,208
jae slot_handle_done
slot_close_paytable:
mov slotPaytable3D,0
ret
slot_handle_controls:
cmp mouseClick3D,0
je slot_handle_keys
cmp mouseY3D,222
jb slot_handle_keys
cmp mouseY3D,238
jae slot_handle_keys
mov mouseClick3D,0
mov eax,mouseX3D
cmp eax,11
jb slot_handle_keys
cmp eax,29
jb slot_bet_down
cmp eax,35
jb slot_handle_keys
cmp eax,53
jb slot_bet_up
cmp eax,120
jb slot_handle_keys
cmp eax,190
jb slot_handle_start
cmp eax,202
jb slot_handle_keys
cmp eax,272
jae slot_handle_keys
mov slotPaytable3D,1
ret
slot_handle_keys:
invoke Pressed3D,50h
test eax,eax
jz @F
mov slotPaytable3D,1
ret
@@:
invoke Pressed3D,57h
test eax,eax
jnz slot_bet_up
invoke Pressed3D,26h
test eax,eax
jnz slot_bet_up
invoke Pressed3D,53h
test eax,eax
jnz slot_bet_down
invoke Pressed3D,28h
test eax,eax
jnz slot_bet_down
invoke Pressed3D,20h
test eax,eax
jnz slot_handle_start
invoke Pressed3D,0Dh
test eax,eax
jz slot_handle_exit_mouse
slot_handle_start:
call StartNativeSlots3D
ret
slot_bet_up:
cmp slotBetIndex3D,6
jae slot_handle_done
inc slotBetIndex3D
jmp slot_bet_changed
slot_bet_down:
cmp slotBetIndex3D,0
je slot_handle_done
dec slotBetIndex3D
slot_bet_changed:
mov ecx,slotBetIndex3D
mov eax,slotBetValues3D[ecx*4]
mov slotBet,eax
mov slotError3D,0
ret
slot_handle_exit_mouse:
call SlotExitMouse3D
slot_handle_done:
ret
HandleNativeSlots3D ENDP
; Clip the 64x64 alpha-tested symbol to its own reel window, not the cabinet.
DrawSlotSymbol3D PROC uses ebx esi edi symbol:DWORD,x:DWORD,y:DWORD
local row:DWORD,lastRow:DWORD,source:DWORD
cmp symbol,7
ja slot_symbol_done
mov eax,slotSymbolsPack3D.pixels
test eax,eax
jz slot_symbol_done
mov ecx,symbol
shl ecx,14
add eax,ecx
mov source,eax
mov eax,y
cmp eax,SLOT_TOP
jge @F
mov eax,SLOT_TOP
@@:
mov row,eax
mov eax,y
add eax,64
cmp eax,SLOT_BOTTOM
jle @F
mov eax,SLOT_BOTTOM
@@:
mov lastRow,eax
slot_symbol_row:
mov eax,row
cmp eax,lastRow
jge slot_symbol_done
mov ecx,eax
sub ecx,y
shl ecx,8
mov esi,source
add esi,ecx
imul eax,640*4
mov ecx,x
lea edi,screenBuffer[eax+ecx*4]
mov ecx,64
slot_symbol_column:
lodsd
test eax,0FF000000h
jz @F
and eax,00FFFFFFh
mov [edi],eax
@@:
add edi,4
dec ecx
jnz slot_symbol_column
inc row
jmp slot_symbol_row
slot_symbol_done:
ret
DrawSlotSymbol3D ENDP
DrawSlotReel3D PROC uses ebx esi edi index:DWORD
local offsetPx:DWORD,baseStop:DWORD,symbolY:DWORD,symbolX:DWORD
invoke SlotReelPosition3D,index
xor edx,edx
mov ecx,64
div ecx
mov offsetPx,edx
xor edx,edx
mov ecx,20
div ecx
mov baseStop,edx
mov ebx,index
mov eax,slotWindows3D[ebx*4]
add eax,12
mov symbolX,eax
mov eax,160
sub eax,offsetPx
sub eax,64
mov symbolY,eax
mov esi,baseStop
add esi,19
xor edi,edi
slot_reel_symbol:
mov eax,esi
xor edx,edx
mov ecx,20
div ecx
mov eax,slotStrip3D[edx*4]
invoke DrawSlotSymbol3D,eax,symbolX,symbolY
add symbolY,64
inc esi
inc edi
cmp edi,4
jb slot_reel_symbol
ret
DrawSlotReel3D ENDP
RenderNativeSlots3D PROC uses ebx esi edi
; The validated cabinet is opaque and already framebuffer-sized.
mov esi,slotCabinetPack3D.pixels
test esi,esi
jz slot_render_done
lea edi,screenBuffer
mov ecx,SCREEN_SIZE
rep movsd
xor esi,esi
slot_render_reels:
invoke DrawSlotReel3D,esi
inc esi
cmp esi,3
jb slot_render_reels
; The payline is fixed at the center of the three physical drums.
invoke DrawBox,86,94,4,3,00E9CE71h
invoke DrawBox,232,94,4,3,00E9CE71h
cmp slotSpinState,SLOT_RESULT
jne slot_render_header
mov eax,slotWinAmount
cmp eax,slotStake3D
jbe slot_render_header
mov eax,slotEffects3D
xor edx,edx
mov ecx,200
div ecx
test eax,1
jnz slot_render_header
invoke DrawBox,90,94,142,1,00E9CE71h
slot_render_header:
invoke DrawBox,0,0,320,19,00151D20h
invoke DrawString8x8,8,6,OFFSET slotTitle3D,00E8D7ADh
invoke DrawString8x8,54,6,OFFSET textBank3D,00A8DDB9h
invoke FormatNumber,bankroll,OFFSET hudNumBuffer
invoke DrawString8x8,103,6,OFFSET hudNumBuffer,00F4F3E8h
invoke DrawBoxBorder,252,3,60,14,002C3637h,00687672h,1
invoke DrawString8x8,258,6,OFFSET cardExitButton3D,00E9D8B0h
mov ebx,OFFSET slotReadyText3D
cmp slotSpinState,SLOT_SPIN
jne @F
mov ebx,OFFSET slotRollingText3D
@@:
cmp slotSpinState,SLOT_RESULT
jne @F
mov ebx,OFFSET slotLoseText3D
mov eax,slotWinAmount
cmp eax,slotStake3D
jb @F
mov ebx,OFFSET slotRefundText3D
je @F
mov ebx,OFFSET slotWinText3D
@@:
cmp slotError3D,0
je @F
mov ebx,OFFSET slotNoMoney3D
@@:
cmp slotLeaveAfter3D,0
je @F
mov ebx,OFFSET slotExitText3D
@@:
; Keep the message on the generated inset plate, with fixed-size numerals.
invoke DrawBox,98,147,126,12,00151D20h
invoke DrawString8x8,104,149,ebx,00E8D7ADh
cmp slotSpinState,SLOT_RESULT
jne slot_render_controls
cmp ebx,OFFSET slotWinText3D
je @F
cmp ebx,OFFSET slotRefundText3D
jne slot_render_controls
@@:
invoke FormatNumber,slotWinAmount,OFFSET hudNumBuffer
invoke DrawString8x8,164,149,OFFSET hudNumBuffer,00A8DDB9h
slot_render_controls:
invoke DrawBox,0,198,320,42,00151D20h
invoke DrawString8x8,11,201,OFFSET slotBetText3D,00E8D7ADh
invoke FormatNumber,slotBet,OFFSET hudNumBuffer
invoke DrawString8x8,75,201,OFFSET hudNumBuffer,00F4F3E8h
cmp slotSpinState,SLOT_RESULT
jne @F
invoke DrawSlotTotals3D,slotWinAmount,slotStake3D,120
@@:
mov ebx,1
cmp slotSpinState,SLOT_SPIN
jne @F
xor ebx,ebx
@@:
mov edi,006D7470h
test ebx,ebx
jz @F
mov edi,00EEE5CDh
@@:
invoke DrawBoxBorder,11,222,18,16,0025372Ch,edi,1
invoke DrawBoxBorder,35,222,18,16,0025372Ch,edi,1
invoke DrawString8x8,16,226,OFFSET tableMinusText3D,edi
invoke DrawString8x8,40,226,OFFSET tablePlusText3D,edi
invoke DrawTableButton3D,120,OFFSET slotSpinText3D,ebx
invoke DrawTableButton3D,202,OFFSET slotPayText3D,ebx
cmp slotPaytable3D,0
je slot_render_done
invoke DrawBoxBorder,30,23,260,198,00151D20h,00D1B16Eh,1
invoke DrawString8x8,76,31,OFFSET slotPayTitle3D,00E8D7ADh
invoke DrawString8x8,42,48,OFFSET slotTripleText3D,00A8DDB9h
xor esi,esi
slot_render_pay_row:
mov edi,esi
imul edi,12
add edi,62
mov eax,slotSymbolNames3D[esi*4]
invoke DrawString8x8,62,edi,eax,00F4F3E8h
invoke FormatNumber,slotTriple3D[esi*4],OFFSET hudNumBuffer
invoke DrawString8x8,212,edi,OFFSET strMultiplier3D,00E8D7ADh
invoke DrawString8x8,220,edi,OFFSET hudNumBuffer,00E8D7ADh
inc esi
cmp esi,8
jb slot_render_pay_row
invoke DrawString8x8,62,160,OFFSET slotPairText3D,00A8DDB9h
invoke DrawString8x8,62,173,OFFSET slotCherryPair3D,00A8DDB9h
invoke DrawString8x8,42,188,OFFSET slotPayNote3D,00A8DDB9h
invoke DrawBoxBorder,112,204,96,15,003B6C59h,00E9D8B0h,1
invoke DrawString8x8,128,207,OFFSET slotCloseText3D,00E9D8B0h
slot_render_done:
ret
RenderNativeSlots3D ENDP
; Gross is the actual credited sum, including any returned stake.
DrawSlotTotals3D PROC uses ebx esi edi gross:DWORD,stake:DWORD,x:DWORD
mov ebx,x
lea edi,[ebx+72]
invoke DrawString8x8,ebx,201,OFFSET slotWinText3D,00E8D7ADh
invoke FormatNumber,gross,OFFSET hudNumBuffer
invoke DrawString8x8,edi,201,OFFSET hudNumBuffer,00F4F3E8h
invoke DrawString8x8,ebx,211,OFFSET slotNetText3D,00E8D7ADh
mov eax,gross
sub eax,stake
mov esi,00D0D4D0h
lea ebx,slotNetBuffer3D
test eax,eax
jz totals_format
mov BYTE PTR [ebx],'+'
mov esi,00A8DDB9h
jns @F
mov BYTE PTR [ebx],'-'
mov esi,00EE9988h
neg eax
@@:
inc ebx
totals_format:
invoke FormatNumber,eax,ebx
invoke DrawString8x8,edi,211,OFFSET slotNetBuffer3D,esi
ret
DrawSlotTotals3D ENDP