; ============================================================================== ; 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