KAZIK/casino3d.inc
Игорь Федосеев b1cd66b322 fix(ui,audio): eliminate cyan color bug, restore authentic IBM VGA Cyrillic font, implement native 2.5D Skill Check
- Fix Little-Endian DIB color inversion (0000FFFFh/0000D7FFh -> 00FFFF00h/00FFD700h) restoring luxurious Gold, Emerald Felt, and Crimson Red palettes across the entire game
- Extract authentic IBM VGA 8x8 font from app866.fon fixing Cyrillic glyph distortion ('М', 'Л', 'П', 'Д')
- Implement native in-engine 2.5D Dead by Daylight Skill Check (MODE_SKILL) eliminating external console popups
- Fix audio mappings to dedicated minigame sounds with zero gunshots outside Russian roulette
- Update visual rasterization test suite and verified 640x480 preview renders
2026-09-30 21:17:07 +03:00

5369 lines
130 KiB
PHP
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

; ==============================================================================
; CASINO 2.5D - MASM32 SOFTWARE RAYCASTER (CP1251)
; Graphical migration; this is not id Software's Doom engine.
; ==============================================================================
includelib gdi32.lib
includelib winmm.lib
CreateWindowExA PROTO :DWORD,:DWORD,:DWORD,:DWORD,:DWORD,:DWORD,:DWORD,:DWORD,:DWORD,:DWORD,:DWORD,:DWORD
RegisterClassExA PROTO :DWORD
DefWindowProcA PROTO :DWORD,:DWORD,:DWORD,:DWORD
ShowWindow PROTO :DWORD,:DWORD
UpdateWindow PROTO :DWORD
GetDC PROTO :DWORD
ReleaseDC PROTO :DWORD,:DWORD
StretchDIBits PROTO :DWORD,:DWORD,:DWORD,:DWORD,:DWORD,:DWORD,:DWORD,:DWORD,:DWORD,:DWORD,:DWORD,:DWORD,:DWORD
PeekMessageA PROTO :DWORD,:DWORD,:DWORD,:DWORD,:DWORD
TranslateMessage PROTO :DWORD
DispatchMessageA PROTO :DWORD
PostQuitMessage PROTO :DWORD
DestroyWindow PROTO :DWORD
SetWindowTextA PROTO :DWORD,:DWORD
SetForegroundWindow PROTO :DWORD
GetConsoleWindow PROTO
GetSystemMetrics PROTO :DWORD
CreateFileA PROTO :DWORD,:DWORD,:DWORD,:DWORD,:DWORD,:DWORD,:DWORD
ReadFile PROTO :DWORD,:DWORD,:DWORD,:DWORD,:DWORD
CloseHandle PROTO :DWORD
GetAsyncKeyState PROTO :DWORD
PlaySoundA PROTO :DWORD,:DWORD,:DWORD
GetModuleFileNameA PROTO :DWORD,:DWORD,:DWORD
Sleep PROTO :DWORD
C3D_POINT STRUCT
x dd ?
y dd ?
C3D_POINT ENDS
C3D_MSG STRUCT
hwnd dd ?
message dd ?
wParam dd ?
lParam dd ?
time dd ?
pt C3D_POINT <>
C3D_MSG ENDS
C3D_WNDCLASSEX STRUCT
cbSize dd ?
style dd ?
lpfnWndProc dd ?
cbClsExtra dd ?
cbWndExtra dd ?
hInstance dd ?
hIcon dd ?
hCursor dd ?
hbrBackground dd ?
lpszMenuName dd ?
lpszClassName dd ?
hIconSm dd ?
C3D_WNDCLASSEX ENDS
C3D_BITMAPINFOHEADER STRUCT
biSize dd ?
biWidth dd ?
biHeight dd ?
biPlanes dw ?
biBitCount dw ?
biCompression dd ?
biSizeImage dd ?
biXPelsPerMeter dd ?
biYPelsPerMeter dd ?
biClrUsed dd ?
biClrImportant dd ?
C3D_BITMAPINFOHEADER ENDS
C3D_BITMAPINFO STRUCT
bmiHeader C3D_BITMAPINFOHEADER <>
bmiColors dd ?
C3D_BITMAPINFO ENDS
SpriteObject STRUCT
posX dd ?
posY dd ?
baseTexId dd ?
frameCount dd ?
curFrame dd ?
animTimer dd ?
animSpeed dd ?
interactId dd ?
promptPtr dd ?
distSq dd ?
SpriteObject ENDS
SCREEN_W equ 640
SCREEN_H equ 480
HALF_W equ 320
HALF_H equ 240
SCREEN_SIZE equ (SCREEN_W * SCREEN_H)
WIN_SCALE equ 1
WINDOW_W equ (SCREEN_W * WIN_SCALE)
WINDOW_H equ (SCREEN_H * WIN_SCALE)
FP_1 equ 65536
FP_HALF equ 32768
CHROMA_KEY equ 00FF00FFh
MODE_WALK equ 0
MODE_SLOTS equ 1
MODE_BLACKJACK equ 2
MODE_ROULETTE equ 3
MODE_SHOP equ 4
MODE_ATM equ 5
MODE_COIN equ 6
MODE_DICE equ 7
MODE_SKULLS equ 8
MODE_SKILL equ 9
WS_OVERLAPPEDWINDOW equ 00CF0000h
SW_SHOW equ 5
SW_HIDE equ 0
PM_REMOVE equ 1
WM_DESTROY equ 0002h
WM_CLOSE equ 0010h
WM_QUIT equ 0012h
CS_HREDRAW equ 2
CS_VREDRAW equ 1
DIB_RGB_COLORS equ 0
SRCCOPY equ 00CC0020h
INVALID_FILE_HANDLE equ -1
include casino3d_data.inc
include font8x8.inc
include src_graphics\platform_data.inc
.data
ALIGN 4
h3DInst dd 0
h3DWnd dd 0
h3DDC dd 0
hCasinoConsole dd 0
bmi3D C3D_BITMAPINFO <>
msg3D C3D_MSG <>
wc3D C3D_WNDCLASSEX <>
sz3DClassName db "Casino3DRetroClass",0
sz3DWindowTitle db "Assembler Casino - 2.5D",0
szTexturesRelPath db "assets\textures\casino3d-hd.bin",0
szTexturesFullPath db 260 dup(0)
soundCoin db "assets\audio\<5C><><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>.wav",0
soundCoinDing db "assets\audio\<5C><><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20> <20><><EFBFBD><EFBFBD> Ultrakill.wav",0
soundCards db "assets\audio\playing_cards_deck_flick_through_001_20485.wav",0
soundRoulette db "assets\audio\roulette-wheel-throw-2.wav",0
soundJackpot db "assets\audio\<5C><><EFBFBD><EFBFBD> <20><><EFBFBD>.wav",0
soundVictory db "assets\audio\victory-tf2.wav",0
soundClick db "assets\audio\revolverdryfirec.wav",0
soundShuffle db "assets\audio\moving-stone.wav",0
soundLose db "assets\audio\<5C><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>.wav",0
playerX dd (16 * FP_1 + FP_HALF)
playerY dd (16 * FP_1 + FP_HALF)
playerAngle dd 384
playerDirX dd 0
playerDirY dd -FP_1
playerPlaneX dd (FP_1 * 66 / 100)
playerPlaneY dd 0
engineMode dd 0
interactTargetId dd 0
interactPromptPtr dd 0
dancerLuckBuff dd 0
flashTimer dd 0
flashMessage db 128 dup(0)
promptDancer db "[E] <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> - <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> $100",0
promptBlackjack db "[E] <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> (21)",0
promptPoker db "[E] <20><><EFBFBD><EFBFBD><EFBFBD> (TEXAS HOLD'EM)",0
promptDurak db "[E] <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>: <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>",0
promptCasinoRoulette db "[E] <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>",0
promptClassicSlot db "[E] <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> 777",0
promptCloverSlot db "[E] <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> CLOVERPIT (5x3)",0
promptDice db "[E] <EFBFBD><EFBFBD><EFBFBD><EFBFBD> <EFBFBD> <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> (CRAPS)",0
promptSkulls db "[E] <EFBFBD><EFBFBD>Ϩ<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> (<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>)",0
promptCoin db "[E] <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> (<EFBFBD>Ш<EFBFBD>/<EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>)",0
promptSkillCheck db "[E] <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>",0
promptBuckshot db "[E] BUCKSHOT ROULETTE",0
promptRussianRoulette db "[E] <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> (VIP)",0
promptOnlineRR db "[E] <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> (NET)",0
promptUmamusume db "[E] <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>",0
promptHellTower db "[E] <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <EFBFBD><EFBFBD><EFBFBD> (10 <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>)",0
promptShop db "[E] <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <EFBFBD> <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>",0
promptATM db "[E] <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <EFBFBD> <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>",0
promptPlayerTerminal db "[E] <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>: <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <EFBFBD> <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>",0
promptObserver db "[E] <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> (<EFBFBD><EFBFBD>)",0
szTitleBlackjack db "[KAZIK 3D CASINO] - <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> (21)",0
szTitlePoker db "[KAZIK 3D CASINO] - <EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> (TEXAS HOLD'EM)",0
szTitleDurak db "[KAZIK 3D CASINO] - <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD>",0
szTitleCasinoRoulette db "[KAZIK 3D CASINO] - <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>",0
szTitleClassicSlot db "[KAZIK 3D CASINO] - <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD> 777",0
szTitleCloverSlot db "[KAZIK 3D CASINO] - <20><><EFBFBD><EFBFBD>-<2D><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> CLOVERPIT (5x3)",0
szTitleDice db "[KAZIK 3D CASINO] - <20><><EFBFBD><EFBFBD> <20> <20><><EFBFBD><EFBFBD><EFBFBD> (CRAPS)",0
szTitleSkulls db "[KAZIK 3D CASINO] - <20><>Ϩ<EFBFBD><CFA8><EFBFBD><EFBFBD><EFBFBD>",0
szTitleCoin db "[KAZIK 3D CASINO] - <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> (<28>Ш<EFBFBD>/<2F><><EFBFBD><EFBFBD><EFBFBD>)",0
szTitleSkillCheck db "[KAZIK 3D CASINO] - <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>",0
szTitleBuckshot db "[KAZIK 3D CASINO] - BUCKSHOT ROULETTE",0
szTitleRussianRoulette db "[KAZIK 3D CASINO] - <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>",0
szTitleOnlineRR db "[KAZIK 3D CASINO] - <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>",0
szTitleUmamusume db "[KAZIK 3D CASINO] - <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>",0
szTitleHellTower db "[KAZIK 3D CASINO] - <20><><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD> (<28><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>)",0
szTitleShop db "[KAZIK 3D CASINO] - <20><><EFBFBD><EFBFBD><EFBFBD> <20> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>",0
szTitleATM db "[KAZIK 3D CASINO] - <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>",0
szTitleTerminal db "[KAZIK 3D CASINO] - <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>",0
szTitleObserver db "[KAZIK 3D CASINO] - <20><><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> (<28><>)",0
textCabinetFooter db "[ <20><><EFBFBD><EFBFBD><EFBFBD>: <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> 0 / <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> 'N' <20><><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20> <20><><EFBFBD> ]",0
msgDancerTipped db "<22><> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> $100 <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>! <20><><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>!",0
msgNeedMoney db "<22><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD> <20> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>!",0
statusHUDFormat db "<22><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>: $",0
targetHUDFormat db " <20><><EFBFBD><EFBFBD>: $",0
luckHUDFormat db " <20><><EFBFBD><EFBFBD><EFBFBD>: +",0
controlsHUD db "WASD/<2F><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>: <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> | E: <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> | ESC: <20><><EFBFBD><EFBFBD>",0
NUM_SPRITES equ 22
INTERACT_NONE equ 0
INTERACT_BLACKJACK equ 1
INTERACT_POKER equ 2
INTERACT_SLOTS_777 equ 3
INTERACT_ROULETTE equ 4
INTERACT_SKULLS equ 5
INTERACT_SHOP equ 6
INTERACT_ATM equ 7
INTERACT_DANCER equ 8
INTERACT_HELL_TOWER equ 9
INTERACT_DURAK equ 10
INTERACT_BUCKSHOT equ 11
INTERACT_COIN equ 12
INTERACT_DICE equ 13
INTERACT_SLOTS_CLOVER equ 14
INTERACT_UMAMUSUME equ 15
INTERACT_OBSERVER equ 16
INTERACT_TERMINAL equ 17
INTERACT_ONLINE_RR equ 18
INTERACT_RUSSIAN_ROULETTE equ 19
INTERACT_SKILL_CHECK equ 20
ALIGN 4
casinoSprites SpriteObject NUM_SPRITES dup(<>)
sortedSprites dd NUM_SPRITES dup(0)
rowDistTable dd 120 dup(0)
rngSeed3D dd 12345678h
slotBet dd 50
slotReel1 dd 0
slotReel2 dd 1
slotReel3 dd 2
slotSpinState dd 0
slotSpinTimer dd 0
slotWinAmount dd 0
slotWinMsg db 64 dup(0)
bjState dd 0
bjBet dd 100
bjPlayerCards dd 10 dup(0)
bjPlayerCardCount dd 0
bjPlayerScore dd 0
bjDealerCards dd 10 dup(0)
bjDealerCardCount dd 0
bjDealerScore dd 0
bjDealerHideHole dd 1
bjOutcomeMsg db 64 dup(0)
roulState dd 0
roulBetType dd 1
roulBetAmount dd 100
roulWheelAngle dd 0
roulBallAngle dd 0
roulSpinTimer dd 0
roulWinningNum dd 0
roulPayout dd 0
roulOutcomeMsg db 64 dup(0)
coinRxAnimTable db 26, 22, 16, 6, 16, 22, 26, 22, 16, 6
; --- Native 2.5D Coin Flip ---
coin3d_bet dd 50
coin3d_choice dd 1 ; 1 = <20><><EFBFBD><EFBFBD>, 2 = <20><><EFBFBD><EFBFBD><EFBFBD>
coin3d_state dd 0 ; 0 = Idle, 1 = Flipping, 2 = Result
coin3d_timer dd 0
coin3d_result dd 1 ; 1 = <20><><EFBFBD><EFBFBD>, 2 = <20><><EFBFBD><EFBFBD><EFBFBD>
coin3d_streak dd 0
coin3d_win dd 0
textCoinTitle db "* * * <20> <20> <20> <20> <20> <20> <20> <20> <20> <20> <20> <20> <20> * * *",0
textCoinHeads db "<22>Ш<EFBFBD>",0
textCoinTails db "<22><><EFBFBD><EFBFBD><EFBFBD>",0
textCoinSide1 db "[1] <20>Ш<EFBFBD>",0
textCoinSide2 db "[2] <20><><EFBFBD><EFBFBD><EFBFBD>",0
textCoinFlipping db "<22><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20> <20><>˨<EFBFBD><CBA8>...",0
textCoinWin db "<22><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>: +$",0
textCoinLose db "<22><> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>!",0
textCoinStreakFmt db "<22><><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD>: x",0
textCoinSelected db "<22><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>",0
textCoinKey1 db "[1] <20>Ш<EFBFBD>",0
textCoinKey2 db "[2] <20><><EFBFBD><EFBFBD><EFBFBD>",0
textCoinKeySpace db "[SPACE]",0
; --- Native 2.5D Dice Game ---
dice3d_bet dd 50
dice3d_choice dd 1 ; 1 = ׸<>, 2 = <20><><EFBFBD><EFBFBD><EFBFBD>
dice3d_state dd 0 ; 0 = Idle, 1 = Rolling, 2 = Result
dice3d_timer dd 0
dice3d_val1 dd 4
dice3d_val2 dd 6
dice3d_sum dd 10
dice3d_win dd 0
textDiceTitle db "=== G R A N D C R A P S ===",0
textDiceEven db "[1] ר<>",0
textDiceOdd db "[2] <20><><EFBFBD><EFBFBD><EFBFBD>",0
textDiceEvenNums db " 2 4 6 8 10 ",0
textDiceOddNums db " 3 5 7 9 11 ",0
textDiceSumHdr db "<22><><EFBFBD><EFBFBD><EFBFBD>: ",0
textDicePlus db " + ",0
textDiceEqual db " = ",0
textDiceEvenResult db " (ר<>)",0
textDiceOddResult db " (<28><><EFBFBD><EFBFBD><EFBFBD>)",0
textDiceRolling db "<22><><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD> <20><> <20><><EFBFBD><EFBFBD><EFBFBD>...",0
textDiceWin db "<22><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>: +$",0
textDiceWinMult db "! (x2)",0
textDiceLose db "<22><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>!",0
textDiceKey1 db "[1] ר<>",0
textDiceKey2 db "[2] <20><><EFBFBD><EFBFBD><EFBFBD>",0
textDiceKeySpace db "[SPACE]",0
; --- Native 2.5D Skulls Game ---
skulls3d_bet dd 50
skulls3d_state dd 0 ; 0 = Idle, 1 = Show ball, 2 = Shuffle, 3 = Pick, 4 = Reveal
skulls3d_timer dd 0
skulls3d_ballPos dd 1 ; 0, 1, 2
skulls3d_choice dd 1 ; 0, 1, 2
skulls3d_win dd 0
skulls3d_swapPair0 dd 0
skulls3d_swapPair1 dd 1
skulls3d_swapPair2 dd 2
textSkullsTitle db "* * * <20> <20> <20> <20> <20> <20> <20> <20> <20> * * *",0
textSkullsPhase0 db "<22><><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20> <20><><EFBFBD> [<5B><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>]",0
textSkullsPhase1 db "<22><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>, <20><><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD>...",0
textSkullsPhase2 db "<22><><EFBFBD><EFBFBD><EFBFBD>, <20><><EFBFBD><EFBFBD><EFBFBD>, <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD>...",0
textSkullsPhase3 db "<22><><EFBFBD> <20><><EFBFBD>? <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>: [1], [2] <20><><EFBFBD> [3]!",0
textSkullsWin db "<22><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>: +$",0
textSkullsWinMult db "! (x3) <20><> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>!",0
textSkullsLose db "<22><><EFBFBD><EFBFBD>! <20><><EFBFBD> <20><><EFBFBD> <20> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD>!",0
textSkullsAgain db "[<5B><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>] - <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20>٨ <20><><EFBFBD>",0
textSkullsKey1 db "[1]",0
textSkullsKey2 db "[2]",0
textSkullsKey3 db "[3]",0
textSkullsKeySpace db "[SPACE] <20><><EFBFBD><EFBFBD><EFBFBD>",0
; --- Native 2.5D Skill Check (Dead by Daylight Survivor Check) ---
skill3d_bet dd 50
skill3d_state dd 0 ; 0=Ready, 1=Active, 2=Hit Result, 3=Miss Result, 4=Escaped, 5=Defeated
skill3d_timer dd 0
skill3d_needle dd 55 ; Needle X (52..268)
skill3d_speed dd 4
skill3d_dir dd 1 ; 1=Right, -1=Left
skill3d_zone_start dd 140
skill3d_zone_width dd 48
skill3d_great_start dd 176
skill3d_great_width dd 12
skill3d_hits dd 0
skill3d_misses dd 0
skill3d_last_result dd 0
skill3d_win_amount dd 0
textSkillTitle db "=== S K I L L C H E C K ===",0
textSkillHitsHdr db "<22><><EFBFBD>: ",0
textSkillMissHdr db "<22><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>: ",0
textSkillReadyMsg db "<22><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> [<5B><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>] <20><><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>",0
textSkillPrompt db "<22><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> [<5B><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>] <20> <20><><EFBFBD><EFBFBD>!",0
textSkillHitMsg db "<22><><EFBFBD>! <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>!",0
textSkillGreatMsg db "<22><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>! GREAT SKILL CHECK! +<2B><><EFBFBD><EFBFBD><EFBFBD>!",0
textSkillMissMsg db "<22><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>! <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>!",0
textSkillEscape db "<22><><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>! <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>: +$",0
textSkillLost db "<22><> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>! <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>!",0
textSkillKeySpace db "[SPACE] <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>",0
textSkillKeyBet db "[<5B><><EFBFBD><EFBFBD><EFBFBD>/<2F><><EFBFBD><EFBFBD>]",0
; --- Shared UI Strings ---
textKeyEsc db "[ESC]",0
textBankPrompt db "<22><><EFBFBD><EFBFBD>: $",0
textBetPrompt db "<22><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>: $",0
textBetHint db " [W/S]",0
shopMsg db 128 dup(0)
atmMsg db 128 dup(0)
strWin db "<22><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>! +$",0
strLose db "<22><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>",0
strJackpot db "<22><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>! +$",0
strPush db "<22><><EFBFBD><EFBFBD><EFBFBD> (PUSH)",0
strDealerBust db "<22><><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>! <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>! +$",0
strPlayerBust db "<22><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> (>21)! <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>",0
sym7 db " 777 ",0
symBar db " BAR ",0
symBell db " BELL",0
symCherry db "CHERRY",0
symClover db "CLOVER",0
symGem db " GEM ",0
symCrown db "CROWN",0
cardRankStr db "A ",0,"2 ",0,"3 ",0,"4 ",0,"5 ",0,"6 ",0,"7 ",0,"8 ",0,"9 ",0,"10",0,"J ",0,"Q ",0,"K ",0
.data?
ALIGN 4
screenBuffer dd SCREEN_SIZE dup(?)
ALIGN 4
zBuffer dd SCREEN_W dup(?)
ALIGN 4
texturesBuffer dd (48 * 128 * 128) dup(?)
hudNumBuffer db 32 dup(?)
.code
; --- 3D Window Procedure ---
Casino3DWndProc PROC hwnd:DWORD, uMsg:DWORD, wParam:DWORD, lParam:DWORD
invoke WindowEvents3D, hwnd, uMsg, wParam, lParam
ret
Casino3DWndProc ENDP
; --- Random Generator ---
RandomRange3D PROC maxVal:DWORD
mov eax, rngSeed3D
imul eax, 1103515245
add eax, 12345
mov rngSeed3D, eax
shr eax, 16
and eax, 7FFFh
xor edx, edx
div maxVal
mov eax, edx
ret
RandomRange3D ENDP
; --- Copy String ---
CopyString3D PROC src:DWORD, dst:DWORD
push esi
push edi
mov esi, src
mov edi, dst
@@:
mov al, [esi]
mov [edi], al
test al, al
jz @F
inc esi
inc edi
jmp @B
@@:
pop edi
pop esi
ret
CopyString3D ENDP
; --- Format Number to Decimal String ---
FormatNumber PROC num:DWORD, buf:DWORD
push ebx
push esi
push edi
mov eax, num
mov edi, buf
test eax, eax
jns fn_pos
mov BYTE PTR [edi], '-'
inc edi
neg eax
fn_pos:
mov ebx, 10
push 0
fn_div:
xor edx, edx
div ebx
add dl, '0'
push edx
test eax, eax
jnz fn_div
fn_pop:
pop eax
test al, al
jz fn_done
mov [edi], al
inc edi
jmp fn_pop
fn_done:
mov BYTE PTR [edi], 0
pop edi
pop esi
pop ebx
ret
FormatNumber ENDP
; --- Fast 2D Drawing Primitives ---
DrawBox PROTO :DWORD,:DWORD,:DWORD,:DWORD,:DWORD
DrawPixel PROC x:DWORD, y:DWORD, color:DWORD
invoke DrawBox, x, y, 1, 1, color
ret
DrawPixel ENDP
DrawBox PROC x:DWORD, y:DWORD, w:DWORD, h:DWORD, color:DWORD
shl x, 1
shl y, 1
shl w, 1
shl h, 1
push ebx
push esi
push edi
mov edi, y
box_row_loop:
mov eax, y
add eax, h
cmp edi, eax
jge box_done
cmp edi, 0
jl next_box_row
cmp edi, SCREEN_H
jge box_done
mov esi, x
box_col_loop:
mov eax, x
add eax, w
cmp esi, eax
jge next_box_row
cmp esi, 0
jl next_box_col
cmp esi, SCREEN_W
jge next_box_row
mov ecx, edi
imul ecx, SCREEN_W
add ecx, esi
mov edx, color
mov [screenBuffer + ecx*4], edx
next_box_col:
inc esi
jmp box_col_loop
next_box_row:
inc edi
jmp box_row_loop
box_done:
pop edi
pop esi
pop ebx
ret
DrawBox ENDP
DrawBoxBorder PROC uses ebx x:DWORD, y:DWORD, w:DWORD, h:DWORD, fillColor:DWORD, borderColor:DWORD, bWidth:DWORD
invoke DrawBox, x, y, w, h, borderColor
mov eax, x
add eax, bWidth
mov edx, y
add edx, bWidth
mov ecx, w
sub ecx, bWidth
sub ecx, bWidth
mov ebx, h
sub ebx, bWidth
sub ebx, bWidth
invoke DrawBox, eax, edx, ecx, ebx, fillColor
ret
DrawBoxBorder ENDP
DrawCircle PROC cxVal:DWORD, cyVal:DWORD, radius:DWORD, color:DWORD
push ebx
push esi
push edi
mov eax, radius
neg eax
mov edi, eax
circ_y:
cmp edi, radius
jg circ_done
mov eax, radius
neg eax
mov esi, eax
circ_x:
cmp esi, radius
jg next_circ_y
mov eax, esi
imul eax, eax
mov ebx, edi
imul ebx, ebx
add eax, ebx
mov edx, radius
imul edx, edx
cmp eax, edx
jg next_circ_x
mov eax, cxVal
add eax, esi
mov ecx, cyVal
add ecx, edi
invoke DrawPixel, eax, ecx, color
next_circ_x:
inc esi
jmp circ_x
next_circ_y:
inc edi
jmp circ_y
circ_done:
pop edi
pop esi
pop ebx
ret
DrawCircle ENDP
DrawChar8x8 PROC uses ebx esi edi x:DWORD, y:DWORD, chVal:DWORD, color:DWORD
local column:DWORD
mov eax, chVal
and eax, 255
lea esi, [font8x8 + eax*8]
xor edi, edi
glyph_row:
movzx ebx, BYTE PTR [esi+edi]
mov column, 0
glyph_col:
test ebx, 80h
jz glyph_next
mov eax, x
add eax, column
mov edx, y
add edx, edi
invoke DrawPixel, eax, edx, color
glyph_next:
shl ebx, 1
inc column
cmp column, 8
jl glyph_col
inc edi
cmp edi, 8
jl glyph_row
ret
DrawChar8x8 ENDP
DrawString8x8 PROC x:DWORD, y:DWORD, strPtr:DWORD, color:DWORD
push ebx
push esi
mov esi, strPtr
mov ebx, x
str_loop:
movzx eax, BYTE PTR [esi]
test al, al
jz str_done
invoke DrawChar8x8, ebx, y, eax, color
add ebx, 8
inc esi
jmp str_loop
str_done:
pop esi
pop ebx
ret
DrawString8x8 ENDP
; --- True 3D Perspective Floor & Ceiling Rendering ---
RenderCeilingAndFloor PROC uses ebx esi edi
local floorRow:DWORD
local pDist:DWORD
local fStepX:DWORD
local fStepY:DWORD
local fX:DWORD
local fY:DWORD
local shade:DWORD
local cShade:DWORD
; Horizon line: row 120
mov edi, HALF_H
floor_scanlines:
cmp edi, SCREEN_H
jge floor_done
mov floorRow, edi
; Distance = (HALF_H * FP_1) / (y - HALF_H)
mov eax, edi
sub eax, HALF_H
inc eax
mov ecx, eax
mov eax, HALF_H * FP_1
cdq
idiv ecx
mov pDist, eax
; Distance shading (closer is brighter, far horizon is dark)
mov edx, pDist
shr edx, 13
mov eax, 255
sub eax, edx
cmp eax, 35
jge @F
mov eax, 35
@@:
mov shade, eax
mov edx, eax
sub edx, 25
cmp edx, 20
jge @F
mov edx, 20
@@:
mov cShade, edx
; Step along scanline: (2 * playerPlane) * pDist / SCREEN_W
mov eax, playerPlaneX
shl eax, 1
imul pDist
shrd eax, edx, 16
cdq
mov ecx, SCREEN_W
idiv ecx
mov fStepX, eax
mov eax, playerPlaneY
shl eax, 1
imul pDist
shrd eax, edx, 16
cdq
mov ecx, SCREEN_W
idiv ecx
mov fStepY, eax
; Starting floor coordinates at x=0:
; player + pDist * (playerDir - playerPlane)
mov eax, playerDirX
sub eax, playerPlaneX
imul pDist
shrd eax, edx, 16
add eax, playerX
mov fX, eax
mov eax, playerDirY
sub eax, playerPlaneY
imul pDist
shrd eax, edx, 16
add eax, playerY
mov fY, eax
; Fill scanline for floor (y) and ceiling (SCREEN_H - 1 - y)
xor esi, esi
col_floor_loop:
cmp esi, SCREEN_W
jge next_floor_row
; Carpet Texture (Slot 3: 3 * 4096 * 4 = 49152 bytes)
mov eax, fX
shr eax, 9
and eax, 127
mov edx, fY
shr edx, 9
and edx, 127
shl edx, 7
add edx, eax
mov eax, [texturesBuffer + (3 * 128 * 128 * 4) + edx*4]
; Shade Floor RGB
mov ebx, shade
movzx ecx, al
imul ecx, ebx
shr ecx, 8
push ecx
movzx ecx, ah
imul ecx, ebx
shr ecx, 8
shl ecx, 8
shr eax, 16
movzx eax, al
imul eax, ebx
shr eax, 8
shl eax, 16
or eax, ecx
pop ecx
or eax, ecx
; Store to Floor pixel
mov ecx, floorRow
imul ecx, SCREEN_W
add ecx, esi
mov [screenBuffer + ecx*4], eax
; Ceiling Spotlight Texture (Slot 5: 5 * 4096 * 4 = 81920 bytes)
mov eax, [texturesBuffer + (5 * 128 * 128 * 4) + edx*4]
mov ebx, cShade
movzx ecx, al
imul ecx, ebx
shr ecx, 8
push ecx
movzx ecx, ah
imul ecx, ebx
shr ecx, 8
shl ecx, 8
shr eax, 16
movzx eax, al
imul eax, ebx
shr eax, 8
shl eax, 16
or eax, ecx
pop ecx
or eax, ecx
; Store to Ceiling pixel: (SCREEN_H - 1 - floorRow)
mov ecx, SCREEN_H - 1
sub ecx, floorRow
imul ecx, SCREEN_W
add ecx, esi
mov [screenBuffer + ecx*4], eax
mov eax, fStepX
add fX, eax
mov eax, fStepY
add fY, eax
inc esi
jmp col_floor_loop
next_floor_row:
inc edi
jmp floor_scanlines
floor_done:
ret
RenderCeilingAndFloor ENDP
; --- DDA Raycasting Walls ---
RenderWalls PROC
local col:DWORD
local camX:DWORD
local rayDirX:DWORD
local rayDirY:DWORD
local mapX:DWORD
local mapY:DWORD
local deltaDistX:DWORD
local deltaDistY:DWORD
local stepX:DWORD
local stepY:DWORD
local sideDistX:DWORD
local sideDistY:DWORD
local side:DWORD
local perpWallDist:DWORD
local lineH:DWORD
local drawStart:DWORD
local drawEnd:DWORD
local wallHit:DWORD
local texX:DWORD
local texId:DWORD
local shade:DWORD
push ebx
push esi
push edi
mov eax, playerAngle
and eax, 511
mov ebx, [tableCos + eax*4]
mov playerDirX, ebx
mov ebx, [tableSin + eax*4]
mov playerDirY, ebx
mov eax, ebx
imul eax, -66
cdq
mov ecx, 100
idiv ecx
mov playerPlaneX, eax
mov eax, playerDirX
imul eax, 66
cdq
idiv ecx
mov playerPlaneY, eax
mov col, 0
col_loop:
cmp col, SCREEN_W
jge walls_done
mov eax, col
shl eax, 1
sub eax, SCREEN_W
imul eax, FP_1
cdq
mov ecx, SCREEN_W
idiv ecx
mov camX, eax
mov eax, playerPlaneX
imul camX
shrd eax, edx, 16
add eax, playerDirX
mov rayDirX, eax
mov eax, playerPlaneY
imul camX
shrd eax, edx, 16
add eax, playerDirY
mov rayDirY, eax
mov eax, playerX
sar eax, 16
mov mapX, eax
mov eax, playerY
sar eax, 16
mov mapY, eax
mov eax, rayDirX
test eax, eax
jnz calc_delta_x
mov deltaDistX, 7FFFFFFFh
jmp calc_delta_y
calc_delta_x:
test eax, eax
jns @F
neg eax
@@:
mov ebx, eax
cmp ebx, 4
jbe delta_x_clamp
xor eax, eax
mov edx, 1
div ebx
mov deltaDistX, eax
jmp calc_delta_y
delta_x_clamp:
mov deltaDistX, 7FFFFFFFh
calc_delta_y:
mov eax, rayDirY
test eax, eax
jnz calc_delta_y_ok
mov deltaDistY, 7FFFFFFFh
jmp check_step
calc_delta_y_ok:
test eax, eax
jns @F
neg eax
@@:
mov ebx, eax
cmp ebx, 4
jbe delta_y_clamp
xor eax, eax
mov edx, 1
div ebx
mov deltaDistY, eax
jmp check_step
delta_y_clamp:
mov deltaDistY, 7FFFFFFFh
check_step:
cmp rayDirX, 0
jge step_x_pos
mov stepX, -1
mov eax, playerX
mov edx, mapX
shl edx, 16
sub eax, edx
imul deltaDistX
shrd eax, edx, 16
mov sideDistX, eax
jmp check_step_y
step_x_pos:
mov stepX, 1
mov eax, mapX
inc eax
shl eax, 16
sub eax, playerX
imul deltaDistX
shrd eax, edx, 16
mov sideDistX, eax
check_step_y:
cmp rayDirY, 0
jge step_y_pos
mov stepY, -1
mov eax, playerY
mov edx, mapY
shl edx, 16
sub eax, edx
imul deltaDistY
shrd eax, edx, 16
mov sideDistY, eax
jmp dda_start
step_y_pos:
mov stepY, 1
mov eax, mapY
inc eax
shl eax, 16
sub eax, playerY
imul deltaDistY
shrd eax, edx, 16
mov sideDistY, eax
dda_start:
xor ecx, ecx
dda_step_loop:
inc ecx
cmp ecx, 64
jge hit_wall
mov eax, sideDistX
cmp eax, sideDistY
jge step_in_y
mov eax, deltaDistX
add sideDistX, eax
mov eax, stepX
add mapX, eax
mov side, 0
jmp check_tile
step_in_y:
mov eax, deltaDistY
add sideDistY, eax
mov eax, stepY
add mapY, eax
mov side, 1
check_tile:
cmp mapX, 0
jl hit_wall
cmp mapX, MAP_WIDTH
jge hit_wall
cmp mapY, 0
jl hit_wall
cmp mapY, MAP_HEIGHT
jge hit_wall
mov eax, mapY
shl eax, 5
add eax, mapX
movzx eax, BYTE PTR [casinoMap + eax]
test eax, eax
jnz hit_wall
jmp dda_step_loop
hit_wall:
cmp side, 0
jne perp_y
mov eax, sideDistX
sub eax, deltaDistX
mov perpWallDist, eax
jmp perp_done
perp_y:
mov eax, sideDistY
sub eax, deltaDistY
mov perpWallDist, eax
perp_done:
cmp perpWallDist, 2048
jge @F
mov perpWallDist, 2048
@@:
mov eax, col
mov edx, perpWallDist
mov [zBuffer + eax*4], edx
; High casino ceiling: lineH = (SCREEN_H * FP_1 * 180 / 240) / perpWallDist
mov eax, SCREEN_H
imul eax, FP_1
cdq
idiv perpWallDist
mov lineH, eax
mov eax, lineH
shr eax, 1
mov ecx, HALF_H
sub ecx, eax
mov drawStart, ecx
mov eax, lineH
shr eax, 1
mov ecx, HALF_H
add ecx, eax
mov drawEnd, ecx
cmp side, 0
jne hit_side_y
mov eax, perpWallDist
imul rayDirY
shrd eax, edx, 16
add eax, playerY
mov wallHit, eax
jmp calc_tex_x
hit_side_y:
mov eax, perpWallDist
imul rayDirX
shrd eax, edx, 16
add eax, playerX
mov wallHit, eax
calc_tex_x:
; MASK WITH 0FFFFh to prevent texture scrambling!
mov eax, wallHit
and eax, 0FFFFh
shr eax, 9
and eax, 127
mov texX, eax
cmp side, 0
jne @F
cmp rayDirX, 0
jle @F
mov eax, 127
sub eax, texX
mov texX, eax
@@:
cmp side, 1
jne select_tex
cmp rayDirY, 0
jge select_tex
mov eax, 127
sub eax, texX
mov texX, eax
select_tex:
mov eax, mapY
shl eax, 5
add eax, mapX
movzx eax, BYTE PTR [casinoMap + eax]
mov texId, eax
cmp texId, 0
jne @F
mov texId, 1
@@:
mov eax, perpWallDist
shr eax, 13
mov edx, 256
sub edx, eax
cmp edx, 75
jge @F
mov edx, 75
@@:
cmp side, 1
jne @F
imul edx, 3
shr edx, 2
@@:
mov shade, edx
cmp drawStart, 0
jge @F
mov drawStart, 0
@@:
cmp drawEnd, SCREEN_H
jl @F
mov drawEnd, SCREEN_H - 1
@@:
mov eax, lineH
cmp eax, 1
jge @F
mov eax, 1
mov lineH, eax
@@:
mov eax, 128 * FP_1
cdq
idiv lineH
mov esi, eax ; stepY
mov eax, lineH
shr eax, 1
add eax, drawStart
sub eax, HALF_H
imul eax, esi
mov edi, eax ; texPos
mov ecx, drawStart
draw_stripe_loop:
cmp ecx, drawEnd
jg next_col
mov eax, edi
shr eax, 16
and eax, 127
shl eax, 7
add eax, texX
mov edx, texId
shl edx, 14
add eax, edx
mov eax, [texturesBuffer + eax*4]
; Shade wall pixel
mov ebx, shade
movzx edx, al
imul edx, ebx
shr edx, 8
push edx
movzx edx, ah
imul edx, ebx
shr edx, 8
shl edx, 8
shr eax, 16
movzx eax, al
imul eax, ebx
shr eax, 8
shl eax, 16
or eax, edx
pop edx
or eax, edx
mov edx, ecx
imul edx, SCREEN_W
add edx, col
mov [screenBuffer + edx*4], eax
add edi, esi
inc ecx
jmp draw_stripe_loop
next_col:
inc col
jmp col_loop
walls_done:
pop edi
pop esi
pop ebx
ret
RenderWalls ENDP
; --- Render 3D Billboard Sprites ---
RenderSprites PROC
local sprIdx:DWORD
local relX:DWORD
local relY:DWORD
local invDet:DWORD
local transX:DWORD
local transY:DWORD
local sprScreenX:DWORD
local sprH:DWORD
local sprW:DWORD
local drawStartY:DWORD
local drawEndY:DWORD
local drawStartX:DWORD
local drawEndX:DWORD
local stripe:DWORD
local texX:DWORD
local texY:DWORD
local shade:DWORD
local texSlot:DWORD
push ebx
push esi
push edi
xor esi, esi
calc_dist_loop:
cmp esi, NUM_SPRITES
jge sort_sprites
mov eax, esi
imul eax, SIZEOF SpriteObject
mov edx, [casinoSprites + eax].posX
sub edx, playerX
sar edx, 8
imul edx, edx
mov ebx, edx
mov edx, [casinoSprites + eax].posY
sub edx, playerY
sar edx, 8
imul edx, edx
add ebx, edx
mov [casinoSprites + eax].distSq, ebx
mov [sortedSprites + esi*4], esi
inc esi
jmp calc_dist_loop
sort_sprites:
xor esi, esi
sort_outer:
cmp esi, NUM_SPRITES - 1
jge render_sorted_sprites
mov edi, esi
inc edi
sort_inner:
cmp edi, NUM_SPRITES
jge next_sort_outer
mov eax, [sortedSprites + esi*4]
imul eax, SIZEOF SpriteObject
mov eax, [casinoSprites + eax].distSq
mov ebx, [sortedSprites + edi*4]
imul ebx, SIZEOF SpriteObject
mov ebx, [casinoSprites + ebx].distSq
cmp eax, ebx
jge @F
mov ecx, [sortedSprites + esi*4]
mov edx, [sortedSprites + edi*4]
mov [sortedSprites + esi*4], edx
mov [sortedSprites + edi*4], ecx
@@:
inc edi
jmp sort_inner
next_sort_outer:
inc esi
jmp sort_outer
render_sorted_sprites:
xor esi, esi
draw_spr_loop:
cmp esi, NUM_SPRITES
jge sprites_rendered
mov eax, [sortedSprites + esi*4]
mov sprIdx, eax
imul eax, SIZEOF SpriteObject
; Sample animation by elapsed time. Pausing freezes the clock.
push eax
mov ecx, [casinoSprites + eax].animSpeed
cmp ecx, 0
jg @F
mov ecx, 1
@@:
imul ecx, 40
mov eax, animationClock3D
xor edx, edx
div ecx
pop ebx
mov ecx, [casinoSprites + ebx].frameCount
cmp ecx, 0
jg @F
mov ecx, 1
@@:
xor edx, edx
div ecx
mov [casinoSprites + ebx].curFrame, edx
mov eax, ebx
cmp [casinoSprites + eax].distSq, 16
jle next_spr
mov edx, [casinoSprites + eax].posX
sub edx, playerX
mov relX, edx
mov edx, [casinoSprites + eax].posY
sub edx, playerY
mov relY, edx
mov eax, playerPlaneX
imul playerDirY
shrd eax, edx, 16
mov ebx, eax
mov eax, playerDirX
imul playerPlaneY
shrd eax, edx, 16
sub ebx, eax
mov eax, ebx
test eax, eax
jns @F
neg eax
@@:
cmp eax, 4
jbe next_spr
; 2^32 needs the full EDX:EAX dividend, not a truncated multiply.
xor eax, eax
mov edx, 1
idiv ebx
mov invDet, eax
mov eax, playerDirY
imul relX
shrd eax, edx, 16
mov ebx, eax
mov eax, playerDirX
imul relY
shrd eax, edx, 16
sub ebx, eax
mov eax, ebx
imul invDet
shrd eax, edx, 16
mov transX, eax
mov eax, playerPlaneY
neg eax
imul relX
shrd eax, edx, 16
mov ebx, eax
mov eax, playerPlaneX
imul relY
shrd eax, edx, 16
add ebx, eax
mov eax, ebx
imul invDet
shrd eax, edx, 16
mov transY, eax
cmp transY, 4096
jle next_spr
mov eax, transX
imul eax, HALF_W
cdq
idiv transY
add eax, HALF_W
mov sprScreenX, eax
mov eax, SCREEN_H
imul eax, FP_1
cdq
idiv transY
test eax, eax
jns @F
neg eax
@@:
cmp eax, 1
jge @F
jmp next_spr
@@:
cmp eax, SCREEN_H * 2
jle @F
mov eax, SCREEN_H * 2
@@:
mov sprH, eax
mov sprW, eax
mov eax, HALF_H
mov ebx, sprH
shr ebx, 1
sub eax, ebx
mov drawStartY, eax
add eax, sprH
mov drawEndY, eax
mov eax, sprScreenX
mov ebx, sprW
shr ebx, 1
sub eax, ebx
mov drawStartX, eax
add eax, sprW
mov drawEndX, eax
cmp drawStartY, 0
jge @F
mov drawStartY, 0
@@:
cmp drawEndY, SCREEN_H
jl @F
mov drawEndY, SCREEN_H - 1
@@:
mov eax, transY
shr eax, 13
mov edx, 256
sub edx, eax
cmp edx, 110
jge @F
mov edx, 110
@@:
mov shade, edx
mov eax, sprIdx
imul eax, SIZEOF SpriteObject
mov edx, [casinoSprites + eax].baseTexId
add edx, [casinoSprites + eax].curFrame
mov texSlot, edx
mov eax, drawStartX
mov stripe, eax
spr_stripe_loop:
mov eax, stripe
cmp eax, drawEndX
jge next_spr
cmp eax, 0
jl next_spr_stripe
cmp eax, SCREEN_W
jge next_spr
mov edx, transY
cmp edx, [zBuffer + eax*4]
jge next_spr_stripe
mov eax, stripe
sub eax, sprScreenX
mov ebx, sprW
shr ebx, 1
add eax, ebx
shl eax, 7
cdq
idiv sprW
cmp eax, 0
jl next_spr_stripe
cmp eax, 128
jge next_spr_stripe
mov texX, eax
mov edi, drawStartY
spr_pix_y_loop:
cmp edi, drawEndY
jg next_spr_stripe
mov eax, edi
sub eax, HALF_H
mov ebx, sprH
shr ebx, 1
add eax, ebx
shl eax, 7
cdq
idiv sprH
cmp eax, 0
jl next_spr_y
cmp eax, 128
jge next_spr_y
mov texY, eax
shl eax, 7
add eax, texX
mov edx, texSlot
shl edx, 14
add eax, edx
mov eax, [texturesBuffer + eax*4]
; Chromakey magenta filter
cmp eax, CHROMA_KEY
je next_spr_y
do_draw_sprite_pix:
mov ebx, shade
movzx edx, al
imul edx, ebx
shr edx, 8
push edx
movzx edx, ah
imul edx, ebx
shr edx, 8
shl edx, 8
shr eax, 16
movzx eax, al
imul eax, ebx
shr eax, 8
shl eax, 16
or eax, edx
pop edx
or eax, edx
mov ecx, edi
imul ecx, SCREEN_W
add ecx, stripe
mov [screenBuffer + ecx*4], eax
next_spr_y:
inc edi
jmp spr_pix_y_loop
next_spr_stripe:
inc stripe
jmp spr_stripe_loop
next_spr:
inc esi
jmp draw_spr_loop
sprites_rendered:
pop edi
pop esi
pop ebx
ret
RenderSprites ENDP
; --- HUD & Minimap Radar ---
RenderHUD PROC uses ebx esi edi
invoke DrawBox, 0, 0, 320, 16, 0014191Dh
invoke DrawString8x8, 8, 4, OFFSET textBank3D, 00D8BC6Ah
invoke FormatNumber, bankroll, OFFSET hudNumBuffer
invoke DrawString8x8, 64, 4, OFFSET hudNumBuffer, 00FFFFFFh
invoke DrawString8x8, 176, 4, OFFSET textWindowKeys3D, 00A8B6BBh
invoke DrawBox, 0, 226, 320, 14, 0014191Dh
invoke DrawString8x8, 12, 230, OFFSET textWalkKeys3D, 00A8B6BBh
invoke DrawBox, 159, 118, 2, 5, 00E7DFC8h
invoke DrawBox, 157, 120, 6, 1, 00E7DFC8h
cmp interactPromptPtr, 0
je @F
invoke DrawBoxBorder, 4, 199, 312, 18, 0014191Dh, 00D8BC6Ah, 1
invoke DrawString8x8, 10, 204, interactPromptPtr, 00F5E2B0h
@@:
cmp flashTimer, 0
je hud_finished
dec flashTimer
invoke DrawBox, 4, 22, 312, 16, 0014191Dh
invoke DrawString8x8, 10, 26, OFFSET flashMessage, 00FFFFFFh
hud_finished:
ret
RenderHUD ENDP
RenderMinimap PROC uses ebx esi edi
local radarX:DWORD
local radarY:DWORD
local radarSize:DWORD
mov radarX, 320 - 48
mov radarY, 20
mov radarSize, 44
invoke DrawBoxBorder, radarX, radarY, radarSize, radarSize, 00101510h, 00FFD700h, 1
; Draw Sprites on radar
xor esi, esi
radar_spr_loop:
cmp esi, NUM_SPRITES
jge draw_player_radar
mov eax, esi
imul eax, SIZEOF SpriteObject
mov eax, [casinoSprites + eax].posX
sar eax, 16
imul eax, radarSize
shr eax, 5
add eax, radarX
mov ebx, eax
mov eax, esi
imul eax, SIZEOF SpriteObject
mov eax, [casinoSprites + eax].posY
sar eax, 16
imul eax, radarSize
shr eax, 5
add eax, radarY
invoke DrawPixel, ebx, eax, 00FFAA00h
inc esi
jmp radar_spr_loop
draw_player_radar:
mov eax, playerX
sar eax, 16
imul eax, radarSize
shr eax, 5
add eax, radarX
mov ebx, eax
mov eax, playerY
sar eax, 16
imul eax, radarSize
shr eax, 5
add eax, radarY
invoke DrawCircle, ebx, eax, 2, 00FF2020h
ret
RenderMinimap ENDP
; ==============================================================================
; IN-ENGINE 2.5D MINI-GAME: SLOTS 777
; ==============================================================================
HandleSlotsInput PROC
cmp slotSpinState, 1
je slots_input_done
invoke Pressed3D, 20h ; SPACE -> Spin
test ah, 80h
jz check_bet_adjust
mov eax, bankroll
cmp eax, slotBet
jl @F
sub eax, slotBet
mov bankroll, eax
mov slotSpinState, 1
mov slotSpinTimer, 0
mov slotWinAmount, 0
invoke PlaySoundA, OFFSET soundClick, 0, 1
jmp slots_input_done
@@:
invoke CopyString3D, OFFSET msgNeedMoney, OFFSET flashMessage
mov flashTimer, 60
check_bet_adjust:
invoke Pressed3D, 26h ; UP / W
test ah, 80h
jnz inc_bet
invoke Pressed3D, 57h
test ah, 80h
jz check_bet_down
inc_bet:
cmp slotBet, 500
jge slots_input_done
cmp slotBet, 100
jge @F
cmp slotBet, 50
jge set_100
mov slotBet, 50
jmp slots_input_done
set_100:
mov slotBet, 100
jmp slots_input_done
@@:
mov slotBet, 500
jmp slots_input_done
check_bet_down:
invoke Pressed3D, 28h ; DOWN / S
test ah, 80h
jnz dec_bet
invoke Pressed3D, 53h
test ah, 80h
jz slots_input_done
dec_bet:
cmp slotBet, 50
jle set_10
cmp slotBet, 100
jle set_50
mov slotBet, 100
jmp slots_input_done
set_50:
mov slotBet, 50
jmp slots_input_done
set_10:
mov slotBet, 10
slots_input_done:
ret
HandleSlotsInput ENDP
RenderSlotsGame PROC uses ebx esi edi
; Cabinet Background (Dark Cherry Wood & Gold)
invoke DrawBox, 0, 0, SCREEN_W, SCREEN_H, 00150A10h
invoke DrawBoxBorder, 10, 10, 300, 220, 00251015h, 00FFD700h, 3
; Illuminated Top Marquee
invoke DrawBoxBorder, 25, 20, 270, 32, 000A0505h, 00FFFF00h, 2
invoke DrawString8x8, 55, 32, OFFSET textSlots3D, 00FFD700h
; Spinning Animation Logic
cmp slotSpinState, 1
jne draw_reels
inc slotSpinTimer
cmp slotSpinTimer, 22
jge @F
invoke RandomRange3D, 7
mov slotReel1, eax
@@:
cmp slotSpinTimer, 36
jge @F
invoke RandomRange3D, 7
mov slotReel2, eax
@@:
cmp slotSpinTimer, 50
jge @F
invoke RandomRange3D, 7
mov slotReel3, eax
@@:
cmp slotSpinTimer, 50
jl draw_reels
; Spin finished! Check outcome!
mov slotSpinState, 0
mov eax, slotReel1
cmp eax, slotReel2
jne check_pairs
cmp eax, slotReel3
jne check_pairs
; 3 Matching!
cmp eax, 0 ; 777!
jne @F
mov eax, slotBet
imul eax, 25
mov slotWinAmount, eax
add bankroll, eax
invoke PlaySoundA, OFFSET soundJackpot, 0, 1
jmp draw_reels
@@:
cmp eax, 6 ; CROWN!
jne @F
mov eax, slotBet
imul eax, 50
mov slotWinAmount, eax
add bankroll, eax
invoke PlaySoundA, OFFSET soundJackpot, 0, 1
jmp draw_reels
@@:
mov eax, slotBet
imul eax, 10
mov slotWinAmount, eax
add bankroll, eax
invoke PlaySoundA, OFFSET soundCoin, 0, 1
jmp draw_reels
check_pairs:
mov eax, slotReel1
cmp eax, slotReel2
je pair_win
mov eax, slotReel2
cmp eax, slotReel3
je pair_win
mov eax, slotReel1
cmp eax, slotReel3
je pair_win
jmp draw_reels
pair_win:
mov eax, slotBet
imul eax, 2
mov slotWinAmount, eax
add bankroll, eax
invoke PlaySoundA, OFFSET soundCoin, 0, 1
draw_reels:
; Reels Window
invoke DrawBoxBorder, 30, 62, 260, 95, 000F0F12h, 0000A5FFh, 2
; Reel 1 (45..105)
invoke DrawBoxBorder, 45, 68, 65, 82, 00F0F0F5h, 00505050h, 2
mov eax, slotReel1
call DrawReelSymbolAt1
; Reel 2 (128..188)
invoke DrawBoxBorder, 128, 68, 65, 82, 00F0F0F5h, 00505050h, 2
mov eax, slotReel2
call DrawReelSymbolAt2
; Reel 3 (210..270)
invoke DrawBoxBorder, 210, 68, 65, 82, 00F0F0F5h, 00505050h, 2
mov eax, slotReel3
call DrawReelSymbolAt3
; Bottom Control Panel
invoke DrawBoxBorder, 20, 165, 280, 58, 00151515h, 00FFD700h, 1
invoke DrawString8x8, 28, 172, OFFSET textBank3D, 00FFD700h
invoke FormatNumber, bankroll, OFFSET hudNumBuffer
invoke DrawString8x8, 110, 172, OFFSET hudNumBuffer, 00FFFF00h
invoke DrawString8x8, 175, 172, OFFSET textBet3D, 00FFD700h
invoke FormatNumber, slotBet, OFFSET hudNumBuffer
invoke DrawString8x8, 240, 172, OFFSET hudNumBuffer, 0050FF50h
cmp slotWinAmount, 0
jle draw_slot_ctrls
invoke DrawString8x8, 28, 187, OFFSET strWin, 00FFFF00h
invoke FormatNumber, slotWinAmount, OFFSET hudNumBuffer
invoke DrawString8x8, 110, 187, OFFSET hudNumBuffer, 00FFFF00h
draw_slot_ctrls:
invoke DrawString8x8, 28, 204, OFFSET textSlotsKeys3D, 00A0A0A0h
ret
RenderSlotsGame ENDP
DrawReelSymbolAt1 PROC
cmp eax, 0
jne @F
invoke DrawString8x8, 52, 105, OFFSET sym7, 00FF2020h
ret
@@:
cmp eax, 1
jne @F
invoke DrawString8x8, 52, 105, OFFSET symBar, 00FFAA00h
ret
@@:
cmp eax, 2
jne @F
invoke DrawString8x8, 52, 105, OFFSET symBell, 00FFD700h
ret
@@:
cmp eax, 3
jne @F
invoke DrawString8x8, 48, 105, OFFSET symCherry, 000000D0h
ret
@@:
cmp eax, 4
jne @F
invoke DrawString8x8, 48, 105, OFFSET symClover, 0000A000h
ret
@@:
cmp eax, 5
jne @F
invoke DrawString8x8, 52, 105, OFFSET symGem, 00FFFF00h
ret
@@:
invoke DrawString8x8, 52, 105, OFFSET symCrown, 00FFD700h
ret
DrawReelSymbolAt1 ENDP
DrawReelSymbolAt2 PROC
cmp eax, 0
jne @F
invoke DrawString8x8, 135, 105, OFFSET sym7, 00FF2020h
ret
@@:
cmp eax, 1
jne @F
invoke DrawString8x8, 135, 105, OFFSET symBar, 00FFAA00h
ret
@@:
cmp eax, 2
jne @F
invoke DrawString8x8, 135, 105, OFFSET symBell, 00FFD700h
ret
@@:
cmp eax, 3
jne @F
invoke DrawString8x8, 131, 105, OFFSET symCherry, 000000D0h
ret
@@:
cmp eax, 4
jne @F
invoke DrawString8x8, 131, 105, OFFSET symClover, 0000A000h
ret
@@:
cmp eax, 5
jne @F
invoke DrawString8x8, 135, 105, OFFSET symGem, 00FFFF00h
ret
@@:
invoke DrawString8x8, 135, 105, OFFSET symCrown, 00FFD700h
ret
DrawReelSymbolAt2 ENDP
DrawReelSymbolAt3 PROC
cmp eax, 0
jne @F
invoke DrawString8x8, 218, 105, OFFSET sym7, 00FF2020h
ret
@@:
cmp eax, 1
jne @F
invoke DrawString8x8, 218, 105, OFFSET symBar, 00FFAA00h
ret
@@:
cmp eax, 2
jne @F
invoke DrawString8x8, 218, 105, OFFSET symBell, 00FFD700h
ret
@@:
cmp eax, 3
jne @F
invoke DrawString8x8, 214, 105, OFFSET symCherry, 000000D0h
ret
@@:
cmp eax, 4
jne @F
invoke DrawString8x8, 214, 105, OFFSET symClover, 0000A000h
ret
@@:
cmp eax, 5
jne @F
invoke DrawString8x8, 218, 105, OFFSET symGem, 00FFFF00h
ret
@@:
invoke DrawString8x8, 218, 105, OFFSET symCrown, 00FFD700h
ret
DrawReelSymbolAt3 ENDP
; ==============================================================================
; IN-ENGINE 2.5D MINI-GAME: BLACKJACK (21)
; ==============================================================================
HandleBlackjackInput PROC uses ebx
cmp bjState, 0 ; Need Deal
jne check_bj_player_turn
invoke Pressed3D, 20h ; SPACE -> Deal
test ah, 80h
jz check_bj_bet_change
mov eax, bankroll
cmp eax, bjBet
jl bj_need_cash
sub eax, bjBet
mov bankroll, eax
; Deal 2 cards to player, 2 cards to dealer
mov bjPlayerCardCount, 0
mov bjDealerCardCount, 0
mov bjDealerHideHole, 1
; Player Card 1
invoke RandomRange3D, 13
inc eax
mov ebx, bjPlayerCardCount
mov [bjPlayerCards + ebx*4], eax
inc bjPlayerCardCount
; Dealer Card 1
invoke RandomRange3D, 13
inc eax
mov ebx, bjDealerCardCount
mov [bjDealerCards + ebx*4], eax
inc bjDealerCardCount
; Player Card 2
invoke RandomRange3D, 13
inc eax
mov ebx, bjPlayerCardCount
mov [bjPlayerCards + ebx*4], eax
inc bjPlayerCardCount
; Dealer Card 2 (Hole card)
invoke RandomRange3D, 13
inc eax
mov ebx, bjDealerCardCount
mov [bjDealerCards + ebx*4], eax
inc bjDealerCardCount
invoke PlaySoundA, OFFSET soundCards, 0, 1
; Calc Player Score
call CalcPlayerBJScore
cmp bjPlayerScore, 21
jne set_bj_turn
; Instant Blackjack!
mov bjDealerHideHole, 0
mov eax, bjBet
imul eax, 5
shr eax, 1
add bankroll, eax
invoke CopyString3D, OFFSET strWin, OFFSET bjOutcomeMsg
invoke PlaySoundA, OFFSET soundJackpot, 0, 1
mov bjState, 2
ret
set_bj_turn:
mov bjState, 1
mov BYTE PTR [bjOutcomeMsg], 0
ret
bj_need_cash:
invoke CopyString3D, OFFSET msgNeedMoney, OFFSET flashMessage
mov flashTimer, 60
ret
check_bj_player_turn:
cmp bjState, 1
jne check_bj_round_over
invoke Pressed3D, 48h ; 'H' -> Hit
test ah, 80h
jz check_bj_stand
invoke RandomRange3D, 13
inc eax
mov ebx, bjPlayerCardCount
cmp ebx, 8
jge @F
mov [bjPlayerCards + ebx*4], eax
inc bjPlayerCardCount
@@:
invoke PlaySoundA, OFFSET soundCards, 0, 1
call CalcPlayerBJScore
cmp bjPlayerScore, 21
jle bj_input_done
; Bust!
invoke CopyString3D, OFFSET strPlayerBust, OFFSET bjOutcomeMsg
mov bjDealerHideHole, 0
mov bjState, 2
ret
check_bj_stand:
invoke Pressed3D, 53h ; 'S' -> Stand
test ah, 80h
jz bj_input_done
; Dealer Turn
mov bjDealerHideHole, 0
dealer_loop:
call CalcDealerBJScore
cmp bjDealerScore, 17
jge dealer_finished
invoke RandomRange3D, 13
inc eax
mov ebx, bjDealerCardCount
cmp ebx, 8
jge dealer_finished
mov [bjDealerCards + ebx*4], eax
inc bjDealerCardCount
jmp dealer_loop
dealer_finished:
cmp bjDealerScore, 21
jle compare_scores
; Dealer Bust!
mov eax, bjBet
shl eax, 1
add bankroll, eax
invoke CopyString3D, OFFSET strDealerBust, OFFSET bjOutcomeMsg
invoke PlaySoundA, OFFSET soundCoin, 0, 1
mov bjState, 2
ret
compare_scores:
mov eax, bjPlayerScore
cmp eax, bjDealerScore
jle check_dealer_won
; Player Won!
mov eax, bjBet
shl eax, 1
add bankroll, eax
invoke CopyString3D, OFFSET strWin, OFFSET bjOutcomeMsg
invoke PlaySoundA, OFFSET soundCoin, 0, 1
mov bjState, 2
ret
check_dealer_won:
cmp eax, bjDealerScore
jl dealer_wins
; Push (Tie)
mov eax, bjBet
add bankroll, eax
invoke CopyString3D, OFFSET strPush, OFFSET bjOutcomeMsg
mov bjState, 2
ret
dealer_wins:
invoke CopyString3D, OFFSET strLose, OFFSET bjOutcomeMsg
mov bjState, 2
ret
check_bj_round_over:
invoke Pressed3D, 20h ; SPACE -> Next Hand
test ah, 80h
jz bj_input_done
mov bjState, 0
ret
check_bj_bet_change:
invoke Pressed3D, 26h ; UP
test ah, 80h
jz @F
cmp bjBet, 500
jge bj_input_done
add bjBet, 50
ret
@@:
invoke Pressed3D, 28h ; DOWN
test ah, 80h
jz bj_input_done
cmp bjBet, 50
jle bj_input_done
sub bjBet, 50
bj_input_done:
ret
HandleBlackjackInput ENDP
CalcPlayerBJScore PROC uses ebx esi
xor eax, eax
xor ebx, ebx
xor esi, esi
calc_p_loop:
cmp esi, bjPlayerCardCount
jge calc_p_done
mov edx, [bjPlayerCards + esi*4]
cmp edx, 10
jle @F
mov edx, 10
@@:
cmp edx, 1
jne add_p_val
inc ebx ; count Aces
add eax, 11
jmp next_p_card
add_p_val:
add eax, edx
next_p_card:
inc esi
jmp calc_p_loop
calc_p_done:
; Soft Ace reduction
reduce_p_ace:
cmp eax, 21
jle store_p_score
test ebx, ebx
jz store_p_score
sub eax, 10
dec ebx
jmp reduce_p_ace
store_p_score:
mov bjPlayerScore, eax
ret
CalcPlayerBJScore ENDP
CalcDealerBJScore PROC uses ebx esi
xor eax, eax
xor ebx, ebx
xor esi, esi
calc_d_loop:
cmp esi, bjDealerCardCount
jge calc_d_done
mov edx, [bjDealerCards + esi*4]
cmp edx, 10
jle @F
mov edx, 10
@@:
cmp edx, 1
jne add_d_val
inc ebx
add eax, 11
jmp next_d_card
add_d_val:
add eax, edx
next_d_card:
inc esi
jmp calc_d_loop
calc_d_done:
reduce_d_ace:
cmp eax, 21
jle store_d_score
test ebx, ebx
jz store_d_score
sub eax, 10
dec ebx
jmp reduce_d_ace
store_d_score:
mov bjDealerScore, eax
ret
CalcDealerBJScore ENDP
RenderBlackjackGame PROC uses ebx esi edi
; Emerald Felt Table Background
invoke DrawBox, 0, 0, SCREEN_W, SCREEN_H, 000A3015h
invoke DrawBoxBorder, 10, 10, 300, 220, 000D4018h, 00FFD700h, 3
; Dealer Area Top
invoke DrawString8x8, 25, 20, OFFSET textBJ3D, 00FFD700h
invoke DrawString8x8, 25, 35, OFFSET textDealer3D, 00FFFFFFh
invoke FormatNumber, bjDealerScore, OFFSET hudNumBuffer
invoke DrawString8x8, 120, 35, OFFSET hudNumBuffer, 00FFFF00h
; Dealer Cards
xor esi, esi
draw_dealer_cards:
cmp esi, bjDealerCardCount
jge draw_player_bj_area
mov eax, esi
imul eax, 45
add eax, 25
mov ebx, eax
cmp esi, 1
jne draw_dealer_face
cmp bjDealerHideHole, 1
jne draw_dealer_face
; Face Down Card
mov eax, selectedBack3D
mov eax, cardBackColors3D[eax*4]
invoke DrawBoxBorder, ebx, 48, 38, 52, eax, 00FFFFFFh, 2
jmp next_dealer_card_draw
draw_dealer_face:
invoke DrawBoxBorder, ebx, 48, 38, 52, 00F0F0F5h, 00000000h, 2
mov eax, [bjDealerCards + esi*4]
dec eax
imul eax, 3
lea edx, [cardRankStr + eax]
mov eax, ebx
add eax, 8
invoke DrawString8x8, eax, 68, edx, 00000000h
next_dealer_card_draw:
inc esi
jmp draw_dealer_cards
draw_player_bj_area:
; Player Area Bottom
invoke DrawString8x8, 25, 110, OFFSET textPlayer3D, 00FFFFFFh
invoke FormatNumber, bjPlayerScore, OFFSET hudNumBuffer
invoke DrawString8x8, 120, 110, OFFSET hudNumBuffer, 0050FF50h
; Player Cards
xor esi, esi
draw_player_cards:
cmp esi, bjPlayerCardCount
jge draw_bj_footer
mov eax, esi
imul eax, 45
add eax, 25
mov ebx, eax
invoke DrawBoxBorder, ebx, 124, 38, 52, 00F0F0F5h, 00000000h, 2
mov eax, [bjPlayerCards + esi*4]
dec eax
imul eax, 3
lea edx, [cardRankStr + eax]
mov eax, ebx
add eax, 8
invoke DrawString8x8, eax, 144, edx, 00000000h
inc esi
jmp draw_player_cards
draw_bj_footer:
; Footer Status & Controls
invoke DrawBoxBorder, 20, 182, 280, 42, 00102010h, 00FFD700h, 1
cmp BYTE PTR [bjOutcomeMsg], 0
je draw_bj_controls
invoke DrawString8x8, 28, 188, OFFSET bjOutcomeMsg, 00FFFF00h
invoke DrawString8x8, 28, 204, OFFSET textNext3D, 00A0A0A0h
ret
draw_bj_controls:
invoke DrawString8x8, 28, 188, OFFSET textBJKeys3D, 00FFFFFFh
invoke DrawString8x8, 28, 204, OFFSET textDeal3D, 00A0A0A0h
ret
RenderBlackjackGame ENDP
; ==============================================================================
; IN-ENGINE 2.5D MINI-GAME: ROULETTE
; ==============================================================================
HandleRouletteInput PROC uses ebx
cmp roulState, 1
je roul_input_done
invoke Pressed3D, 31h ; '1' -> RED
test ah, 80h
jz @F
mov roulBetType, 1
@@:
invoke Pressed3D, 32h ; '2' -> BLACK
test ah, 80h
jz @F
mov roulBetType, 2
@@:
invoke Pressed3D, 33h ; '3' -> ZERO (0)
test ah, 80h
jz @F
mov roulBetType, 3
@@:
invoke Pressed3D, 34h ; '4' -> EVEN
test ah, 80h
jz @F
mov roulBetType, 4
@@:
invoke Pressed3D, 35h ; '5' -> ODD
test ah, 80h
jz check_roul_spin
mov roulBetType, 5
check_roul_spin:
invoke Pressed3D, 20h ; SPACE -> Spin
test ah, 80h
jz roul_input_done
mov eax, bankroll
cmp eax, roulBetAmount
jl roul_no_cash
sub eax, roulBetAmount
mov bankroll, eax
mov roulState, 1
mov roulSpinTimer, 50
mov roulPayout, 0
invoke PlaySoundA, OFFSET soundRoulette, 0, 1
ret
roul_no_cash:
invoke CopyString3D, OFFSET msgNeedMoney, OFFSET flashMessage
mov flashTimer, 60
roul_input_done:
ret
HandleRouletteInput ENDP
RenderRouletteGame PROC uses ebx esi edi
; Table felt background
invoke DrawBox, 0, 0, SCREEN_W, SCREEN_H, 00151525h
invoke DrawBoxBorder, 10, 10, 300, 220, 00201525h, 00FFD700h, 3
; 2.5D Rotating Wheel on Left
invoke DrawCircle, 85, 110, 65, 00102550h
invoke DrawCircle, 85, 110, 60, 00FFD700h
invoke DrawCircle, 85, 110, 52, 00101010h
invoke DrawCircle, 85, 110, 22, 00FFD700h ; Center brass turret
; Spinning Wheel / Ball Logic
cmp roulState, 1
jne draw_roul_ball
dec roulSpinTimer
add roulWheelAngle, 8
sub roulBallAngle, 14
cmp roulSpinTimer, 0
jg draw_roul_ball
; Wheel stopped! Determine result!
mov roulState, 2
invoke RandomRange3D, 37
mov roulWinningNum, eax
; Check bet
cmp roulBetType, 1 ; RED
jne check_ro_black
call IsNumberRed
test eax, eax
jz ro_lost
mov eax, roulBetAmount
shl eax, 1
mov roulPayout, eax
add bankroll, eax
invoke CopyString3D, OFFSET strWin, OFFSET roulOutcomeMsg
invoke PlaySoundA, OFFSET soundCoin, 0, 1
jmp draw_roul_ball
check_ro_black:
cmp roulBetType, 2 ; BLACK
jne check_ro_zero
cmp roulWinningNum, 0
je ro_lost
call IsNumberRed
test eax, eax
jnz ro_lost
mov eax, roulBetAmount
shl eax, 1
mov roulPayout, eax
add bankroll, eax
invoke CopyString3D, OFFSET strWin, OFFSET roulOutcomeMsg
invoke PlaySoundA, OFFSET soundCoin, 0, 1
jmp draw_roul_ball
check_ro_zero:
cmp roulBetType, 3 ; ZERO
jne check_ro_even
cmp roulWinningNum, 0
jne ro_lost
mov eax, roulBetAmount
imul eax, 36
mov roulPayout, eax
add bankroll, eax
invoke CopyString3D, OFFSET strJackpot, OFFSET roulOutcomeMsg
invoke PlaySoundA, OFFSET soundJackpot, 0, 1
jmp draw_roul_ball
check_ro_even:
cmp roulBetType, 4 ; EVEN
jne check_ro_odd
mov eax, roulWinningNum
test eax, eax
jz ro_lost
test al, 1
jnz ro_lost
mov eax, roulBetAmount
shl eax, 1
mov roulPayout, eax
add bankroll, eax
invoke CopyString3D, OFFSET strWin, OFFSET roulOutcomeMsg
invoke PlaySoundA, OFFSET soundCoin, 0, 1
jmp draw_roul_ball
check_ro_odd:
mov eax, roulWinningNum
test eax, eax
jz ro_lost
test al, 1
jz ro_lost
mov eax, roulBetAmount
shl eax, 1
mov roulPayout, eax
add bankroll, eax
invoke CopyString3D, OFFSET strWin, OFFSET roulOutcomeMsg
invoke PlaySoundA, OFFSET soundCoin, 0, 1
jmp draw_roul_ball
ro_lost:
invoke CopyString3D, OFFSET strLose, OFFSET roulOutcomeMsg
draw_roul_ball:
; Draw White Ball on Rim
mov eax, roulBallAngle
and eax, 511
mov ebx, [tableCos + eax*4]
imul ebx, 42
sar ebx, 16
add ebx, 85
mov eax, roulBallAngle
and eax, 511
mov edx, [tableSin + eax*4]
imul edx, 42
sar edx, 16
add edx, 110
invoke DrawCircle, ebx, edx, 3, 00FFFFFFh
; Right Betting Board
invoke DrawBoxBorder, 175, 25, 125, 28, 001010C0h, 00FFFFFFh, 2 ; [1] RED
invoke DrawString8x8, 190, 35, OFFSET textRed3D, 00FFFFFFh
invoke DrawBoxBorder, 175, 60, 125, 28, 00151515h, 00FFFFFFh, 2 ; [2] BLACK
invoke DrawString8x8, 190, 70, OFFSET textBlack3D, 00FFFFFFh
invoke DrawBoxBorder, 175, 95, 125, 28, 00106010h, 00FFFFFFh, 2 ; [3] ZERO
invoke DrawString8x8, 190, 105, OFFSET textZero3D, 00FFFFFFh
invoke DrawBoxBorder, 175, 130, 60, 26, 00302020h, 00FFFFFFh, 1 ; [4] EVEN
invoke DrawString8x8, 185, 139, OFFSET textEven3D, 00FFFFFFh
invoke DrawBoxBorder, 240, 130, 60, 26, 00302020h, 00FFFFFFh, 1 ; [5] ODD
invoke DrawString8x8, 250, 139, OFFSET textOdd3D, 00FFFFFFh
; Highlight Active Bet
cmp roulBetType, 1
jne @F
invoke DrawBoxBorder, 173, 23, 129, 32, 0, 00FFFF00h, 2
@@:
cmp roulBetType, 2
jne @F
invoke DrawBoxBorder, 173, 58, 129, 32, 0, 00FFFF00h, 2
@@:
cmp roulBetType, 3
jne @F
invoke DrawBoxBorder, 173, 93, 129, 32, 0, 00FFFF00h, 2
@@:
cmp roulBetType, 4
jne @F
invoke DrawBoxBorder, 173, 128, 64, 30, 0, 00FFFF00h, 2
@@:
cmp roulBetType, 5
jne draw_ro_footer
invoke DrawBoxBorder, 238, 128, 64, 30, 0, 00FFFF00h, 2
draw_ro_footer:
invoke DrawBoxBorder, 20, 180, 280, 42, 00101015h, 00FFD700h, 1
cmp roulState, 2
jne @F
invoke DrawString8x8, 28, 186, OFFSET textResult3D, 00FFD700h
invoke FormatNumber, roulWinningNum, OFFSET hudNumBuffer
invoke DrawString8x8, 85, 186, OFFSET hudNumBuffer, 00FFFF00h
invoke DrawString8x8, 130, 186, OFFSET roulOutcomeMsg, 0050FF50h
@@:
invoke DrawString8x8, 28, 202, OFFSET textSpin3D, 00A0A0A0h
ret
RenderRouletteGame ENDP
IsNumberRed PROC
mov eax, roulWinningNum
cmp eax, 1
je red_yes
cmp eax, 3
je red_yes
cmp eax, 5
je red_yes
cmp eax, 7
je red_yes
cmp eax, 9
je red_yes
cmp eax, 12
je red_yes
cmp eax, 14
je red_yes
cmp eax, 16
je red_yes
cmp eax, 18
je red_yes
cmp eax, 19
je red_yes
cmp eax, 21
je red_yes
cmp eax, 23
je red_yes
cmp eax, 25
je red_yes
cmp eax, 27
je red_yes
cmp eax, 30
je red_yes
cmp eax, 32
je red_yes
cmp eax, 34
je red_yes
cmp eax, 36
je red_yes
xor eax, eax
ret
red_yes:
mov eax, 1
ret
IsNumberRed ENDP
; ==============================================================================
; IN-ENGINE 2.5D MINI-GAME: BAR & SHOP
; ==============================================================================
HandleShopInput PROC uses ebx esi
xor esi, esi
shop_choice:
inc esi
lea eax, [esi+30h]
invoke Pressed3D, eax
test eax, eax
jnz shop_chosen
cmp esi, 3
jb shop_choice
ret
shop_chosen:
bt ownedBacks3D, esi
jc shop_equip
mov ebx, 1500
cmp esi, 1
jne @F
mov ebx, 1000
@@:
cmp bankroll, ebx
jb shop_no_money
sub bankroll, ebx
bts ownedBacks3D, esi
shop_equip:
mov selectedBack3D, esi
invoke CopyString3D, OFFSET textBought3D, OFFSET shopMsg
call SaveProgress3D
ret
shop_no_money:
invoke CopyString3D, OFFSET textNoCash3D, OFFSET shopMsg
ret
HandleShopInput ENDP
RenderShopGame PROC
invoke DrawBox, 0, 0, SCREEN_W, SCREEN_H, 00150A0Ah
invoke DrawBoxBorder, 10, 10, 300, 220, 00251515h, 00FFD700h, 3
invoke DrawString8x8, 25, 20, OFFSET textShop3D, 00FFD700h
invoke DrawBoxBorder, 20, 40, 280, 32, 001A1010h, 00FFFFFFh, 1
invoke DrawString8x8, 28, 46, OFFSET textItem1_3D, 00FFFF00h
invoke DrawString8x8, 28, 58, OFFSET textShopHint3D, 00A0A0A0h
invoke DrawBoxBorder, 20, 80, 280, 32, 001A1010h, 00FFFFFFh, 1
invoke DrawString8x8, 28, 86, OFFSET textItem2_3D, 00FFFF00h
invoke DrawString8x8, 28, 98, OFFSET textShopHint3D, 00A0A0A0h
invoke DrawBoxBorder, 20, 120, 280, 32, 001A1010h, 00FFFFFFh, 1
invoke DrawString8x8, 28, 126, OFFSET textItem3_3D, 00FFFF00h
invoke DrawString8x8, 28, 138, OFFSET textShopHint3D, 00A0A0A0h
invoke DrawBoxBorder, 20, 165, 280, 55, 00100A0Ah, 00FFD700h, 1
invoke DrawString8x8, 28, 172, OFFSET textBank3D, 00FFD700h
invoke FormatNumber, bankroll, OFFSET hudNumBuffer
invoke DrawString8x8, 110, 172, OFFSET hudNumBuffer, 00FFFF00h
cmp BYTE PTR [shopMsg], 0
je @F
invoke DrawString8x8, 28, 188, OFFSET shopMsg, 0050FF50h
@@:
invoke DrawString8x8, 28, 204, OFFSET textBack3D, 00A0A0A0h
ret
RenderShopGame ENDP
; ==============================================================================
; IN-ENGINE 2.5D MINI-GAME: ATM TERMINAL
; ==============================================================================
HandleATMInput PROC
ret
HandleATMInput ENDP
RenderATMGame PROC
invoke DrawBox, 0, 0, 320, 240, 00172120h
invoke DrawString8x8, 24, 30, OFFSET textATM3D, 00D8BC6Ah
invoke DrawString8x8, 24, 70, OFFSET textBank3D, 00FFFFFFh
invoke FormatNumber, bankroll, OFFSET hudNumBuffer
invoke DrawString8x8, 96, 70, OFFSET hudNumBuffer, 0089DAB2h
invoke DrawString8x8, 24, 115, OFFSET textATMNote3D, 00B7C8C1h
invoke DrawString8x8, 24, 140, OFFSET textATMNote2_3D, 00B7C8C1h
invoke DrawString8x8, 24, 208, OFFSET textBack3D, 00D8BC6Ah
ret
RenderATMGame ENDP
; ==============================================================================
; ==============================================================================
; ==============================================================================
; SHARED RICH UI PROCEDURES
; ==============================================================================
DrawKeycap3D PROC uses ebx esi edi, x:DWORD, y:DWORD, strPtr:DWORD, isActive:DWORD
local keyW:DWORD
mov esi, strPtr
xor ecx, ecx
keycap_len:
mov al, [esi+ecx]
test al, al
jz keycap_len_done
inc ecx
jmp keycap_len
keycap_len_done:
shl ecx, 3
add ecx, 8
mov keyW, ecx
; Drop shadow
mov eax, y
add eax, 2
invoke DrawBox, x, eax, keyW, 13, 0008080Ch
; Border and Fill
cmp isActive, 0
je keycap_inactive
mov eax, 00FFFF00h ; Bright Yellow active border
mov edx, 001B4B22h ; Casino Green active fill
mov ebx, 00FFFF00h ; Bright Yellow active text
jmp keycap_draw_box
keycap_inactive:
mov eax, 00606870h ; Slate inactive border
mov edx, 001A1C22h ; Charcoal inactive fill
mov ebx, 00D0D8E0h ; Silver inactive text
keycap_draw_box:
push ebx
invoke DrawBoxBorder, x, y, keyW, 13, edx, eax, 1
pop ebx
; Text label
mov eax, x
add eax, 4
mov edx, y
add edx, 3
invoke DrawString8x8, eax, edx, strPtr, ebx
mov eax, keyW
add eax, 4
ret
DrawKeycap3D ENDP
DrawChipStack PROC uses ebx esi edi, x:DWORD, y:DWORD, chipCount:DWORD
mov edi, chipCount
xor esi, esi
chip_loop:
cmp esi, edi
jge chip_done
mov eax, esi
shl eax, 2
mov edx, y
sub edx, eax
; Shadow
mov eax, x
add eax, 2
mov ecx, edx
add ecx, 5
invoke DrawBox, eax, ecx, 20, 2, 00061004h
; Red Clay Chip body with white rim
invoke DrawBoxBorder, x, edx, 24, 6, 00B81515h, 00FFFFFFh, 1
; White stripe inlays
mov eax, x
add eax, 4
mov ecx, edx
add ecx, 1
invoke DrawBox, eax, ecx, 3, 4, 00FFFFFFh
mov eax, x
add eax, 17
mov ecx, edx
add ecx, 1
invoke DrawBox, eax, ecx, 3, 4, 00FFFFFFh
inc esi
jmp chip_loop
chip_done:
ret
DrawChipStack ENDP
DrawDetailedCoin PROC uses ebx esi edi, cxVal:DWORD, cyVal:DWORD, rxVal:DWORD, ryVal:DWORD, outerColor:DWORD, innerColor:DWORD, reliefType:DWORD
local rxSq:DWORD
local rySq:DWORD
local rxRySq:DWORD
local threshSq:DWORD
local curDy:DWORD
local curDx:DWORD
local curX:DWORD
local curY:DWORD
mov eax, rxVal
cmp eax, 0
jle coin_draw_done
mov eax, ryVal
cmp eax, 0
jle coin_draw_done
mov eax, rxVal
imul eax, rxVal
mov rxSq, eax
mov eax, ryVal
imul eax, ryVal
mov rySq, eax
imul eax, rxSq
mov rxRySq, eax
; 3/4 threshold for rim bevel
mov ecx, 3
imul eax, ecx
shr eax, 2
mov threshSq, eax
; Scan rows
mov eax, ryVal
neg eax
mov curDy, eax
coin_row_loop:
mov eax, curDy
cmp eax, ryVal
jg coin_relief_check
mov edx, cyVal
add edx, curDy
mov curY, edx
; Scan columns
mov eax, rxVal
neg eax
mov curDx, eax
coin_col_loop:
mov eax, curDx
cmp eax, rxVal
jg coin_col_next_row
mov ecx, cxVal
add ecx, curDx
mov curX, ecx
; val = dx*dx*rySq + dy*dy*rxSq
mov eax, curDx
imul eax, curDx
imul eax, rySq
mov ebx, eax
mov eax, curDy
imul eax, curDy
imul eax, rxSq
add eax, ebx
cmp eax, rxRySq
ja coin_pixel_outside
cmp eax, threshSq
jb coin_draw_inner
invoke DrawPixel, curX, curY, outerColor
jmp coin_pixel_outside
coin_draw_inner:
invoke DrawPixel, curX, curY, innerColor
coin_pixel_outside:
inc curDx
jmp coin_col_loop
coin_col_next_row:
inc curDy
jmp coin_row_loop
coin_relief_check:
cmp rxVal, 14
jl coin_draw_done
cmp reliefType, 1
je coin_draw_eagle
cmp reliefType, 2
je coin_draw_numeral
jmp coin_draw_done
coin_draw_eagle:
; Imperial Eagle relief (Dark Gold 009A7A00h / Bright 00FFD700h)
mov eax, cxVal
sub eax, 3
mov edx, cyVal
sub edx, 14
invoke DrawBox, eax, edx, 7, 2, 009A7A00h
mov eax, cxVal
sub eax, 4
mov edx, cyVal
sub edx, 12
invoke DrawBox, eax, edx, 9, 2, 009A7A00h
mov eax, cxVal
sub eax, 2
mov edx, cyVal
sub edx, 9
invoke DrawBox, eax, edx, 5, 12, 009A7A00h
mov eax, cxVal
sub eax, 1
mov edx, cyVal
sub edx, 8
invoke DrawBox, eax, edx, 3, 10, 00FFD700h
mov eax, cxVal
sub eax, 10
mov edx, cyVal
sub edx, 8
invoke DrawBox, eax, edx, 7, 3, 009A7A00h
mov eax, cxVal
sub eax, 13
mov edx, cyVal
sub edx, 5
invoke DrawBox, eax, edx, 10, 3, 009A7A00h
mov eax, cxVal
sub eax, 11
mov edx, cyVal
sub edx, 2
invoke DrawBox, eax, edx, 7, 3, 009A7A00h
mov eax, cxVal
add eax, 4
mov edx, cyVal
sub edx, 8
invoke DrawBox, eax, edx, 7, 3, 009A7A00h
mov eax, cxVal
add eax, 4
mov edx, cyVal
sub edx, 5
invoke DrawBox, eax, edx, 10, 3, 009A7A00h
mov eax, cxVal
add eax, 5
mov edx, cyVal
sub edx, 2
invoke DrawBox, eax, edx, 7, 3, 009A7A00h
mov eax, cxVal
sub eax, 4
mov edx, cyVal
add edx, 4
invoke DrawBox, eax, edx, 9, 3, 009A7A00h
mov eax, cxVal
sub eax, 3
mov edx, cyVal
add edx, 7
invoke DrawBox, eax, edx, 7, 3, 009A7A00h
jmp coin_draw_done
coin_draw_numeral:
; Roman numeral 'I' & laurel
mov eax, cxVal
sub eax, 5
mov edx, cyVal
sub edx, 10
invoke DrawBox, eax, edx, 11, 3, 009A7A00h
mov eax, cxVal
sub eax, 2
mov edx, cyVal
sub edx, 7
invoke DrawBox, eax, edx, 5, 14, 009A7A00h
mov eax, cxVal
sub eax, 1
mov edx, cyVal
sub edx, 6
invoke DrawBox, eax, edx, 3, 12, 00FFD700h
mov eax, cxVal
sub eax, 6
mov edx, cyVal
add edx, 7
invoke DrawBox, eax, edx, 13, 3, 009A7A00h
; Laurel dots
mov eax, cxVal
sub eax, 12
mov edx, cyVal
sub edx, 8
invoke DrawBox, eax, edx, 2, 2, 009A7A00h
mov eax, cxVal
add eax, 11
mov edx, cyVal
sub edx, 8
invoke DrawBox, eax, edx, 2, 2, 009A7A00h
mov eax, cxVal
sub eax, 12
mov edx, cyVal
invoke DrawBox, eax, edx, 2, 2, 009A7A00h
mov eax, cxVal
add eax, 11
mov edx, cyVal
invoke DrawBox, eax, edx, 2, 2, 009A7A00h
mov eax, cxVal
sub eax, 12
mov edx, cyVal
add edx, 8
invoke DrawBox, eax, edx, 2, 2, 009A7A00h
mov eax, cxVal
add eax, 11
mov edx, cyVal
add edx, 8
invoke DrawBox, eax, edx, 2, 2, 009A7A00h
coin_draw_done:
ret
DrawDetailedCoin ENDP
; ==============================================================================
; IN-ENGINE 2.5D MINI-GAME: COIN FLIP
; ==============================================================================
InitCoinGame PROC
mov coin3d_state, 0
mov coin3d_timer, 0
mov coin3d_streak, 0
mov coin3d_win, 0
ret
InitCoinGame ENDP
HandleCoinInput PROC
cmp coin3d_state, 0
je coin_handle_idle
cmp coin3d_state, 1
je coin_handle_flipping
cmp coin3d_state, 2
je coin_handle_result
ret
coin_handle_idle:
invoke Pressed3D, 26h ; UP
test eax, eax
jnz coin_bet_up
invoke Pressed3D, 57h ; 'W'
test eax, eax
jnz coin_bet_up
invoke Pressed3D, 28h ; DOWN
test eax, eax
jnz coin_bet_down
invoke Pressed3D, 53h ; 'S'
test eax, eax
jnz coin_bet_down
invoke Pressed3D, 31h ; '1'
test eax, eax
jnz coin_pick_1
invoke Pressed3D, 32h ; '2'
test eax, eax
jnz coin_pick_2
invoke Pressed3D, 20h ; SPACE
test eax, eax
jnz coin_start_flip
ret
coin_bet_up:
mov eax, coin3d_bet
add eax, 50
cmp eax, bankroll
jle @F
mov eax, bankroll
@@:
cmp eax, 5000
jle @F
mov eax, 5000
@@:
mov coin3d_bet, eax
invoke PlaySoundA, OFFSET soundClick, 0, 1
ret
coin_bet_down:
mov eax, coin3d_bet
sub eax, 50
cmp eax, 50
jge @F
mov eax, 50
@@:
mov coin3d_bet, eax
invoke PlaySoundA, OFFSET soundClick, 0, 1
ret
coin_pick_1:
mov coin3d_choice, 1
invoke PlaySoundA, OFFSET soundClick, 0, 1
ret
coin_pick_2:
mov coin3d_choice, 2
invoke PlaySoundA, OFFSET soundClick, 0, 1
ret
coin_start_flip:
mov eax, coin3d_bet
cmp eax, bankroll
jle @F
mov eax, bankroll
mov coin3d_bet, eax
test eax, eax
jz coin_done
@@:
mov eax, coin3d_bet
sub bankroll, eax
mov coin3d_state, 1
mov coin3d_timer, 40
invoke PlaySoundA, OFFSET soundCoin, 0, 1
ret
coin_handle_flipping:
dec coin3d_timer
cmp coin3d_timer, 0
jg coin_done
invoke RandomRange3D, 2
inc eax
mov coin3d_result, eax
mov edx, coin3d_choice
cmp eax, edx
jne coin_flip_lost
; Won!
inc coin3d_streak
mov eax, coin3d_bet
shl eax, 1
add bankroll, eax
mov coin3d_win, eax
mov coin3d_state, 2
invoke PlaySoundA, OFFSET soundCoinDing, 0, 1
ret
coin_flip_lost:
mov coin3d_streak, 0
mov coin3d_win, 0
mov coin3d_state, 2
invoke PlaySoundA, OFFSET soundLose, 0, 1
ret
coin_handle_result:
invoke Pressed3D, 20h
test eax, eax
jz coin_done
mov coin3d_state, 0
invoke PlaySoundA, OFFSET soundClick, 0, 1
coin_done:
ret
HandleCoinInput ENDP
RenderCoinGame PROC uses ebx esi edi
local cyVal:DWORD
local rxVal:DWORD
local kx:DWORD
; Background & Cabinet border
invoke DrawBox, 0, 0, 320, 240, 00140906h
invoke DrawBoxBorder, 6, 6, 308, 228, 0022150Fh, 00482E1Bh, 3
; Header
invoke DrawBoxBorder, 20, 12, 280, 26, 001C100Ah, 00FFD700h, 2
invoke DrawString8x8, 44, 21, OFFSET textCoinTitle, 00FFFF00h
; Corner rivets
invoke DrawBox, 12, 12, 3, 3, 00FFD700h
invoke DrawBox, 306, 12, 3, 3, 00FFD700h
invoke DrawBox, 12, 226, 3, 3, 00FFD700h
invoke DrawBox, 306, 226, 3, 3, 00FFD700h
; Status meters
invoke DrawBoxBorder, 20, 44, 110, 18, 000E1A0Ah, 00224B1Ah, 1
invoke DrawString8x8, 24, 49, OFFSET textBankPrompt, 003CFF3Ch
invoke FormatNumber, bankroll, OFFSET hudNumBuffer
invoke DrawString8x8, 72, 49, OFFSET hudNumBuffer, 003CFF3Ch
invoke DrawBoxBorder, 190, 44, 110, 18, 001A100Ah, 003A2814h, 1
invoke DrawString8x8, 194, 49, OFFSET textBetPrompt, 00FFD700h
invoke FormatNumber, coin3d_bet, OFFSET hudNumBuffer
invoke DrawString8x8, 254, 49, OFFSET hudNumBuffer, 00FFD700h
; Left: Heads
cmp coin3d_choice, 1
jne coin_left_inactive
invoke DrawBoxBorder, 20, 72, 76, 68, 00101828h, 00FFFF00h, 2
invoke DrawString8x8, 30, 78, OFFSET textCoinSide1, 00FFFF00h
invoke DrawDetailedCoin, 58, 106, 14, 14, 00D0A000h, 00FFD700h, 1
invoke DrawString8x8, 24, 126, OFFSET textCoinSelected, 003CFF3Ch
jmp coin_right_side
coin_left_inactive:
invoke DrawBoxBorder, 20, 72, 76, 68, 000A101Ch, 00404855h, 1
invoke DrawString8x8, 30, 78, OFFSET textCoinSide1, 00D0D8E0h
invoke DrawDetailedCoin, 58, 106, 14, 14, 009A7A00h, 00D0A000h, 1
coin_right_side:
; Right: Tails
cmp coin3d_choice, 2
jne coin_right_inactive
invoke DrawBoxBorder, 224, 72, 76, 68, 00101828h, 00FFFF00h, 2
invoke DrawString8x8, 234, 78, OFFSET textCoinSide2, 00FFFF00h
invoke DrawDetailedCoin, 262, 106, 14, 14, 00D0A000h, 00FFD700h, 2
invoke DrawString8x8, 228, 126, OFFSET textCoinSelected, 003CFF3Ch
jmp coin_center_area
coin_right_inactive:
invoke DrawBoxBorder, 224, 72, 76, 68, 000A101Ch, 00404855h, 1
invoke DrawString8x8, 234, 78, OFFSET textCoinSide2, 00D0D8E0h
invoke DrawDetailedCoin, 262, 106, 14, 14, 009A7A00h, 00D0A000h, 2
coin_center_area:
; Center spotlight
invoke DrawCircle, 160, 110, 48, 00121620h
invoke DrawCircle, 160, 110, 44, 00FFD700h
invoke DrawCircle, 160, 110, 42, 000E141Eh
cmp coin3d_state, 1
je coin_render_flipping
cmp coin3d_state, 2
je coin_render_result
; Idle coin
invoke DrawDetailedCoin, 160, 110, 26, 26, 00D0A000h, 00FFD700h, coin3d_choice
jmp coin_render_keys
coin_render_flipping:
mov eax, coin3d_timer
and eax, 7
movzx eax, byte ptr [coinRxAnimTable + eax]
mov rxVal, eax
invoke DrawDetailedCoin, 160, 110, rxVal, 26, 00D0A000h, 00FFD700h, 0
invoke DrawString8x8, 88, 160, OFFSET textCoinFlipping, 00FFFF00h
jmp coin_render_keys
coin_render_result:
invoke DrawDetailedCoin, 160, 110, 26, 26, 00D0A000h, 00FFD700h, coin3d_result
mov eax, coin3d_result
cmp eax, coin3d_choice
jne coin_render_loss_msg
; Win banner
invoke DrawBoxBorder, 44, 154, 232, 22, 000E141Eh, 003CFF3Ch, 1
invoke DrawString8x8, 64, 161, OFFSET textCoinWin, 003CFF3Ch
invoke FormatNumber, coin3d_win, OFFSET hudNumBuffer
invoke DrawString8x8, 152, 161, OFFSET hudNumBuffer, 003CFF3Ch
jmp coin_render_keys
coin_render_loss_msg:
invoke DrawBoxBorder, 44, 154, 232, 22, 000E141Eh, 00C81414h, 1
invoke DrawString8x8, 114, 161, OFFSET textCoinLose, 00FF6464h
coin_render_keys:
mov kx, 16
xor eax, eax
cmp coin3d_choice, 1
sete al
invoke DrawKeycap3D, kx, 192, OFFSET textCoinKey1, eax
add kx, eax
xor eax, eax
cmp coin3d_choice, 2
sete al
invoke DrawKeycap3D, kx, 192, OFFSET textCoinKey2, eax
add kx, eax
invoke DrawKeycap3D, kx, 192, OFFSET textCoinKeySpace, 1
add kx, eax
invoke DrawKeycap3D, kx, 192, OFFSET textKeyEsc, 0
ret
RenderCoinGame ENDP
; ==============================================================================
; IN-ENGINE 2.5D MINI-GAME: CRAPS / DICE
; ==============================================================================
DrawCrapsDie PROC uses ebx esi edi, x:DWORD, y:DWORD, sizeVal:DWORD, valNum:DWORD
; Drop shadow
mov eax, x
add eax, 3
mov edx, y
add edx, sizeVal
invoke DrawBox, eax, edx, sizeVal, 3, 00081403h
mov eax, x
add eax, sizeVal
mov edx, y
add edx, 3
invoke DrawBox, eax, edx, 3, sizeVal, 00081403h
; Ivory body & bevel
invoke DrawBoxBorder, x, y, sizeVal, sizeVal, 00FAF4F0h, 00403535h, 1
mov eax, x
inc eax
mov edx, y
inc edx
mov ecx, sizeVal
sub ecx, 2
invoke DrawBox, eax, edx, ecx, 1, 00FFFFFFh
invoke DrawBox, eax, edx, 1, ecx, 00FFFFFFh
; Ruby pips (00C81515h)
mov eax, valNum
test al, 1
jz @F
; Center pip
mov eax, x
add eax, 18
mov edx, y
add edx, 18
invoke DrawCircle, eax, edx, 3, 00C81515h
dec eax
dec edx
invoke DrawPixel, eax, edx, 00FFFFFFh
@@:
cmp valNum, 2
jl die_pips_done
mov eax, x
add eax, 9
mov edx, y
add edx, 9
invoke DrawCircle, eax, edx, 3, 00C81515h
mov eax, x
add eax, 27
mov edx, y
add edx, 27
invoke DrawCircle, eax, edx, 3, 00C81515h
cmp valNum, 4
jl die_pips_done
mov eax, x
add eax, 27
mov edx, y
add edx, 9
invoke DrawCircle, eax, edx, 3, 00C81515h
mov eax, x
add eax, 9
mov edx, y
add edx, 27
invoke DrawCircle, eax, edx, 3, 00C81515h
cmp valNum, 6
jl die_pips_done
mov eax, x
add eax, 9
mov edx, y
add edx, 18
invoke DrawCircle, eax, edx, 3, 00C81515h
mov eax, x
add eax, 27
mov edx, y
add edx, 18
invoke DrawCircle, eax, edx, 3, 00C81515h
die_pips_done:
ret
DrawCrapsDie ENDP
InitDiceGame PROC
mov dice3d_state, 0
mov dice3d_timer, 0
mov dice3d_win, 0
ret
InitDiceGame ENDP
HandleDiceInput PROC
cmp dice3d_state, 0
je dice_handle_idle
cmp dice3d_state, 1
je dice_handle_rolling
cmp dice3d_state, 2
je dice_handle_result
ret
dice_handle_idle:
invoke Pressed3D, 26h ; UP
test eax, eax
jnz dice_bet_up
invoke Pressed3D, 57h ; 'W'
test eax, eax
jnz dice_bet_up
invoke Pressed3D, 28h ; DOWN
test eax, eax
jnz dice_bet_down
invoke Pressed3D, 53h ; 'S'
test eax, eax
jnz dice_bet_down
invoke Pressed3D, 31h ; '1'
test eax, eax
jnz dice_pick_1
invoke Pressed3D, 32h ; '2'
test eax, eax
jnz dice_pick_2
invoke Pressed3D, 20h ; SPACE
test eax, eax
jnz dice_start_roll
ret
dice_bet_up:
mov eax, dice3d_bet
add eax, 50
cmp eax, bankroll
jle @F
mov eax, bankroll
@@:
cmp eax, 5000
jle @F
mov eax, 5000
@@:
mov dice3d_bet, eax
invoke PlaySoundA, OFFSET soundClick, 0, 1
ret
dice_bet_down:
mov eax, dice3d_bet
sub eax, 50
cmp eax, 50
jge @F
mov eax, 50
@@:
mov dice3d_bet, eax
invoke PlaySoundA, OFFSET soundClick, 0, 1
ret
dice_pick_1:
mov dice3d_choice, 1
invoke PlaySoundA, OFFSET soundClick, 0, 1
ret
dice_pick_2:
mov dice3d_choice, 2
invoke PlaySoundA, OFFSET soundClick, 0, 1
ret
dice_start_roll:
mov eax, dice3d_bet
cmp eax, bankroll
jle @F
mov eax, bankroll
mov dice3d_bet, eax
test eax, eax
jz dice_done
@@:
mov eax, dice3d_bet
sub bankroll, eax
mov dice3d_state, 1
mov dice3d_timer, 35
invoke PlaySoundA, OFFSET soundCards, 0, 1
ret
dice_handle_rolling:
dec dice3d_timer
cmp dice3d_timer, 0
jg dice_randomize_tumble
; Roll finished!
invoke RandomRange3D, 6
inc eax
mov dice3d_val1, eax
invoke RandomRange3D, 6
inc eax
mov dice3d_val2, eax
mov edx, dice3d_val1
add edx, eax
mov dice3d_sum, edx
; Parity check
mov eax, edx
and eax, 1
jnz dice_sum_is_odd
; Even
mov eax, 1
jmp dice_check_win
dice_sum_is_odd:
mov eax, 2
dice_check_win:
cmp eax, dice3d_choice
jne dice_roll_lost
; Won!
mov eax, dice3d_bet
shl eax, 1
add bankroll, eax
mov dice3d_win, eax
mov dice3d_state, 2
invoke PlaySoundA, OFFSET soundVictory, 0, 1
ret
dice_roll_lost:
mov dice3d_win, 0
mov dice3d_state, 2
invoke PlaySoundA, OFFSET soundLose, 0, 1
ret
dice_randomize_tumble:
invoke RandomRange3D, 6
inc eax
mov dice3d_val1, eax
invoke RandomRange3D, 6
inc eax
mov dice3d_val2, eax
ret
dice_handle_result:
invoke Pressed3D, 20h
test eax, eax
jz dice_done
mov dice3d_state, 0
invoke PlaySoundA, OFFSET soundClick, 0, 1
dice_done:
ret
HandleDiceInput ENDP
RenderDiceGame PROC uses ebx esi edi
local kx:DWORD
; Mahogany frame & Deep Felt Green table
invoke DrawBox, 0, 0, 320, 240, 00140906h
invoke DrawBoxBorder, 6, 6, 308, 228, 000A3816h, 00FFD700h, 2
; Header
invoke DrawBoxBorder, 20, 12, 280, 26, 00072E13h, 00FFD700h, 2
invoke DrawString8x8, 48, 21, OFFSET textDiceTitle, 00FFFF00h
; Status
invoke DrawBoxBorder, 20, 44, 110, 18, 00072E13h, 001B4B22h, 1
invoke DrawString8x8, 24, 49, OFFSET textBankPrompt, 003CFF3Ch
invoke FormatNumber, bankroll, OFFSET hudNumBuffer
invoke DrawString8x8, 72, 49, OFFSET hudNumBuffer, 003CFF3Ch
invoke DrawBoxBorder, 190, 44, 110, 18, 00072E13h, 001B4B22h, 1
invoke DrawString8x8, 194, 49, OFFSET textBetPrompt, 00FFD700h
invoke FormatNumber, dice3d_bet, OFFSET hudNumBuffer
invoke DrawString8x8, 254, 49, OFFSET hudNumBuffer, 00FFD700h
; [1] ר<>
cmp dice3d_choice, 1
jne dice_even_inactive
invoke DrawBoxBorder, 16, 70, 88, 48, 00072E13h, 00FFFF00h, 2
invoke DrawString8x8, 30, 76, OFFSET textDiceEven, 00FFFF00h
invoke DrawString8x8, 22, 90, OFFSET textDiceEvenNums, 00FFD700h
invoke DrawString8x8, 26, 104, OFFSET textCoinSelected, 003CFF3Ch
jmp dice_odd_side
dice_even_inactive:
invoke DrawBoxBorder, 16, 70, 88, 48, 00072E13h, 001B4B22h, 1
invoke DrawString8x8, 30, 76, OFFSET textDiceEven, 00D0D8E0h
invoke DrawString8x8, 22, 90, OFFSET textDiceEvenNums, 0080B090h
dice_odd_side:
; [2] <20><><EFBFBD><EFBFBD><EFBFBD>
cmp dice3d_choice, 2
jne dice_odd_inactive
invoke DrawBoxBorder, 216, 70, 88, 48, 00072E13h, 00FFFF00h, 2
invoke DrawString8x8, 226, 76, OFFSET textDiceOdd, 00FFFF00h
invoke DrawString8x8, 224, 90, OFFSET textDiceOddNums, 00FFD700h
invoke DrawString8x8, 226, 104, OFFSET textCoinSelected, 003CFF3Ch
jmp dice_center_cubes
dice_odd_inactive:
invoke DrawBoxBorder, 216, 70, 88, 48, 00072E13h, 001B4B22h, 1
invoke DrawString8x8, 226, 76, OFFSET textDiceOdd, 00D0D8E0h
invoke DrawString8x8, 224, 90, OFFSET textDiceOddNums, 0080B090h
dice_center_cubes:
; 2 Dice in center
invoke DrawCrapsDie, 116, 76, 36, dice3d_val1
invoke DrawCrapsDie, 168, 76, 36, dice3d_val2
cmp dice3d_state, 1
je dice_render_rolling
cmp dice3d_state, 2
je dice_render_result
jmp dice_render_keys
dice_render_rolling:
invoke DrawString8x8, 76, 138, OFFSET textDiceRolling, 00FFFF00h
jmp dice_render_keys
dice_render_result:
invoke DrawBoxBorder, 36, 130, 248, 36, 00072E13h, 00FFD700h, 1
invoke DrawString8x8, 44, 135, OFFSET textDiceSumHdr, 00FFD700h
invoke FormatNumber, dice3d_val1, OFFSET hudNumBuffer
invoke DrawString8x8, 92, 135, OFFSET hudNumBuffer, 00FFFF00h
invoke DrawString8x8, 110, 135, OFFSET textDicePlus, 00FFD700h
invoke FormatNumber, dice3d_val2, OFFSET hudNumBuffer
invoke DrawString8x8, 126, 135, OFFSET hudNumBuffer, 00FFFF00h
invoke DrawString8x8, 144, 135, OFFSET textDiceEqual, 00FFD700h
invoke FormatNumber, dice3d_sum, OFFSET hudNumBuffer
invoke DrawString8x8, 168, 135, OFFSET hudNumBuffer, 00FFFF00h
mov eax, dice3d_sum
and eax, 1
jnz dice_render_odd_res
invoke DrawString8x8, 186, 135, OFFSET textDiceEvenResult, 003CFF3Ch
jmp dice_render_outcome
dice_render_odd_res:
invoke DrawString8x8, 186, 135, OFFSET textDiceOddResult, 003CFF3Ch
dice_render_outcome:
mov eax, dice3d_win
test eax, eax
jz dice_render_loss_outcome
invoke DrawString8x8, 68, 150, OFFSET textDiceWin, 003CFF3Ch
invoke FormatNumber, dice3d_win, OFFSET hudNumBuffer
invoke DrawString8x8, 156, 150, OFFSET hudNumBuffer, 003CFF3Ch
invoke DrawString8x8, 188, 150, OFFSET textDiceWinMult, 003CFF3Ch
jmp dice_render_keys
dice_render_loss_outcome:
invoke DrawString8x8, 116, 150, OFFSET textDiceLose, 00FF6464h
dice_render_keys:
mov kx, 16
xor eax, eax
cmp dice3d_choice, 1
sete al
invoke DrawKeycap3D, kx, 192, OFFSET textDiceKey1, eax
add kx, eax
xor eax, eax
cmp dice3d_choice, 2
sete al
invoke DrawKeycap3D, kx, 192, OFFSET textDiceKey2, eax
add kx, eax
invoke DrawKeycap3D, kx, 192, OFFSET textDiceKeySpace, 1
add kx, eax
invoke DrawKeycap3D, kx, 192, OFFSET textKeyEsc, 0
ret
RenderDiceGame ENDP
; ==============================================================================
; IN-ENGINE 2.5D MINI-GAME: SKULLS & CUPS (<28><>Ϩ<EFBFBD><CFA8><EFBFBD><EFBFBD><EFBFBD>)
; ==============================================================================
DrawGlowingOrb PROC uses ebx esi edi, cxVal:DWORD, cyVal:DWORD
invoke DrawCircle, cxVal, cyVal, 14, 002E1E08h
invoke DrawCircle, cxVal, cyVal, 11, 00583A10h
invoke DrawCircle, cxVal, cyVal, 8, 008A581Ah
invoke DrawCircle, cxVal, cyVal, 6, 00D0B000h
invoke DrawCircle, cxVal, cyVal, 4, 00FFE000h
mov eax, cxVal
dec eax
mov edx, cyVal
dec edx
invoke DrawCircle, eax, edx, 2, 00FFFF80h
dec eax
dec edx
invoke DrawPixel, eax, edx, 00FFFFFFh
ret
DrawGlowingOrb ENDP
DrawGothicCup PROC uses ebx esi edi, x:DWORD, y:DWORD, cupId:DWORD, isLifted:DWORD, hasBall:DWORD
local liftY:DWORD
mov eax, y
cmp isLifted, 0
je @F
sub eax, 36
@@:
mov liftY, eax
; Drop shadow
cmp isLifted, 0
jne cup_shadow_lifted
mov eax, x
add eax, 6
mov edx, y
add edx, 42
invoke DrawBox, eax, edx, 36, 4, 0010040Ah
jmp cup_ball_check
cup_shadow_lifted:
mov eax, x
add eax, 10
mov edx, y
add edx, 42
invoke DrawBox, eax, edx, 28, 2, 001A0612h
cup_ball_check:
cmp isLifted, 0
je cup_body_draw
cmp hasBall, 0
je cup_body_draw
mov eax, x
add eax, 24
mov edx, y
add edx, 26
invoke DrawGlowingOrb, eax, edx
cup_body_draw:
; Base pedestal
mov eax, x
add eax, 6
mov edx, liftY
add edx, 36
invoke DrawBoxBorder, eax, edx, 36, 6, 00301A22h, 00D0B000h, 1
; Stem
mov eax, x
add eax, 18
mov edx, liftY
add edx, 28
invoke DrawBox, eax, edx, 12, 8, 00452533h
mov eax, x
add eax, 22
invoke DrawBox, eax, edx, 4, 8, 006E4055h
; Goblet Bowl
mov eax, x
add eax, 8
mov edx, liftY
add edx, 8
invoke DrawBoxBorder, eax, edx, 32, 20, 00401E2Dh, 00FFD700h, 1
mov eax, x
add eax, 14
mov edx, liftY
add edx, 10
invoke DrawBox, eax, edx, 6, 16, 00703550h
mov eax, x
add eax, 17
invoke DrawBox, eax, edx, 3, 16, 00A05078h
; Golden Rim
mov eax, x
add eax, 4
mov edx, liftY
add edx, 2
invoke DrawBoxBorder, eax, edx, 40, 7, 00200A15h, 00FFFF00h, 1
mov eax, x
add eax, 12
mov edx, liftY
add edx, 4
invoke DrawBox, eax, edx, 16, 2, 00FFFF00h
; Skull face emblem
mov eax, x
add eax, 21
mov edx, liftY
add edx, 12
invoke DrawBox, eax, edx, 6, 5, 00FFD700h
mov eax, x
add eax, 22
mov edx, liftY
add edx, 17
invoke DrawBox, eax, edx, 4, 3, 00FFD700h
mov eax, x
add eax, 22
mov edx, liftY
add edx, 14
invoke DrawPixel, eax, edx, 00200A15h
mov eax, x
add eax, 24
invoke DrawPixel, eax, edx, 00200A15h
; Cup number label
mov eax, x
add eax, 21
mov edx, liftY
add edx, 24
mov ecx, cupId
add ecx, '1'
invoke DrawChar8x8, eax, edx, ecx, 00FFFF00h
ret
DrawGothicCup ENDP
InitSkullsGame PROC
mov skulls3d_state, 0
mov skulls3d_timer, 0
mov skulls3d_win, 0
invoke RandomRange3D, 3
mov skulls3d_ballPos, eax
mov skulls3d_choice, 1
ret
InitSkullsGame ENDP
FinalizeSkullsGuess PROC uses ebx
mov eax, skulls3d_choice
cmp eax, skulls3d_ballPos
jne skulls_guess_wrong
; Won! 3x payout
mov eax, skulls3d_bet
imul eax, 3
add bankroll, eax
mov skulls3d_win, eax
mov skulls3d_state, 4
invoke PlaySoundA, OFFSET soundJackpot, 0, 1
ret
skulls_guess_wrong:
mov skulls3d_win, 0
mov skulls3d_state, 4
invoke PlaySoundA, OFFSET soundLose, 0, 1
ret
FinalizeSkullsGuess ENDP
HandleSkullsInput PROC
cmp skulls3d_state, 0
je skulls_handle_idle
cmp skulls3d_state, 1
je skulls_handle_show
cmp skulls3d_state, 2
je skulls_handle_shuffle
cmp skulls3d_state, 3
je skulls_handle_pick
cmp skulls3d_state, 4
je skulls_handle_reveal
ret
skulls_handle_idle:
invoke Pressed3D, 26h ; UP
test eax, eax
jnz skulls_bet_up
invoke Pressed3D, 57h ; 'W'
test eax, eax
jnz skulls_bet_up
invoke Pressed3D, 28h ; DOWN
test eax, eax
jnz skulls_bet_down
invoke Pressed3D, 53h ; 'S'
test eax, eax
jnz skulls_bet_down
invoke Pressed3D, 20h ; SPACE
test eax, eax
jnz skulls_start_game
ret
skulls_bet_up:
mov eax, skulls3d_bet
add eax, 50
cmp eax, bankroll
jle @F
mov eax, bankroll
@@:
cmp eax, 5000
jle @F
mov eax, 5000
@@:
mov skulls3d_bet, eax
invoke PlaySoundA, OFFSET soundClick, 0, 1
ret
skulls_bet_down:
mov eax, skulls3d_bet
sub eax, 50
cmp eax, 50
jge @F
mov eax, 50
@@:
mov skulls3d_bet, eax
invoke PlaySoundA, OFFSET soundClick, 0, 1
ret
skulls_start_game:
mov eax, skulls3d_bet
cmp eax, bankroll
jle @F
mov eax, bankroll
mov skulls3d_bet, eax
test eax, eax
jz skulls_done
@@:
mov eax, skulls3d_bet
sub bankroll, eax
invoke RandomRange3D, 3
mov skulls3d_ballPos, eax
mov skulls3d_state, 1
mov skulls3d_timer, 45
invoke PlaySoundA, OFFSET soundShuffle, 0, 1
ret
skulls_handle_show:
dec skulls3d_timer
cmp skulls3d_timer, 0
jg skulls_done
mov skulls3d_state, 2
mov skulls3d_timer, 60
invoke PlaySoundA, OFFSET soundShuffle, 0, 1
ret
skulls_handle_shuffle:
dec skulls3d_timer
cmp skulls3d_timer, 0
jg skulls_done
invoke RandomRange3D, 3
mov skulls3d_ballPos, eax
mov skulls3d_state, 3
ret
skulls_handle_pick:
invoke Pressed3D, 31h ; '1'
test eax, eax
jnz skulls_pick_1
invoke Pressed3D, 32h ; '2'
test eax, eax
jnz skulls_pick_2
invoke Pressed3D, 33h ; '3'
test eax, eax
jnz skulls_pick_3
ret
skulls_pick_1:
mov skulls3d_choice, 0
call FinalizeSkullsGuess
ret
skulls_pick_2:
mov skulls3d_choice, 1
call FinalizeSkullsGuess
ret
skulls_pick_3:
mov skulls3d_choice, 2
call FinalizeSkullsGuess
ret
skulls_handle_reveal:
invoke Pressed3D, 20h
test eax, eax
jz skulls_done
mov skulls3d_state, 0
invoke PlaySoundA, OFFSET soundClick, 0, 1
skulls_done:
ret
HandleSkullsInput ENDP
RenderSkullsGame PROC uses ebx esi edi
local kx:DWORD
; Mahogany & Gothic Purple table
invoke DrawBox, 0, 0, 320, 240, 00140906h
invoke DrawBoxBorder, 6, 6, 308, 228, 00300F22h, 00FFD700h, 2
; Header
invoke DrawBoxBorder, 20, 12, 280, 26, 001A0812h, 00FFD700h, 2
invoke DrawString8x8, 40, 21, OFFSET textSkullsTitle, 00FFFF00h
; Status
invoke DrawBoxBorder, 20, 44, 110, 18, 001A0812h, 00452033h, 1
invoke DrawString8x8, 24, 49, OFFSET textBankPrompt, 003CFF3Ch
invoke FormatNumber, bankroll, OFFSET hudNumBuffer
invoke DrawString8x8, 72, 49, OFFSET hudNumBuffer, 003CFF3Ch
invoke DrawBoxBorder, 190, 44, 110, 18, 001A0812h, 00452033h, 1
invoke DrawString8x8, 194, 49, OFFSET textBetPrompt, 00FFD700h
invoke FormatNumber, skulls3d_bet, OFFSET hudNumBuffer
invoke DrawString8x8, 254, 49, OFFSET hudNumBuffer, 00FFD700h
; Subtitle phase prompts
cmp skulls3d_state, 0
jne @F
invoke DrawString8x8, 56, 62, OFFSET textSkullsPhase0, 00FFD700h
jmp skulls_render_cups
@@:
cmp skulls3d_state, 1
jne @F
invoke DrawString8x8, 56, 62, OFFSET textSkullsPhase1, 00FFFF00h
jmp skulls_render_cups
@@:
cmp skulls3d_state, 2
jne @F
invoke DrawString8x8, 56, 62, OFFSET textSkullsPhase2, 00FFFF00h
jmp skulls_render_cups
@@:
cmp skulls3d_state, 3
jne @F
invoke DrawString8x8, 40, 62, OFFSET textSkullsPhase3, 00FFFF00h
jmp skulls_render_cups
@@:
; Reveal outcome
mov eax, skulls3d_win
test eax, eax
jz skulls_show_loss_text
invoke DrawString8x8, 40, 62, OFFSET textSkullsWin, 003CFF3Ch
invoke FormatNumber, skulls3d_win, OFFSET hudNumBuffer
invoke DrawString8x8, 136, 62, OFFSET hudNumBuffer, 003CFF3Ch
invoke DrawString8x8, 168, 62, OFFSET textSkullsWinMult, 003CFF3Ch
jmp skulls_render_cups
skulls_show_loss_text:
invoke DrawString8x8, 40, 62, OFFSET textSkullsLose, 00FF6464h
skulls_render_cups:
; Draw Cup 1 (X=36, Y=114)
mov ebx, 0
mov edx, 0
cmp skulls3d_state, 1
jne @F
cmp skulls3d_ballPos, 0
jne @F
mov ebx, 1
mov edx, 1
@@:
cmp skulls3d_state, 4
jne @F
cmp skulls3d_choice, 0
sete bl
cmp skulls3d_ballPos, 0
sete dl
@@:
invoke DrawGothicCup, 36, 114, 0, ebx, edx
; Draw Cup 2 (X=136, Y=114)
mov ebx, 0
mov edx, 0
cmp skulls3d_state, 1
jne @F
cmp skulls3d_ballPos, 1
jne @F
mov ebx, 1
mov edx, 1
@@:
cmp skulls3d_state, 4
jne @F
cmp skulls3d_choice, 1
sete bl
cmp skulls3d_ballPos, 1
sete dl
@@:
invoke DrawGothicCup, 136, 114, 1, ebx, edx
; Draw Cup 3 (X=236, Y=114)
mov ebx, 0
mov edx, 0
cmp skulls3d_state, 1
jne @F
cmp skulls3d_ballPos, 2
jne @F
mov ebx, 1
mov edx, 1
@@:
cmp skulls3d_state, 4
jne @F
cmp skulls3d_choice, 2
sete bl
cmp skulls3d_ballPos, 2
sete dl
@@:
invoke DrawGothicCup, 236, 114, 2, ebx, edx
; Cup selection indicators
invoke DrawString8x8, 54, 168, OFFSET textSkullsKey1, 00D0D8E0h
invoke DrawString8x8, 150, 168, OFFSET textSkullsKey2, 00D0D8E0h
invoke DrawString8x8, 250, 168, OFFSET textSkullsKey3, 00D0D8E0h
; Keycaps
mov kx, 16
xor eax, eax
cmp skulls3d_choice, 0
sete al
invoke DrawKeycap3D, kx, 192, OFFSET textSkullsKey1, eax
add kx, eax
xor eax, eax
cmp skulls3d_choice, 1
sete al
invoke DrawKeycap3D, kx, 192, OFFSET textSkullsKey2, eax
add kx, eax
xor eax, eax
cmp skulls3d_choice, 2
sete al
invoke DrawKeycap3D, kx, 192, OFFSET textSkullsKey3, eax
add kx, eax
invoke DrawKeycap3D, kx, 192, OFFSET textSkullsKeySpace, 1
add kx, eax
invoke DrawKeycap3D, kx, 192, OFFSET textKeyEsc, 0
ret
RenderSkullsGame ENDP
; ==============================================================================
; IN-ENGINE 2.5D MINI-GAME: SKILL CHECK (DEAD BY DAYLIGHT SURVIVOR CHECK)
; ==============================================================================
InitSkillGame PROC
mov skill3d_state, 0
mov skill3d_timer, 0
mov skill3d_hits, 0
mov skill3d_misses, 0
mov skill3d_needle, 55
mov skill3d_speed, 4
mov skill3d_dir, 1
mov skill3d_last_result, 0
mov skill3d_win_amount, 0
; Randomize initial zone: 80 + RandomRange(90) -> 80..170
invoke RandomRange3D, 90
add eax, 80
mov skill3d_zone_start, eax
; Great zone: start + 20 + RandomRange(12)
invoke RandomRange3D, 12
add eax, skill3d_zone_start
add eax, 20
mov skill3d_great_start, eax
ret
InitSkillGame ENDP
HandleSkillInput PROC uses ebx esi
mov eax, skill3d_state
cmp eax, 0
je skill_handle_ready
cmp eax, 1
je skill_handle_active
cmp eax, 2
je skill_handle_round_wait
cmp eax, 3
je skill_handle_round_wait
cmp eax, 4
je skill_handle_end_wait
cmp eax, 5
je skill_handle_end_wait
ret
skill_handle_ready:
invoke Pressed3D, 26h ; UP
test eax, eax
jnz skill_bet_up
invoke Pressed3D, 57h ; 'W'
test eax, eax
jnz skill_bet_up
invoke Pressed3D, 28h ; DOWN
test eax, eax
jnz skill_bet_down
invoke Pressed3D, 53h ; 'S'
test eax, eax
jnz skill_bet_down
jmp skill_check_start
skill_bet_up:
mov eax, skill3d_bet
add eax, 50
cmp eax, bankroll
jle @F
mov eax, bankroll
@@:
cmp eax, 5000
jle @F
mov eax, 5000
@@:
mov skill3d_bet, eax
invoke PlaySoundA, OFFSET soundClick, 0, 1
ret
skill_bet_down:
mov eax, skill3d_bet
sub eax, 50
cmp eax, 50
jge @F
mov eax, 50
@@:
mov skill3d_bet, eax
invoke PlaySoundA, OFFSET soundClick, 0, 1
ret
skill_check_start:
invoke Pressed3D, 20h ; SPACE
test eax, eax
jz skill_input_done
; Deduct bet on game start if beginning of run
mov eax, skill3d_hits
or eax, skill3d_misses
jnz @F
mov eax, skill3d_bet
cmp eax, bankroll
jle skill_has_funds
mov eax, bankroll
mov skill3d_bet, eax
test eax, eax
jz skill_input_done
skill_has_funds:
mov eax, skill3d_bet
sub bankroll, eax
@@:
mov skill3d_state, 1
mov skill3d_needle, 55
mov skill3d_dir, 1
invoke PlaySoundA, OFFSET soundClick, 0, 1
ret
skill_handle_active:
; Move needle smoothly
mov eax, skill3d_needle
mov edx, skill3d_speed
cmp skill3d_dir, 1
je skill_move_right
sub eax, edx
cmp eax, 52
jge skill_update_needle
mov eax, 52
mov skill3d_dir, 1
jmp skill_update_needle
skill_move_right:
add eax, edx
cmp eax, 268
jle skill_update_needle
mov eax, 268
mov skill3d_dir, -1
skill_update_needle:
mov skill3d_needle, eax
; Check SPACE pressed (Reaction Hit Attempt!)
invoke Pressed3D, 20h
test eax, eax
jz skill_input_done
; Is needle in Great Sweet Spot?
mov eax, skill3d_needle
mov edx, skill3d_great_start
cmp eax, edx
jl check_success_zone
add edx, skill3d_great_width
cmp eax, edx
jg check_success_zone
; GREAT HIT!
mov skill3d_last_result, 2
add skill3d_hits, 2
mov skill3d_state, 2
mov skill3d_timer, 40
invoke PlaySoundA, OFFSET soundCoinDing, 0, 1
jmp skill_check_finish_round
check_success_zone:
mov eax, skill3d_needle
mov edx, skill3d_zone_start
cmp eax, edx
jl skill_was_miss
add edx, skill3d_zone_width
cmp eax, edx
jg skill_was_miss
; NORMAL HIT!
mov skill3d_last_result, 1
inc skill3d_hits
mov skill3d_state, 2
mov skill3d_timer, 40
invoke PlaySoundA, OFFSET soundVictory, 0, 1
jmp skill_check_finish_round
skill_was_miss:
; MISS!
mov skill3d_last_result, 0
inc skill3d_misses
mov skill3d_state, 3
mov skill3d_timer, 45
invoke PlaySoundA, OFFSET soundLose, 0, 1
skill_check_finish_round:
cmp skill3d_hits, 5
jge skill_game_escaped
cmp skill3d_misses, 3
jge skill_game_lost
ret
skill_game_escaped:
mov skill3d_state, 4
mov skill3d_timer, 0
; Payout: 3x total return (+$2x bet profit)
mov eax, skill3d_bet
imul eax, 3
add bankroll, eax
mov eax, skill3d_bet
shl eax, 1
mov skill3d_win_amount, eax
invoke PlaySoundA, OFFSET soundJackpot, 0, 1
ret
skill_game_lost:
mov skill3d_state, 5
mov skill3d_timer, 0
invoke PlaySoundA, OFFSET soundLose, 0, 1
ret
skill_handle_round_wait:
dec skill3d_timer
cmp skill3d_timer, 0
jg skill_input_done
; Next round setup
invoke RandomRange3D, 90
add eax, 80
mov skill3d_zone_start, eax
invoke RandomRange3D, 12
add eax, skill3d_zone_start
add eax, 20
mov skill3d_great_start, eax
mov eax, skill3d_hits
shr eax, 1
add eax, 4
mov skill3d_speed, eax
mov skill3d_state, 1
ret
skill_handle_end_wait:
invoke Pressed3D, 20h
test eax, eax
jz skill_input_done
call InitSkillGame
ret
skill_input_done:
ret
HandleSkillInput ENDP
RenderSkillGame PROC uses ebx esi edi
local kx:DWORD
local tx:DWORD
; Industrial Steel bezel
invoke DrawBox, 0, 0, 320, 240, 00121416h
invoke DrawBoxBorder, 6, 6, 308, 228, 001A1D20h, 00FFD700h, 2
; Header
invoke DrawBoxBorder, 20, 12, 280, 26, 00121418h, 00FFD700h, 2
invoke DrawString8x8, 40, 21, OFFSET textSkillTitle, 00FFFF00h
; Status
invoke DrawBoxBorder, 20, 44, 110, 18, 00121418h, 002A3540h, 1
invoke DrawString8x8, 24, 49, OFFSET textBankPrompt, 003CFF3Ch
invoke FormatNumber, bankroll, OFFSET hudNumBuffer
invoke DrawString8x8, 72, 49, OFFSET hudNumBuffer, 003CFF3Ch
invoke DrawBoxBorder, 190, 44, 110, 18, 00121418h, 002A3540h, 1
invoke DrawString8x8, 194, 49, OFFSET textBetPrompt, 00FFD700h
invoke FormatNumber, skill3d_bet, OFFSET hudNumBuffer
invoke DrawString8x8, 254, 49, OFFSET hudNumBuffer, 00FFD700h
; Survivor Progress
invoke DrawString8x8, 24, 70, OFFSET textSkillHitsHdr, 003CFF3Ch
invoke FormatNumber, skill3d_hits, OFFSET hudNumBuffer
invoke DrawString8x8, 64, 70, OFFSET hudNumBuffer, 003CFF3Ch
invoke DrawString8x8, 180, 70, OFFSET textSkillMissHdr, 00FF6464h
invoke FormatNumber, skill3d_misses, OFFSET hudNumBuffer
invoke DrawString8x8, 240, 70, OFFSET hudNumBuffer, 00FF6464h
; Dial Frame (Track: X=50..270, Y=102..134)
invoke DrawBoxBorder, 50, 102, 220, 32, 000F1114h, 00404855h, 2
; Calibrated ticks
mov tx, 60
skill_ticks_loop:
cmp tx, 260
jge skill_draw_zones
invoke DrawBox, tx, 104, 1, 6, 00303845h
invoke DrawBox, tx, 126, 1, 6, 00303845h
add tx, 12
jmp skill_ticks_loop
skill_draw_zones:
; Normal Success Zone (Green)
invoke DrawBoxBorder, skill3d_zone_start, 106, skill3d_zone_width, 24, 00155020h, 003CFF3Ch, 1
; Great Zone (Gold)
invoke DrawBoxBorder, skill3d_great_start, 106, skill3d_great_width, 24, 00FFD700h, 00FFFF00h, 1
; Pointer / Needle at skill3d_needle
mov eax, skill3d_needle
dec eax
invoke DrawBox, eax, 98, 3, 40, 00FFFFFFh
mov eax, skill3d_needle
sub eax, 2
invoke DrawBox, eax, 96, 5, 2, 00FF3030h
invoke DrawBox, eax, 138, 5, 2, 00FF3030h
; Center prompts / outcome
cmp skill3d_state, 0
jne @F
invoke DrawString8x8, 52, 150, OFFSET textSkillReadyMsg, 00FFD700h
invoke DrawString8x8, 76, 166, OFFSET textSkillPrompt, 00D0D8E0h
jmp skill_render_keys
@@:
cmp skill3d_state, 1
jne @F
invoke DrawString8x8, 76, 150, OFFSET textSkillPrompt, 00FFFF00h
jmp skill_render_keys
@@:
cmp skill3d_state, 2
jne @F
cmp skill3d_last_result, 2
jne skill_normal_hit_text
invoke DrawString8x8, 36, 150, OFFSET textSkillGreatMsg, 00FFFF00h
jmp skill_render_keys
skill_normal_hit_text:
invoke DrawString8x8, 64, 150, OFFSET textSkillHitMsg, 003CFF3Ch
jmp skill_render_keys
@@:
cmp skill3d_state, 3
jne @F
invoke DrawString8x8, 88, 150, OFFSET textSkillMissMsg, 00FF6464h
jmp skill_render_keys
@@:
cmp skill3d_state, 4
jne @F
invoke DrawString8x8, 48, 150, OFFSET textSkillEscape, 003CFF3Ch
invoke FormatNumber, skill3d_win_amount, OFFSET hudNumBuffer
invoke DrawString8x8, 240, 150, OFFSET hudNumBuffer, 003CFF3Ch
invoke DrawString8x8, 64, 166, OFFSET textSkullsAgain, 00FFD700h
jmp skill_render_keys
@@:
invoke DrawString8x8, 44, 150, OFFSET textSkillLost, 00FF6464h
invoke DrawString8x8, 64, 166, OFFSET textSkullsAgain, 00FFD700h
skill_render_keys:
mov kx, 16
invoke DrawKeycap3D, kx, 192, OFFSET textSkillKeySpace, 1
add kx, eax
invoke DrawKeycap3D, kx, 192, OFFSET textSkillKeyBet, 0
add kx, eax
invoke DrawKeycap3D, kx, 192, OFFSET textKeyEsc, 0
ret
RenderSkillGame ENDP
HandlePlayerInput PROC uses ebx esi edi
local speed:DWORD
local nextX:DWORD
local nextY:DWORD
mov eax, deltaTime3D
imul eax, 200
mov speed, eax
cmp keys3D[10h], 0
je @F
shl speed, 1
@@:
mov eax, deltaTime3D
shr eax, 2
inc eax
cmp keys3D[41h], 0
jne input_turn_left
cmp keys3D[25h], 0
je input_right
input_turn_left:
sub playerAngle, eax
input_right:
cmp keys3D[44h], 0
jne input_turn_right
cmp keys3D[27h], 0
je input_forward
input_turn_right:
add playerAngle, eax
input_forward:
and playerAngle, 511
call UpdateCamera3D
xor edi, edi
cmp keys3D[57h], 0
jne input_go_forward
cmp keys3D[26h], 0
je input_back
input_go_forward:
inc edi
input_back:
cmp keys3D[53h], 0
jne input_go_back
cmp keys3D[28h], 0
je input_move
input_go_back:
dec edi
input_move:
test edi, edi
jz input_action
imul edi, speed
mov eax, playerDirX
imul edi
shrd eax, edx, 16
add eax, playerX
mov nextX, eax
mov eax, playerDirY
imul edi
shrd eax, edx, 16
add eax, playerY
mov nextY, eax
invoke CanWalk3D, nextX, playerY
test eax, eax
jz @F
mov eax, nextX
mov playerX, eax
@@:
invoke CanWalk3D, playerX, nextY
test eax, eax
jz input_action
mov eax, nextY
mov playerY, eax
input_action:
invoke Pressed3D, 45h
test eax, eax
jz @F
call Trigger3DInteraction
@@:
ret
HandlePlayerInput ENDP
CheckInteractions PROC uses ebx esi edi
local nearest:DWORD
mov nearest, 262144
mov interactTargetId, 0
mov interactPromptPtr, 0
xor esi, esi
interaction_scan:
cmp esi, NUM_SPRITES
jge interaction_done
imul edi, esi, SIZEOF SpriteObject
cmp [casinoSprites+edi].interactId, 0
je interaction_next
mov eax, [casinoSprites+edi].posX
sub eax, playerX
sar eax, 8
mov ebx, eax
imul eax, eax
mov ecx, eax
mov eax, [casinoSprites+edi].posY
sub eax, playerY
sar eax, 8
mov edx, eax
imul eax, eax
add ecx, eax
cmp ecx, nearest
jae interaction_next
; Only target objects in front of the camera.
mov eax, playerDirX
sar eax, 8
imul eax, ebx
mov ebx, playerDirY
sar ebx, 8
imul ebx, edx
add eax, ebx
cmp eax, 18000
jl interaction_next
mov nearest, ecx
mov eax, [casinoSprites+edi].interactId
mov interactTargetId, eax
mov eax, [casinoSprites+edi].promptPtr
mov interactPromptPtr, eax
interaction_next:
inc esi
jmp interaction_scan
interaction_done:
ret
CheckInteractions ENDP
; --- RenderCabinetBezel: <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><> 3D <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> ---
RenderCabinetBezel PROC uses ebx esi edi, pTitle:DWORD
; <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> 3D-<2D><><EFBFBD> <20> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD> (<28><><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>)
mov ecx, SCREEN_SIZE
xor esi, esi
dim_bezel_loop:
mov eax, [screenBuffer + esi*4]
shr eax, 1
and eax, 007F7F7Fh
mov [screenBuffer + esi*4], eax
inc esi
loop dim_bezel_loop
; <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
invoke DrawBoxBorder, 10, 14, 300, 212, 000C0E14h, 00D8BC6Ah, 2
; <20><><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD>
invoke DrawBox, 12, 16, 296, 16, 00221A10h
invoke DrawString8x8, 20, 20, pTitle, 00F5E2B0h
; <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
invoke DrawBox, 12, 210, 296, 14, 00141416h
invoke DrawString8x8, 20, 213, OFFSET textCabinetFooter, 00AAAAAAh
; <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20> <20><><EFBFBD><EFBFBD>
call Present3D
ret
RenderCabinetBezel ENDP
; --- LaunchClassicGame: <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD> <20> UI <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> ---
LaunchClassicGame PROC uses ebx esi edi, pGameProc:DWORD, gameId:DWORD, pTitle:DWORD
LOCAL rcClient[16]:BYTE
LOCAL ptScreen[8]:BYTE
LOCAL fontInfo[84]:BYTE
LOCAL conWnd:DWORD
LOCAL conW:DWORD, conH:DWORD, conX:DWORD, conY:DWORD
LOCAL viewW:DWORD, viewH:DWORD
LOCAL offsetX:DWORD, offsetY:DWORD
mov eax, gameId
mov currentGameId, eax
; 1. <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><> 3D <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
cmp pTitle, 0
je @F
invoke RenderCabinetBezel, pTitle
@@:
; 2. <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
invoke AllocConsole
test eax, eax
jz launch_ret
invoke GetStdHandle, STD_OUTPUT_HANDLE
mov hOut, eax
invoke GetStdHandle, STD_INPUT_HANDLE
mov hIn, eax
invoke SetConsoleCP, 1251
invoke SetConsoleOutputCP, 1251
cmp pTitle, 0
je @F
invoke SetConsoleTitleA, pTitle
@@:
call EnableAnsi
call ConfigureConsoleSize
; 3. <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD> Consolas Bold 16pt
lea edi, fontInfo
xor eax, eax
mov ecx, 21
rep stosd
mov dword ptr fontInfo[0], 84 ; cbSize
mov word ptr fontInfo[8], 0 ; dwFontSize.X
mov word ptr fontInfo[10], 16 ; dwFontSize.Y
mov dword ptr fontInfo[16], 700 ; FontWeight = FW_BOLD
mov word ptr fontInfo[20], 'C'
mov word ptr fontInfo[22], 'o'
mov word ptr fontInfo[24], 'n'
mov word ptr fontInfo[26], 's'
mov word ptr fontInfo[28], 'o'
mov word ptr fontInfo[30], 'l'
mov word ptr fontInfo[32], 'a'
mov word ptr fontInfo[34], 's'
mov word ptr fontInfo[36], 0
lea eax, fontInfo
invoke SetCurrentConsoleFontEx, hOut, 0, eax
; 4. <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
invoke GetConsoleWindow
mov conWnd, eax
test eax, eax
jz run_game_body
; 5. <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD> Windows <20> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>/<2F><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
invoke GetWindowLongA, conWnd, -16 ; GWL_STYLE
and eax, NOT (00C00000h or 00040000h or 00080000h or 00010000h or 00020000h)
or eax, 80000000h ; WS_POPUP
invoke SetWindowLongA, conWnd, -16, eax
; <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>/<2F><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD> <20> <20><><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD>
cmp h3DWnd, 0
je show_con_fallback
invoke SetWindowLongA, conWnd, -8, h3DWnd ; GWL_HWNDPARENT
; 6. <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
lea eax, rcClient
invoke GetClientRect, h3DWnd, eax
mov esi, dword ptr rcClient[8] ; <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
mov edi, dword ptr rcClient[12] ; <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
test esi, esi
jz show_con_fallback
test edi, edi
jz show_con_fallback
; <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> 4:3 <20><><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD> <20> Present3D
mov viewW, esi
mov eax, esi
imul eax, 3
shr eax, 2
cmp eax, edi
jle calc_view_h
mov eax, edi
imul eax, 4
xor edx, edx
mov ecx, 3
div ecx
mov viewW, eax
mov eax, edi
calc_view_h:
mov viewH, eax
mov ebx, esi
sub ebx, viewW
shr ebx, 1
mov offsetX, ebx
mov ebx, edi
sub ebx, viewH
shr ebx, 1
mov offsetY, ebx
; <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
mov dword ptr ptScreen[0], 0
mov dword ptr ptScreen[4], 0
lea eax, ptScreen
invoke ClientToScreen, h3DWnd, eax
; conW = viewW * 280 / 320 (<28><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>)
mov eax, viewW
imul eax, 280
xor edx, edx
mov ecx, 320
div ecx
mov conW, eax
; conH = viewH * 168 / 240
mov eax, viewH
imul eax, 168
xor edx, edx
mov ecx, 240
div ecx
mov conH, eax
; conX = ptScreen.x + offsetX + (viewW * 20 / 320)
mov eax, viewW
imul eax, 20
xor edx, edx
mov ecx, 320
div ecx
add eax, offsetX
add eax, dword ptr ptScreen[0]
mov conX, eax
; conY = ptScreen.y + offsetY + (viewH * 38 / 240)
mov eax, viewH
imul eax, 38
xor edx, edx
mov ecx, 240
div ecx
add eax, offsetY
add eax, dword ptr ptScreen[4]
mov conY, eax
; <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
invoke SetWindowPos, conWnd, 0, conX, conY, conW, conH, 20h or 40h ; SWP_FRAMECHANGED | SWP_SHOWWINDOW
jmp set_con_focus
show_con_fallback:
invoke ShowWindow, conWnd, 5 ; SW_SHOW
set_con_focus:
invoke SetForegroundWindow, conWnd
invoke SetFocus, conWnd
run_game_body:
; <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD>!
call pGameProc
; <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
invoke FreeConsole
mov hOut, 0
mov hIn, 0
; <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD> <20> <20><><EFBFBD><EFBFBD> 3D <20><><EFBFBD><EFBFBD>
cmp h3DWnd, 0
je cleanup_game_input
invoke SetForegroundWindow, h3DWnd
invoke SetFocus, h3DWnd
cleanup_game_input:
mov ecx, 256
xor eax, eax
lea edi, keys3D
rep stosb
mov ecx, 256
lea edi, pressedKeys3D
rep stosb
invoke GetTickCount
mov previousTick3D, eax
mov frameStart3D, eax
mov deltaTime3D, 0
call SaveProgress3D
launch_ret:
ret
LaunchClassicGame ENDP
Trigger3DInteraction PROC
mov eax, interactTargetId
test eax, eax
jz trigger_done
cmp eax, INTERACT_DANCER
jne check_target_bj
cmp bankroll, 100
jl dancer_no_cash
sub bankroll, 100
inc dancerLuckBuff
invoke CopyString3D, OFFSET textTips3D, OFFSET flashMessage
mov flashTimer, 100
invoke PlaySoundA, OFFSET soundJackpot, 0, 1
ret
dancer_no_cash:
invoke CopyString3D, OFFSET msgNeedMoney, OFFSET flashMessage
mov flashTimer, 60
ret
check_target_bj:
cmp eax, INTERACT_BLACKJACK
jne check_target_poker
invoke LaunchClassicGame, OFFSET Game21, 1, OFFSET szTitleBlackjack
ret
check_target_poker:
cmp eax, INTERACT_POKER
jne check_target_durak
invoke LaunchClassicGame, OFFSET GamePoker, 2, OFFSET szTitlePoker
ret
check_target_durak:
cmp eax, INTERACT_DURAK
jne check_target_slots777
invoke LaunchClassicGame, OFFSET GameDurak, 10, OFFSET szTitleDurak
ret
check_target_slots777:
cmp eax, INTERACT_SLOTS_777
jne check_target_slots_clover
invoke LaunchClassicGame, OFFSET GameClassicSlot, 9, OFFSET szTitleClassicSlot
ret
check_target_slots_clover:
cmp eax, INTERACT_SLOTS_CLOVER
jne check_target_roulette
invoke LaunchClassicGame, OFFSET GameSlot, 3, OFFSET szTitleCloverSlot
ret
check_target_roulette:
cmp eax, INTERACT_ROULETTE
jne check_target_dice
invoke LaunchClassicGame, OFFSET GameCasinoRoulette, 8, OFFSET szTitleCasinoRoulette
ret
check_target_dice:
cmp eax, INTERACT_DICE
jne check_target_skulls
call InitDiceGame
mov engineMode, MODE_DICE
ret
check_target_skulls:
cmp eax, INTERACT_SKULLS
jne check_target_coin
call InitSkullsGame
mov engineMode, MODE_SKULLS
ret
check_target_coin:
cmp eax, INTERACT_COIN
jne check_target_skill
call InitCoinGame
mov engineMode, MODE_COIN
ret
check_target_skill:
cmp eax, INTERACT_SKILL_CHECK
jne check_target_buckshot
call InitSkillGame
mov engineMode, MODE_SKILL
ret
check_target_buckshot:
cmp eax, INTERACT_BUCKSHOT
jne check_target_rr
invoke LaunchClassicGame, OFFSET GameBuckshot, 13, OFFSET szTitleBuckshot
ret
check_target_rr:
cmp eax, INTERACT_RUSSIAN_ROULETTE
jne check_target_online_rr
invoke LaunchClassicGame, OFFSET GameRoulette, 4, OFFSET szTitleRussianRoulette
ret
check_target_online_rr:
cmp eax, INTERACT_ONLINE_RR
jne check_target_umamusume
invoke LaunchClassicGame, OFFSET GameOnlineCasino, 20, OFFSET szTitleOnlineRR
ret
check_target_umamusume:
cmp eax, INTERACT_UMAMUSUME
jne check_target_hell
invoke LaunchClassicGame, OFFSET GameUmamusume, 21, OFFSET szTitleUmamusume
ret
check_target_hell:
cmp eax, INTERACT_HELL_TOWER
jne check_target_shop
invoke LaunchClassicGame, OFFSET GameTournament, 666, OFFSET szTitleHellTower
ret
check_target_shop:
cmp eax, INTERACT_SHOP
jne check_target_atm
invoke LaunchClassicGame, OFFSET GameShop, 0, OFFSET szTitleShop
ret
check_target_atm:
cmp eax, INTERACT_ATM
jne check_target_terminal
mov engineMode, MODE_ATM
ret
check_target_terminal:
cmp eax, INTERACT_TERMINAL
jne check_target_observer
invoke LaunchClassicGame, OFFSET GamePlayerTerminal, 0, OFFSET szTitleTerminal
ret
check_target_observer:
cmp eax, INTERACT_OBSERVER
jne target_unported
invoke LaunchClassicGame, OFFSET GameObserver, 14, OFFSET szTitleObserver
ret
target_unported:
invoke CopyString3D, OFFSET textUnavailable3D, OFFSET flashMessage
mov flashTimer, 150
trigger_done:
ret
Trigger3DInteraction ENDP
; --- Engine Initialization ---
Init3DEngine PROC
local screenCX:DWORD
local screenCY:DWORD
local posX:DWORD
local posY:DWORD
local bytesRead:DWORD
push ebx
push esi
push edi
call Create3DWindow
test eax, eax
jz init_failed
call LoadTextures3D
test eax, eax
jz init_failed
init_sprites_table:
; Sprite 0: VIP Dancer 1 (Stage Left)
mov casinoSprites[0*SIZEOF SpriteObject].posX, (13 * FP_1 + FP_HALF)
mov casinoSprites[0*SIZEOF SpriteObject].posY, (4 * FP_1)
mov casinoSprites[0*SIZEOF SpriteObject].baseTexId, 10
mov casinoSprites[0*SIZEOF SpriteObject].frameCount, 12
mov casinoSprites[0*SIZEOF SpriteObject].curFrame, 0
mov casinoSprites[0*SIZEOF SpriteObject].animTimer, 0
mov casinoSprites[0*SIZEOF SpriteObject].animSpeed, 5
mov casinoSprites[0*SIZEOF SpriteObject].interactId, INTERACT_DANCER
mov casinoSprites[0*SIZEOF SpriteObject].promptPtr, OFFSET promptDancer
; Sprite 1: VIP Dancer 2 (Center Stage Star)
mov casinoSprites[1*SIZEOF SpriteObject].posX, (16 * FP_1 + FP_HALF)
mov casinoSprites[1*SIZEOF SpriteObject].posY, (3 * FP_1 + FP_HALF)
mov casinoSprites[1*SIZEOF SpriteObject].baseTexId, 10
mov casinoSprites[1*SIZEOF SpriteObject].frameCount, 12
mov casinoSprites[1*SIZEOF SpriteObject].curFrame, 2
mov casinoSprites[1*SIZEOF SpriteObject].animTimer, 0
mov casinoSprites[1*SIZEOF SpriteObject].animSpeed, 5
mov casinoSprites[1*SIZEOF SpriteObject].interactId, INTERACT_DANCER
mov casinoSprites[1*SIZEOF SpriteObject].promptPtr, OFFSET promptDancer
; Sprite 2: VIP Dancer 3 (Stage Right)
mov casinoSprites[2*SIZEOF SpriteObject].posX, (19 * FP_1 + FP_HALF)
mov casinoSprites[2*SIZEOF SpriteObject].posY, (4 * FP_1)
mov casinoSprites[2*SIZEOF SpriteObject].baseTexId, 10
mov casinoSprites[2*SIZEOF SpriteObject].frameCount, 12
mov casinoSprites[2*SIZEOF SpriteObject].curFrame, 1
mov casinoSprites[2*SIZEOF SpriteObject].animTimer, 0
mov casinoSprites[2*SIZEOF SpriteObject].animSpeed, 5
mov casinoSprites[2*SIZEOF SpriteObject].interactId, INTERACT_DANCER
mov casinoSprites[2*SIZEOF SpriteObject].promptPtr, OFFSET promptDancer
; Sprite 3: VIP Blackjack (Front Center Left)
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].baseTexId, 30
mov casinoSprites[3*SIZEOF SpriteObject].frameCount, 1
mov casinoSprites[3*SIZEOF SpriteObject].curFrame, 0
mov casinoSprites[3*SIZEOF SpriteObject].animTimer, 0
mov casinoSprites[3*SIZEOF SpriteObject].animSpeed, 1
mov casinoSprites[3*SIZEOF SpriteObject].interactId, INTERACT_BLACKJACK
mov casinoSprites[3*SIZEOF SpriteObject].promptPtr, OFFSET promptBlackjack
; Sprite 4: European Roulette Table (Front Center)
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].baseTexId, 31
mov casinoSprites[4*SIZEOF SpriteObject].frameCount, 1
mov casinoSprites[4*SIZEOF SpriteObject].curFrame, 0
mov casinoSprites[4*SIZEOF SpriteObject].animTimer, 0
mov casinoSprites[4*SIZEOF SpriteObject].animSpeed, 1
mov casinoSprites[4*SIZEOF SpriteObject].interactId, INTERACT_ROULETTE
mov casinoSprites[4*SIZEOF SpriteObject].promptPtr, OFFSET promptCasinoRoulette
; Sprite 5: Texas Hold'em Poker Table (Front Center Right)
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].baseTexId, 30
mov casinoSprites[5*SIZEOF SpriteObject].frameCount, 1
mov casinoSprites[5*SIZEOF SpriteObject].curFrame, 0
mov casinoSprites[5*SIZEOF SpriteObject].animTimer, 0
mov casinoSprites[5*SIZEOF SpriteObject].animSpeed, 1
mov casinoSprites[5*SIZEOF SpriteObject].interactId, INTERACT_POKER
mov casinoSprites[5*SIZEOF SpriteObject].promptPtr, OFFSET promptPoker
; Sprite 6: Podkidnoy Durak Card Table
mov casinoSprites[6*SIZEOF SpriteObject].posX, (24 * FP_1 + FP_HALF)
mov casinoSprites[6*SIZEOF SpriteObject].posY, (8 * FP_1)
mov casinoSprites[6*SIZEOF SpriteObject].baseTexId, 30
mov casinoSprites[6*SIZEOF SpriteObject].frameCount, 1
mov casinoSprites[6*SIZEOF SpriteObject].curFrame, 0
mov casinoSprites[6*SIZEOF SpriteObject].animTimer, 0
mov casinoSprites[6*SIZEOF SpriteObject].animSpeed, 1
mov casinoSprites[6*SIZEOF SpriteObject].interactId, INTERACT_DURAK
mov casinoSprites[6*SIZEOF SpriteObject].promptPtr, OFFSET promptDurak
; Sprite 7: Classic Slots 777 (West Arcade 1)
mov casinoSprites[7*SIZEOF SpriteObject].posX, (6 * FP_1)
mov casinoSprites[7*SIZEOF SpriteObject].posY, (8 * FP_1)
mov casinoSprites[7*SIZEOF SpriteObject].baseTexId, 24
mov casinoSprites[7*SIZEOF SpriteObject].frameCount, 3
mov casinoSprites[7*SIZEOF SpriteObject].curFrame, 0
mov casinoSprites[7*SIZEOF SpriteObject].animTimer, 0
mov casinoSprites[7*SIZEOF SpriteObject].animSpeed, 8
mov casinoSprites[7*SIZEOF SpriteObject].interactId, INTERACT_SLOTS_777
mov casinoSprites[7*SIZEOF SpriteObject].promptPtr, OFFSET promptClassicSlot
; Sprite 8: CloverPit Slots 5x3 (West Arcade 2)
mov casinoSprites[8*SIZEOF SpriteObject].posX, (6 * FP_1)
mov casinoSprites[8*SIZEOF SpriteObject].posY, (11 * FP_1)
mov casinoSprites[8*SIZEOF SpriteObject].baseTexId, 24
mov casinoSprites[8*SIZEOF SpriteObject].frameCount, 3
mov casinoSprites[8*SIZEOF SpriteObject].curFrame, 1
mov casinoSprites[8*SIZEOF SpriteObject].animTimer, 0
mov casinoSprites[8*SIZEOF SpriteObject].animSpeed, 8
mov casinoSprites[8*SIZEOF SpriteObject].interactId, INTERACT_SLOTS_CLOVER
mov casinoSprites[8*SIZEOF SpriteObject].promptPtr, OFFSET promptCloverSlot
; Sprite 9: Craps & Dice Table (West Arcade 3)
mov casinoSprites[9*SIZEOF SpriteObject].posX, (6 * FP_1)
mov casinoSprites[9*SIZEOF SpriteObject].posY, (14 * FP_1)
mov casinoSprites[9*SIZEOF SpriteObject].baseTexId, 30
mov casinoSprites[9*SIZEOF SpriteObject].frameCount, 1
mov casinoSprites[9*SIZEOF SpriteObject].curFrame, 0
mov casinoSprites[9*SIZEOF SpriteObject].animTimer, 0
mov casinoSprites[9*SIZEOF SpriteObject].animSpeed, 1
mov casinoSprites[9*SIZEOF SpriteObject].interactId, INTERACT_DICE
mov casinoSprites[9*SIZEOF SpriteObject].promptPtr, OFFSET promptDice
; Sprite 10: Skulls & Cups Table
mov casinoSprites[10*SIZEOF SpriteObject].posX, (10 * FP_1)
mov casinoSprites[10*SIZEOF SpriteObject].posY, (15 * FP_1)
mov casinoSprites[10*SIZEOF SpriteObject].baseTexId, 30
mov casinoSprites[10*SIZEOF SpriteObject].frameCount, 1
mov casinoSprites[10*SIZEOF SpriteObject].curFrame, 0
mov casinoSprites[10*SIZEOF SpriteObject].animTimer, 0
mov casinoSprites[10*SIZEOF SpriteObject].animSpeed, 1
mov casinoSprites[10*SIZEOF SpriteObject].interactId, INTERACT_SKULLS
mov casinoSprites[10*SIZEOF SpriteObject].promptPtr, OFFSET promptSkulls
; Sprite 11: Coin Toss Stand
mov casinoSprites[11*SIZEOF SpriteObject].posX, (14 * FP_1)
mov casinoSprites[11*SIZEOF SpriteObject].posY, (15 * FP_1)
mov casinoSprites[11*SIZEOF SpriteObject].baseTexId, 30
mov casinoSprites[11*SIZEOF SpriteObject].frameCount, 1
mov casinoSprites[11*SIZEOF SpriteObject].curFrame, 0
mov casinoSprites[11*SIZEOF SpriteObject].animTimer, 0
mov casinoSprites[11*SIZEOF SpriteObject].animSpeed, 1
mov casinoSprites[11*SIZEOF SpriteObject].interactId, INTERACT_COIN
mov casinoSprites[11*SIZEOF SpriteObject].promptPtr, OFFSET promptCoin
; Sprite 12: Skill Check Stand
mov casinoSprites[12*SIZEOF SpriteObject].posX, (18 * FP_1)
mov casinoSprites[12*SIZEOF SpriteObject].posY, (15 * FP_1)
mov casinoSprites[12*SIZEOF SpriteObject].baseTexId, 30
mov casinoSprites[12*SIZEOF SpriteObject].frameCount, 1
mov casinoSprites[12*SIZEOF SpriteObject].curFrame, 0
mov casinoSprites[12*SIZEOF SpriteObject].animTimer, 0
mov casinoSprites[12*SIZEOF SpriteObject].animSpeed, 1
mov casinoSprites[12*SIZEOF SpriteObject].interactId, INTERACT_SKILL_CHECK
mov casinoSprites[12*SIZEOF SpriteObject].promptPtr, OFFSET promptSkillCheck
; Sprite 13: Umamusume Derby Lounge
mov casinoSprites[13*SIZEOF SpriteObject].posX, (22 * FP_1)
mov casinoSprites[13*SIZEOF SpriteObject].posY, (15 * FP_1)
mov casinoSprites[13*SIZEOF SpriteObject].baseTexId, 30
mov casinoSprites[13*SIZEOF SpriteObject].frameCount, 1
mov casinoSprites[13*SIZEOF SpriteObject].curFrame, 0
mov casinoSprites[13*SIZEOF SpriteObject].animTimer, 0
mov casinoSprites[13*SIZEOF SpriteObject].animSpeed, 1
mov casinoSprites[13*SIZEOF SpriteObject].interactId, INTERACT_UMAMUSUME
mov casinoSprites[13*SIZEOF SpriteObject].promptPtr, OFFSET promptUmamusume
; Sprite 14: Boutique & Shop (East Wing)
mov casinoSprites[14*SIZEOF SpriteObject].posX, (26 * FP_1)
mov casinoSprites[14*SIZEOF SpriteObject].posY, (12 * FP_1)
mov casinoSprites[14*SIZEOF SpriteObject].baseTexId, 32
mov casinoSprites[14*SIZEOF SpriteObject].frameCount, 1
mov casinoSprites[14*SIZEOF SpriteObject].curFrame, 0
mov casinoSprites[14*SIZEOF SpriteObject].animTimer, 0
mov casinoSprites[14*SIZEOF SpriteObject].animSpeed, 1
mov casinoSprites[14*SIZEOF SpriteObject].interactId, INTERACT_SHOP
mov casinoSprites[14*SIZEOF SpriteObject].promptPtr, OFFSET promptShop
; Sprite 15: Cashier & ATM (East Wing)
mov casinoSprites[15*SIZEOF SpriteObject].posX, (26 * FP_1)
mov casinoSprites[15*SIZEOF SpriteObject].posY, (16 * FP_1)
mov casinoSprites[15*SIZEOF SpriteObject].baseTexId, 33
mov casinoSprites[15*SIZEOF SpriteObject].frameCount, 1
mov casinoSprites[15*SIZEOF SpriteObject].curFrame, 0
mov casinoSprites[15*SIZEOF SpriteObject].animTimer, 0
mov casinoSprites[15*SIZEOF SpriteObject].animSpeed, 1
mov casinoSprites[15*SIZEOF SpriteObject].interactId, INTERACT_ATM
mov casinoSprites[15*SIZEOF SpriteObject].promptPtr, OFFSET promptATM
; Sprite 16: Player Terminal (East Wing)
mov casinoSprites[16*SIZEOF SpriteObject].posX, (26 * FP_1)
mov casinoSprites[16*SIZEOF SpriteObject].posY, (20 * FP_1)
mov casinoSprites[16*SIZEOF SpriteObject].baseTexId, 33
mov casinoSprites[16*SIZEOF SpriteObject].frameCount, 1
mov casinoSprites[16*SIZEOF SpriteObject].curFrame, 0
mov casinoSprites[16*SIZEOF SpriteObject].animTimer, 0
mov casinoSprites[16*SIZEOF SpriteObject].animSpeed, 1
mov casinoSprites[16*SIZEOF SpriteObject].interactId, INTERACT_TERMINAL
mov casinoSprites[16*SIZEOF SpriteObject].promptPtr, OFFSET promptPlayerTerminal
; Sprite 17: Buckshot Roulette (South-West)
mov casinoSprites[17*SIZEOF SpriteObject].posX, (12 * FP_1)
mov casinoSprites[17*SIZEOF SpriteObject].posY, (22 * FP_1)
mov casinoSprites[17*SIZEOF SpriteObject].baseTexId, 30
mov casinoSprites[17*SIZEOF SpriteObject].frameCount, 1
mov casinoSprites[17*SIZEOF SpriteObject].curFrame, 0
mov casinoSprites[17*SIZEOF SpriteObject].animTimer, 0
mov casinoSprites[17*SIZEOF SpriteObject].animSpeed, 1
mov casinoSprites[17*SIZEOF SpriteObject].interactId, INTERACT_BUCKSHOT
mov casinoSprites[17*SIZEOF SpriteObject].promptPtr, OFFSET promptBuckshot
; Sprite 18: Observer Lounge (South-East)
mov casinoSprites[18*SIZEOF SpriteObject].posX, (20 * FP_1)
mov casinoSprites[18*SIZEOF SpriteObject].posY, (22 * FP_1)
mov casinoSprites[18*SIZEOF SpriteObject].baseTexId, 30
mov casinoSprites[18*SIZEOF SpriteObject].frameCount, 1
mov casinoSprites[18*SIZEOF SpriteObject].curFrame, 0
mov casinoSprites[18*SIZEOF SpriteObject].animTimer, 0
mov casinoSprites[18*SIZEOF SpriteObject].animSpeed, 1
mov casinoSprites[18*SIZEOF SpriteObject].interactId, INTERACT_OBSERVER
mov casinoSprites[18*SIZEOF SpriteObject].promptPtr, OFFSET promptObserver
; Sprite 19: Russian Roulette (Backroom Entrance)
mov casinoSprites[19*SIZEOF SpriteObject].posX, (16 * FP_1)
mov casinoSprites[19*SIZEOF SpriteObject].posY, (25 * FP_1)
mov casinoSprites[19*SIZEOF SpriteObject].baseTexId, 34
mov casinoSprites[19*SIZEOF SpriteObject].frameCount, 1
mov casinoSprites[19*SIZEOF SpriteObject].curFrame, 0
mov casinoSprites[19*SIZEOF SpriteObject].animTimer, 0
mov casinoSprites[19*SIZEOF SpriteObject].animSpeed, 1
mov casinoSprites[19*SIZEOF SpriteObject].interactId, INTERACT_RUSSIAN_ROULETTE
mov casinoSprites[19*SIZEOF SpriteObject].promptPtr, OFFSET promptRussianRoulette
; Sprite 20: Online Russian Roulette (Backroom Secret Terminal)
mov casinoSprites[20*SIZEOF SpriteObject].posX, (18 * FP_1)
mov casinoSprites[20*SIZEOF SpriteObject].posY, (25 * FP_1)
mov casinoSprites[20*SIZEOF SpriteObject].baseTexId, 34
mov casinoSprites[20*SIZEOF SpriteObject].frameCount, 1
mov casinoSprites[20*SIZEOF SpriteObject].curFrame, 0
mov casinoSprites[20*SIZEOF SpriteObject].animTimer, 0
mov casinoSprites[20*SIZEOF SpriteObject].animSpeed, 1
mov casinoSprites[20*SIZEOF SpriteObject].interactId, INTERACT_ONLINE_RR
mov casinoSprites[20*SIZEOF SpriteObject].promptPtr, OFFSET promptOnlineRR
; Sprite 21: Hell Tower Portal (South Wing Deep End)
mov casinoSprites[21*SIZEOF SpriteObject].posX, (16 * FP_1 + FP_HALF)
mov casinoSprites[21*SIZEOF SpriteObject].posY, (29 * FP_1)
mov casinoSprites[21*SIZEOF SpriteObject].baseTexId, 4
mov casinoSprites[21*SIZEOF SpriteObject].frameCount, 1
mov casinoSprites[21*SIZEOF SpriteObject].curFrame, 0
mov casinoSprites[21*SIZEOF SpriteObject].animTimer, 0
mov casinoSprites[21*SIZEOF SpriteObject].animSpeed, 1
mov casinoSprites[21*SIZEOF SpriteObject].interactId, INTERACT_HELL_TOWER
mov casinoSprites[21*SIZEOF SpriteObject].promptPtr, OFFSET promptHellTower
mov eax, 1
jmp init_return
init_failed:
xor eax, eax
init_return:
pop edi
pop esi
pop ebx
ret
Init3DEngine ENDP
; --- Main Loop of the 3D Casino Engine ---
StartCasino3D PROC uses ebx esi edi
call Init3DEngine
test eax, eax
jz engine_shutdown
invoke GetTickCount
mov rngSeed3D, eax
mov previousTick3D, eax
engine_loop:
invoke PeekMessageA, OFFSET msg3D, 0, 0, 0, PM_REMOVE
test eax, eax
jz dispatch_frame
cmp msg3D.message, WM_QUIT
je engine_shutdown
invoke TranslateMessage, OFFSET msg3D
invoke DispatchMessageA, OFFSET msg3D
jmp engine_loop
dispatch_frame:
invoke GetTickCount
mov frameStart3D, eax
sub eax, previousTick3D
cmp eax, 50
jbe @F
mov eax, 50
@@:
mov deltaTime3D, eax
mov eax, frameStart3D
mov previousTick3D, eax
invoke GetForegroundWindow
cmp eax, h3DWnd
jne engine_idle
invoke IsIconic, h3DWnd
test eax, eax
jnz engine_idle
invoke Pressed3D, 7Ah
test eax, eax
jz @F
call ToggleFullscreen3D
@@:
invoke Pressed3D, 1Bh
test eax, eax
jz engine_tick
cmp engineMode, MODE_WALK
jne leave_table
xor paused3D, 1
jmp engine_tick
leave_table:
; An already paid round cannot be skipped or settled twice.
cmp slotSpinState, 1
je engine_tick
cmp roulState, 1
je engine_tick
cmp coin3d_state, 1
je engine_tick
cmp dice3d_state, 1
je engine_tick
cmp skulls3d_state, 1
je engine_tick
cmp skulls3d_state, 2
je engine_tick
cmp engineMode, MODE_SKILL
jne @F
cmp skill3d_state, 1
je engine_tick
@@:
mov engineMode, MODE_WALK
engine_tick:
cmp paused3D, 0
jne draw_pause
mov eax, deltaTime3D
add animationClock3D, eax
cmp engineMode, MODE_WALK
jne check_slots_mode
call UpdateCamera3D
call CheckInteractions
call HandlePlayerInput
call UpdateCamera3D
call RenderCeilingAndFloor
call RenderWalls
call RenderSprites
call RenderHUD
call RenderMinimap
jmp present_frame
check_slots_mode:
cmp engineMode, MODE_SLOTS
jne check_bj_mode
call HandleSlotsInput
call RenderSlotsGame
jmp present_frame
check_bj_mode:
cmp engineMode, MODE_BLACKJACK
jne check_roul_mode
call HandleBlackjackInput
call RenderBlackjackGame
jmp present_frame
check_roul_mode:
cmp engineMode, MODE_ROULETTE
jne check_shop_mode
call HandleRouletteInput
call RenderRouletteGame
jmp present_frame
check_shop_mode:
cmp engineMode, MODE_SHOP
jne check_atm_mode
call HandleShopInput
call RenderShopGame
jmp present_frame
check_atm_mode:
cmp engineMode, MODE_ATM
jne check_coin_mode
call HandleATMInput
call RenderATMGame
jmp present_frame
check_coin_mode:
cmp engineMode, MODE_COIN
jne check_dice_mode
call HandleCoinInput
call RenderCoinGame
jmp present_frame
check_dice_mode:
cmp engineMode, MODE_DICE
jne check_skulls_mode
call HandleDiceInput
call RenderDiceGame
jmp present_frame
check_skulls_mode:
cmp engineMode, MODE_SKULLS
jne check_skill_mode
call HandleSkullsInput
call RenderSkullsGame
jmp present_frame
check_skill_mode:
cmp engineMode, MODE_SKILL
jne present_frame
call HandleSkillInput
call RenderSkillGame
jmp present_frame
draw_pause:
invoke DrawBoxBorder, 65, 75, 190, 85, 00151C21h, 00D8BC6Ah, 2
invoke DrawString8x8, 86, 88, OFFSET textPause3D, 00FFFFFFh
invoke DrawString8x8, 78, 111, OFFSET textResume3D, 00D8BC6Ah
invoke DrawString8x8, 78, 131, OFFSET textQuit3D, 00BBBBBBh
invoke Pressed3D, 51h
test eax, eax
jnz engine_shutdown
present_frame:
call Present3D
lea edi, pressedKeys3D
xor eax, eax
mov ecx, 64
rep stosd
invoke GetTickCount
sub eax, frameStart3D
cmp eax, 16
jae engine_loop
mov ecx, 16
sub ecx, eax
invoke Sleep, ecx
jmp engine_loop
engine_idle:
invoke Sleep, 50
jmp engine_loop
engine_shutdown:
call SaveProgress3D
cmp h3DDC, 0
je @F
invoke ReleaseDC, h3DWnd, h3DDC
mov h3DDC, 0
@@:
cmp h3DWnd, 0
je @F
invoke DestroyWindow, h3DWnd
mov h3DWnd, 0
@@:
ret
StartCasino3D ENDP
include src_graphics\platform_code.inc