KAZIK/src_graphics/russian_roulette.inc
Игорь Федосеев 2024aacd31 feat(tower): implement 3D Hell Tower mode and clean legacy console code
- Add 3D Hell Tower mode with 10 boss floors, briefings, and outcome tracking across games
- Refactor poker.asm by removing >10,600 lines of dead legacy console games and menus
- Rebuild poker.exe with clean binary output and update .gitignore
2026-10-15 19:49:50 +03:00

765 lines
17 KiB
PHP

; Native roulette: one cylinder, one paid stake, cinematic states in the same window.
.code
FreeRussianAssets3D PROC
invoke FreeAnimPack3D,OFFSET rrPartyArt3D
invoke FreeAnimPack3D,OFFSET rr3d_room
invoke FreeAnimPack3D,OFFSET rr3d_dealer
invoke FreeAnimPack3D,OFFSET rr3d_hands
cmp rr3d_assets, 0
je @F
invoke HeapFree, rr3d_heap, 0, rr3d_assets
mov rr3d_assets, 0
@@:
ret
FreeRussianAssets3D ENDP
LoadRussianAssets3D PROC uses ebx
local count:DWORD
cmp rr3d_assets, 0
jne rr_assets_ready
invoke CreateFileA, OFFSET rrAssetPath3D, 80000000h, 1, 0, 3, 80h, 0
cmp eax, -1
je rr_assets_failed
mov ebx, eax
invoke GetProcessHeap
mov rr3d_heap, eax
invoke HeapAlloc, eax, 0, 4194304
mov rr3d_assets, eax
test eax, eax
jz rr_assets_close_failed
invoke ReadFile, ebx, rr3d_assets, 4194304, ADDR count, 0
test eax, eax
jz rr_assets_close_failed
cmp count, 4194304
jne rr_assets_close_failed
invoke CloseHandle, ebx
rr_assets_ready:
invoke LoadAnimPack3D,OFFSET rr3d_room,OFFSET bs3d_roomPath
test eax,eax
jz rr_view_failed
cmp rr3d_room.imageWidth,640
jne rr_view_failed
cmp rr3d_room.height,480
jne rr_view_failed
invoke LoadAnimPack3D,OFFSET rr3d_dealer,OFFSET bs3d_dealerPath
test eax,eax
jz rr_view_failed
cmp rr3d_dealer.frames,16
jne rr_view_failed
invoke LoadAnimPack3D,OFFSET rr3d_hands,OFFSET rrHandsPath3D
test eax,eax
jz rr_view_failed
cmp rr3d_hands.frames,16
jne rr_view_failed
mov eax, 1
ret
rr_view_failed:
call FreeRussianAssets3D
jmp rr_assets_failed
rr_assets_close_failed:
invoke CloseHandle, ebx
call FreeRussianAssets3D
rr_assets_failed:
invoke MessageBoxA, h3DWnd, OFFSET rrAssetError3D, OFFSET rrTitleText3D, 10h
xor eax, eax
ret
LoadRussianAssets3D ENDP
InitRussianGame3D PROC
call LoadRussianAssets3D
test eax, eax
jz @F
mov rr3d_state, RR_READY
mov rr3d_timer, 0
mov rr3d_payout, 0
mov rr3d_error, 0
mov cardExitActive3D,0
call RRPartyInit3D
@@:
ret
InitRussianGame3D ENDP
StartRussianRound3D PROC uses ebx esi
cmp rr3d_state, RR_READY
jne rr_start_done
mov eax, rr3d_bet
test eax, eax
jle rr_start_empty
cmp eax, bankroll
ja rr_start_empty
cmp rr3d_bullets, 1
jb rr_start_empty
cmp rr3d_bullets, 3
ja rr_start_empty
call RRPartyReset3D
mov eax,rr3d_bet
mov rrPartyStake3D,eax
mov rrPartySettled3D,0
sub bankroll, eax
mov rr3d_payout, 0
mov rr3d_error, 0
call RRLoadCylinder3D
invoke RandomRange3D, rrPartySize3D
mov rr3d_turn, eax
mov rr3d_state, RR_LOAD
mov rr3d_timer, 0
invoke PlayCasinoSound3D, OFFSET rrLoadSound3D, 0, 20003h
call SaveProgress3D
jmp rr_start_done
rr_start_empty:
mov rr3d_error, 1
rr_start_done:
ret
StartRussianRound3D ENDP
AdvanceRussianScene3D PROC
mov eax, rr3d_state
cmp eax, RR_LOAD
je rr_next_spin
cmp eax, RR_SPIN
je rr_next_turn
cmp eax, RR_RAISE
je rr_next_fire
cmp eax, RR_FIRE
je rr_next_outcome
cmp eax, RR_DRY
je rr_next_chamber
cmp eax, RR_GLITCH
je rr_next_dark
cmp eax, RR_DARK
je rr_next_gman
cmp eax, RR_GMAN
je rr_next_return
cmp eax, RR_RETURN
je rr_next_casino
ret
rr_next_spin:
mov rr3d_state, RR_SPIN
ret
rr_next_turn:
mov rr3d_state, RR_PLAYER
cmp rr3d_turn, 0
je @F
mov rr3d_state, RR_RAISE
@@:
ret
rr_next_fire:
mov eax, rr3d_chamber
bt rr3d_mask, eax
setc al
movzx eax, al
mov rr3d_shot, eax
mov rr3d_state, RR_FIRE
test eax, eax
jz @F
invoke PlayCasinoSound3D, OFFSET rrFireSound3D, 0, 20003h
ret
@@:
invoke PlayCasinoSound3D, OFFSET rrDrySound3D, 0, 20003h
ret
rr_next_outcome:
cmp rr3d_shot, 0
jne rr_live_round
mov rr3d_state, RR_DRY
ret
rr_live_round:
cmp rrPartyCount3D,1
jbe @F
call RRPartyHit3D
ret
@@:
cmp rr3d_turn, 0
je rr_player_lost
mov eax, rr3d_bet
shl eax, 1
mov rr3d_payout, eax
add bankroll, eax
mov rr3d_state, RR_WIN
mov rrPartySettled3D,1
invoke PlayCasinoSound3D, OFFSET soundRoundWin, 0, 20003h
invoke NpcRecordRound3D,6,1
call SaveProgress3D
ret
rr_player_lost:
mov rrPartySettled3D,1
mov rr3d_state, RR_GLITCH
invoke NpcRecordRound3D,6,0
call SaveProgress3D
ret
rr_next_chamber:
cmp rrPartyCount3D,1
jbe @F
call RRPartyNext3D
ret
@@:
inc rr3d_chamber
cmp rr3d_chamber, 6
jb @F
mov rr3d_chamber, 0
@@:
xor rr3d_turn, 1
jmp rr_next_turn
rr_next_dark:
mov rr3d_state, RR_DARK
ret
rr_next_gman:
mov rr3d_state, RR_GMAN
invoke GetFileAttributesA, OFFSET rrGmanSound3D
cmp eax, -1
je @F
invoke PlayCasinoSound3D, OFFSET rrGmanSound3D, 0, 20003h
@@:
ret
rr_next_return:
mov rr3d_state, RR_RETURN
invoke PlayCasinoSound3D, 0, 0, 0
ret
rr_next_casino:
mov rr3d_state, RR_READY
mov rr3d_timer, 0
mov engineMode, MODE_WALK
mov paused3D, 0
ret
AdvanceRussianScene3D ENDP
HandleRussianInput3D PROC uses ebx
call HandleCardExit3D
test eax,eax
jnz rr_input_done
call RRPartyInput3D
cmp cardExitActive3D,0
jne rr_input_done
cmp engineMode,MODE_RUSSIAN
jne rr_input_done
cmp rr3d_state, RR_READY
je rr_input_ready
cmp rr3d_state, RR_PLAYER
je rr_input_fire
cmp rr3d_state, RR_WIN
je rr_input_next
mov eax, deltaTime3D
add rr3d_timer, eax
rr_update_scene:
mov ebx, rr3d_state
mov ecx, rr3d_durations[ebx*4]
test ecx, ecx
jz rr_input_done
cmp rr3d_timer, ecx
jb rr_input_done
sub rr3d_timer, ecx
call AdvanceRussianScene3D
cmp engineMode, MODE_WALK
jne rr_update_scene
ret
rr_input_ready:
invoke Pressed3D, 57h
test eax, eax
jnz rr_bet_up
invoke Pressed3D, 26h
test eax, eax
jnz rr_bet_up
invoke Pressed3D, 53h
test eax, eax
jnz rr_bet_down
invoke Pressed3D, 28h
test eax, eax
jnz rr_bet_down
invoke Pressed3D, 31h
test eax, eax
jz @F
mov rr3d_bullets, 1
@@:
invoke Pressed3D, 32h
test eax, eax
jz @F
mov rr3d_bullets, 2
@@:
invoke Pressed3D, 33h
test eax, eax
jz @F
mov rr3d_bullets, 3
@@:
invoke Pressed3D, 20h
test eax, eax
jz rr_input_done
call StartRussianRound3D
ret
rr_bet_up:
mov eax, rr3d_bet
add eax, 50
cmp eax, 5000
jbe @F
mov eax, 5000
@@:
cmp eax, bankroll
jbe @F
mov eax, bankroll
@@:
mov rr3d_bet, eax
mov rr3d_error, 0
ret
rr_bet_down:
sub rr3d_bet, 50
cmp rr3d_bet, 50
jge rr_input_done
mov rr3d_bet, 50
ret
rr_input_fire:
invoke Pressed3D, 20h
test eax, eax
jz rr_input_done
mov rr3d_state, RR_RAISE
mov rr3d_timer, 0
ret
rr_input_next:
cmp tournamentMode, 1
jne @F
invoke Pressed3D, 20h
test eax, eax
jnz rr_tourney_report
invoke Pressed3D, 0Dh
test eax, eax
jnz rr_tourney_report
ret
rr_tourney_report:
cmp rr3d_state, RR_WIN
jne rr_tourney_loss
invoke TowerReportRoundOutcome, 1
ret
rr_tourney_loss:
invoke TowerReportRoundOutcome, 2
ret
@@:
invoke Pressed3D, 20h
test eax, eax
jz rr_input_done
mov rr3d_state, RR_READY
mov rr3d_timer, 0
call RRPartyReset3D
rr_input_done:
ret
HandleRussianInput3D ENDP
; Inverse-mapped rotation keeps every frame aligned and transparent.
DrawRouletteSprite3D PROC uses ebx esi edi frame:DWORD,centerX:DWORD,centerY:DWORD,wide:DWORD,tall:DWORD,angle:DWORD
local sx:DWORD,sy:DWORD,cosa:DWORD,sina:DWORD,base:DWORD
local px:DWORD,py:DWORD,loX:DWORD,hiX:DWORD,hiY:DWORD,rad:DWORD
cmp rr3d_assets, 0
je rr_sprite_done
mov eax, frame
shl eax, 18
add eax, rr3d_assets
mov base, eax
mov eax, angle
and eax, 511
mov ecx, tableSin[eax*4]
mov sina, ecx
mov ecx, tableCos[eax*4]
mov cosa, ecx
mov eax, wide
add eax, tall
shr eax, 1
mov rad, eax
mov ecx, centerX
sub ecx, eax
cmp ecx, 0
jge @F
xor ecx, ecx
@@:
mov loX, ecx
add eax, centerX
cmp eax, 319
jle @F
mov eax, 319
@@:
mov hiX, eax
mov eax, centerY
sub eax, rad
cmp eax, 0
jge @F
xor eax, eax
@@:
mov py, eax
mov eax, centerY
add eax, rad
cmp eax, 239
jle @F
mov eax, 239
@@:
mov hiY, eax
; Axis-aligned frames need only their rectangular footprint.
cmp angle, 0
jne rr_sprite_row
mov eax, wide
shr eax, 1
mov ecx, centerX
sub ecx, eax
cmp ecx, 0
jge @F
xor ecx, ecx
@@:
mov loX, ecx
add eax, centerX
cmp eax, 319
jle @F
mov eax, 319
@@:
mov hiX, eax
mov eax, tall
shr eax, 1
mov ecx, centerY
sub ecx, eax
cmp ecx, 0
jge @F
xor ecx, ecx
@@:
mov py, ecx
add eax, centerY
cmp eax, 239
jle @F
mov eax, 239
@@:
mov hiY, eax
rr_sprite_row:
mov eax, loX
mov px, eax
rr_sprite_pixel:
mov eax, px
sub eax, centerX
mov sx, eax
mov ebx, py
sub ebx, centerY
mov sy, ebx
imul eax, cosa
imul ebx, sina
add eax, ebx
sar eax, 8
cdq
idiv wide
add eax, 128
cmp eax, 255
ja rr_sprite_skip
mov esi, eax
mov eax, sy
imul eax, cosa
mov ebx, sx
imul ebx, sina
sub eax, ebx
sar eax, 8
cdq
idiv tall
add eax, 128
cmp eax, 255
ja rr_sprite_skip
shl eax, 8
add eax, esi
mov esi, base
mov ebx, [esi+eax*4]
test ebx, 80000000h
jz rr_sprite_skip
mov eax, py
imul eax, SCREEN_W*2
mov edx, px
shl edx, 1
add eax, edx
lea edi, screenBuffer[eax*4]
mov [edi], ebx
mov [edi+4], ebx
mov [edi+SCREEN_W*4], ebx
mov [edi+SCREEN_W*4+4], ebx
rr_sprite_skip:
inc px
mov eax, px
cmp eax, hiX
jle rr_sprite_pixel
inc py
mov eax, py
cmp eax, hiY
jle rr_sprite_row
rr_sprite_done:
ret
DrawRouletteSprite3D ENDP
; Visual noise never consumes the gameplay RNG or changes the outcome.
RenderRussianGlitch3D PROC uses ebx esi edi strength:DWORD
local visualSeed:DWORD,scanRow:DWORD
mov eax, rr3d_timer
xor eax, 13579BDFh
mov visualSeed, eax
mov scanRow, 0
rr_glitch_row:
mov eax, visualSeed
imul eax, 1664525
add eax, 1013904223
mov visualSeed, eax
shr eax, 16
and eax, 255
cmp eax, strength
jae rr_glitch_next
mov eax, scanRow
imul eax, SCREEN_W*4*2
lea edi, screenBuffer[eax]
mov esi, SCREEN_W*2
mov ebx, 001ECFD8h
test scanRow, 2
jz @F
mov ebx, 00983478h
@@:
rr_glitch_pixels:
xor [edi], ebx
add edi, 4
dec esi
jnz rr_glitch_pixels
rr_glitch_next:
add scanRow, 3
cmp scanRow, 240
jb rr_glitch_row
ret
RenderRussianGlitch3D ENDP
RenderRussianCylinder3D PROC uses ebx esi
local loaded:DWORD,hx:DWORD,hy:DWORD
invoke DrawRouletteSprite3D, 2, 251, 112, 62, 62, 0
mov eax, rr3d_timer
xor edx, edx
mov ecx, 450
div ecx
cmp eax, rr3d_bullets
jbe @F
mov eax, rr3d_bullets
@@:
mov loaded, eax
xor esi, esi
xor ebx, ebx
rr_draw_chambers:
bt rr3d_mask, esi
jnc rr_next_hole
cmp ebx, loaded
jae rr_next_hole
inc ebx
imul eax, esi, 512
xor edx, edx
mov ecx, 6
div ecx
sub eax, 128
and eax, 511
mov edx, tableCos[eax*4]
imul edx, 17
sar edx, 16
add edx, 251
mov hx, edx
mov edx, tableSin[eax*4]
imul edx, 17
sar edx, 16
add edx, 112
mov hy, edx
invoke DrawCircle, hx, hy, 7, 00C49B41h
invoke DrawCircle, hx, hy, 3, 006E5129h
rr_next_hole:
inc esi
cmp esi, 6
jb rr_draw_chambers
ret
RenderRussianCylinder3D ENDP
RenderRussianHall3D PROC
call UpdateCamera3D
call RenderCeilingAndFloor
call RenderWalls
call RenderSprites
call RenderHUD
call RenderMinimap
ret
RenderRussianHall3D ENDP
RenderRussianGame3D PROC uses ebx esi edi
local angle:DWORD,poseY:DWORD,poseX:DWORD,scale:DWORD
cmp engineMode, MODE_WALK
je rr_render_hall
cmp rr3d_state, RR_RETURN
je rr_render_return
cmp rr3d_state, RR_DARK
je rr_render_dark
cmp rr3d_state, RR_GMAN
je rr_render_gman
call RenderRussianTable3D
call RenderRussianExit3D
ret
invoke DrawBox, 0, 0, 320, 240, 00100D17h
invoke DrawBoxBorder, 7, 7, 306, 226, 00192320h, 00BE994Ah, 2
invoke DrawBox, 15, 64, 290, 110, 000E3025h
invoke DrawBox, 15, 165, 290, 9, 004E2D24h
invoke DrawString8x8, 96, 18, OFFSET rrTitleText3D, 00EBD5A0h
invoke DrawString8x8, 18, 43, OFFSET textBankPrompt, 003CFF3Ch
invoke FormatNumber, bankroll, OFFSET hudNumBuffer
invoke DrawString8x8, 66, 43, OFFSET hudNumBuffer, 003CFF3Ch
invoke DrawString8x8, 195, 43, OFFSET textBetPrompt, 00FFD700h
invoke FormatNumber, rr3d_bet, OFFSET hudNumBuffer
invoke DrawString8x8, 251, 43, OFFSET hudNumBuffer, 00FFD700h
mov eax, rr3d_state
cmp eax, RR_LOAD
je rr_render_loading
cmp eax, RR_SPIN
je rr_render_spin
cmp eax, RR_RAISE
je rr_render_raise
cmp eax, RR_FIRE
je rr_render_fire
cmp eax, RR_DRY
je rr_render_dry
cmp eax, RR_WIN
je rr_render_win
cmp eax, RR_GLITCH
je rr_render_glitch
invoke DrawRouletteSprite3D, 0, 160, 114, 165, 104, 0
cmp rr3d_state, RR_PLAYER
je rr_render_player
invoke DrawString8x8, 18, 180, OFFSET rrCartridgeText3D, 00EBD5A0h
invoke FormatNumber, rr3d_bullets, OFFSET hudNumBuffer
invoke DrawString8x8, 90, 180, OFFSET hudNumBuffer, 00FFFFFFh
invoke DrawString8x8, 18, 197, OFFSET rrBulletKeys3D, 00C1C9CFh
invoke DrawString8x8, 197, 197, OFFSET rrBetKeys3D, 00C1C9CFh
invoke DrawString8x8, 18, 218, OFFSET rrStartText3D, 003CFF3Ch
cmp rr3d_error, 0
je rr_render_done
invoke DrawString8x8, 18, 181, OFFSET textNoCash3D, 00FF6464h
ret
rr_render_player:
invoke DrawString8x8, 130, 180, OFFSET rrPlayerText3D, 003CFF3Ch
invoke DrawString8x8, 55, 207, OFFSET rrFireText3D, 00EBD5A0h
ret
rr_render_loading:
mov eax, rr3d_timer
xor edx, edx
mov ecx, 450
div ecx
mov ebx, 1
cmp eax, rr3d_bullets
jae @F
cmp edx, 180
jb @F
cmp edx, 390
jae @F
mov ebx, 7
@@:
push eax
push edx
invoke DrawRouletteSprite3D, ebx, 121, 112, 170, 112, 0
call RenderRussianCylinder3D
pop edx
pop eax
cmp eax, rr3d_bullets
jae rr_loading_label
mov eax, edx
imul eax, 41
xor edx, edx
mov ecx, 450
div ecx
mov edx, 156
sub edx, eax
invoke DrawRouletteSprite3D, 3, 251, edx, 32, 18, 128
rr_loading_label:
invoke DrawString8x8, 100, 192, OFFSET rrLoadText3D, 00EBD5A0h
ret
rr_render_spin:
mov eax, 1400
sub eax, rr3d_timer
imul eax, eax
shl eax, 1
xor edx, edx
mov ecx, 1400
div ecx
mov angle, eax
invoke DrawRouletteSprite3D, 0, 160, 113, 160, 105, angle
invoke DrawString8x8, 92, 192, OFFSET rrSpinText3D, 00EBD5A0h
ret
rr_render_raise:
mov eax, rr3d_timer
imul eax, 15
xor edx, edx
mov ecx, 750
div ecx
mov ebx, 114
sub ebx, eax
mov poseY, ebx
mov poseX, 164
invoke DrawRouletteSprite3D, 6, 67, 115, 91, 119, 0
invoke DrawRouletteSprite3D, 4, poseX, poseY, 174, 114, 0
jmp rr_render_turn_label
rr_render_fire:
invoke DrawRouletteSprite3D, 6, 67, 115, 91, 119, 0
mov eax, 4
cmp rr3d_shot, 0
je @F
mov eax, 5
@@:
invoke DrawRouletteSprite3D, eax, 164, 99, 174, 114, 0
cmp rr3d_shot, 0
je rr_render_done
invoke DrawString8x8, 132, 192, OFFSET rrBangText3D, 00FF9864h
ret
rr_render_dry:
invoke DrawRouletteSprite3D, 4, 170, 114, 174, 114, 0
invoke DrawString8x8, 108, 192, OFFSET rrClickText3D, 00B6DDD0h
ret
rr_render_turn_label:
mov eax, OFFSET rrPlayerText3D
cmp rr3d_turn, 0
je @F
mov eax, OFFSET rrDealerText3D
@@:
invoke DrawString8x8, 125, 192, eax, 00EBD5A0h
ret
rr_render_win:
invoke DrawRouletteSprite3D, 0, 160, 114, 165, 104, 0
invoke DrawString8x8, 80, 188, OFFSET rrVictoryText3D, 003CFF3Ch
invoke FormatNumber, rr3d_payout, OFFSET hudNumBuffer
invoke DrawString8x8, 160, 188, OFFSET hudNumBuffer, 003CFF3Ch
invoke DrawString8x8, 88, 216, OFFSET rrRoundText3D, 00EBD5A0h
ret
rr_render_glitch:
invoke DrawRouletteSprite3D, 4, 164, 99, 174, 114, 0
invoke RenderRussianGlitch3D, 190
ret
rr_render_dark:
invoke DrawBox, 0, 0, 320, 240, 0
ret
rr_render_gman:
invoke DrawBox, 0, 0, 320, 240, 0004090Ch
mov eax, rr3d_timer
xor edx, edx
mov ecx, 180
div ecx
and eax, 7
add eax, 8
mov esi, eax
mov eax, rr3d_timer
xor edx, edx
mov ecx, 120
div ecx
add eax, 180
mov scale, eax
invoke DrawRouletteSprite3D, esi, 160, 110, scale, scale, 0
invoke DrawBox, 0, 220, 320, 20, 0004090Ch
invoke DrawString8x8, 52, 227, OFFSET rrWakeText3D, 00D7DFE3h
cmp rr3d_timer, 400
jae rr_render_done
invoke RenderRussianGlitch3D, 48
ret
rr_render_return:
call RenderRussianHall3D
mov eax, 700
sub eax, rr3d_timer
imul eax, 170
xor edx, edx
mov ecx, 700
div ecx
invoke RenderRussianGlitch3D, eax
ret
rr_render_hall:
call RenderRussianHall3D
rr_render_done:
call RenderRussianExit3D
ret
RenderRussianGame3D ENDP
include src_graphics\russian_party.inc