KAZIK/src_graphics/renderer.inc

2502 lines
56 KiB
PHP
Raw Blame History

This file contains ambiguous Unicode characters

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

; ==============================================================================
; CASINO 3D ENGINE - DOOM / WOLFENSTEIN 3D RAYCASTER FOR MASM32 (CP1251)
; ==============================================================================
includelib gdi32.lib
includelib winmm.lib
; Windows API Prototypes
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
; Structures
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 ? ; 16.16 FP
posY dd ? ; 16.16 FP
baseTexId dd ? ; Texture slot index
frameCount dd ? ; Number of animation frames
curFrame dd ? ; Current frame (0..frameCount-1)
animTimer dd ? ; Frame tick counter
animSpeed dd ? ; Ticks per frame
interactId dd ? ; Interaction action ID
promptPtr dd ? ; Prompt string pointer
distSq dd ? ; Distance squared to player
SpriteObject ENDS
; Constants
SCREEN_W equ 320
SCREEN_H equ 240
HALF_W equ 160
HALF_H equ 120
SCREEN_SIZE equ (SCREEN_W * SCREEN_H)
WIN_SCALE equ 3
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
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
SND_ASYNC equ 0001h
SND_FILENAME equ 00020000h
INVALID_FILE_HANDLE equ -1
; Precalculated Math, Map, and Font
include casino3d_data.inc
include font8x8.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 "CASINO 3D - RETRO DOOM ENGINE [MASM32]",0
szTexturesRelPath db "assets\textures\casino3d.bin",0
szTexturesFullPath db 260 dup(0)
; Audio files
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
; Player State (Spawns in central hall looking towards strip club and tables)
playerX dd (15 * FP_1 + FP_HALF)
playerY dd (14 * FP_1 + FP_HALF)
playerAngle dd 0 ; 0..511
playerDirX dd FP_1
playerDirY dd 0
playerPlaneX dd 0
playerPlaneY dd (FP_1 * 66 / 100)
radarActive dd 1
interactTargetId dd 0
interactPromptPtr dd 0
dancerLuckBuff dd 0
flashTimer dd 0
flashMessage db 128 dup(0)
; Prompts in CP1251
promptDancer db "[E] ТАНЦОВЩИЦА: КИНУТЬ $100 НА ЧАЙ (+УДАЧА)",0
promptSlot1 db "[E] КРУТИТЬ СЛОТ-МАШИНУ 777",0
promptSlot2 db "[E] ИГРАТЬ В CLOVERPIT (СЛОТЫ 5x3)",0
promptBlackjack db "[E] СЕСТЬ ЗА СТОЛ: 21 / BLACKJACK",0
promptPoker db "[E] СЕСТЬ ЗА СТОЛ: ТЕХАССКИЙ ПОКЕР",0
promptRoulette db "[E] СЕСТЬ ЗА СТОЛ: РУЛЕТКА КАЗИНО",0
promptShop db "[E] БАРМЕН: МАГАЗИН ТАЛИСМАНОВ И ЧИТОВ",0
promptATM db "[E] БАНКОМАТ: ПРОВЕРИТЬ БАЛАНС И КВОТУ",0
promptBackroom db "[E] BUCKSHOT / РУССКАЯ РУЛЕТКА",0
promptDurak db "[E] СЕСТЬ ЗА СТОЛ: ПОДКИДНОЙ ДУРАК",0
promptHell db "[E] ВОЙТИ В ПОРТАЛ: БАШНЯ АДА (FLOOR 666)",0
msgDancerTipped db "Вы кинули $100 танцовщице! Удача в играх повышена!",0
msgNeedMoney db "Недостаточно денег для чаевых!",0
statusHUDFormat db "БАНК: $",0
targetHUDFormat db " ЦЕЛЬ: $",0
luckHUDFormat db " УДАЧА: +",0
controlsHUD db "WASD/Стрелки: Ходить | M: Радар | E: Действие | ESC: Меню",0
NUM_SPRITES equ 13
ALIGN 4
casinoSprites SpriteObject NUM_SPRITES dup(<>)
sortedSprites dd NUM_SPRITES dup(0)
.data?
ALIGN 4
screenBuffer dd SCREEN_SIZE dup(?)
ALIGN 4
zBuffer dd SCREEN_W dup(?)
ALIGN 4
texturesBuffer dd (48 * 64 * 64) dup(?)
hudNumBuffer db 32 dup(?)
.code
; --- 3D Window Message Procedure ---
Casino3DWndProc PROC hwnd:DWORD, uMsg:DWORD, wParam:DWORD, lParam:DWORD
cmp uMsg, WM_DESTROY
jne @F
invoke PostQuitMessage, 0
xor eax, eax
ret
@@:
cmp uMsg, WM_CLOSE
jne @F
invoke PostQuitMessage, 0
xor eax, eax
ret
@@:
invoke DefWindowProcA, hwnd, uMsg, wParam, lParam
ret
Casino3DWndProc ENDP
; --- Initialize 3D Engine Window & Load Textures ---
Init3DEngine PROC
local bytesRead:DWORD
push ebx
push esi
push edi
invoke GetConsoleWindow
mov hCasinoConsole, eax
; Setup BITMAPINFO
mov bmi3D.bmiHeader.biSize, SIZEOF C3D_BITMAPINFOHEADER
mov bmi3D.bmiHeader.biWidth, SCREEN_W
mov bmi3D.bmiHeader.biHeight, -SCREEN_H
mov bmi3D.bmiHeader.biPlanes, 1
mov bmi3D.bmiHeader.biBitCount, 32
mov bmi3D.bmiHeader.biCompression, 0
mov bmi3D.bmiHeader.biSizeImage, SCREEN_SIZE * 4
mov bmi3D.bmiHeader.biXPelsPerMeter, 0
mov bmi3D.bmiHeader.biYPelsPerMeter, 0
mov bmi3D.bmiHeader.biClrUsed, 0
mov bmi3D.bmiHeader.biClrImportant, 0
cmp h3DWnd, 0
jne init_window_already_exists
mov wc3D.cbSize, SIZEOF C3D_WNDCLASSEX
mov wc3D.style, CS_HREDRAW or CS_VREDRAW
mov wc3D.lpfnWndProc, OFFSET Casino3DWndProc
mov wc3D.cbClsExtra, 0
mov wc3D.cbWndExtra, 0
mov wc3D.hInstance, 0
mov wc3D.hIcon, 0
mov wc3D.hCursor, 0
mov wc3D.hbrBackground, 0
mov wc3D.lpszMenuName, 0
mov wc3D.lpszClassName, OFFSET sz3DClassName
mov wc3D.hIconSm, 0
invoke RegisterClassExA, OFFSET wc3D
invoke GetSystemMetrics, 0
sub eax, WINDOW_W
shr eax, 1
mov ebx, eax
invoke GetSystemMetrics, 1
sub eax, WINDOW_H
shr eax, 1
mov ecx, eax
invoke CreateWindowExA, 0, OFFSET sz3DClassName, OFFSET sz3DWindowTitle,\
WS_OVERLAPPEDWINDOW, ebx, ecx, WINDOW_W + 16, WINDOW_H + 39,\
0, 0, 0, 0
mov h3DWnd, eax
invoke GetDC, h3DWnd
mov h3DDC, eax
init_window_already_exists:
invoke ShowWindow, h3DWnd, SW_SHOW
invoke UpdateWindow, h3DWnd
invoke SetForegroundWindow, h3DWnd
; Resolve full path to casino3d.bin
invoke GetModuleFileNameA, 0, OFFSET szTexturesFullPath, 260
; Find last backslash
lea esi, [szTexturesFullPath]
mov edi, esi
find_slash:
mov al, [esi]
test al, al
jz copy_rel_path
cmp al, '\'
jne @F
lea edi, [esi + 1]
@@:
inc esi
jmp find_slash
copy_rel_path:
lea esi, [szTexturesRelPath]
@@:
mov al, [esi]
mov [edi], al
test al, al
jz do_open_tex
inc esi
inc edi
jmp @B
do_open_tex:
invoke CreateFileA, OFFSET szTexturesFullPath, 80000000h, 1, 0, 3, 80h, 0
cmp eax, INVALID_FILE_HANDLE
jne read_tex_data
; Fallback to relative path
invoke CreateFileA, OFFSET szTexturesRelPath, 80000000h, 1, 0, 3, 80h, 0
cmp eax, INVALID_FILE_HANDLE
je generate_all_fallback_textures
read_tex_data:
mov ebx, eax
lea ecx, bytesRead
invoke ReadFile, ebx, OFFSET texturesBuffer, (48 * 64 * 64 * 4), ecx, 0
invoke CloseHandle, ebx
jmp init_sprites_table
generate_all_fallback_textures:
xor edi, edi
fill_fallback_loop:
cmp edi, (48 * 64 * 64)
jge init_sprites_table
mov eax, edi
and eax, 003Fh
mov ebx, edi
shr ebx, 6
and ebx, 003Fh
xor eax, ebx
and eax, 8
jz @F
mov DWORD PTR [texturesBuffer + edi*4], 00802020h
jmp next_fallback_pix
@@:
mov DWORD PTR [texturesBuffer + edi*4], 00202080h
next_fallback_pix:
inc edi
jmp fill_fallback_loop
init_sprites_table:
; Sprite 0: Dancer 1
mov casinoSprites[0*SIZEOF SpriteObject].posX, (5 * FP_1 + FP_HALF)
mov casinoSprites[0*SIZEOF SpriteObject].posY, (4 * FP_1 + FP_HALF)
mov casinoSprites[0*SIZEOF SpriteObject].baseTexId, 10
mov casinoSprites[0*SIZEOF SpriteObject].frameCount, 4
mov casinoSprites[0*SIZEOF SpriteObject].curFrame, 0
mov casinoSprites[0*SIZEOF SpriteObject].animTimer, 0
mov casinoSprites[0*SIZEOF SpriteObject].animSpeed, 6
mov casinoSprites[0*SIZEOF SpriteObject].interactId, 8
mov casinoSprites[0*SIZEOF SpriteObject].promptPtr, OFFSET promptDancer
; Sprite 1: Dancer 2
mov casinoSprites[1*SIZEOF SpriteObject].posX, (8 * FP_1 + FP_HALF)
mov casinoSprites[1*SIZEOF SpriteObject].posY, (4 * FP_1 + FP_HALF)
mov casinoSprites[1*SIZEOF SpriteObject].baseTexId, 10
mov casinoSprites[1*SIZEOF SpriteObject].frameCount, 4
mov casinoSprites[1*SIZEOF SpriteObject].curFrame, 2
mov casinoSprites[1*SIZEOF SpriteObject].animTimer, 0
mov casinoSprites[1*SIZEOF SpriteObject].animSpeed, 6
mov casinoSprites[1*SIZEOF SpriteObject].interactId, 8
mov casinoSprites[1*SIZEOF SpriteObject].promptPtr, OFFSET promptDancer
; Sprite 2: Slot 1
mov casinoSprites[2*SIZEOF SpriteObject].posX, (12 * FP_1 + FP_HALF)
mov casinoSprites[2*SIZEOF SpriteObject].posY, (12 * FP_1 + FP_HALF)
mov casinoSprites[2*SIZEOF SpriteObject].baseTexId, 20
mov casinoSprites[2*SIZEOF SpriteObject].frameCount, 3
mov casinoSprites[2*SIZEOF SpriteObject].curFrame, 0
mov casinoSprites[2*SIZEOF SpriteObject].animTimer, 0
mov casinoSprites[2*SIZEOF SpriteObject].animSpeed, 8
mov casinoSprites[2*SIZEOF SpriteObject].interactId, 3
mov casinoSprites[2*SIZEOF SpriteObject].promptPtr, OFFSET promptSlot1
; Sprite 3: Slot 2 (CloverPit)
mov casinoSprites[3*SIZEOF SpriteObject].posX, (15 * FP_1 + FP_HALF)
mov casinoSprites[3*SIZEOF SpriteObject].posY, (12 * FP_1 + FP_HALF)
mov casinoSprites[3*SIZEOF SpriteObject].baseTexId, 20
mov casinoSprites[3*SIZEOF SpriteObject].frameCount, 3
mov casinoSprites[3*SIZEOF SpriteObject].curFrame, 1
mov casinoSprites[3*SIZEOF SpriteObject].animTimer, 0
mov casinoSprites[3*SIZEOF SpriteObject].animSpeed, 8
mov casinoSprites[3*SIZEOF SpriteObject].interactId, 3
mov casinoSprites[3*SIZEOF SpriteObject].promptPtr, OFFSET promptSlot2
; Sprite 4: Slot 3
mov casinoSprites[4*SIZEOF SpriteObject].posX, (18 * FP_1 + FP_HALF)
mov casinoSprites[4*SIZEOF SpriteObject].posY, (12 * FP_1 + FP_HALF)
mov casinoSprites[4*SIZEOF SpriteObject].baseTexId, 20
mov casinoSprites[4*SIZEOF SpriteObject].frameCount, 3
mov casinoSprites[4*SIZEOF SpriteObject].curFrame, 2
mov casinoSprites[4*SIZEOF SpriteObject].animTimer, 0
mov casinoSprites[4*SIZEOF SpriteObject].animSpeed, 8
mov casinoSprites[4*SIZEOF SpriteObject].interactId, 3
mov casinoSprites[4*SIZEOF SpriteObject].promptPtr, OFFSET promptSlot1
; Sprite 5: Blackjack Table
mov casinoSprites[5*SIZEOF SpriteObject].posX, (10 * FP_1 + FP_HALF)
mov casinoSprites[5*SIZEOF SpriteObject].posY, (15 * FP_1 + FP_HALF)
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 promptBlackjack
; Sprite 6: Poker Table
mov casinoSprites[6*SIZEOF SpriteObject].posX, (18 * FP_1 + FP_HALF)
mov casinoSprites[6*SIZEOF SpriteObject].posY, (15 * FP_1 + FP_HALF)
mov casinoSprites[6*SIZEOF SpriteObject].baseTexId, 30
mov casinoSprites[6*SIZEOF SpriteObject].frameCount, 1
mov casinoSprites[6*SIZEOF SpriteObject].curFrame, 0
mov casinoSprites[6*SIZEOF SpriteObject].animTimer, 0
mov casinoSprites[6*SIZEOF SpriteObject].animSpeed, 1
mov casinoSprites[6*SIZEOF SpriteObject].interactId, 2
mov casinoSprites[6*SIZEOF SpriteObject].promptPtr, OFFSET promptPoker
; Sprite 7: Roulette Table
mov casinoSprites[7*SIZEOF SpriteObject].posX, (22 * FP_1 + FP_HALF)
mov casinoSprites[7*SIZEOF SpriteObject].posY, (14 * FP_1 + FP_HALF)
mov casinoSprites[7*SIZEOF SpriteObject].baseTexId, 31
mov casinoSprites[7*SIZEOF SpriteObject].frameCount, 1
mov casinoSprites[7*SIZEOF SpriteObject].curFrame, 0
mov casinoSprites[7*SIZEOF SpriteObject].animTimer, 0
mov casinoSprites[7*SIZEOF SpriteObject].animSpeed, 1
mov casinoSprites[7*SIZEOF SpriteObject].interactId, 4
mov casinoSprites[7*SIZEOF SpriteObject].promptPtr, OFFSET promptRoulette
; Sprite 8: Bartender / Shop
mov casinoSprites[8*SIZEOF SpriteObject].posX, (7 * FP_1 + FP_HALF)
mov casinoSprites[8*SIZEOF SpriteObject].posY, (22 * FP_1 + FP_HALF)
mov casinoSprites[8*SIZEOF SpriteObject].baseTexId, 32
mov casinoSprites[8*SIZEOF SpriteObject].frameCount, 1
mov casinoSprites[8*SIZEOF SpriteObject].curFrame, 0
mov casinoSprites[8*SIZEOF SpriteObject].animTimer, 0
mov casinoSprites[8*SIZEOF SpriteObject].animSpeed, 1
mov casinoSprites[8*SIZEOF SpriteObject].interactId, 6
mov casinoSprites[8*SIZEOF SpriteObject].promptPtr, OFFSET promptShop
; Sprite 9: Bank ATM
mov casinoSprites[9*SIZEOF SpriteObject].posX, (24 * FP_1 + FP_HALF)
mov casinoSprites[9*SIZEOF SpriteObject].posY, (13 * FP_1 + FP_HALF)
mov casinoSprites[9*SIZEOF SpriteObject].baseTexId, 33
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, 7
mov casinoSprites[9*SIZEOF SpriteObject].promptPtr, OFFSET promptATM
; Sprite 10: Backroom Table
mov casinoSprites[10*SIZEOF SpriteObject].posX, (23 * FP_1 + FP_HALF)
mov casinoSprites[10*SIZEOF SpriteObject].posY, (23 * FP_1 + FP_HALF)
mov casinoSprites[10*SIZEOF SpriteObject].baseTexId, 34
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, 5
mov casinoSprites[10*SIZEOF SpriteObject].promptPtr, OFFSET promptBackroom
; Sprite 11: Durak Table
mov casinoSprites[11*SIZEOF SpriteObject].posX, (26 * FP_1 + FP_HALF)
mov casinoSprites[11*SIZEOF SpriteObject].posY, (23 * FP_1 + FP_HALF)
mov casinoSprites[11*SIZEOF SpriteObject].baseTexId, 30
mov casinoSprites[11*SIZEOF SpriteObject].frameCount, 1
mov casinoSprites[11*SIZEOF SpriteObject].curFrame, 0
mov casinoSprites[11*SIZEOF SpriteObject].animTimer, 0
mov casinoSprites[11*SIZEOF SpriteObject].animSpeed, 1
mov casinoSprites[11*SIZEOF SpriteObject].interactId, 10
mov casinoSprites[11*SIZEOF SpriteObject].promptPtr, OFFSET promptDurak
; Sprite 12: Hell Portal
mov casinoSprites[12*SIZEOF SpriteObject].posX, (24 * FP_1 + FP_HALF)
mov casinoSprites[12*SIZEOF SpriteObject].posY, (3 * FP_1 + FP_HALF)
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
pop edi
pop esi
pop ebx
ret
Init3DEngine ENDP
; --- Fast 2D Drawing Primitives ---
DrawPixel PROC x:DWORD, y:DWORD, color:DWORD
mov eax, x
cmp eax, 0
jl @F
cmp eax, SCREEN_W
jge @F
mov ecx, y
cmp ecx, 0
jl @F
cmp ecx, SCREEN_H
jge @F
imul ecx, SCREEN_W
add ecx, eax
mov edx, color
mov [screenBuffer + ecx*4], edx
@@:
ret
DrawPixel ENDP
DrawBox PROC x:DWORD, y:DWORD, w:DWORD, h:DWORD, color:DWORD
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
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 x:DWORD, y:DWORD, chVal:DWORD, color:DWORD
push ebx
push esi
push edi
mov eax, chVal
and eax, 0FFh
shl eax, 3
lea esi, [font8x8 + eax]
xor edi, edi
char_row_loop:
cmp edi, 8
jge char_done
mov ecx, y
add ecx, edi
cmp ecx, 0
jl next_char_row
cmp ecx, SCREEN_H
jge char_done
movzx ebx, BYTE PTR [esi + edi]
xor edx, edx
char_col_loop:
cmp edx, 8
jge next_char_row
mov eax, x
add eax, edx
cmp eax, 0
jl next_char_col
cmp eax, SCREEN_W
jge next_char_row
test ebx, 80h
jz next_char_col
push ecx
imul ecx, SCREEN_W
add ecx, eax
push edx
mov edx, color
mov [screenBuffer + ecx*4], edx
pop edx
pop ecx
next_char_col:
shl ebx, 1
inc edx
jmp char_col_loop
next_char_row:
inc edi
jmp char_row_loop
char_done:
pop edi
pop esi
pop ebx
ret
DrawChar8x8 ENDP
DrawText8x8 PROC x:DWORD, y:DWORD, strPtr:DWORD, color:DWORD
push esi
push edi
mov esi, strPtr
mov edi, x
text_loop:
movzx eax, BYTE PTR [esi]
test al, al
jz text_done
invoke DrawChar8x8, edi, y, eax, color
add edi, 8
inc esi
jmp text_loop
text_done:
pop edi
pop esi
ret
DrawText8x8 ENDP
; --- Render Floor & Ceiling ---
RenderCeilingAndFloor PROC uses ebx esi edi
; Ceiling (Slot 5: 5 * 4096 = 20480 DWORDs = 81920 bytes)
xor edi, edi
ceiling_y_loop:
cmp edi, HALF_H
jge floor_render
mov ecx, edi
imul ecx, SCREEN_W
mov eax, edi
and eax, 63
shl eax, 6
xor esi, esi
ceiling_x_loop:
cmp esi, SCREEN_W
jge next_ceiling_y
mov ebx, esi
and ebx, 63
add ebx, eax
mov edx, [texturesBuffer + 81920 + ebx*4]
add ecx, esi
mov [screenBuffer + ecx*4], edx
sub ecx, esi
inc esi
jmp ceiling_x_loop
next_ceiling_y:
inc edi
jmp ceiling_y_loop
floor_render:
; Carpet Floor (Slot 3: 3 * 4096 = 12288 DWORDs = 49152 bytes)
mov edi, HALF_H
floor_y_loop:
cmp edi, SCREEN_H
jge bg_done
mov ecx, edi
imul ecx, SCREEN_W
mov eax, edi
and eax, 63
shl eax, 6
mov edx, edi
sub edx, HALF_H
shl edx, 1
add edx, 40
cmp edx, 255
jbe @F
mov edx, 255
@@:
mov ebx, edx
xor esi, esi
floor_x_loop:
cmp esi, SCREEN_W
jge next_floor_y
mov edx, esi
and edx, 63
add edx, eax
mov eax, [texturesBuffer + 49152 + edx*4]
; Shade RGB
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
add ecx, esi
mov [screenBuffer + ecx*4], eax
sub ecx, esi
mov eax, edi
and eax, 63
shl eax, 6
inc esi
jmp floor_x_loop
next_floor_y:
inc edi
jmp floor_y_loop
bg_done:
ret
RenderCeilingAndFloor ENDP
; --- DDA Raycasting Walls Rendering ---
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
imul ebx, -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
cmp rayDirX, 0
jne @F
mov deltaDistX, 7FFFFFFFh
jmp calc_delta_y
@@:
mov eax, FP_1
imul eax, FP_1
cdq
idiv rayDirX
test eax, eax
jns @F
neg eax
@@:
mov deltaDistX, eax
calc_delta_y:
cmp rayDirY, 0
jne @F
mov deltaDistY, 7FFFFFFFh
jmp calc_step_x
@@:
mov eax, FP_1
imul eax, FP_1
cdq
idiv rayDirY
test eax, eax
jns @F
neg eax
@@:
mov deltaDistY, eax
calc_step_x:
cmp rayDirX, 0
jge step_x_pos
mov stepX, -1
mov eax, mapX
shl eax, 16
mov ecx, playerX
sub ecx, eax
mov eax, ecx
imul deltaDistX
shrd eax, edx, 16
mov sideDistX, eax
jmp calc_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
calc_step_y:
cmp rayDirY, 0
jge step_y_pos
mov stepY, -1
mov eax, mapY
shl eax, 16
mov ecx, playerY
sub ecx, eax
mov eax, ecx
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
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:
mov eax, wallHit
shr eax, 10
and eax, 63
mov texX, eax
cmp side, 0
jne @F
cmp rayDirX, 0
jle @F
mov eax, 63
sub eax, texX
mov texX, eax
@@:
cmp side, 1
jne select_tex
cmp rayDirY, 0
jge select_tex
mov eax, 63
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, 12
mov edx, 256
sub edx, eax
cmp edx, 35
jge @F
mov edx, 35
@@:
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
@@:
; Vertical texture sampling loop
mov eax, 64 * 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, 63
shl eax, 6
add eax, texX
; CORRECTED TEXTURE SLOT DWORD INDEX: texId * 4096 (shl 12)
mov edx, texId
shl edx, 12
add eax, edx
mov eax, [texturesBuffer + eax*4]
; Apply shading
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 2.5D 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
; Advance sprite animation
mov edx, [casinoSprites + eax].animTimer
inc edx
cmp edx, [casinoSprites + eax].animSpeed
jl store_anim
xor edx, edx
mov ecx, [casinoSprites + eax].curFrame
inc ecx
cmp ecx, [casinoSprites + eax].frameCount
jl @F
xor ecx, ecx
@@:
mov [casinoSprites + eax].curFrame, ecx
store_anim:
mov [casinoSprites + eax].animTimer, edx
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
mov eax, FP_1
imul eax, FP_1
cdq
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
; Depth culling
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
@@:
; Limit maximum sprite height to screen height * 2 to prevent full-screen box blowout
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, 12
mov edx, 256
sub edx, eax
cmp edx, 40
jge @F
mov edx, 40
@@:
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, 6
cdq
idiv sprW
cmp eax, 0
jl next_spr_stripe
cmp eax, 64
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, 6
cdq
idiv sprH
cmp eax, 0
jl next_spr_y
cmp eax, 64
jge next_spr_y
mov texY, eax
shl eax, 6
add eax, texX
; CORRECTED TEXTURE SLOT DWORD INDEX: texSlot * 4096 (shl 12)
mov edx, texSlot
shl edx, 12
add eax, edx
mov eax, [texturesBuffer + eax*4]
; ROBUST CHROMAKEY FILTER:
; Skip if pure magenta or black
cmp eax, CHROMA_KEY
je next_spr_y
test eax, eax
jz next_spr_y
; Skip if near-magenta: Green is low (< 0x20) and Blue & Red are both high (> 0xD0)
mov ecx, eax
and ecx, 0000FF00h ; Green
cmp ecx, 00002000h
ja do_draw_sprite_pix
mov ecx, eax
and ecx, 00FF0000h ; Red
cmp ecx, 00D00000h
jb do_draw_sprite_pix
mov ecx, eax
and ecx, 000000FFh ; Blue
cmp ecx, 000000D0h
ja 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 edx, edi
imul edx, SCREEN_W
add edx, stripe
mov [screenBuffer + edx*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
; --- Radar / Minimap Overlay ---
RenderMinimap PROC uses ebx esi edi
cmp radarActive, 0
je map_done
invoke DrawBox, 248, 2, 68, 68, 00101018h
invoke DrawBox, 249, 3, 66, 66, 00403010h
xor edi, edi
map_y_row:
cmp edi, MAP_HEIGHT
jge draw_map_sprites
xor esi, esi
map_x_col:
cmp esi, MAP_WIDTH
jge next_map_row
mov eax, edi
shl eax, 5
add eax, esi
movzx eax, BYTE PTR [casinoMap + eax]
test eax, eax
jz next_map_col
mov eax, esi
shl eax, 1
add eax, 250
mov ebx, edi
shl ebx, 1
add ebx, 4
invoke DrawPixel, eax, ebx, 00908050h
inc eax
invoke DrawPixel, eax, ebx, 00908050h
dec eax
inc ebx
invoke DrawPixel, eax, ebx, 00706030h
inc eax
invoke DrawPixel, eax, ebx, 00706030h
next_map_col:
inc esi
jmp map_x_col
next_map_row:
inc edi
jmp map_y_row
draw_map_sprites:
xor esi, esi
map_spr_loop:
cmp esi, NUM_SPRITES
jge draw_map_player
mov eax, esi
imul eax, SIZEOF SpriteObject
mov edx, [casinoSprites + eax].posX
shr edx, 16
shl edx, 1
add edx, 250
mov ecx, [casinoSprites + eax].posY
shr ecx, 16
shl ecx, 1
add ecx, 4
mov ebx, [casinoSprites + eax].interactId
cmp ebx, 8
jne @F
mov ebx, 00FF40A0h ; Pink
jmp draw_spr_dot
@@:
cmp ebx, 6
jne @F
mov ebx, 0040D0FFh ; Cyan
jmp draw_spr_dot
@@:
cmp ebx, 9
jne @F
mov ebx, 00FF2020h ; Red
jmp draw_spr_dot
@@:
mov ebx, 0030FF40h ; Green
draw_spr_dot:
invoke DrawPixel, edx, ecx, ebx
inc edx
invoke DrawPixel, edx, ecx, ebx
inc esi
jmp map_spr_loop
draw_map_player:
mov edx, playerX
shr edx, 16
shl edx, 1
add edx, 250
mov ecx, playerY
shr ecx, 16
shl ecx, 1
add ecx, 4
invoke DrawPixel, edx, ecx, 00FFFF00h
inc edx
invoke DrawPixel, edx, ecx, 00FFFF00h
dec edx
inc ecx
invoke DrawPixel, edx, ecx, 00FFFF00h
inc edx
invoke DrawPixel, edx, ecx, 00FFFF00h
mov eax, playerDirX
sar eax, 13
add edx, eax
mov eax, playerDirY
sar eax, 13
add ecx, eax
invoke DrawPixel, edx, ecx, 00FFCC00h
map_done:
ret
RenderMinimap ENDP
; --- Format UInt to Decimal String in hudNumBuffer ---
FormatUIntString PROC val:DWORD
push ebx
push esi
push edi
mov eax, val
lea edi, [hudNumBuffer + 31]
mov BYTE PTR [edi], 0
dec edi
mov ebx, 10
conv_loop:
xor edx, edx
div ebx
add dl, '0'
mov [edi], dl
dec edi
test eax, eax
jnz conv_loop
inc edi
mov eax, edi
pop edi
pop esi
pop ebx
ret
FormatUIntString ENDP
; --- Render HUD Status Bar & Prompts ---
RenderHUD PROC uses ebx esi edi
invoke DrawBox, 0, 216, SCREEN_W, 24, 00141418h
invoke DrawBox, 0, 216, SCREEN_W, 1, 00D4AF37h
invoke DrawText8x8, 8, 220, OFFSET statusHUDFormat, 00D4AF37h
invoke FormatUIntString, bankroll
invoke DrawText8x8, 64, 220, eax, 0040FF40h
invoke DrawText8x8, 120, 220, OFFSET targetHUDFormat, 00D4AF37h
invoke FormatUIntString, targetBank
invoke DrawText8x8, 192, 220, eax, 0040D0FFh
invoke DrawText8x8, 240, 220, OFFSET luckHUDFormat, 00FF40A0h
invoke FormatUIntString, dancerLuckBuff
invoke DrawText8x8, 304, 220, eax, 00FF40A0h
cmp flashTimer, 0
jle check_interaction_prompt
dec flashTimer
invoke DrawBox, 10, 95, SCREEN_W - 20, 20, 00101018h
invoke DrawBox, 10, 95, SCREEN_W - 20, 1, 0030FF30h
invoke DrawBox, 10, 114, SCREEN_W - 20, 1, 0030FF30h
invoke DrawText8x8, 16, 101, OFFSET flashMessage, 0030FF30h
check_interaction_prompt:
cmp interactPromptPtr, 0
je show_controls_prompt
invoke DrawBox, 12, 188, SCREEN_W - 24, 20, 00141010h
invoke DrawBox, 12, 188, SCREEN_W - 24, 1, 00FFFF00h
invoke DrawBox, 12, 207, SCREEN_W - 24, 1, 00FFFF00h
invoke DrawText8x8, 18, 194, interactPromptPtr, 00FFFF00h
jmp hud_done
show_controls_prompt:
invoke DrawText8x8, 6, 6, OFFSET controlsHUD, 00888888h
hud_done:
ret
RenderHUD ENDP
; --- Proximity Interaction Detection ---
CheckInteractions PROC uses ebx esi edi
mov interactTargetId, 0
mov interactPromptPtr, 0
xor esi, esi
check_loop:
cmp esi, NUM_SPRITES
jge check_done
mov eax, esi
imul eax, SIZEOF SpriteObject
mov ebx, [casinoSprites + eax].distSq
cmp ebx, 262144
jge next_check
mov edx, [casinoSprites + eax].interactId
mov interactTargetId, edx
mov edx, [casinoSprites + eax].promptPtr
mov interactPromptPtr, edx
jmp check_done
next_check:
inc esi
jmp check_loop
check_done:
ret
CheckInteractions ENDP
CopyString 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
CopyString ENDP
; ==============================================================================
; VISUAL GAME ANIMATIONS
; ==============================================================================
AnimChipFlight PROC startX:DWORD, startY:DWORD, targetX:DWORD, targetY:DWORD, chipColor:DWORD
local frame:DWORD
local curX:DWORD
local curY:DWORD
local arcH:DWORD
push ebx
push esi
push edi
invoke PlaySoundA, OFFSET soundCoin, 0, SND_ASYNC or SND_FILENAME
mov frame, 0
chip_frame_loop:
cmp frame, 16
jge chip_landed
mov eax, frame
imul eax, 100
shr eax, 4
mov ecx, eax
mov eax, targetX
sub eax, startX
imul eax, ecx
cdq
mov ebx, 100
idiv ebx
add eax, startX
mov curX, eax
mov eax, targetY
sub eax, startY
imul eax, ecx
cdq
idiv ebx
add eax, startY
mov ebx, 100
sub ebx, ecx
imul ebx, ecx
cdq
mov esi, 100
idiv esi
shr eax, 1
sub eax, curY
neg eax
mov curY, eax
invoke DrawCircle, curX, curY, 6, 00D4AF37h
invoke DrawCircle, curX, curY, 4, chipColor
invoke DrawPixel, curX, curY, 00FFFFFFh
invoke StretchDIBits, h3DDC, 0, 0, WINDOW_W, WINDOW_H,\
0, 0, SCREEN_W, SCREEN_H,\
OFFSET screenBuffer, OFFSET bmi3D, DIB_RGB_COLORS, SRCCOPY
invoke Sleep, 16
inc frame
jmp chip_frame_loop
chip_landed:
invoke DrawCircle, targetX, targetY, 7, 00D4AF37h
invoke DrawCircle, targetX, targetY, 5, chipColor
invoke StretchDIBits, h3DDC, 0, 0, WINDOW_W, WINDOW_H,\
0, 0, SCREEN_W, SCREEN_H,\
OFFSET screenBuffer, OFFSET bmi3D, DIB_RGB_COLORS, SRCCOPY
invoke Sleep, 40
pop edi
pop esi
pop ebx
ret
AnimChipFlight ENDP
AnimReelSpin PROC sym1:DWORD, sym2:DWORD, sym3:DWORD, isJackpot:DWORD
local frame:DWORD
local rPos1:DWORD
local rPos2:DWORD
local rPos3:DWORD
push ebx
push esi
push edi
invoke PlaySoundA, OFFSET soundClick, 0, SND_ASYNC or SND_FILENAME
mov rPos1, 0
mov rPos2, 0
mov rPos3, 0
mov frame, 0
reel_loop:
cmp frame, 80
jge spin_finished
invoke DrawBox, 50, 40, 220, 140, 00101018h
invoke DrawBox, 50, 40, 220, 2, 00D4AF37h
invoke DrawBox, 50, 178, 220, 2, 00D4AF37h
cmp frame, 35
jge @F
add rPos1, 16
@@:
cmp frame, 55
jge @F
add rPos2, 16
@@:
cmp frame, 75
jge @F
add rPos3, 16
@@:
invoke DrawBox, 70, 55, 45, 95, 00202028h
mov eax, rPos1
and eax, 31
invoke DrawBox, 75, 75, 35, 35, 00D02020h
invoke DrawBox, 135, 55, 45, 95, 00202028h
mov eax, rPos2
and eax, 31
invoke DrawBox, 140, 75, 35, 35, 0020D020h
invoke DrawBox, 200, 55, 45, 95, 00202028h
mov eax, rPos3
and eax, 31
invoke DrawBox, 205, 75, 35, 35, 002020D0h
invoke DrawBox, 50, 92, 220, 1, 00FF0000h
invoke StretchDIBits, h3DDC, 0, 0, WINDOW_W, WINDOW_H,\
0, 0, SCREEN_W, SCREEN_H,\
OFFSET screenBuffer, OFFSET bmi3D, DIB_RGB_COLORS, SRCCOPY
invoke Sleep, 16
inc frame
jmp reel_loop
spin_finished:
cmp isJackpot, 0
je spin_exit
invoke PlaySoundA, OFFSET soundJackpot, 0, SND_ASYNC or SND_FILENAME
invoke DrawBox, 60, 45, 200, 25, 00FFD700h
invoke DrawBox, 62, 47, 196, 21, 00800000h
invoke StretchDIBits, h3DDC, 0, 0, WINDOW_W, WINDOW_H,\
0, 0, SCREEN_W, SCREEN_H,\
OFFSET screenBuffer, OFFSET bmi3D, DIB_RGB_COLORS, SRCCOPY
invoke Sleep, 250
spin_exit:
pop edi
pop esi
pop ebx
ret
AnimReelSpin ENDP
AnimCardDealAndFlip PROC targetX:DWORD, targetY:DWORD, rankChar:DWORD, isRed:DWORD
local frame:DWORD
local curX:DWORD
local curY:DWORD
local cardW:DWORD
push ebx
push esi
push edi
invoke PlaySoundA, OFFSET soundCards, 0, SND_ASYNC or SND_FILENAME
mov frame, 0
slide_loop:
cmp frame, 12
jge start_flip
mov eax, targetX
sub eax, 260
imul eax, frame
cdq
mov ecx, 12
idiv ecx
add eax, 260
mov curX, eax
mov eax, targetY
sub eax, 30
imul eax, frame
cdq
idiv ecx
add eax, 30
mov curY, eax
invoke DrawBox, curX, curY, 24, 34, 00000000h
invoke DrawBox, curX, curY, 22, 32, 00103080h
invoke DrawBox, curX, curY, 22, 1, 00D4AF37h
invoke StretchDIBits, h3DDC, 0, 0, WINDOW_W, WINDOW_H,\
0, 0, SCREEN_W, SCREEN_H,\
OFFSET screenBuffer, OFFSET bmi3D, DIB_RGB_COLORS, SRCCOPY
invoke Sleep, 16
inc frame
jmp slide_loop
start_flip:
mov frame, 0
flip_loop:
cmp frame, 10
jge flip_done
cmp frame, 5
jge flip_expand
mov eax, 5
sub eax, frame
imul eax, 22
cdq
mov ecx, 5
idiv ecx
mov cardW, eax
mov eax, 22
sub eax, cardW
shr eax, 1
add eax, targetX
mov curX, eax
invoke DrawBox, curX, targetY, cardW, 32, 00103080h
jmp flip_frame_show
flip_expand:
mov eax, frame
sub eax, 5
imul eax, 22
cdq
mov ecx, 5
idiv ecx
mov cardW, eax
mov eax, 22
sub eax, cardW
shr eax, 1
add eax, targetX
mov curX, eax
invoke DrawBox, curX, targetY, cardW, 32, 00FFFFFFh
invoke DrawBox, curX, targetY, cardW, 1, 00000000h
mov edx, 00000000h
cmp isRed, 0
je @F
mov edx, 00CC0000h
@@:
invoke DrawChar8x8, curX, targetY, rankChar, edx
flip_frame_show:
invoke StretchDIBits, h3DDC, 0, 0, WINDOW_W, WINDOW_H,\
0, 0, SCREEN_W, SCREEN_H,\
OFFSET screenBuffer, OFFSET bmi3D, DIB_RGB_COLORS, SRCCOPY
invoke Sleep, 16
inc frame
jmp flip_loop
flip_done:
pop edi
pop esi
pop ebx
ret
AnimCardDealAndFlip ENDP
AnimRouletteWheel PROC winningNumber:DWORD
local frame:DWORD
local wheelAng:DWORD
local ballAng:DWORD
local ballRadius:DWORD
local ballX:DWORD
local ballY:DWORD
push ebx
push esi
push edi
invoke PlaySoundA, OFFSET soundRoulette, 0, SND_ASYNC or SND_FILENAME
mov wheelAng, 0
mov ballAng, 0
mov ballRadius, 52
mov frame, 0
roulette_anim_loop:
cmp frame, 90
jge roulette_finished
add wheelAng, 12
and wheelAng, 511
add ballAng, 28
and ballAng, 511
cmp frame, 45
jl @F
cmp ballRadius, 36
jle @F
dec ballRadius
@@:
invoke DrawCircle, 160, 105, 60, 00603010h
invoke DrawCircle, 160, 105, 56, 00D4AF37h
invoke DrawCircle, 160, 105, 52, 00181818h
mov eax, wheelAng
and eax, 511
mov ebx, [tableCos + eax*4]
sar ebx, 10
add ebx, 160
mov ecx, [tableSin + eax*4]
sar ecx, 10
add ecx, 105
invoke DrawCircle, ebx, ecx, 4, 00CC0000h
add eax, 64
and eax, 511
mov ebx, [tableCos + eax*4]
sar ebx, 10
add ebx, 160
mov ecx, [tableSin + eax*4]
sar ecx, 10
add ecx, 105
invoke DrawCircle, ebx, ecx, 4, 00108010h
invoke DrawCircle, 160, 105, 14, 00D4AF37h
invoke DrawCircle, 160, 105, 8, 00FFFF80h
mov eax, ballAng
and eax, 511
mov ebx, [tableCos + eax*4]
imul ebx, ballRadius
sar ebx, 16
add ebx, 160
mov ballX, ebx
mov ecx, [tableSin + eax*4]
imul ecx, ballRadius
sar ecx, 16
add ecx, 105
mov ballY, ecx
invoke DrawCircle, ballX, ballY, 3, 00FFFFFFh
invoke StretchDIBits, h3DDC, 0, 0, WINDOW_W, WINDOW_H,\
0, 0, SCREEN_W, SCREEN_H,\
OFFSET screenBuffer, OFFSET bmi3D, DIB_RGB_COLORS, SRCCOPY
invoke Sleep, 16
inc frame
jmp roulette_anim_loop
roulette_finished:
invoke Sleep, 200
pop edi
pop esi
pop ebx
ret
AnimRouletteWheel ENDP
; --- Trigger Interaction ---
Trigger3DInteraction PROC
push ebx
push esi
push edi
mov eax, interactTargetId
test eax, eax
jz interact_exit
cmp eax, 8
jne handle_mini_games
cmp bankroll, 100
jge tip_dancer_ok
invoke CopyString, OFFSET msgNeedMoney, OFFSET flashMessage
mov flashTimer, 80
jmp interact_exit
tip_dancer_ok:
sub bankroll, 100
inc dancerLuckBuff
mov cheatLuckyWin, 1
invoke CopyString, OFFSET msgDancerTipped, OFFSET flashMessage
mov flashTimer, 120
invoke PlayHakariSound
jmp interact_exit
handle_mini_games:
cmp eax, 3
jne check_blackjack
invoke AnimReelSpin, 7, 7, 7, 1
jmp launch_console_game
check_blackjack:
cmp eax, 1
jne check_roulette
invoke AnimChipFlight, 160, 210, 160, 140, 002040D0h
invoke AnimCardDealAndFlip, 120, 110, 'A', 1
invoke AnimCardDealAndFlip, 150, 110, 'K', 0
jmp launch_console_game
check_roulette:
cmp eax, 4
jne launch_console_game
invoke AnimChipFlight, 160, 210, 200, 160, 00D02020h
invoke AnimRouletteWheel, 17
launch_console_game:
invoke ShowWindow, h3DWnd, SW_HIDE
invoke SetForegroundWindow, hCasinoConsole
mov eax, interactTargetId
cmp eax, 1
jne @F
mov currentGameId, 1
call Game21
jmp game_finished
@@:
cmp eax, 2
jne @F
mov currentGameId, 2
call GamePoker
jmp game_finished
@@:
cmp eax, 3
jne @F
mov currentGameId, 3
call PlaySlotIntroSound
call GameSlot
jmp game_finished
@@:
cmp eax, 4
jne @F
mov currentGameId, 4
call GameRoulette
jmp game_finished
@@:
cmp eax, 5
jne @F
mov currentGameId, 13
call GameBuckshot
jmp game_finished
@@:
cmp eax, 6
jne @F
call GameShop
jmp game_finished
@@:
cmp eax, 7
jne @F
call AccountMenu
jmp game_finished
@@:
cmp eax, 9
jne @F
mov currentGameId, 666
call GameTournament
jmp game_finished
@@:
cmp eax, 10
jne game_finished
mov currentGameId, 11
call GameDurak
game_finished:
call CheckVictory
invoke ShowWindow, h3DWnd, SW_SHOW
invoke UpdateWindow, h3DWnd
invoke SetForegroundWindow, h3DWnd
interact_exit:
pop edi
pop esi
pop ebx
ret
Trigger3DInteraction ENDP
; --- Player Input & Movement Physics ---
HandlePlayerInput PROC
local walkSpd:DWORD
local turnSpd:DWORD
local moveDirX:DWORD
local moveDirY:DWORD
local newX:DWORD
local newY:DWORD
local checkTileX:DWORD
local checkTileY:DWORD
push ebx
push esi
push edi
mov walkSpd, 3200
mov turnSpd, 7
invoke GetAsyncKeyState, 10h
test ah, 80h
jz @F
mov walkSpd, 5600
@@:
invoke GetAsyncKeyState, 41h
test ah, 80h
jnz turn_left
invoke GetAsyncKeyState, 25h
test ah, 80h
jz check_turn_right
turn_left:
mov eax, playerAngle
sub eax, turnSpd
add eax, 512
and eax, 511
mov playerAngle, eax
check_turn_right:
invoke GetAsyncKeyState, 44h
test ah, 80h
jnz turn_right
invoke GetAsyncKeyState, 27h
test ah, 80h
jz check_walk_forward
turn_right:
mov eax, playerAngle
add eax, turnSpd
and eax, 511
mov playerAngle, eax
check_walk_forward:
invoke GetAsyncKeyState, 57h
test ah, 80h
jnz walk_fwd
invoke GetAsyncKeyState, 26h
test ah, 80h
jz check_walk_back
walk_fwd:
mov eax, playerDirX
imul walkSpd
shrd eax, edx, 16
add eax, playerX
mov newX, eax
mov eax, playerDirY
imul walkSpd
shrd eax, edx, 16
add eax, playerY
mov newY, eax
mov eax, newX
sar eax, 16
mov checkTileX, eax
mov eax, playerY
sar eax, 16
mov checkTileY, eax
mov eax, checkTileY
shl eax, 5
add eax, checkTileX
movzx eax, BYTE PTR [casinoMap + eax]
test eax, eax
jnz @F
mov eax, newX
mov playerX, eax
@@:
mov eax, playerX
sar eax, 16
mov checkTileX, eax
mov eax, newY
sar eax, 16
mov checkTileY, eax
mov eax, checkTileY
shl eax, 5
add eax, checkTileX
movzx eax, BYTE PTR [casinoMap + eax]
test eax, eax
jnz check_walk_back
mov eax, newY
mov playerY, eax
check_walk_back:
invoke GetAsyncKeyState, 53h
test ah, 80h
jnz walk_back
invoke GetAsyncKeyState, 28h
test ah, 80h
jz check_radar_toggle
walk_back:
mov eax, playerDirX
imul walkSpd
shrd eax, edx, 16
mov ebx, playerX
sub ebx, eax
mov newX, ebx
mov eax, playerDirY
imul walkSpd
shrd eax, edx, 16
mov ebx, playerY
sub ebx, eax
mov newY, ebx
mov eax, newX
sar eax, 16
mov checkTileX, eax
mov eax, playerY
sar eax, 16
mov checkTileY, eax
mov eax, checkTileY
shl eax, 5
add eax, checkTileX
movzx eax, BYTE PTR [casinoMap + eax]
test eax, eax
jnz @F
mov eax, newX
mov playerX, eax
@@:
mov eax, playerX
sar eax, 16
mov checkTileX, eax
mov eax, newY
sar eax, 16
mov checkTileY, eax
mov eax, checkTileY
shl eax, 5
add eax, checkTileX
movzx eax, BYTE PTR [casinoMap + eax]
test eax, eax
jnz check_radar_toggle
mov eax, newY
mov playerY, eax
check_radar_toggle:
invoke GetAsyncKeyState, 4Dh
test ah, 80h
jnz toggle_radar
invoke GetAsyncKeyState, 09h
test ah, 80h
jz check_action_key
toggle_radar:
xor radarActive, 1
invoke Sleep, 120
check_action_key:
invoke GetAsyncKeyState, 45h
test ah, 80h
jnz do_action
invoke GetAsyncKeyState, 20h
test ah, 80h
jz input_done
do_action:
call Trigger3DInteraction
invoke Sleep, 150
input_done:
pop edi
pop esi
pop ebx
ret
HandlePlayerInput ENDP
; --- Main Loop of the 3D Casino Engine ---
StartCasino3D PROC uses ebx esi edi
call Init3DEngine
call PlaySlotIntroSound
engine_loop:
lea eax, [msg3D]
invoke PeekMessageA, eax, 0, 0, 0, PM_REMOVE
test eax, eax
jz @F
cmp msg3D.message, WM_QUIT
je exit_3d_engine
lea eax, [msg3D]
invoke TranslateMessage, eax
lea eax, [msg3D]
invoke DispatchMessageA, eax
@@:
invoke GetAsyncKeyState, 1Bh
test ah, 80h
jnz exit_3d_engine
call HandlePlayerInput
call CheckInteractions
call RenderCeilingAndFloor
call RenderWalls
call RenderSprites
call RenderHUD
call RenderMinimap
invoke StretchDIBits, h3DDC, 0, 0, WINDOW_W, WINDOW_H,\
0, 0, SCREEN_W, SCREEN_H,\
OFFSET screenBuffer, OFFSET bmi3D, DIB_RGB_COLORS, SRCCOPY
invoke Sleep, 16
jmp engine_loop
exit_3d_engine:
cmp h3DWnd, 0
je @F
invoke ShowWindow, h3DWnd, SW_HIDE
@@:
invoke SetForegroundWindow, hCasinoConsole
ret
StartCasino3D ENDP