2975 lines
68 KiB
PHP
2975 lines
68 KiB
PHP
|
|
; ==============================================================================
|
|
; 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\Звон падающей монеты.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\Джекпот.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 "Вы бросили $100 танцовщице! УДАЧА АКТИВИРОВАНА!",0
|
|
msgNeedMoney db "Недостаточно денег в кошельке!",0
|
|
statusHUDFormat db "БАНКРОЛЛ: $",0
|
|
targetHUDFormat db " ЦЕЛЬ: $",0
|
|
luckHUDFormat db " УДАЧА: +",0
|
|
controlsHUD db "WASD/Стрелки: Ходьба | E: Действие | ESC: Меню",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 "ПОБЕДА! +$",0
|
|
strLose db "ПРОИГРЫШ",0
|
|
strJackpot db "ДЖЕКПОТ! +$",0
|
|
strPush db "НИЧЬЯ (PUSH)",0
|
|
strDealerBust db "ДИЛЕР ПЕРЕБРАЛ! ПОБЕДА! +$",0
|
|
strPlayerBust db "ПЕРЕБОР (>21)! ПРОИГРЫШ",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
|
|
; 2^32 needs the full EDX:EAX dividend, not a truncated multiply.
|
|
xor eax, eax
|
|
mov edx, 1
|
|
idiv ebx
|
|
mov deltaDistX, eax
|
|
|
|
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
|
|
; 2^32 needs the full EDX:EAX dividend, not a truncated multiply.
|
|
xor eax, eax
|
|
mov edx, 1
|
|
idiv ebx
|
|
mov deltaDistY, eax
|
|
|
|
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, 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
|
|
imul ecx, 40
|
|
mov eax, animationClock3D
|
|
xor edx, edx
|
|
div ecx
|
|
pop ebx
|
|
xor edx, edx
|
|
div [casinoSprites + ebx].frameCount
|
|
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
|
|
test ebx, ebx
|
|
jz 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, 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
|