KAZIK/casino3d.inc

3009 lines
68 KiB
PHP
Raw Blame History

; ==============================================================================
; 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
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><EFBFBD><EFBFBD> <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD>.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><EFBFBD><EFBFBD><EFBFBD>.wav",0
soundClick db "assets\audio\b05e1ac8be34248.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] CABARET - TIP $100",0
promptSlot1 db "[E] SLOTS 777",0
promptSlot2 db "[E] SLOTS 777",0
promptBlackjack db "[E] BLACKJACK / 21",0
promptPoker db "POKER - UNDER CONSTRUCTION",0
promptRoulette db "[E] ROULETTE",0
promptShop db "[E] BOUTIQUE",0
promptATM db "[E] CASHIER",0
promptBackroom db "BACKROOM - UNDER CONSTRUCTION",0
promptDurak db "DURAK - UNDER CONSTRUCTION",0
promptHell db "TOWER - UNDER CONSTRUCTION",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 13
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)
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, 0000D7FFh, 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, 000000FFh
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, 0000D7FFh, 3
; Illuminated Top Marquee
invoke DrawBoxBorder, 25, 20, 270, 32, 000A0505h, 0000FFFFh, 2
invoke DrawString8x8, 55, 32, OFFSET textSlots3D, 0000D7FFh
; 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, 0000D7FFh, 1
invoke DrawString8x8, 28, 172, OFFSET textBank3D, 0000D7FFh
invoke FormatNumber, bankroll, OFFSET hudNumBuffer
invoke DrawString8x8, 110, 172, OFFSET hudNumBuffer, 0000FFFFh
invoke DrawString8x8, 175, 172, OFFSET textBet3D, 0000D7FFh
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, 0000FFFFh
invoke FormatNumber, slotWinAmount, OFFSET hudNumBuffer
invoke DrawString8x8, 110, 187, OFFSET hudNumBuffer, 0000FFFFh
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, 000000FFh
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, 0000D7FFh
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, 0000D7FFh
ret
DrawReelSymbolAt1 ENDP
DrawReelSymbolAt2 PROC
cmp eax, 0
jne @F
invoke DrawString8x8, 135, 105, OFFSET sym7, 000000FFh
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, 0000D7FFh
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, 0000D7FFh
ret
DrawReelSymbolAt2 ENDP
DrawReelSymbolAt3 PROC
cmp eax, 0
jne @F
invoke DrawString8x8, 218, 105, OFFSET sym7, 000000FFh
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, 0000D7FFh
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, 0000D7FFh
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, 0000D7FFh, 3
; Dealer Area Top
invoke DrawString8x8, 25, 20, OFFSET textBJ3D, 0000D7FFh
invoke DrawString8x8, 25, 35, OFFSET textDealer3D, 00FFFFFFh
invoke FormatNumber, bjDealerScore, OFFSET hudNumBuffer
invoke DrawString8x8, 120, 35, OFFSET hudNumBuffer, 0000FFFFh
; 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, 0000D7FFh, 1
cmp BYTE PTR [bjOutcomeMsg], 0
je draw_bj_controls
invoke DrawString8x8, 28, 188, OFFSET bjOutcomeMsg, 0000FFFFh
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, 0000D7FFh, 3
; 2.5D Rotating Wheel on Left
invoke DrawCircle, 85, 110, 65, 00102550h
invoke DrawCircle, 85, 110, 60, 0000D7FFh
invoke DrawCircle, 85, 110, 52, 00101010h
invoke DrawCircle, 85, 110, 22, 0000D7FFh ; 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, 0000FFFFh, 2
@@:
cmp roulBetType, 2
jne @F
invoke DrawBoxBorder, 173, 58, 129, 32, 0, 0000FFFFh, 2
@@:
cmp roulBetType, 3
jne @F
invoke DrawBoxBorder, 173, 93, 129, 32, 0, 0000FFFFh, 2
@@:
cmp roulBetType, 4
jne @F
invoke DrawBoxBorder, 173, 128, 64, 30, 0, 0000FFFFh, 2
@@:
cmp roulBetType, 5
jne draw_ro_footer
invoke DrawBoxBorder, 238, 128, 64, 30, 0, 0000FFFFh, 2
draw_ro_footer:
invoke DrawBoxBorder, 20, 180, 280, 42, 00101015h, 0000D7FFh, 1
cmp roulState, 2
jne @F
invoke DrawString8x8, 28, 186, OFFSET textResult3D, 0000D7FFh
invoke FormatNumber, roulWinningNum, OFFSET hudNumBuffer
invoke DrawString8x8, 85, 186, OFFSET hudNumBuffer, 0000FFFFh
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, 0000D7FFh, 3
invoke DrawString8x8, 25, 20, OFFSET textShop3D, 0000D7FFh
invoke DrawBoxBorder, 20, 40, 280, 32, 001A1010h, 00FFFFFFh, 1
invoke DrawString8x8, 28, 46, OFFSET textItem1_3D, 0000FFFFh
invoke DrawString8x8, 28, 58, OFFSET textShopHint3D, 00A0A0A0h
invoke DrawBoxBorder, 20, 80, 280, 32, 001A1010h, 00FFFFFFh, 1
invoke DrawString8x8, 28, 86, OFFSET textItem2_3D, 0000FFFFh
invoke DrawString8x8, 28, 98, OFFSET textShopHint3D, 00A0A0A0h
invoke DrawBoxBorder, 20, 120, 280, 32, 001A1010h, 00FFFFFFh, 1
invoke DrawString8x8, 28, 126, OFFSET textItem3_3D, 0000FFFFh
invoke DrawString8x8, 28, 138, OFFSET textShopHint3D, 00A0A0A0h
invoke DrawBoxBorder, 20, 165, 280, 55, 00100A0Ah, 0000D7FFh, 1
invoke DrawString8x8, 28, 172, OFFSET textBank3D, 0000D7FFh
invoke FormatNumber, bankroll, OFFSET hudNumBuffer
invoke DrawString8x8, 110, 172, OFFSET hudNumBuffer, 0000FFFFh
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
; --- Player Input & Movement Physics ---
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
Trigger3DInteraction PROC
mov eax, interactTargetId
test eax, eax
jz @F
cmp eax, 8 ; DANCER
jne check_target_slots
cmp bankroll, 100
jl dancer_no_cash
sub bankroll, 100
inc dancerLuckBuff
; Tips are cosmetic and must not silently change game odds.
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_slots:
cmp eax, 3 ; SLOTS
jne check_target_bj
mov engineMode, MODE_SLOTS
invoke PlaySoundA, OFFSET soundClick, 0, 1
ret
check_target_bj:
cmp eax, 1 ; BLACKJACK
jne check_target_roulette
mov engineMode, MODE_BLACKJACK
mov bjState, 0
ret
check_target_roulette:
cmp eax, 4 ; ROULETTE
jne check_target_shop
mov engineMode, MODE_ROULETTE
mov roulState, 0
ret
check_target_shop:
cmp eax, 6 ; SHOP
jne check_target_atm
mov engineMode, MODE_SHOP
ret
check_target_atm:
cmp eax, 7 ; ATM
jne target_unported
mov engineMode, MODE_ATM
ret
target_unported:
invoke CopyString3D, OFFSET textUnavailable3D, OFFSET flashMessage
mov flashTimer, 150
@@:
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, 8
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, 8
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, 8
mov casinoSprites[2*SIZEOF SpriteObject].promptPtr, OFFSET promptDancer
; Sprite 3: Blackjack Table with Dealer (Front Center Left)
mov casinoSprites[3*SIZEOF SpriteObject].posX, (12 * FP_1 + FP_HALF)
mov casinoSprites[3*SIZEOF SpriteObject].posY, (10 * 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, 1
mov casinoSprites[3*SIZEOF SpriteObject].promptPtr, OFFSET promptBlackjack
; Sprite 4: 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, 4
mov casinoSprites[4*SIZEOF SpriteObject].promptPtr, OFFSET promptRoulette
; Sprite 5: Poker Table (Front Center Right)
mov casinoSprites[5*SIZEOF SpriteObject].posX, (21 * FP_1)
mov casinoSprites[5*SIZEOF SpriteObject].posY, (10 * 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, 1
mov casinoSprites[5*SIZEOF SpriteObject].promptPtr, OFFSET promptPoker
; Sprite 6: Slot Machine 1 (West Arcade)
mov casinoSprites[6*SIZEOF SpriteObject].posX, (6 * FP_1)
mov casinoSprites[6*SIZEOF SpriteObject].posY, (8 * FP_1)
mov casinoSprites[6*SIZEOF SpriteObject].baseTexId, 24
mov casinoSprites[6*SIZEOF SpriteObject].frameCount, 3
mov casinoSprites[6*SIZEOF SpriteObject].curFrame, 0
mov casinoSprites[6*SIZEOF SpriteObject].animTimer, 0
mov casinoSprites[6*SIZEOF SpriteObject].animSpeed, 8
mov casinoSprites[6*SIZEOF SpriteObject].interactId, 3
mov casinoSprites[6*SIZEOF SpriteObject].promptPtr, OFFSET promptSlot1
; Sprite 7: Slot Machine 2 (CloverPit)
mov casinoSprites[7*SIZEOF SpriteObject].posX, (6 * FP_1)
mov casinoSprites[7*SIZEOF SpriteObject].posY, (11 * FP_1)
mov casinoSprites[7*SIZEOF SpriteObject].baseTexId, 24
mov casinoSprites[7*SIZEOF SpriteObject].frameCount, 3
mov casinoSprites[7*SIZEOF SpriteObject].curFrame, 1
mov casinoSprites[7*SIZEOF SpriteObject].animTimer, 0
mov casinoSprites[7*SIZEOF SpriteObject].animSpeed, 8
mov casinoSprites[7*SIZEOF SpriteObject].interactId, 3
mov casinoSprites[7*SIZEOF SpriteObject].promptPtr, OFFSET promptSlot2
; Sprite 8: Slot Machine 3
mov casinoSprites[8*SIZEOF SpriteObject].posX, (6 * FP_1)
mov casinoSprites[8*SIZEOF SpriteObject].posY, (14 * FP_1)
mov casinoSprites[8*SIZEOF SpriteObject].baseTexId, 24
mov casinoSprites[8*SIZEOF SpriteObject].frameCount, 3
mov casinoSprites[8*SIZEOF SpriteObject].curFrame, 2
mov casinoSprites[8*SIZEOF SpriteObject].animTimer, 0
mov casinoSprites[8*SIZEOF SpriteObject].animSpeed, 8
mov casinoSprites[8*SIZEOF SpriteObject].interactId, 3
mov casinoSprites[8*SIZEOF SpriteObject].promptPtr, OFFSET promptSlot1
; Sprite 9: Bartender / Bar Counter (East Wing)
mov casinoSprites[9*SIZEOF SpriteObject].posX, (26 * FP_1)
mov casinoSprites[9*SIZEOF SpriteObject].posY, (12 * FP_1)
mov casinoSprites[9*SIZEOF SpriteObject].baseTexId, 32
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, 6
mov casinoSprites[9*SIZEOF SpriteObject].promptPtr, OFFSET promptShop
; Sprite 10: ATM Bank Terminal (East Wing)
mov casinoSprites[10*SIZEOF SpriteObject].posX, (26 * FP_1)
mov casinoSprites[10*SIZEOF SpriteObject].posY, (16 * FP_1)
mov casinoSprites[10*SIZEOF SpriteObject].baseTexId, 33
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, 7
mov casinoSprites[10*SIZEOF SpriteObject].promptPtr, OFFSET promptATM
; Sprite 11: Underground Table (South Wing)
mov casinoSprites[11*SIZEOF SpriteObject].posX, (16 * FP_1 + FP_HALF)
mov casinoSprites[11*SIZEOF SpriteObject].posY, (24 * FP_1)
mov casinoSprites[11*SIZEOF SpriteObject].baseTexId, 34
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, 5
mov casinoSprites[11*SIZEOF SpriteObject].promptPtr, OFFSET promptBackroom
; Sprite 12: Secret Demon Portal (South Wing)
mov casinoSprites[12*SIZEOF SpriteObject].posX, (16 * FP_1 + FP_HALF)
mov casinoSprites[12*SIZEOF SpriteObject].posY, (29 * FP_1)
mov casinoSprites[12*SIZEOF SpriteObject].baseTexId, 4
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, 9
mov casinoSprites[12*SIZEOF SpriteObject].promptPtr, OFFSET promptHell
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
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:
call HandleATMInput
call RenderATMGame
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