; ============================================================================== ; CASINO 2.5D - MASM32 SOFTWARE RAYCASTER (CP1251) ; Graphical migration; this is not id Software's Doom engine. ; ============================================================================== includelib gdi32.lib includelib winmm.lib CreateWindowExA PROTO :DWORD,:DWORD,:DWORD,:DWORD,:DWORD,:DWORD,:DWORD,:DWORD,:DWORD,:DWORD,:DWORD,:DWORD RegisterClassExA PROTO :DWORD DefWindowProcA PROTO :DWORD,:DWORD,:DWORD,:DWORD ShowWindow PROTO :DWORD,:DWORD UpdateWindow PROTO :DWORD GetDC PROTO :DWORD ReleaseDC PROTO :DWORD,:DWORD StretchDIBits PROTO :DWORD,:DWORD,:DWORD,:DWORD,:DWORD,:DWORD,:DWORD,:DWORD,:DWORD,:DWORD,:DWORD,:DWORD,:DWORD PeekMessageA PROTO :DWORD,:DWORD,:DWORD,:DWORD,:DWORD TranslateMessage PROTO :DWORD DispatchMessageA PROTO :DWORD PostQuitMessage PROTO :DWORD DestroyWindow PROTO :DWORD SetWindowTextA PROTO :DWORD,:DWORD SetForegroundWindow PROTO :DWORD GetConsoleWindow PROTO GetSystemMetrics PROTO :DWORD CreateFileA PROTO :DWORD,:DWORD,:DWORD,:DWORD,:DWORD,:DWORD,:DWORD ReadFile PROTO :DWORD,:DWORD,:DWORD,:DWORD,:DWORD CloseHandle PROTO :DWORD GetAsyncKeyState PROTO :DWORD PlaySoundA PROTO :DWORD,:DWORD,:DWORD GetModuleFileNameA PROTO :DWORD,:DWORD,:DWORD Sleep PROTO :DWORD C3D_POINT STRUCT x dd ? y dd ? C3D_POINT ENDS C3D_MSG STRUCT hwnd dd ? message dd ? wParam dd ? lParam dd ? time dd ? pt C3D_POINT <> C3D_MSG ENDS C3D_WNDCLASSEX STRUCT cbSize dd ? style dd ? lpfnWndProc dd ? cbClsExtra dd ? cbWndExtra dd ? hInstance dd ? hIcon dd ? hCursor dd ? hbrBackground dd ? lpszMenuName dd ? lpszClassName dd ? hIconSm dd ? C3D_WNDCLASSEX ENDS C3D_BITMAPINFOHEADER STRUCT biSize dd ? biWidth dd ? biHeight dd ? biPlanes dw ? biBitCount dw ? biCompression dd ? biSizeImage dd ? biXPelsPerMeter dd ? biYPelsPerMeter dd ? biClrUsed dd ? biClrImportant dd ? C3D_BITMAPINFOHEADER ENDS C3D_BITMAPINFO STRUCT bmiHeader C3D_BITMAPINFOHEADER <> bmiColors dd ? C3D_BITMAPINFO ENDS SpriteObject STRUCT posX dd ? posY dd ? baseTexId dd ? frameCount dd ? curFrame dd ? animTimer dd ? animSpeed dd ? interactId dd ? promptPtr dd ? distSq dd ? SpriteObject ENDS SCREEN_W equ 640 SCREEN_H equ 480 HALF_W equ 320 HALF_H equ 240 SCREEN_SIZE equ (SCREEN_W * SCREEN_H) WIN_SCALE equ 1 WINDOW_W equ (SCREEN_W * WIN_SCALE) WINDOW_H equ (SCREEN_H * WIN_SCALE) FP_1 equ 65536 FP_HALF equ 32768 CHROMA_KEY equ 00FF00FFh MODE_WALK equ 0 MODE_SLOTS equ 1 MODE_BLACKJACK equ 2 MODE_ROULETTE equ 3 MODE_SHOP equ 4 MODE_ATM equ 5 MODE_COIN equ 6 MODE_DICE equ 7 MODE_SKULLS equ 8 WS_OVERLAPPEDWINDOW equ 00CF0000h SW_SHOW equ 5 SW_HIDE equ 0 PM_REMOVE equ 1 WM_DESTROY equ 0002h WM_CLOSE equ 0010h WM_QUIT equ 0012h CS_HREDRAW equ 2 CS_VREDRAW equ 1 DIB_RGB_COLORS equ 0 SRCCOPY equ 00CC0020h INVALID_FILE_HANDLE equ -1 include casino3d_data.inc include font8x8.inc include src_graphics\platform_data.inc .data ALIGN 4 h3DInst dd 0 h3DWnd dd 0 h3DDC dd 0 hCasinoConsole dd 0 bmi3D C3D_BITMAPINFO <> msg3D C3D_MSG <> wc3D C3D_WNDCLASSEX <> sz3DClassName db "Casino3DRetroClass",0 sz3DWindowTitle db "Assembler Casino - 2.5D",0 szTexturesRelPath db "assets\textures\casino3d-hd.bin",0 szTexturesFullPath db 260 dup(0) soundCoin db "assets\audio\Çâóê ìîíåòû áðîøåííîé â âîçäóõ è óïàâøåé íà ïîâåðõíîñòü.wav",0 soundCoinDing db "assets\audio\Çâóê ìîíåòû â èãðå Ultrakill.wav",0 soundCards db "assets\audio\playing_cards_deck_flick_through_001_20485.wav",0 soundRoulette db "assets\audio\roulette-wheel-throw-2.wav",0 soundJackpot db "assets\audio\Äæýê ïîò.wav",0 soundVictory db "assets\audio\victory-tf2.wav",0 soundClick db "assets\audio\revolverdryfirec.wav",0 soundShuffle db "assets\audio\moving-stone.wav",0 soundLose db "assets\audio\Ïðîèãðûø.wav",0 playerX dd (16 * FP_1 + FP_HALF) playerY dd (16 * FP_1 + FP_HALF) playerAngle dd 384 playerDirX dd 0 playerDirY dd -FP_1 playerPlaneX dd (FP_1 * 66 / 100) playerPlaneY dd 0 engineMode dd 0 interactTargetId dd 0 interactPromptPtr dd 0 dancerLuckBuff dd 0 flashTimer dd 0 flashMessage db 128 dup(0) promptDancer db "[E] ÊÀÁÀÐÅ - ×ÀÅÂÛÅ $100",0 promptBlackjack db "[E] ÁËÝÊÄÆÅÊ (21)",0 promptPoker db "[E] ÏÎÊÅÐ (TEXAS HOLD'EM)",0 promptDurak db "[E] ÊÀÐÒÛ: ÏÎÄÊÈÄÍÎÉ ÄÓÐÀÊ",0 promptCasinoRoulette db "[E] ÅÂÐÎÏÅÉÑÊÀß ÐÓËÅÒÊÀ",0 promptClassicSlot db "[E] ÊËÀÑÑÈ×ÅÑÊÈÅ ÑËÎÒÛ 777",0 promptCloverSlot db "[E] ÑËÎÒÛ CLOVERPIT (5x3)",0 promptDice db "[E] ÈÃÐÀ  ÊÎÑÒÈ (CRAPS)",0 promptSkulls db "[E] ÍÀϨÐÑÒÊÈ (×ÅÐÅÏÀ)",0 promptCoin db "[E] ÌÎÍÅÒÊÀ (ÎШË/ÐÅØÊÀ)",0 promptSkillCheck db "[E] ÒÐÅÍÈÐÎÂÊÀ ÐÅÀÊÖÈÈ",0 promptBuckshot db "[E] BUCKSHOT ROULETTE",0 promptRussianRoulette db "[E] ÐÓÑÑÊÀß ÐÓËÅÒÊÀ (VIP)",0 promptOnlineRR db "[E] ÑÅÒÅÂÀß ÐÓËÅÒÊÀ (NET)",0 promptUmamusume db "[E] ÑÊÀ×ÊÈ ÓÌÀÌÓÑÓÌÝ",0 promptHellTower db "[E] ÁÀØÍß ÀÄÀ (10 ÝÒÀÆÅÉ)",0 promptShop db "[E] ÁÓÒÈÊ È ÒÀËÈÑÌÀÍÛ",0 promptATM db "[E] ÁÀÍÊÎÌÀÒ È ÁÀËÀÍÑ",0 promptPlayerTerminal db "[E] ÒÅÐÌÈÍÀË: ÑÒÀÒÛ È À×ÈÂÊÈ",0 promptObserver db "[E] ÐÅÆÈÌ ÍÀÁËÞÄÀÒÅËß (ÈÈ)",0 szTitleBlackjack db "[KAZIK 3D CASINO] - ÁËÝÊÄÆÅÊ (21)",0 szTitlePoker db "[KAZIK 3D CASINO] - ÏÎÊÅÐ (TEXAS HOLD'EM)",0 szTitleDurak db "[KAZIK 3D CASINO] - ÏÎÄÊÈÄÍÎÉ ÄÓÐÀÊ",0 szTitleCasinoRoulette db "[KAZIK 3D CASINO] - ÅÂÐÎÏÅÉÑÊÀß ÐÓËÅÒÊÀ",0 szTitleClassicSlot db "[KAZIK 3D CASINO] - ÊËÀÑÑÈ×ÅÑÊÈÅ ÑËÎÒÛ 777",0 szTitleCloverSlot db "[KAZIK 3D CASINO] - ÑËÎÒ-ÌÀØÈÍÀ CLOVERPIT (5x3)",0 szTitleDice db "[KAZIK 3D CASINO] - ÈÃÐÀ  ÊÎÑÒÈ (CRAPS)",0 szTitleSkulls db "[KAZIK 3D CASINO] - ÍÀϨÐÑÒÊÈ",0 szTitleCoin db "[KAZIK 3D CASINO] - ÌÎÍÅÒÊÀ (ÎШË/ÐÅØÊÀ)",0 szTitleSkillCheck db "[KAZIK 3D CASINO] - ÏÐÎÂÅÐÊÀ ÐÅÀÊÖÈÈ",0 szTitleBuckshot db "[KAZIK 3D CASINO] - BUCKSHOT ROULETTE",0 szTitleRussianRoulette db "[KAZIK 3D CASINO] - ÐÓÑÑÊÀß ÐÓËÅÒÊÀ",0 szTitleOnlineRR db "[KAZIK 3D CASINO] - ÑÅÒÅÂÀß ÐÓÑÑÊÀß ÐÓËÅÒÊÀ",0 szTitleUmamusume db "[KAZIK 3D CASINO] - ÑÊÀ×ÊÈ ÓÌÀÌÓÑÓÌÝ",0 szTitleHellTower db "[KAZIK 3D CASINO] - ÁÀØÍß ÀÄÀ (ÒÓÐÍÈÐ)",0 szTitleShop db "[KAZIK 3D CASINO] - ÁÓÒÈÊ È ÒÀËÈÑÌÀÍÛ",0 szTitleATM db "[KAZIK 3D CASINO] - ÁÀÍÊÎÌÀÒ",0 szTitleTerminal db "[KAZIK 3D CASINO] - ÒÅÐÌÈÍÀË ÈÃÐÎÊÀ",0 szTitleObserver db "[KAZIK 3D CASINO] - ÐÅÆÈÌ ÍÀÁËÞÄÀÒÅËß (ÈÈ)",0 textCabinetFooter db "[ ÂÛÕÎÄ: ÂÂÅÄÈÒÅ 0 / ÂÛÁÅÐÈÒÅ 'N' ÄËß ÂÎÇÂÐÀÒÀ  ÇÀË ]",0 msgDancerTipped db "Âû áðîñèëè $100 òàíöîâùèöå! ÓÄÀ×À ÀÊÒÈÂÈÐÎÂÀÍÀ!",0 msgNeedMoney db "Íåäîñòàòî÷íî äåíåã â êîøåëüêå!",0 statusHUDFormat db "ÁÀÍÊÐÎËË: $",0 targetHUDFormat db " ÖÅËÜ: $",0 luckHUDFormat db " ÓÄÀ×À: +",0 controlsHUD db "WASD/Ñòðåëêè: Õîäüáà | E: Äåéñòâèå | ESC: Ìåíþ",0 NUM_SPRITES equ 22 INTERACT_NONE equ 0 INTERACT_BLACKJACK equ 1 INTERACT_POKER equ 2 INTERACT_SLOTS_777 equ 3 INTERACT_ROULETTE equ 4 INTERACT_SKULLS equ 5 INTERACT_SHOP equ 6 INTERACT_ATM equ 7 INTERACT_DANCER equ 8 INTERACT_HELL_TOWER equ 9 INTERACT_DURAK equ 10 INTERACT_BUCKSHOT equ 11 INTERACT_COIN equ 12 INTERACT_DICE equ 13 INTERACT_SLOTS_CLOVER equ 14 INTERACT_UMAMUSUME equ 15 INTERACT_OBSERVER equ 16 INTERACT_TERMINAL equ 17 INTERACT_ONLINE_RR equ 18 INTERACT_RUSSIAN_ROULETTE equ 19 INTERACT_SKILL_CHECK equ 20 ALIGN 4 casinoSprites SpriteObject NUM_SPRITES dup(<>) sortedSprites dd NUM_SPRITES dup(0) rowDistTable dd 120 dup(0) rngSeed3D dd 12345678h slotBet dd 50 slotReel1 dd 0 slotReel2 dd 1 slotReel3 dd 2 slotSpinState dd 0 slotSpinTimer dd 0 slotWinAmount dd 0 slotWinMsg db 64 dup(0) bjState dd 0 bjBet dd 100 bjPlayerCards dd 10 dup(0) bjPlayerCardCount dd 0 bjPlayerScore dd 0 bjDealerCards dd 10 dup(0) bjDealerCardCount dd 0 bjDealerScore dd 0 bjDealerHideHole dd 1 bjOutcomeMsg db 64 dup(0) roulState dd 0 roulBetType dd 1 roulBetAmount dd 100 roulWheelAngle dd 0 roulBallAngle dd 0 roulSpinTimer dd 0 roulWinningNum dd 0 roulPayout dd 0 roulOutcomeMsg db 64 dup(0) ; --- Native 2.5D Coin Flip Game --- coin3d_bet dd 50 coin3d_side dd 1 ; 1 = Îð¸ë, 2 = Ðåøêà coin3d_state dd 0 ; 0 = Idle, 1 = Flipping, 2 = Result coin3d_timer dd 0 coin3d_result dd 1 ; 1 = Îð¸ë, 2 = Ðåøêà coin3d_streak dd 0 coin3d_win dd 0 coinRxAnimTable db 26, 22, 16, 6, 16, 22, 26, 22, 16, 6 ; --- Native 2.5D Coin Flip --- textCoinTitle db "* * * Ç Î Ë Î Ò À ß Ì Î Í Å Ò À * * *",0 textCoinHeads db "ÎШË",0 textCoinTails db "ÐÅØÊÀ",0 textCoinStreak db "ÑÅÐÈß: ",0 textCoinSide1 db "[1] ÎШË",0 textCoinSide2 db "[2] ÐÅØÊÀ",0 textCoinFlipping db "ÌÎÍÅÒÀ  ÏÎ˨ÒÅ...",0 textCoinWin db "ÂÛÈÃÐÛØ: +$",0 textCoinLose db "ÍÅ ÓÃÀÄÀË!",0 textCoinKey1 db "1:ÎШË",0 textCoinKey2 db "2:ÐÅØÊÀ",0 textCoinKeySpace db "ÏÐÎÁÅË:ÁÐÎÑÎÊ",0 textCoinStreakFmt db "ÑÅÐÈß: [X] [X] [X] [ ] [ ] x4!",0 ; --- Native 2.5D Dice Game --- dice3d_bet dd 50 dice3d_choice dd 1 ; 1 = ׸ò, 2 = Íå÷åò dice3d_state dd 0 ; 0 = Idle, 1 = Rolling, 2 = Result dice3d_timer dd 0 dice3d_val1 dd 4 dice3d_val2 dd 6 dice3d_sum dd 10 dice3d_win dd 0 textDiceTitle db "=== G R A N D C R A P S ===",0 textDiceSubtitle db "[ PASS LINE ] [ ANY CRAPS ]",0 textDiceEven db "[1] רÒ",0 textDiceOdd db "[2] ÍÅ×ÅÒ",0 textDiceEvenNums db "2 4 6 8 10",0 textDiceOddNums db "3 5 7 9 11",0 textDiceSumHdr db "ÑÓÌÌÀ: ",0 textDicePlus db " + ",0 textDiceEqual db " = ",0 textDiceEvenResult db " (רÒ)",0 textDiceOddResult db " (ÍÅ×ÅÒ)",0 textDiceRolling db "ÊÎÑÒÈ ËÅÒßÒ ÏÎ ÑÓÊÍÓ...",0 textDiceWin db "ÂÛÈÃÐÛØ: +$",0 textDiceWinMult db "! (x2)",0 textDiceLose db "ÏÐÎÈÃÐÛØ!",0 textDiceKey1 db "1:רÒ",0 textDiceKey2 db "2:ÍÅ×ÅÒ",0 textDiceKeySpace db "ÏÐÎÁÅË:ÁÐÎÑÎÊ",0 ; --- Native 2.5D Skulls Game --- skulls3d_bet dd 50 skulls3d_state dd 0 ; 0 = Idle, 1 = Show ball, 2 = Shuffle, 3 = Pick, 4 = Reveal skulls3d_timer dd 0 skulls3d_ballPos dd 1 ; 0, 1, 2 skulls3d_choice dd 1 ; 0, 1, 2 skulls3d_win dd 0 skulls3d_swapPair0 dd 0 skulls3d_swapPair1 dd 1 skulls3d_swapPair2 dd 2 textSkullsTitle db "+ + + Í À Ï ¨ Ð Ñ Ò Ê È + + +",0 textSkullsPhase0 db "ÄÅËÀÉ ÑÒÀÂÊÓ È ÆÌÈ [ÏÐÎÁÅË]",0 textSkullsPhase1 db "ÑÌÎÒÐÈ, ÃÄÅ ÇÎËÎÒÎÉ ØÀÐ...",0 textSkullsPhase2 db "ÊÐÓ×Ó, ÂÅÐ×Ó, ÇÀÏÓÒÀÒÜ ÕÎ×Ó...",0 textSkullsPhase3 db "ÃÄÅ ØÀÐ? ÂÛÁÈÐÀÉ: [1], [2] ÈËÈ [3]!",0 textSkullsWin db "ÂÅÐÍÎ! ÂÛÏËÀÒÀ x3! +$",0 textSkullsLose db "ÌÈÌÎ! ØÀÐ ÁÛË Â ÄÐÓÃÎÌ ÌÅÑÒÅ!",0 textSkullsAgain db "[ÏÐÎÁÅË] - ÑÛÃÐÀÒÜ ÅÙ¨ ÐÀÇ",0 textSkullsKey1 db "1:ÊÓÁÎÊ",0 textSkullsKey2 db "2:ÊÓÁÎÊ",0 textSkullsKey3 db "3:ÊÓÁÎÊ",0 textSkullsKeySpace db "ÏÐÎÁÅË",0 ; --- Shared UI Strings --- textKeyEsc db "ESC",0 textBankPrompt db "ÁÀÍÊ: $",0 textBetPrompt db "ÑÒÀÂÊÀ: $",0 textBetHint db " [W/S]",0 shopMsg db 128 dup(0) atmMsg db 128 dup(0) strWin db "ÏÎÁÅÄÀ! +$",0 strLose db "ÏÐÎÈÃÐÛØ",0 strJackpot db "ÄÆÅÊÏÎÒ! +$",0 strPush db "ÍÈ×Üß (PUSH)",0 strDealerBust db "ÄÈËÅÐ ÏÅÐÅÁÐÀË! ÏÎÁÅÄÀ! +$",0 strPlayerBust db "ÏÅÐÅÁÎÐ (>21)! ÏÐÎÈÃÐÛØ",0 sym7 db " 777 ",0 symBar db " BAR ",0 symBell db " BELL",0 symCherry db "CHERRY",0 symClover db "CLOVER",0 symGem db " GEM ",0 symCrown db "CROWN",0 cardRankStr db "A ",0,"2 ",0,"3 ",0,"4 ",0,"5 ",0,"6 ",0,"7 ",0,"8 ",0,"9 ",0,"10",0,"J ",0,"Q ",0,"K ",0 .data? ALIGN 4 screenBuffer dd SCREEN_SIZE dup(?) ALIGN 4 zBuffer dd SCREEN_W dup(?) ALIGN 4 texturesBuffer dd (48 * 128 * 128) dup(?) hudNumBuffer db 32 dup(?) .code ; --- 3D Window Procedure --- Casino3DWndProc PROC hwnd:DWORD, uMsg:DWORD, wParam:DWORD, lParam:DWORD invoke WindowEvents3D, hwnd, uMsg, wParam, lParam ret Casino3DWndProc ENDP ; --- Random Generator --- RandomRange3D PROC maxVal:DWORD mov eax, rngSeed3D imul eax, 1103515245 add eax, 12345 mov rngSeed3D, eax shr eax, 16 and eax, 7FFFh xor edx, edx div maxVal mov eax, edx ret RandomRange3D ENDP ; --- Copy String --- CopyString3D PROC src:DWORD, dst:DWORD push esi push edi mov esi, src mov edi, dst @@: mov al, [esi] mov [edi], al test al, al jz @F inc esi inc edi jmp @B @@: pop edi pop esi ret CopyString3D ENDP ; --- Format Number to Decimal String --- FormatNumber PROC num:DWORD, buf:DWORD push ebx push esi push edi mov eax, num mov edi, buf test eax, eax jns fn_pos mov BYTE PTR [edi], '-' inc edi neg eax fn_pos: mov ebx, 10 push 0 fn_div: xor edx, edx div ebx add dl, '0' push edx test eax, eax jnz fn_div fn_pop: pop eax test al, al jz fn_done mov [edi], al inc edi jmp fn_pop fn_done: mov BYTE PTR [edi], 0 pop edi pop esi pop ebx ret FormatNumber ENDP ; --- Fast 2D Drawing Primitives --- DrawBox PROTO :DWORD,:DWORD,:DWORD,:DWORD,:DWORD DrawPixel PROC x:DWORD, y:DWORD, color:DWORD invoke DrawBox, x, y, 1, 1, color ret DrawPixel ENDP DrawBox PROC x:DWORD, y:DWORD, w:DWORD, h:DWORD, color:DWORD shl x, 1 shl y, 1 shl w, 1 shl h, 1 push ebx push esi push edi mov edi, y box_row_loop: mov eax, y add eax, h cmp edi, eax jge box_done cmp edi, 0 jl next_box_row cmp edi, SCREEN_H jge box_done mov esi, x box_col_loop: mov eax, x add eax, w cmp esi, eax jge next_box_row cmp esi, 0 jl next_box_col cmp esi, SCREEN_W jge next_box_row mov ecx, edi imul ecx, SCREEN_W add ecx, esi mov edx, color mov [screenBuffer + ecx*4], edx next_box_col: inc esi jmp box_col_loop next_box_row: inc edi jmp box_row_loop box_done: pop edi pop esi pop ebx ret DrawBox ENDP DrawBoxBorder PROC uses ebx x:DWORD, y:DWORD, w:DWORD, h:DWORD, fillColor:DWORD, borderColor:DWORD, bWidth:DWORD invoke DrawBox, x, y, w, h, borderColor mov eax, x add eax, bWidth mov edx, y add edx, bWidth mov ecx, w sub ecx, bWidth sub ecx, bWidth mov ebx, h sub ebx, bWidth sub ebx, bWidth invoke DrawBox, eax, edx, ecx, ebx, fillColor ret DrawBoxBorder ENDP DrawCircle PROC cxVal:DWORD, cyVal:DWORD, radius:DWORD, color:DWORD push ebx push esi push edi mov eax, radius neg eax mov edi, eax circ_y: cmp edi, radius jg circ_done mov eax, radius neg eax mov esi, eax circ_x: cmp esi, radius jg next_circ_y mov eax, esi imul eax, eax mov ebx, edi imul ebx, ebx add eax, ebx mov edx, radius imul edx, edx cmp eax, edx jg next_circ_x mov eax, cxVal add eax, esi mov ecx, cyVal add ecx, edi invoke DrawPixel, eax, ecx, color next_circ_x: inc esi jmp circ_x next_circ_y: inc edi jmp circ_y circ_done: pop edi pop esi pop ebx ret DrawCircle ENDP DrawChar8x8 PROC uses ebx esi edi x:DWORD, y:DWORD, chVal:DWORD, color:DWORD local column:DWORD mov eax, chVal and eax, 255 lea esi, [font8x8 + eax*8] xor edi, edi glyph_row: movzx ebx, BYTE PTR [esi+edi] mov column, 0 glyph_col: test ebx, 80h jz glyph_next mov eax, x add eax, column mov edx, y add edx, edi invoke DrawPixel, eax, edx, color glyph_next: shl ebx, 1 inc column cmp column, 8 jl glyph_col inc edi cmp edi, 8 jl glyph_row ret DrawChar8x8 ENDP DrawString8x8 PROC x:DWORD, y:DWORD, strPtr:DWORD, color:DWORD push ebx push esi mov esi, strPtr mov ebx, x str_loop: movzx eax, BYTE PTR [esi] test al, al jz str_done invoke DrawChar8x8, ebx, y, eax, color add ebx, 8 inc esi jmp str_loop str_done: pop esi pop ebx ret DrawString8x8 ENDP ; --- True 3D Perspective Floor & Ceiling Rendering --- RenderCeilingAndFloor PROC uses ebx esi edi local floorRow:DWORD local pDist:DWORD local fStepX:DWORD local fStepY:DWORD local fX:DWORD local fY:DWORD local shade:DWORD local cShade:DWORD ; Horizon line: row 120 mov edi, HALF_H floor_scanlines: cmp edi, SCREEN_H jge floor_done mov floorRow, edi ; Distance = (HALF_H * FP_1) / (y - HALF_H) mov eax, edi sub eax, HALF_H inc eax mov ecx, eax mov eax, HALF_H * FP_1 cdq idiv ecx mov pDist, eax ; Distance shading (closer is brighter, far horizon is dark) mov edx, pDist shr edx, 13 mov eax, 255 sub eax, edx cmp eax, 35 jge @F mov eax, 35 @@: mov shade, eax mov edx, eax sub edx, 25 cmp edx, 20 jge @F mov edx, 20 @@: mov cShade, edx ; Step along scanline: (2 * playerPlane) * pDist / SCREEN_W mov eax, playerPlaneX shl eax, 1 imul pDist shrd eax, edx, 16 cdq mov ecx, SCREEN_W idiv ecx mov fStepX, eax mov eax, playerPlaneY shl eax, 1 imul pDist shrd eax, edx, 16 cdq mov ecx, SCREEN_W idiv ecx mov fStepY, eax ; Starting floor coordinates at x=0: ; player + pDist * (playerDir - playerPlane) mov eax, playerDirX sub eax, playerPlaneX imul pDist shrd eax, edx, 16 add eax, playerX mov fX, eax mov eax, playerDirY sub eax, playerPlaneY imul pDist shrd eax, edx, 16 add eax, playerY mov fY, eax ; Fill scanline for floor (y) and ceiling (SCREEN_H - 1 - y) xor esi, esi col_floor_loop: cmp esi, SCREEN_W jge next_floor_row ; Carpet Texture (Slot 3: 3 * 4096 * 4 = 49152 bytes) mov eax, fX shr eax, 9 and eax, 127 mov edx, fY shr edx, 9 and edx, 127 shl edx, 7 add edx, eax mov eax, [texturesBuffer + (3 * 128 * 128 * 4) + edx*4] ; Shade Floor RGB mov ebx, shade movzx ecx, al imul ecx, ebx shr ecx, 8 push ecx movzx ecx, ah imul ecx, ebx shr ecx, 8 shl ecx, 8 shr eax, 16 movzx eax, al imul eax, ebx shr eax, 8 shl eax, 16 or eax, ecx pop ecx or eax, ecx ; Store to Floor pixel mov ecx, floorRow imul ecx, SCREEN_W add ecx, esi mov [screenBuffer + ecx*4], eax ; Ceiling Spotlight Texture (Slot 5: 5 * 4096 * 4 = 81920 bytes) mov eax, [texturesBuffer + (5 * 128 * 128 * 4) + edx*4] mov ebx, cShade movzx ecx, al imul ecx, ebx shr ecx, 8 push ecx movzx ecx, ah imul ecx, ebx shr ecx, 8 shl ecx, 8 shr eax, 16 movzx eax, al imul eax, ebx shr eax, 8 shl eax, 16 or eax, ecx pop ecx or eax, ecx ; Store to Ceiling pixel: (SCREEN_H - 1 - floorRow) mov ecx, SCREEN_H - 1 sub ecx, floorRow imul ecx, SCREEN_W add ecx, esi mov [screenBuffer + ecx*4], eax mov eax, fStepX add fX, eax mov eax, fStepY add fY, eax inc esi jmp col_floor_loop next_floor_row: inc edi jmp floor_scanlines floor_done: ret RenderCeilingAndFloor ENDP ; --- DDA Raycasting Walls --- RenderWalls PROC local col:DWORD local camX:DWORD local rayDirX:DWORD local rayDirY:DWORD local mapX:DWORD local mapY:DWORD local deltaDistX:DWORD local deltaDistY:DWORD local stepX:DWORD local stepY:DWORD local sideDistX:DWORD local sideDistY:DWORD local side:DWORD local perpWallDist:DWORD local lineH:DWORD local drawStart:DWORD local drawEnd:DWORD local wallHit:DWORD local texX:DWORD local texId:DWORD local shade:DWORD push ebx push esi push edi mov eax, playerAngle and eax, 511 mov ebx, [tableCos + eax*4] mov playerDirX, ebx mov ebx, [tableSin + eax*4] mov playerDirY, ebx mov eax, ebx imul eax, -66 cdq mov ecx, 100 idiv ecx mov playerPlaneX, eax mov eax, playerDirX imul eax, 66 cdq idiv ecx mov playerPlaneY, eax mov col, 0 col_loop: cmp col, SCREEN_W jge walls_done mov eax, col shl eax, 1 sub eax, SCREEN_W imul eax, FP_1 cdq mov ecx, SCREEN_W idiv ecx mov camX, eax mov eax, playerPlaneX imul camX shrd eax, edx, 16 add eax, playerDirX mov rayDirX, eax mov eax, playerPlaneY imul camX shrd eax, edx, 16 add eax, playerDirY mov rayDirY, eax mov eax, playerX sar eax, 16 mov mapX, eax mov eax, playerY sar eax, 16 mov mapY, eax mov eax, rayDirX test eax, eax jnz calc_delta_x mov deltaDistX, 7FFFFFFFh jmp calc_delta_y calc_delta_x: test eax, eax jns @F neg eax @@: mov ebx, eax cmp ebx, 4 jbe delta_x_clamp xor eax, eax mov edx, 1 div ebx mov deltaDistX, eax jmp calc_delta_y delta_x_clamp: mov deltaDistX, 7FFFFFFFh calc_delta_y: mov eax, rayDirY test eax, eax jnz calc_delta_y_ok mov deltaDistY, 7FFFFFFFh jmp check_step calc_delta_y_ok: test eax, eax jns @F neg eax @@: mov ebx, eax cmp ebx, 4 jbe delta_y_clamp xor eax, eax mov edx, 1 div ebx mov deltaDistY, eax jmp check_step delta_y_clamp: mov deltaDistY, 7FFFFFFFh check_step: cmp rayDirX, 0 jge step_x_pos mov stepX, -1 mov eax, playerX mov edx, mapX shl edx, 16 sub eax, edx imul deltaDistX shrd eax, edx, 16 mov sideDistX, eax jmp check_step_y step_x_pos: mov stepX, 1 mov eax, mapX inc eax shl eax, 16 sub eax, playerX imul deltaDistX shrd eax, edx, 16 mov sideDistX, eax check_step_y: cmp rayDirY, 0 jge step_y_pos mov stepY, -1 mov eax, playerY mov edx, mapY shl edx, 16 sub eax, edx imul deltaDistY shrd eax, edx, 16 mov sideDistY, eax jmp dda_start step_y_pos: mov stepY, 1 mov eax, mapY inc eax shl eax, 16 sub eax, playerY imul deltaDistY shrd eax, edx, 16 mov sideDistY, eax dda_start: xor ecx, ecx dda_step_loop: inc ecx cmp ecx, 64 jge hit_wall mov eax, sideDistX cmp eax, sideDistY jge step_in_y mov eax, deltaDistX add sideDistX, eax mov eax, stepX add mapX, eax mov side, 0 jmp check_tile step_in_y: mov eax, deltaDistY add sideDistY, eax mov eax, stepY add mapY, eax mov side, 1 check_tile: cmp mapX, 0 jl hit_wall cmp mapX, MAP_WIDTH jge hit_wall cmp mapY, 0 jl hit_wall cmp mapY, MAP_HEIGHT jge hit_wall mov eax, mapY shl eax, 5 add eax, mapX movzx eax, BYTE PTR [casinoMap + eax] test eax, eax jnz hit_wall jmp dda_step_loop hit_wall: cmp side, 0 jne perp_y mov eax, sideDistX sub eax, deltaDistX mov perpWallDist, eax jmp perp_done perp_y: mov eax, sideDistY sub eax, deltaDistY mov perpWallDist, eax perp_done: cmp perpWallDist, 2048 jge @F mov perpWallDist, 2048 @@: mov eax, col mov edx, perpWallDist mov [zBuffer + eax*4], edx ; High casino ceiling: lineH = (SCREEN_H * FP_1 * 180 / 240) / perpWallDist mov eax, SCREEN_H imul eax, FP_1 cdq idiv perpWallDist mov lineH, eax mov eax, lineH shr eax, 1 mov ecx, HALF_H sub ecx, eax mov drawStart, ecx mov eax, lineH shr eax, 1 mov ecx, HALF_H add ecx, eax mov drawEnd, ecx cmp side, 0 jne hit_side_y mov eax, perpWallDist imul rayDirY shrd eax, edx, 16 add eax, playerY mov wallHit, eax jmp calc_tex_x hit_side_y: mov eax, perpWallDist imul rayDirX shrd eax, edx, 16 add eax, playerX mov wallHit, eax calc_tex_x: ; MASK WITH 0FFFFh to prevent texture scrambling! mov eax, wallHit and eax, 0FFFFh shr eax, 9 and eax, 127 mov texX, eax cmp side, 0 jne @F cmp rayDirX, 0 jle @F mov eax, 127 sub eax, texX mov texX, eax @@: cmp side, 1 jne select_tex cmp rayDirY, 0 jge select_tex mov eax, 127 sub eax, texX mov texX, eax select_tex: mov eax, mapY shl eax, 5 add eax, mapX movzx eax, BYTE PTR [casinoMap + eax] mov texId, eax cmp texId, 0 jne @F mov texId, 1 @@: mov eax, perpWallDist shr eax, 13 mov edx, 256 sub edx, eax cmp edx, 75 jge @F mov edx, 75 @@: cmp side, 1 jne @F imul edx, 3 shr edx, 2 @@: mov shade, edx cmp drawStart, 0 jge @F mov drawStart, 0 @@: cmp drawEnd, SCREEN_H jl @F mov drawEnd, SCREEN_H - 1 @@: mov eax, lineH cmp eax, 1 jge @F mov eax, 1 mov lineH, eax @@: mov eax, 128 * FP_1 cdq idiv lineH mov esi, eax ; stepY mov eax, lineH shr eax, 1 add eax, drawStart sub eax, HALF_H imul eax, esi mov edi, eax ; texPos mov ecx, drawStart draw_stripe_loop: cmp ecx, drawEnd jg next_col mov eax, edi shr eax, 16 and eax, 127 shl eax, 7 add eax, texX mov edx, texId shl edx, 14 add eax, edx mov eax, [texturesBuffer + eax*4] ; Shade wall pixel mov ebx, shade movzx edx, al imul edx, ebx shr edx, 8 push edx movzx edx, ah imul edx, ebx shr edx, 8 shl edx, 8 shr eax, 16 movzx eax, al imul eax, ebx shr eax, 8 shl eax, 16 or eax, edx pop edx or eax, edx mov edx, ecx imul edx, SCREEN_W add edx, col mov [screenBuffer + edx*4], eax add edi, esi inc ecx jmp draw_stripe_loop next_col: inc col jmp col_loop walls_done: pop edi pop esi pop ebx ret RenderWalls ENDP ; --- Render 3D Billboard Sprites --- RenderSprites PROC local sprIdx:DWORD local relX:DWORD local relY:DWORD local invDet:DWORD local transX:DWORD local transY:DWORD local sprScreenX:DWORD local sprH:DWORD local sprW:DWORD local drawStartY:DWORD local drawEndY:DWORD local drawStartX:DWORD local drawEndX:DWORD local stripe:DWORD local texX:DWORD local texY:DWORD local shade:DWORD local texSlot:DWORD push ebx push esi push edi xor esi, esi calc_dist_loop: cmp esi, NUM_SPRITES jge sort_sprites mov eax, esi imul eax, SIZEOF SpriteObject mov edx, [casinoSprites + eax].posX sub edx, playerX sar edx, 8 imul edx, edx mov ebx, edx mov edx, [casinoSprites + eax].posY sub edx, playerY sar edx, 8 imul edx, edx add ebx, edx mov [casinoSprites + eax].distSq, ebx mov [sortedSprites + esi*4], esi inc esi jmp calc_dist_loop sort_sprites: xor esi, esi sort_outer: cmp esi, NUM_SPRITES - 1 jge render_sorted_sprites mov edi, esi inc edi sort_inner: cmp edi, NUM_SPRITES jge next_sort_outer mov eax, [sortedSprites + esi*4] imul eax, SIZEOF SpriteObject mov eax, [casinoSprites + eax].distSq mov ebx, [sortedSprites + edi*4] imul ebx, SIZEOF SpriteObject mov ebx, [casinoSprites + ebx].distSq cmp eax, ebx jge @F mov ecx, [sortedSprites + esi*4] mov edx, [sortedSprites + edi*4] mov [sortedSprites + esi*4], edx mov [sortedSprites + edi*4], ecx @@: inc edi jmp sort_inner next_sort_outer: inc esi jmp sort_outer render_sorted_sprites: xor esi, esi draw_spr_loop: cmp esi, NUM_SPRITES jge sprites_rendered mov eax, [sortedSprites + esi*4] mov sprIdx, eax imul eax, SIZEOF SpriteObject ; Sample animation by elapsed time. Pausing freezes the clock. push eax mov ecx, [casinoSprites + eax].animSpeed cmp ecx, 0 jg @F mov ecx, 1 @@: imul ecx, 40 mov eax, animationClock3D xor edx, edx div ecx pop ebx mov ecx, [casinoSprites + ebx].frameCount cmp ecx, 0 jg @F mov ecx, 1 @@: xor edx, edx div ecx mov [casinoSprites + ebx].curFrame, edx mov eax, ebx cmp [casinoSprites + eax].distSq, 16 jle next_spr mov edx, [casinoSprites + eax].posX sub edx, playerX mov relX, edx mov edx, [casinoSprites + eax].posY sub edx, playerY mov relY, edx mov eax, playerPlaneX imul playerDirY shrd eax, edx, 16 mov ebx, eax mov eax, playerDirX imul playerPlaneY shrd eax, edx, 16 sub ebx, eax mov eax, ebx test eax, eax jns @F neg eax @@: cmp eax, 4 jbe next_spr ; 2^32 needs the full EDX:EAX dividend, not a truncated multiply. xor eax, eax mov edx, 1 idiv ebx mov invDet, eax mov eax, playerDirY imul relX shrd eax, edx, 16 mov ebx, eax mov eax, playerDirX imul relY shrd eax, edx, 16 sub ebx, eax mov eax, ebx imul invDet shrd eax, edx, 16 mov transX, eax mov eax, playerPlaneY neg eax imul relX shrd eax, edx, 16 mov ebx, eax mov eax, playerPlaneX imul relY shrd eax, edx, 16 add ebx, eax mov eax, ebx imul invDet shrd eax, edx, 16 mov transY, eax cmp transY, 4096 jle next_spr mov eax, transX imul eax, HALF_W cdq idiv transY add eax, HALF_W mov sprScreenX, eax mov eax, SCREEN_H imul eax, FP_1 cdq idiv transY test eax, eax jns @F neg eax @@: cmp eax, 1 jge @F jmp next_spr @@: cmp eax, SCREEN_H * 2 jle @F mov eax, SCREEN_H * 2 @@: mov sprH, eax mov sprW, eax mov eax, HALF_H mov ebx, sprH shr ebx, 1 sub eax, ebx mov drawStartY, eax add eax, sprH mov drawEndY, eax mov eax, sprScreenX mov ebx, sprW shr ebx, 1 sub eax, ebx mov drawStartX, eax add eax, sprW mov drawEndX, eax cmp drawStartY, 0 jge @F mov drawStartY, 0 @@: cmp drawEndY, SCREEN_H jl @F mov drawEndY, SCREEN_H - 1 @@: mov eax, transY shr eax, 13 mov edx, 256 sub edx, eax cmp edx, 110 jge @F mov edx, 110 @@: mov shade, edx mov eax, sprIdx imul eax, SIZEOF SpriteObject mov edx, [casinoSprites + eax].baseTexId add edx, [casinoSprites + eax].curFrame mov texSlot, edx mov eax, drawStartX mov stripe, eax spr_stripe_loop: mov eax, stripe cmp eax, drawEndX jge next_spr cmp eax, 0 jl next_spr_stripe cmp eax, SCREEN_W jge next_spr mov edx, transY cmp edx, [zBuffer + eax*4] jge next_spr_stripe mov eax, stripe sub eax, sprScreenX mov ebx, sprW shr ebx, 1 add eax, ebx shl eax, 7 cdq idiv sprW cmp eax, 0 jl next_spr_stripe cmp eax, 128 jge next_spr_stripe mov texX, eax mov edi, drawStartY spr_pix_y_loop: cmp edi, drawEndY jg next_spr_stripe mov eax, edi sub eax, HALF_H mov ebx, sprH shr ebx, 1 add eax, ebx shl eax, 7 cdq idiv sprH cmp eax, 0 jl next_spr_y cmp eax, 128 jge next_spr_y mov texY, eax shl eax, 7 add eax, texX mov edx, texSlot shl edx, 14 add eax, edx mov eax, [texturesBuffer + eax*4] ; Chromakey magenta filter cmp eax, CHROMA_KEY je next_spr_y do_draw_sprite_pix: mov ebx, shade movzx edx, al imul edx, ebx shr edx, 8 push edx movzx edx, ah imul edx, ebx shr edx, 8 shl edx, 8 shr eax, 16 movzx eax, al imul eax, ebx shr eax, 8 shl eax, 16 or eax, edx pop edx or eax, edx mov ecx, edi imul ecx, SCREEN_W add ecx, stripe mov [screenBuffer + ecx*4], eax next_spr_y: inc edi jmp spr_pix_y_loop next_spr_stripe: inc stripe jmp spr_stripe_loop next_spr: inc esi jmp draw_spr_loop sprites_rendered: pop edi pop esi pop ebx ret RenderSprites ENDP ; --- HUD & Minimap Radar --- RenderHUD PROC uses ebx esi edi invoke DrawBox, 0, 0, 320, 16, 0014191Dh invoke DrawString8x8, 8, 4, OFFSET textBank3D, 00D8BC6Ah invoke FormatNumber, bankroll, OFFSET hudNumBuffer invoke DrawString8x8, 64, 4, OFFSET hudNumBuffer, 00FFFFFFh invoke DrawString8x8, 176, 4, OFFSET textWindowKeys3D, 00A8B6BBh invoke DrawBox, 0, 226, 320, 14, 0014191Dh invoke DrawString8x8, 12, 230, OFFSET textWalkKeys3D, 00A8B6BBh invoke DrawBox, 159, 118, 2, 5, 00E7DFC8h invoke DrawBox, 157, 120, 6, 1, 00E7DFC8h cmp interactPromptPtr, 0 je @F invoke DrawBoxBorder, 4, 199, 312, 18, 0014191Dh, 00D8BC6Ah, 1 invoke DrawString8x8, 10, 204, interactPromptPtr, 00F5E2B0h @@: cmp flashTimer, 0 je hud_finished dec flashTimer invoke DrawBox, 4, 22, 312, 16, 0014191Dh invoke DrawString8x8, 10, 26, OFFSET flashMessage, 00FFFFFFh hud_finished: ret RenderHUD ENDP RenderMinimap PROC uses ebx esi edi local radarX:DWORD local radarY:DWORD local radarSize:DWORD mov radarX, 320 - 48 mov radarY, 20 mov radarSize, 44 invoke DrawBoxBorder, radarX, radarY, radarSize, radarSize, 00101510h, 0000D7FFh, 1 ; Draw Sprites on radar xor esi, esi radar_spr_loop: cmp esi, NUM_SPRITES jge draw_player_radar mov eax, esi imul eax, SIZEOF SpriteObject mov eax, [casinoSprites + eax].posX sar eax, 16 imul eax, radarSize shr eax, 5 add eax, radarX mov ebx, eax mov eax, esi imul eax, SIZEOF SpriteObject mov eax, [casinoSprites + eax].posY sar eax, 16 imul eax, radarSize shr eax, 5 add eax, radarY invoke DrawPixel, ebx, eax, 00FFAA00h inc esi jmp radar_spr_loop draw_player_radar: mov eax, playerX sar eax, 16 imul eax, radarSize shr eax, 5 add eax, radarX mov ebx, eax mov eax, playerY sar eax, 16 imul eax, radarSize shr eax, 5 add eax, radarY invoke DrawCircle, ebx, eax, 2, 000000FFh ret RenderMinimap ENDP ; ============================================================================== ; IN-ENGINE 2.5D MINI-GAME: SLOTS 777 ; ============================================================================== HandleSlotsInput PROC cmp slotSpinState, 1 je slots_input_done invoke Pressed3D, 20h ; SPACE -> Spin test ah, 80h jz check_bet_adjust mov eax, bankroll cmp eax, slotBet jl @F sub eax, slotBet mov bankroll, eax mov slotSpinState, 1 mov slotSpinTimer, 0 mov slotWinAmount, 0 invoke PlaySoundA, OFFSET soundClick, 0, 1 jmp slots_input_done @@: invoke CopyString3D, OFFSET msgNeedMoney, OFFSET flashMessage mov flashTimer, 60 check_bet_adjust: invoke Pressed3D, 26h ; UP / W test ah, 80h jnz inc_bet invoke Pressed3D, 57h test ah, 80h jz check_bet_down inc_bet: cmp slotBet, 500 jge slots_input_done cmp slotBet, 100 jge @F cmp slotBet, 50 jge set_100 mov slotBet, 50 jmp slots_input_done set_100: mov slotBet, 100 jmp slots_input_done @@: mov slotBet, 500 jmp slots_input_done check_bet_down: invoke Pressed3D, 28h ; DOWN / S test ah, 80h jnz dec_bet invoke Pressed3D, 53h test ah, 80h jz slots_input_done dec_bet: cmp slotBet, 50 jle set_10 cmp slotBet, 100 jle set_50 mov slotBet, 100 jmp slots_input_done set_50: mov slotBet, 50 jmp slots_input_done set_10: mov slotBet, 10 slots_input_done: ret HandleSlotsInput ENDP RenderSlotsGame PROC uses ebx esi edi ; Cabinet Background (Dark Cherry Wood & Gold) invoke DrawBox, 0, 0, SCREEN_W, SCREEN_H, 00150A10h invoke DrawBoxBorder, 10, 10, 300, 220, 00251015h, 0000D7FFh, 3 ; Illuminated Top Marquee invoke DrawBoxBorder, 25, 20, 270, 32, 000A0505h, 0000FFFFh, 2 invoke DrawString8x8, 55, 32, OFFSET textSlots3D, 0000D7FFh ; Spinning Animation Logic cmp slotSpinState, 1 jne draw_reels inc slotSpinTimer cmp slotSpinTimer, 22 jge @F invoke RandomRange3D, 7 mov slotReel1, eax @@: cmp slotSpinTimer, 36 jge @F invoke RandomRange3D, 7 mov slotReel2, eax @@: cmp slotSpinTimer, 50 jge @F invoke RandomRange3D, 7 mov slotReel3, eax @@: cmp slotSpinTimer, 50 jl draw_reels ; Spin finished! Check outcome! mov slotSpinState, 0 mov eax, slotReel1 cmp eax, slotReel2 jne check_pairs cmp eax, slotReel3 jne check_pairs ; 3 Matching! cmp eax, 0 ; 777! jne @F mov eax, slotBet imul eax, 25 mov slotWinAmount, eax add bankroll, eax invoke PlaySoundA, OFFSET soundJackpot, 0, 1 jmp draw_reels @@: cmp eax, 6 ; CROWN! jne @F mov eax, slotBet imul eax, 50 mov slotWinAmount, eax add bankroll, eax invoke PlaySoundA, OFFSET soundJackpot, 0, 1 jmp draw_reels @@: mov eax, slotBet imul eax, 10 mov slotWinAmount, eax add bankroll, eax invoke PlaySoundA, OFFSET soundCoin, 0, 1 jmp draw_reels check_pairs: mov eax, slotReel1 cmp eax, slotReel2 je pair_win mov eax, slotReel2 cmp eax, slotReel3 je pair_win mov eax, slotReel1 cmp eax, slotReel3 je pair_win jmp draw_reels pair_win: mov eax, slotBet imul eax, 2 mov slotWinAmount, eax add bankroll, eax invoke PlaySoundA, OFFSET soundCoin, 0, 1 draw_reels: ; Reels Window invoke DrawBoxBorder, 30, 62, 260, 95, 000F0F12h, 0000A5FFh, 2 ; Reel 1 (45..105) invoke DrawBoxBorder, 45, 68, 65, 82, 00F0F0F5h, 00505050h, 2 mov eax, slotReel1 call DrawReelSymbolAt1 ; Reel 2 (128..188) invoke DrawBoxBorder, 128, 68, 65, 82, 00F0F0F5h, 00505050h, 2 mov eax, slotReel2 call DrawReelSymbolAt2 ; Reel 3 (210..270) invoke DrawBoxBorder, 210, 68, 65, 82, 00F0F0F5h, 00505050h, 2 mov eax, slotReel3 call DrawReelSymbolAt3 ; Bottom Control Panel invoke DrawBoxBorder, 20, 165, 280, 58, 00151515h, 0000D7FFh, 1 invoke DrawString8x8, 28, 172, OFFSET textBank3D, 0000D7FFh invoke FormatNumber, bankroll, OFFSET hudNumBuffer invoke DrawString8x8, 110, 172, OFFSET hudNumBuffer, 0000FFFFh invoke DrawString8x8, 175, 172, OFFSET textBet3D, 0000D7FFh invoke FormatNumber, slotBet, OFFSET hudNumBuffer invoke DrawString8x8, 240, 172, OFFSET hudNumBuffer, 0050FF50h cmp slotWinAmount, 0 jle draw_slot_ctrls invoke DrawString8x8, 28, 187, OFFSET strWin, 0000FFFFh invoke FormatNumber, slotWinAmount, OFFSET hudNumBuffer invoke DrawString8x8, 110, 187, OFFSET hudNumBuffer, 0000FFFFh draw_slot_ctrls: invoke DrawString8x8, 28, 204, OFFSET textSlotsKeys3D, 00A0A0A0h ret RenderSlotsGame ENDP DrawReelSymbolAt1 PROC cmp eax, 0 jne @F invoke DrawString8x8, 52, 105, OFFSET sym7, 000000FFh ret @@: cmp eax, 1 jne @F invoke DrawString8x8, 52, 105, OFFSET symBar, 00FFAA00h ret @@: cmp eax, 2 jne @F invoke DrawString8x8, 52, 105, OFFSET symBell, 0000D7FFh ret @@: cmp eax, 3 jne @F invoke DrawString8x8, 48, 105, OFFSET symCherry, 000000D0h ret @@: cmp eax, 4 jne @F invoke DrawString8x8, 48, 105, OFFSET symClover, 0000A000h ret @@: cmp eax, 5 jne @F invoke DrawString8x8, 52, 105, OFFSET symGem, 00FFFF00h ret @@: invoke DrawString8x8, 52, 105, OFFSET symCrown, 0000D7FFh ret DrawReelSymbolAt1 ENDP DrawReelSymbolAt2 PROC cmp eax, 0 jne @F invoke DrawString8x8, 135, 105, OFFSET sym7, 000000FFh ret @@: cmp eax, 1 jne @F invoke DrawString8x8, 135, 105, OFFSET symBar, 00FFAA00h ret @@: cmp eax, 2 jne @F invoke DrawString8x8, 135, 105, OFFSET symBell, 0000D7FFh ret @@: cmp eax, 3 jne @F invoke DrawString8x8, 131, 105, OFFSET symCherry, 000000D0h ret @@: cmp eax, 4 jne @F invoke DrawString8x8, 131, 105, OFFSET symClover, 0000A000h ret @@: cmp eax, 5 jne @F invoke DrawString8x8, 135, 105, OFFSET symGem, 00FFFF00h ret @@: invoke DrawString8x8, 135, 105, OFFSET symCrown, 0000D7FFh ret DrawReelSymbolAt2 ENDP DrawReelSymbolAt3 PROC cmp eax, 0 jne @F invoke DrawString8x8, 218, 105, OFFSET sym7, 000000FFh ret @@: cmp eax, 1 jne @F invoke DrawString8x8, 218, 105, OFFSET symBar, 00FFAA00h ret @@: cmp eax, 2 jne @F invoke DrawString8x8, 218, 105, OFFSET symBell, 0000D7FFh ret @@: cmp eax, 3 jne @F invoke DrawString8x8, 214, 105, OFFSET symCherry, 000000D0h ret @@: cmp eax, 4 jne @F invoke DrawString8x8, 214, 105, OFFSET symClover, 0000A000h ret @@: cmp eax, 5 jne @F invoke DrawString8x8, 218, 105, OFFSET symGem, 00FFFF00h ret @@: invoke DrawString8x8, 218, 105, OFFSET symCrown, 0000D7FFh ret DrawReelSymbolAt3 ENDP ; ============================================================================== ; IN-ENGINE 2.5D MINI-GAME: BLACKJACK (21) ; ============================================================================== HandleBlackjackInput PROC uses ebx cmp bjState, 0 ; Need Deal jne check_bj_player_turn invoke Pressed3D, 20h ; SPACE -> Deal test ah, 80h jz check_bj_bet_change mov eax, bankroll cmp eax, bjBet jl bj_need_cash sub eax, bjBet mov bankroll, eax ; Deal 2 cards to player, 2 cards to dealer mov bjPlayerCardCount, 0 mov bjDealerCardCount, 0 mov bjDealerHideHole, 1 ; Player Card 1 invoke RandomRange3D, 13 inc eax mov ebx, bjPlayerCardCount mov [bjPlayerCards + ebx*4], eax inc bjPlayerCardCount ; Dealer Card 1 invoke RandomRange3D, 13 inc eax mov ebx, bjDealerCardCount mov [bjDealerCards + ebx*4], eax inc bjDealerCardCount ; Player Card 2 invoke RandomRange3D, 13 inc eax mov ebx, bjPlayerCardCount mov [bjPlayerCards + ebx*4], eax inc bjPlayerCardCount ; Dealer Card 2 (Hole card) invoke RandomRange3D, 13 inc eax mov ebx, bjDealerCardCount mov [bjDealerCards + ebx*4], eax inc bjDealerCardCount invoke PlaySoundA, OFFSET soundCards, 0, 1 ; Calc Player Score call CalcPlayerBJScore cmp bjPlayerScore, 21 jne set_bj_turn ; Instant Blackjack! mov bjDealerHideHole, 0 mov eax, bjBet imul eax, 5 shr eax, 1 add bankroll, eax invoke CopyString3D, OFFSET strWin, OFFSET bjOutcomeMsg invoke PlaySoundA, OFFSET soundJackpot, 0, 1 mov bjState, 2 ret set_bj_turn: mov bjState, 1 mov BYTE PTR [bjOutcomeMsg], 0 ret bj_need_cash: invoke CopyString3D, OFFSET msgNeedMoney, OFFSET flashMessage mov flashTimer, 60 ret check_bj_player_turn: cmp bjState, 1 jne check_bj_round_over invoke Pressed3D, 48h ; 'H' -> Hit test ah, 80h jz check_bj_stand invoke RandomRange3D, 13 inc eax mov ebx, bjPlayerCardCount cmp ebx, 8 jge @F mov [bjPlayerCards + ebx*4], eax inc bjPlayerCardCount @@: invoke PlaySoundA, OFFSET soundCards, 0, 1 call CalcPlayerBJScore cmp bjPlayerScore, 21 jle bj_input_done ; Bust! invoke CopyString3D, OFFSET strPlayerBust, OFFSET bjOutcomeMsg mov bjDealerHideHole, 0 mov bjState, 2 ret check_bj_stand: invoke Pressed3D, 53h ; 'S' -> Stand test ah, 80h jz bj_input_done ; Dealer Turn mov bjDealerHideHole, 0 dealer_loop: call CalcDealerBJScore cmp bjDealerScore, 17 jge dealer_finished invoke RandomRange3D, 13 inc eax mov ebx, bjDealerCardCount cmp ebx, 8 jge dealer_finished mov [bjDealerCards + ebx*4], eax inc bjDealerCardCount jmp dealer_loop dealer_finished: cmp bjDealerScore, 21 jle compare_scores ; Dealer Bust! mov eax, bjBet shl eax, 1 add bankroll, eax invoke CopyString3D, OFFSET strDealerBust, OFFSET bjOutcomeMsg invoke PlaySoundA, OFFSET soundCoin, 0, 1 mov bjState, 2 ret compare_scores: mov eax, bjPlayerScore cmp eax, bjDealerScore jle check_dealer_won ; Player Won! mov eax, bjBet shl eax, 1 add bankroll, eax invoke CopyString3D, OFFSET strWin, OFFSET bjOutcomeMsg invoke PlaySoundA, OFFSET soundCoin, 0, 1 mov bjState, 2 ret check_dealer_won: cmp eax, bjDealerScore jl dealer_wins ; Push (Tie) mov eax, bjBet add bankroll, eax invoke CopyString3D, OFFSET strPush, OFFSET bjOutcomeMsg mov bjState, 2 ret dealer_wins: invoke CopyString3D, OFFSET strLose, OFFSET bjOutcomeMsg mov bjState, 2 ret check_bj_round_over: invoke Pressed3D, 20h ; SPACE -> Next Hand test ah, 80h jz bj_input_done mov bjState, 0 ret check_bj_bet_change: invoke Pressed3D, 26h ; UP test ah, 80h jz @F cmp bjBet, 500 jge bj_input_done add bjBet, 50 ret @@: invoke Pressed3D, 28h ; DOWN test ah, 80h jz bj_input_done cmp bjBet, 50 jle bj_input_done sub bjBet, 50 bj_input_done: ret HandleBlackjackInput ENDP CalcPlayerBJScore PROC uses ebx esi xor eax, eax xor ebx, ebx xor esi, esi calc_p_loop: cmp esi, bjPlayerCardCount jge calc_p_done mov edx, [bjPlayerCards + esi*4] cmp edx, 10 jle @F mov edx, 10 @@: cmp edx, 1 jne add_p_val inc ebx ; count Aces add eax, 11 jmp next_p_card add_p_val: add eax, edx next_p_card: inc esi jmp calc_p_loop calc_p_done: ; Soft Ace reduction reduce_p_ace: cmp eax, 21 jle store_p_score test ebx, ebx jz store_p_score sub eax, 10 dec ebx jmp reduce_p_ace store_p_score: mov bjPlayerScore, eax ret CalcPlayerBJScore ENDP CalcDealerBJScore PROC uses ebx esi xor eax, eax xor ebx, ebx xor esi, esi calc_d_loop: cmp esi, bjDealerCardCount jge calc_d_done mov edx, [bjDealerCards + esi*4] cmp edx, 10 jle @F mov edx, 10 @@: cmp edx, 1 jne add_d_val inc ebx add eax, 11 jmp next_d_card add_d_val: add eax, edx next_d_card: inc esi jmp calc_d_loop calc_d_done: reduce_d_ace: cmp eax, 21 jle store_d_score test ebx, ebx jz store_d_score sub eax, 10 dec ebx jmp reduce_d_ace store_d_score: mov bjDealerScore, eax ret CalcDealerBJScore ENDP RenderBlackjackGame PROC uses ebx esi edi ; Emerald Felt Table Background invoke DrawBox, 0, 0, SCREEN_W, SCREEN_H, 000A3015h invoke DrawBoxBorder, 10, 10, 300, 220, 000D4018h, 0000D7FFh, 3 ; Dealer Area Top invoke DrawString8x8, 25, 20, OFFSET textBJ3D, 0000D7FFh invoke DrawString8x8, 25, 35, OFFSET textDealer3D, 00FFFFFFh invoke FormatNumber, bjDealerScore, OFFSET hudNumBuffer invoke DrawString8x8, 120, 35, OFFSET hudNumBuffer, 0000FFFFh ; Dealer Cards xor esi, esi draw_dealer_cards: cmp esi, bjDealerCardCount jge draw_player_bj_area mov eax, esi imul eax, 45 add eax, 25 mov ebx, eax cmp esi, 1 jne draw_dealer_face cmp bjDealerHideHole, 1 jne draw_dealer_face ; Face Down Card mov eax, selectedBack3D mov eax, cardBackColors3D[eax*4] invoke DrawBoxBorder, ebx, 48, 38, 52, eax, 00FFFFFFh, 2 jmp next_dealer_card_draw draw_dealer_face: invoke DrawBoxBorder, ebx, 48, 38, 52, 00F0F0F5h, 00000000h, 2 mov eax, [bjDealerCards + esi*4] dec eax imul eax, 3 lea edx, [cardRankStr + eax] mov eax, ebx add eax, 8 invoke DrawString8x8, eax, 68, edx, 00000000h next_dealer_card_draw: inc esi jmp draw_dealer_cards draw_player_bj_area: ; Player Area Bottom invoke DrawString8x8, 25, 110, OFFSET textPlayer3D, 00FFFFFFh invoke FormatNumber, bjPlayerScore, OFFSET hudNumBuffer invoke DrawString8x8, 120, 110, OFFSET hudNumBuffer, 0050FF50h ; Player Cards xor esi, esi draw_player_cards: cmp esi, bjPlayerCardCount jge draw_bj_footer mov eax, esi imul eax, 45 add eax, 25 mov ebx, eax invoke DrawBoxBorder, ebx, 124, 38, 52, 00F0F0F5h, 00000000h, 2 mov eax, [bjPlayerCards + esi*4] dec eax imul eax, 3 lea edx, [cardRankStr + eax] mov eax, ebx add eax, 8 invoke DrawString8x8, eax, 144, edx, 00000000h inc esi jmp draw_player_cards draw_bj_footer: ; Footer Status & Controls invoke DrawBoxBorder, 20, 182, 280, 42, 00102010h, 0000D7FFh, 1 cmp BYTE PTR [bjOutcomeMsg], 0 je draw_bj_controls invoke DrawString8x8, 28, 188, OFFSET bjOutcomeMsg, 0000FFFFh invoke DrawString8x8, 28, 204, OFFSET textNext3D, 00A0A0A0h ret draw_bj_controls: invoke DrawString8x8, 28, 188, OFFSET textBJKeys3D, 00FFFFFFh invoke DrawString8x8, 28, 204, OFFSET textDeal3D, 00A0A0A0h ret RenderBlackjackGame ENDP ; ============================================================================== ; IN-ENGINE 2.5D MINI-GAME: ROULETTE ; ============================================================================== HandleRouletteInput PROC uses ebx cmp roulState, 1 je roul_input_done invoke Pressed3D, 31h ; '1' -> RED test ah, 80h jz @F mov roulBetType, 1 @@: invoke Pressed3D, 32h ; '2' -> BLACK test ah, 80h jz @F mov roulBetType, 2 @@: invoke Pressed3D, 33h ; '3' -> ZERO (0) test ah, 80h jz @F mov roulBetType, 3 @@: invoke Pressed3D, 34h ; '4' -> EVEN test ah, 80h jz @F mov roulBetType, 4 @@: invoke Pressed3D, 35h ; '5' -> ODD test ah, 80h jz check_roul_spin mov roulBetType, 5 check_roul_spin: invoke Pressed3D, 20h ; SPACE -> Spin test ah, 80h jz roul_input_done mov eax, bankroll cmp eax, roulBetAmount jl roul_no_cash sub eax, roulBetAmount mov bankroll, eax mov roulState, 1 mov roulSpinTimer, 50 mov roulPayout, 0 invoke PlaySoundA, OFFSET soundRoulette, 0, 1 ret roul_no_cash: invoke CopyString3D, OFFSET msgNeedMoney, OFFSET flashMessage mov flashTimer, 60 roul_input_done: ret HandleRouletteInput ENDP RenderRouletteGame PROC uses ebx esi edi ; Table felt background invoke DrawBox, 0, 0, SCREEN_W, SCREEN_H, 00151525h invoke DrawBoxBorder, 10, 10, 300, 220, 00201525h, 0000D7FFh, 3 ; 2.5D Rotating Wheel on Left invoke DrawCircle, 85, 110, 65, 00102550h invoke DrawCircle, 85, 110, 60, 0000D7FFh invoke DrawCircle, 85, 110, 52, 00101010h invoke DrawCircle, 85, 110, 22, 0000D7FFh ; Center brass turret ; Spinning Wheel / Ball Logic cmp roulState, 1 jne draw_roul_ball dec roulSpinTimer add roulWheelAngle, 8 sub roulBallAngle, 14 cmp roulSpinTimer, 0 jg draw_roul_ball ; Wheel stopped! Determine result! mov roulState, 2 invoke RandomRange3D, 37 mov roulWinningNum, eax ; Check bet cmp roulBetType, 1 ; RED jne check_ro_black call IsNumberRed test eax, eax jz ro_lost mov eax, roulBetAmount shl eax, 1 mov roulPayout, eax add bankroll, eax invoke CopyString3D, OFFSET strWin, OFFSET roulOutcomeMsg invoke PlaySoundA, OFFSET soundCoin, 0, 1 jmp draw_roul_ball check_ro_black: cmp roulBetType, 2 ; BLACK jne check_ro_zero cmp roulWinningNum, 0 je ro_lost call IsNumberRed test eax, eax jnz ro_lost mov eax, roulBetAmount shl eax, 1 mov roulPayout, eax add bankroll, eax invoke CopyString3D, OFFSET strWin, OFFSET roulOutcomeMsg invoke PlaySoundA, OFFSET soundCoin, 0, 1 jmp draw_roul_ball check_ro_zero: cmp roulBetType, 3 ; ZERO jne check_ro_even cmp roulWinningNum, 0 jne ro_lost mov eax, roulBetAmount imul eax, 36 mov roulPayout, eax add bankroll, eax invoke CopyString3D, OFFSET strJackpot, OFFSET roulOutcomeMsg invoke PlaySoundA, OFFSET soundJackpot, 0, 1 jmp draw_roul_ball check_ro_even: cmp roulBetType, 4 ; EVEN jne check_ro_odd mov eax, roulWinningNum test eax, eax jz ro_lost test al, 1 jnz ro_lost mov eax, roulBetAmount shl eax, 1 mov roulPayout, eax add bankroll, eax invoke CopyString3D, OFFSET strWin, OFFSET roulOutcomeMsg invoke PlaySoundA, OFFSET soundCoin, 0, 1 jmp draw_roul_ball check_ro_odd: mov eax, roulWinningNum test eax, eax jz ro_lost test al, 1 jz ro_lost mov eax, roulBetAmount shl eax, 1 mov roulPayout, eax add bankroll, eax invoke CopyString3D, OFFSET strWin, OFFSET roulOutcomeMsg invoke PlaySoundA, OFFSET soundCoin, 0, 1 jmp draw_roul_ball ro_lost: invoke CopyString3D, OFFSET strLose, OFFSET roulOutcomeMsg draw_roul_ball: ; Draw White Ball on Rim mov eax, roulBallAngle and eax, 511 mov ebx, [tableCos + eax*4] imul ebx, 42 sar ebx, 16 add ebx, 85 mov eax, roulBallAngle and eax, 511 mov edx, [tableSin + eax*4] imul edx, 42 sar edx, 16 add edx, 110 invoke DrawCircle, ebx, edx, 3, 00FFFFFFh ; Right Betting Board invoke DrawBoxBorder, 175, 25, 125, 28, 001010C0h, 00FFFFFFh, 2 ; [1] RED invoke DrawString8x8, 190, 35, OFFSET textRed3D, 00FFFFFFh invoke DrawBoxBorder, 175, 60, 125, 28, 00151515h, 00FFFFFFh, 2 ; [2] BLACK invoke DrawString8x8, 190, 70, OFFSET textBlack3D, 00FFFFFFh invoke DrawBoxBorder, 175, 95, 125, 28, 00106010h, 00FFFFFFh, 2 ; [3] ZERO invoke DrawString8x8, 190, 105, OFFSET textZero3D, 00FFFFFFh invoke DrawBoxBorder, 175, 130, 60, 26, 00302020h, 00FFFFFFh, 1 ; [4] EVEN invoke DrawString8x8, 185, 139, OFFSET textEven3D, 00FFFFFFh invoke DrawBoxBorder, 240, 130, 60, 26, 00302020h, 00FFFFFFh, 1 ; [5] ODD invoke DrawString8x8, 250, 139, OFFSET textOdd3D, 00FFFFFFh ; Highlight Active Bet cmp roulBetType, 1 jne @F invoke DrawBoxBorder, 173, 23, 129, 32, 0, 0000FFFFh, 2 @@: cmp roulBetType, 2 jne @F invoke DrawBoxBorder, 173, 58, 129, 32, 0, 0000FFFFh, 2 @@: cmp roulBetType, 3 jne @F invoke DrawBoxBorder, 173, 93, 129, 32, 0, 0000FFFFh, 2 @@: cmp roulBetType, 4 jne @F invoke DrawBoxBorder, 173, 128, 64, 30, 0, 0000FFFFh, 2 @@: cmp roulBetType, 5 jne draw_ro_footer invoke DrawBoxBorder, 238, 128, 64, 30, 0, 0000FFFFh, 2 draw_ro_footer: invoke DrawBoxBorder, 20, 180, 280, 42, 00101015h, 0000D7FFh, 1 cmp roulState, 2 jne @F invoke DrawString8x8, 28, 186, OFFSET textResult3D, 0000D7FFh invoke FormatNumber, roulWinningNum, OFFSET hudNumBuffer invoke DrawString8x8, 85, 186, OFFSET hudNumBuffer, 0000FFFFh invoke DrawString8x8, 130, 186, OFFSET roulOutcomeMsg, 0050FF50h @@: invoke DrawString8x8, 28, 202, OFFSET textSpin3D, 00A0A0A0h ret RenderRouletteGame ENDP IsNumberRed PROC mov eax, roulWinningNum cmp eax, 1 je red_yes cmp eax, 3 je red_yes cmp eax, 5 je red_yes cmp eax, 7 je red_yes cmp eax, 9 je red_yes cmp eax, 12 je red_yes cmp eax, 14 je red_yes cmp eax, 16 je red_yes cmp eax, 18 je red_yes cmp eax, 19 je red_yes cmp eax, 21 je red_yes cmp eax, 23 je red_yes cmp eax, 25 je red_yes cmp eax, 27 je red_yes cmp eax, 30 je red_yes cmp eax, 32 je red_yes cmp eax, 34 je red_yes cmp eax, 36 je red_yes xor eax, eax ret red_yes: mov eax, 1 ret IsNumberRed ENDP ; ============================================================================== ; IN-ENGINE 2.5D MINI-GAME: BAR & SHOP ; ============================================================================== HandleShopInput PROC uses ebx esi xor esi, esi shop_choice: inc esi lea eax, [esi+30h] invoke Pressed3D, eax test eax, eax jnz shop_chosen cmp esi, 3 jb shop_choice ret shop_chosen: bt ownedBacks3D, esi jc shop_equip mov ebx, 1500 cmp esi, 1 jne @F mov ebx, 1000 @@: cmp bankroll, ebx jb shop_no_money sub bankroll, ebx bts ownedBacks3D, esi shop_equip: mov selectedBack3D, esi invoke CopyString3D, OFFSET textBought3D, OFFSET shopMsg call SaveProgress3D ret shop_no_money: invoke CopyString3D, OFFSET textNoCash3D, OFFSET shopMsg ret HandleShopInput ENDP RenderShopGame PROC invoke DrawBox, 0, 0, SCREEN_W, SCREEN_H, 00150A0Ah invoke DrawBoxBorder, 10, 10, 300, 220, 00251515h, 0000D7FFh, 3 invoke DrawString8x8, 25, 20, OFFSET textShop3D, 0000D7FFh invoke DrawBoxBorder, 20, 40, 280, 32, 001A1010h, 00FFFFFFh, 1 invoke DrawString8x8, 28, 46, OFFSET textItem1_3D, 0000FFFFh invoke DrawString8x8, 28, 58, OFFSET textShopHint3D, 00A0A0A0h invoke DrawBoxBorder, 20, 80, 280, 32, 001A1010h, 00FFFFFFh, 1 invoke DrawString8x8, 28, 86, OFFSET textItem2_3D, 0000FFFFh invoke DrawString8x8, 28, 98, OFFSET textShopHint3D, 00A0A0A0h invoke DrawBoxBorder, 20, 120, 280, 32, 001A1010h, 00FFFFFFh, 1 invoke DrawString8x8, 28, 126, OFFSET textItem3_3D, 0000FFFFh invoke DrawString8x8, 28, 138, OFFSET textShopHint3D, 00A0A0A0h invoke DrawBoxBorder, 20, 165, 280, 55, 00100A0Ah, 0000D7FFh, 1 invoke DrawString8x8, 28, 172, OFFSET textBank3D, 0000D7FFh invoke FormatNumber, bankroll, OFFSET hudNumBuffer invoke DrawString8x8, 110, 172, OFFSET hudNumBuffer, 0000FFFFh cmp BYTE PTR [shopMsg], 0 je @F invoke DrawString8x8, 28, 188, OFFSET shopMsg, 0050FF50h @@: invoke DrawString8x8, 28, 204, OFFSET textBack3D, 00A0A0A0h ret RenderShopGame ENDP ; ============================================================================== ; IN-ENGINE 2.5D MINI-GAME: ATM TERMINAL ; ============================================================================== HandleATMInput PROC ret HandleATMInput ENDP RenderATMGame PROC invoke DrawBox, 0, 0, 320, 240, 00172120h invoke DrawString8x8, 24, 30, OFFSET textATM3D, 00D8BC6Ah invoke DrawString8x8, 24, 70, OFFSET textBank3D, 00FFFFFFh invoke FormatNumber, bankroll, OFFSET hudNumBuffer invoke DrawString8x8, 96, 70, OFFSET hudNumBuffer, 0089DAB2h invoke DrawString8x8, 24, 115, OFFSET textATMNote3D, 00B7C8C1h invoke DrawString8x8, 24, 140, OFFSET textATMNote2_3D, 00B7C8C1h invoke DrawString8x8, 24, 208, OFFSET textBack3D, 00D8BC6Ah ret RenderATMGame ENDP ; ============================================================================== ; ============================================================================== ; SHARED RICH UI PROCEDURES ; ============================================================================== DrawKeycap3D PROC uses ebx esi edi, x:DWORD, y:DWORD, strPtr:DWORD, isActive:DWORD LOCAL capW:DWORD ; Compute string length mov esi, strPtr xor ecx, ecx @@: mov al, [esi+ecx] test al, al jz @F inc ecx jmp @B @@: shl ecx, 3 ; length * 8 add ecx, 8 ; padding 8px mov capW, ecx ; Drop shadow mov eax, x mov edx, y add edx, 2 invoke DrawBox, eax, edx, capW, 13, 0008080Ch ; Body & Border mov eax, 00606870h ; default border mov edx, 001A1C22h ; default fill cmp isActive, 0 je @F mov eax, 0000FFFFh ; active gold border mov edx, 001B4B22h ; active dark green fill @@: invoke DrawBoxBorder, x, y, capW, 13, edx, eax, 1 ; String text mov eax, 00D0D8E0h cmp isActive, 0 je @F mov eax, 0000FFFFh @@: mov edx, x add edx, 4 mov ecx, y add ecx, 3 invoke DrawString8x8, edx, ecx, strPtr, eax mov eax, capW ret DrawKeycap3D ENDP DrawChipStack PROC uses ebx esi edi, x:DWORD, y:DWORD, chipCount:DWORD xor esi, esi chip_loop: cmp esi, chipCount jge chip_done mov eax, esi shl eax, 2 ; esi * 4 mov edx, y sub edx, eax ; cy = y - esi*4 ; Shadow mov eax, x add eax, 2 mov ecx, edx add ecx, 5 invoke DrawBox, eax, ecx, 20, 2, 00041006h ; Chip body invoke DrawBoxBorder, x, edx, 24, 6, 001515B8h, 00FFFFFFh, 1 ; White stripe inlays mov eax, x add eax, 4 mov ecx, edx add ecx, 1 invoke DrawBox, eax, ecx, 3, 4, 00FFFFFFh mov eax, x add eax, 17 invoke DrawBox, eax, ecx, 3, 4, 00FFFFFFh inc esi jmp chip_loop chip_done: ret DrawChipStack ENDP ; ============================================================================== ; IN-ENGINE 2.5D MINI-GAME: COIN FLIP (ÌÎÍÅÒÊÀ) ; ============================================================================== DrawDetailedCoin PROC uses ebx esi edi, cxVal:DWORD, cyVal:DWORD, rxVal:DWORD, ryVal:DWORD, outerColor:DWORD, innerColor:DWORD, reliefType:DWORD LOCAL curDY:DWORD, curDX:DWORD, rxSq:DWORD, rySq:DWORD, rxRySq:DWORD, threshSq:DWORD cmp rxVal, 0 jle coin_draw_ret cmp ryVal, 0 jle coin_draw_ret mov eax, rxVal imul eax, eax mov rxSq, eax mov eax, ryVal imul eax, eax mov rySq, eax mov eax, rxSq imul eax, rySq mov rxRySq, eax mov eax, rxRySq shr eax, 2 imul eax, 3 mov threshSq, eax mov eax, ryVal neg eax mov curDY, eax coin_y_loop: mov eax, curDY cmp eax, ryVal jg check_coin_relief mov eax, rxVal neg eax mov curDX, eax coin_x_loop: mov eax, curDX cmp eax, rxVal jg next_coin_y mov eax, curDX imul eax, eax imul eax, rySq mov ebx, curDY imul ebx, ebx imul ebx, rxSq add eax, ebx cmp eax, rxRySq jg next_coin_x mov ecx, innerColor cmp eax, threshSq jb @F mov ecx, outerColor @@: mov eax, cxVal add eax, curDX mov edx, cyVal add edx, curDY invoke DrawPixel, eax, edx, ecx next_coin_x: inc curDX jmp coin_x_loop next_coin_y: inc curDY jmp coin_y_loop check_coin_relief: cmp rxVal, 14 jl coin_draw_ret cmp reliefType, 1 je draw_eagle_relief cmp reliefType, 2 je draw_wreath_relief jmp coin_draw_ret draw_eagle_relief: ; Crown mov eax, cxVal sub eax, 3 mov edx, cyVal sub edx, 14 invoke DrawBox, eax, edx, 7, 2, 00007A9Ah mov eax, cxVal sub eax, 4 mov edx, cyVal sub edx, 12 invoke DrawBox, eax, edx, 9, 2, 00007A9Ah ; Body & Head mov eax, cxVal sub eax, 2 mov edx, cyVal sub edx, 9 invoke DrawBox, eax, edx, 5, 12, 00007A9Ah mov eax, cxVal dec eax mov edx, cyVal sub edx, 8 invoke DrawBox, eax, edx, 3, 10, 0000D7FFh ; Wings mov eax, cxVal sub eax, 10 mov edx, cyVal sub edx, 8 invoke DrawBox, eax, edx, 7, 3, 00007A9Ah mov eax, cxVal sub eax, 13 mov edx, cyVal sub edx, 5 invoke DrawBox, eax, edx, 10, 3, 00007A9Ah mov eax, cxVal sub eax, 11 mov edx, cyVal sub edx, 2 invoke DrawBox, eax, edx, 7, 3, 00007A9Ah mov eax, cxVal add eax, 4 mov edx, cyVal sub edx, 8 invoke DrawBox, eax, edx, 7, 3, 00007A9Ah mov eax, cxVal add eax, 4 mov edx, cyVal sub edx, 5 invoke DrawBox, eax, edx, 10, 3, 00007A9Ah mov eax, cxVal add eax, 5 mov edx, cyVal sub edx, 2 invoke DrawBox, eax, edx, 7, 3, 00007A9Ah ; Tail mov eax, cxVal sub eax, 4 mov edx, cyVal add edx, 4 invoke DrawBox, eax, edx, 9, 3, 00007A9Ah mov eax, cxVal sub eax, 3 mov edx, cyVal add edx, 7 invoke DrawBox, eax, edx, 7, 3, 00007A9Ah jmp coin_draw_ret draw_wreath_relief: ; Roman numeral 'I' mov eax, cxVal sub eax, 5 mov edx, cyVal sub edx, 10 invoke DrawBox, eax, edx, 11, 3, 00007A9Ah mov eax, cxVal sub eax, 2 mov edx, cyVal sub edx, 7 invoke DrawBox, eax, edx, 5, 14, 00007A9Ah mov eax, cxVal dec eax mov edx, cyVal sub edx, 6 invoke DrawBox, eax, edx, 3, 12, 0000D7FFh mov eax, cxVal sub eax, 6 mov edx, cyVal add edx, 7 invoke DrawBox, eax, edx, 13, 3, 00007A9Ah ; Laurel dots left & right mov eax, cxVal sub eax, 12 mov edx, cyVal sub edx, 10 invoke DrawBox, eax, edx, 2, 2, 00007A9Ah mov eax, cxVal add eax, 11 mov edx, cyVal sub edx, 10 invoke DrawBox, eax, edx, 2, 2, 00007A9Ah mov eax, cxVal sub eax, 12 mov edx, cyVal sub edx, 5 invoke DrawBox, eax, edx, 2, 2, 00007A9Ah mov eax, cxVal add eax, 11 mov edx, cyVal sub edx, 5 invoke DrawBox, eax, edx, 2, 2, 00007A9Ah mov eax, cxVal sub eax, 12 mov edx, cyVal invoke DrawBox, eax, edx, 2, 2, 00007A9Ah mov eax, cxVal add eax, 11 mov edx, cyVal invoke DrawBox, eax, edx, 2, 2, 00007A9Ah mov eax, cxVal sub eax, 12 mov edx, cyVal add edx, 5 invoke DrawBox, eax, edx, 2, 2, 00007A9Ah mov eax, cxVal add eax, 11 mov edx, cyVal add edx, 5 invoke DrawBox, eax, edx, 2, 2, 00007A9Ah coin_draw_ret: ret DrawDetailedCoin ENDP InitCoinGame PROC mov coin3d_state, 0 mov coin3d_timer, 0 mov coin3d_win, 0 cmp coin3d_bet, 10 jge @F mov coin3d_bet, 50 @@: ret InitCoinGame ENDP HandleCoinInput PROC cmp coin3d_state, 1 je coin_input_done invoke Pressed3D, 20h ; SPACE -> Flip! test eax, eax jz check_coin_side mov eax, bankroll cmp eax, coin3d_bet jl coin_no_cash sub eax, coin3d_bet mov bankroll, eax mov coin3d_state, 1 mov coin3d_timer, 0 mov coin3d_win, 0 invoke PlaySoundA, OFFSET soundCoin, 0, 1 jmp coin_input_done coin_no_cash: invoke CopyString3D, OFFSET msgNeedMoney, OFFSET flashMessage mov flashTimer, 60 invoke PlaySoundA, OFFSET soundClick, 0, 1 jmp coin_input_done check_coin_side: invoke Pressed3D, 31h ; '1' test eax, eax jz @F mov coin3d_side, 1 invoke PlaySoundA, OFFSET soundClick, 0, 1 @@: invoke Pressed3D, 32h ; '2' test eax, eax jz check_coin_bet_adjust mov coin3d_side, 2 invoke PlaySoundA, OFFSET soundClick, 0, 1 check_coin_bet_adjust: invoke Pressed3D, 26h ; UP test eax, eax jnz coin_inc_bet invoke Pressed3D, 57h ; W test eax, eax jz check_coin_bet_down coin_inc_bet: invoke PlaySoundA, OFFSET soundClick, 0, 1 cmp coin3d_bet, 500 jge coin_input_done cmp coin3d_bet, 250 jge coin_set_500 cmp coin3d_bet, 100 jge coin_set_250 cmp coin3d_bet, 50 jge coin_set_100 cmp coin3d_bet, 25 jge coin_set_50 jmp coin_set_25 coin_set_500: mov coin3d_bet, 500 jmp coin_input_done coin_set_250: mov coin3d_bet, 250 jmp coin_input_done coin_set_100: mov coin3d_bet, 100 jmp coin_input_done coin_set_50: mov coin3d_bet, 50 jmp coin_input_done coin_set_25: mov coin3d_bet, 25 jmp coin_input_done check_coin_bet_down: invoke Pressed3D, 28h ; DOWN test eax, eax jnz coin_dec_bet invoke Pressed3D, 53h ; S test eax, eax jz coin_input_done coin_dec_bet: invoke PlaySoundA, OFFSET soundClick, 0, 1 cmp coin3d_bet, 25 jle coin_set_10 cmp coin3d_bet, 50 jle coin_set_25 cmp coin3d_bet, 100 jle coin_set_50 cmp coin3d_bet, 250 jle coin_set_100 mov coin3d_bet, 250 jmp coin_input_done coin_set_10: mov coin3d_bet, 10 coin_input_done: ret HandleCoinInput ENDP RenderCoinGame PROC uses ebx esi edi LOCAL cyVal:DWORD, rxVal:DWORD, curX:DWORD ; Cabinet Bezel (Mahogany wood & leather) invoke DrawBox, 0, 0, 320, 240, 00060914h invoke DrawBoxBorder, 6, 6, 308, 228, 000F1522h, 001B2E48h, 3 ; Corner Brass Rivets invoke DrawBox, 12, 12, 3, 3, 0000D7FFh invoke DrawPixel, 13, 13, 00FFFFFFh invoke DrawBox, 306, 12, 3, 3, 0000D7FFh invoke DrawPixel, 307, 13, 00FFFFFFh invoke DrawBox, 12, 226, 3, 3, 0000D7FFh invoke DrawPixel, 13, 227, 00FFFFFFh invoke DrawBox, 306, 226, 3, 3, 0000D7FFh invoke DrawPixel, 307, 227, 00FFFFFFh ; Illuminated Marquee Header invoke DrawBoxBorder, 24, 12, 272, 26, 000A101Ch, 0000D7FFh, 2 invoke DrawString8x8, 48, 21, OFFSET textCoinTitle, 0000FFFFh ; Bulb lights on marquee border mov curX, 28 coin_bulbs: cmp curX, 292 jge coin_meters invoke DrawPixel, curX, 13, 0000FFFFh invoke DrawPixel, curX, 36, 0000D7FFh add curX, 12 jmp coin_bulbs coin_meters: ; Status Meters: Bank & Bet invoke DrawBoxBorder, 20, 44, 114, 18, 000A1A0Eh, 001A4B22h, 1 invoke DrawString8x8, 24, 49, OFFSET textBankPrompt, 0050FF50h invoke FormatNumber, bankroll, OFFSET hudNumBuffer invoke DrawString8x8, 72, 49, OFFSET hudNumBuffer, 0050FF50h invoke DrawBoxBorder, 186, 44, 114, 18, 001A100Ah, 003A2814h, 1 invoke DrawString8x8, 190, 49, OFFSET textBetPrompt, 0000D7FFh invoke FormatNumber, coin3d_bet, OFFSET hudNumBuffer invoke DrawString8x8, 254, 49, OFFSET hudNumBuffer, 0000D7FFh invoke DrawString8x8, 278, 49, OFFSET textBetHint, 00808080h ; Center Velvet Platter invoke DrawCircle, 160, 110, 46, 000090C0h invoke DrawCircle, 160, 110, 44, 0000D7FFh invoke DrawCircle, 160, 110, 41, 00180824h ; Selection Podiums: [1] ÎÐ¨Ë mov eax, 00121620h mov edx, 00404855h mov ecx, 0090A0B0h cmp coin3d_side, 1 jne @F mov eax, 001C3822h mov edx, 0000FFFFh mov ecx, 0000FFFFh @@: push ecx invoke DrawBoxBorder, 20, 72, 76, 52, eax, edx, 2 pop ecx invoke DrawString8x8, 28, 78, OFFSET textCoinSide1, ecx invoke DrawDetailedCoin, 58, 106, 12, 12, 0000A0D0h, 0000D7FFh, 1 ; Selection Podiums: [2] ÐÅØÊÀ mov eax, 00121620h mov edx, 00404855h mov ecx, 0090A0B0h cmp coin3d_side, 2 jne @F mov eax, 001C3822h mov edx, 0000FFFFh mov ecx, 0000FFFFh @@: push ecx invoke DrawBoxBorder, 224, 72, 76, 52, eax, edx, 2 pop ecx invoke DrawString8x8, 232, 78, OFFSET textCoinSide2, ecx invoke DrawDetailedCoin, 262, 106, 12, 12, 000080A0h, 0000B0D0h, 2 ; Flipping animation logic cmp coin3d_state, 1 jne coin_at_rest inc coin3d_timer ; Parabolic toss: cy = 110 - (t * (40 - t)) / 14 mov eax, coin3d_timer mov ecx, 40 sub ecx, eax imul eax, ecx xor edx, edx mov ecx, 14 div ecx mov edx, 110 sub edx, eax mov cyVal, edx ; Width rx from lookup table: (t % 10) mov eax, coin3d_timer xor edx, edx mov ecx, 10 div ecx movzx eax, BYTE PTR [coinRxAnimTable + edx] mov rxVal, eax invoke DrawDetailedCoin, 160, cyVal, rxVal, 26, 0000A0D0h, 0000D7FFh, 0 invoke DrawString8x8, 88, 160, OFFSET textCoinFlipping, 0000FFFFh cmp coin3d_timer, 40 jl coin_draw_controls ; Flip complete! mov coin3d_state, 2 invoke RandomRange3D, 2 inc eax mov coin3d_result, eax mov eax, coin3d_result cmp eax, coin3d_side jne coin_flip_lost ; Won! mov eax, coin3d_bet shl eax, 1 mov coin3d_win, eax add bankroll, eax inc coin3d_streak cmp coin3d_streak, 3 jl @F invoke PlaySoundA, OFFSET soundVictory, 0, 1 jmp coin_draw_controls @@: invoke PlaySoundA, OFFSET soundCoinDing, 0, 1 jmp coin_draw_controls coin_flip_lost: mov coin3d_streak, 0 mov coin3d_win, 0 invoke PlaySoundA, OFFSET soundLose, 0, 1 jmp coin_draw_controls coin_at_rest: ; Draw coin resting in velvet dish mov edx, coin3d_side cmp coin3d_state, 2 jne @F mov edx, coin3d_result @@: invoke DrawDetailedCoin, 160, 110, 26, 26, 0000A0D0h, 0000D7FFh, edx ; Outcome / Streak Display cmp coin3d_state, 2 jne coin_show_streak cmp coin3d_win, 0 je coin_show_lose invoke DrawBoxBorder, 44, 154, 232, 20, 000E141Eh, 0050FF50h, 1 invoke DrawString8x8, 64, 160, OFFSET textCoinWin, 0050FF50h invoke FormatNumber, coin3d_win, OFFSET hudNumBuffer invoke DrawString8x8, 152, 160, OFFSET hudNumBuffer, 0050FF50h jmp coin_draw_controls coin_show_lose: invoke DrawBoxBorder, 44, 154, 232, 20, 000E141Eh, 000000FFh, 1 invoke DrawString8x8, 114, 160, OFFSET textCoinLose, 008080FFh jmp coin_draw_controls coin_show_streak: invoke DrawBoxBorder, 44, 154, 232, 20, 000E141Eh, 0000D7FFh, 1 invoke DrawString8x8, 52, 160, OFFSET textCoinStreakFmt, 0000FFFFh coin_draw_controls: ; Keycaps Control Bar invoke DrawBox, 16, 194, 288, 1, 001E2E40h mov eax, 0 cmp coin3d_side, 1 sete al invoke DrawKeycap3D, 22, 202, OFFSET textCoinKey1, eax mov eax, 0 cmp coin3d_side, 2 sete al invoke DrawKeycap3D, 88, 202, OFFSET textCoinKey2, eax invoke DrawKeycap3D, 160, 202, OFFSET textCoinKeySpace, 1 invoke DrawKeycap3D, 274, 202, OFFSET textKeyEsc, 0 ret RenderCoinGame ENDP ; ============================================================================== ; IN-ENGINE 2.5D MINI-GAME: DICE / CRAPS (ÊÎÑÒÈ) ; ============================================================================== DrawCrapsDie PROC uses ebx esi edi, x:DWORD, y:DWORD, sizeVal:DWORD, valNum:DWORD ; Drop shadow on green felt mov eax, x add eax, 3 mov edx, y add edx, sizeVal invoke DrawBox, eax, edx, sizeVal, 3, 00031408h mov eax, x add eax, sizeVal mov edx, y add edx, 3 invoke DrawBox, eax, edx, 3, sizeVal, 00031408h ; Ivory body & dark border invoke DrawBoxBorder, x, y, sizeVal, sizeVal, 00F0F4FAh, 00353540h, 1 ; Bevel highlight top & left mov eax, sizeVal sub eax, 2 mov edx, x inc edx mov ecx, y inc ecx invoke DrawBox, edx, ecx, eax, 1, 00FFFFFFh invoke DrawBox, edx, ecx, 1, eax, 00FFFFFFh ; Bevel shadow bottom & right mov edx, x inc edx mov ecx, y add ecx, sizeVal sub ecx, 2 invoke DrawBox, edx, ecx, eax, 1, 00C0C6D0h mov edx, x add edx, sizeVal sub edx, 2 mov ecx, y inc ecx invoke DrawBox, edx, ecx, 1, eax, 00C0C6D0h ; Casino Ruby Red circular pips (radius 3) cmp valNum, 1 je draw_die_c cmp valNum, 3 je draw_die_c cmp valNum, 5 je draw_die_c jmp check_die_pips_corners draw_die_c: mov eax, x add eax, 18 mov edx, y add edx, 18 invoke DrawCircle, eax, edx, 3, 001515C8h dec eax dec edx invoke DrawPixel, eax, edx, 00FFFFFFh check_die_pips_corners: cmp valNum, 2 jl die_pips_done mov eax, x add eax, 9 mov edx, y add edx, 9 invoke DrawCircle, eax, edx, 3, 001515C8h mov eax, x add eax, sizeVal sub eax, 10 mov edx, y add edx, sizeVal sub edx, 10 invoke DrawCircle, eax, edx, 3, 001515C8h cmp valNum, 4 jl die_pips_done mov eax, x add eax, sizeVal sub eax, 10 mov edx, y add edx, 9 invoke DrawCircle, eax, edx, 3, 001515C8h mov eax, x add eax, 9 mov edx, y add edx, sizeVal sub edx, 10 invoke DrawCircle, eax, edx, 3, 001515C8h cmp valNum, 6 jl die_pips_done mov eax, x add eax, 9 mov edx, y add edx, 18 invoke DrawCircle, eax, edx, 3, 001515C8h mov eax, x add eax, sizeVal sub eax, 10 mov edx, y add edx, 18 invoke DrawCircle, eax, edx, 3, 001515C8h die_pips_done: ret DrawCrapsDie ENDP InitDiceGame PROC mov dice3d_state, 0 mov dice3d_timer, 0 mov dice3d_win, 0 cmp dice3d_bet, 10 jge @F mov dice3d_bet, 50 @@: ret InitDiceGame ENDP HandleDiceInput PROC cmp dice3d_state, 1 je dice_input_done invoke Pressed3D, 20h ; SPACE -> Roll! test eax, eax jz check_dice_choice mov eax, bankroll cmp eax, dice3d_bet jl dice_no_cash sub eax, dice3d_bet mov bankroll, eax mov dice3d_state, 1 mov dice3d_timer, 0 mov dice3d_win, 0 invoke PlaySoundA, OFFSET soundCards, 0, 1 jmp dice_input_done dice_no_cash: invoke CopyString3D, OFFSET msgNeedMoney, OFFSET flashMessage mov flashTimer, 60 invoke PlaySoundA, OFFSET soundClick, 0, 1 jmp dice_input_done check_dice_choice: invoke Pressed3D, 31h ; '1' test eax, eax jz @F mov dice3d_choice, 1 invoke PlaySoundA, OFFSET soundClick, 0, 1 @@: invoke Pressed3D, 32h ; '2' test eax, eax jz check_dice_bet_adjust mov dice3d_choice, 2 invoke PlaySoundA, OFFSET soundClick, 0, 1 check_dice_bet_adjust: invoke Pressed3D, 26h ; UP test eax, eax jnz dice_inc_bet invoke Pressed3D, 57h ; W test eax, eax jz check_dice_bet_down dice_inc_bet: invoke PlaySoundA, OFFSET soundClick, 0, 1 cmp dice3d_bet, 500 jge dice_input_done cmp dice3d_bet, 250 jge dice_set_500 cmp dice3d_bet, 100 jge dice_set_250 cmp dice3d_bet, 50 jge dice_set_100 cmp dice3d_bet, 25 jge dice_set_50 jmp dice_set_25 dice_set_500: mov dice3d_bet, 500 jmp dice_input_done dice_set_250: mov dice3d_bet, 250 jmp dice_input_done dice_set_100: mov dice3d_bet, 100 jmp dice_input_done dice_set_50: mov dice3d_bet, 50 jmp dice_input_done dice_set_25: mov dice3d_bet, 25 jmp dice_input_done check_dice_bet_down: invoke Pressed3D, 28h ; DOWN test eax, eax jnz dice_dec_bet invoke Pressed3D, 53h ; S test eax, eax jz dice_input_done dice_dec_bet: invoke PlaySoundA, OFFSET soundClick, 0, 1 cmp dice3d_bet, 25 jle dice_set_10 cmp dice3d_bet, 50 jle dice_set_25 cmp dice3d_bet, 100 jle dice_set_50 cmp dice3d_bet, 250 jle dice_set_100 mov dice3d_bet, 250 jmp dice_input_done dice_set_10: mov dice3d_bet, 10 dice_input_done: ret HandleDiceInput ENDP RenderDiceGame PROC uses ebx esi edi LOCAL d1X:DWORD, d1Y:DWORD, d2X:DWORD, d2Y:DWORD, bxX:DWORD ; Craps Emerald Felt & Oak Armrest invoke DrawBox, 0, 0, 320, 240, 00082E12h invoke DrawBoxBorder, 4, 4, 312, 232, 00093816h, 00122244h, 3 invoke DrawBoxBorder, 8, 8, 304, 224, 000A3F19h, 0005140Ah, 2 ; Pyramidal diamond craps backboard texture mov bxX, 12 craps_bumper: cmp bxX, 308 jge craps_felt_markings mov eax, bxX add eax, 4 invoke DrawBox, eax, 11, 4, 4, 00041006h mov eax, bxX add eax, 5 invoke DrawPixel, eax, 12, 000F4820h add bxX, 12 jmp craps_bumper craps_felt_markings: ; Table Markings printed in gold directly on felt invoke DrawString8x8, 72, 20, OFFSET textDiceTitle, 0000D7FFh invoke DrawString8x8, 68, 32, OFFSET textDiceSubtitle, 0000B0A0h ; Meters: Bank & Bet invoke DrawBoxBorder, 16, 46, 108, 16, 0006240Eh, 000E5022h, 1 invoke DrawString8x8, 20, 50, OFFSET textBankPrompt, 0050FF50h invoke FormatNumber, bankroll, OFFSET hudNumBuffer invoke DrawString8x8, 68, 50, OFFSET hudNumBuffer, 0050FF50h invoke DrawBoxBorder, 196, 46, 108, 16, 0006240Eh, 000E5022h, 1 invoke DrawString8x8, 200, 50, OFFSET textBetPrompt, 0000D7FFh invoke FormatNumber, dice3d_bet, OFFSET hudNumBuffer invoke DrawString8x8, 264, 50, OFFSET hudNumBuffer, 0000D7FFh ; Betting Zone Left: [1] ×¨Ò mov eax, 00073014h mov edx, 001A602Ah mov ecx, 0080B090h cmp dice3d_choice, 1 jne @F mov eax, 000B441Dh mov edx, 0000FFFFh mov ecx, 0000FFFFh @@: push ecx invoke DrawBoxBorder, 16, 68, 88, 54, eax, edx, 2 pop ecx invoke DrawString8x8, 24, 74, OFFSET textDiceEven, ecx invoke DrawString8x8, 20, 86, OFFSET textDiceEvenNums, 0000D7FFh cmp dice3d_choice, 1 jne @F invoke DrawChipStack, 48, 110, 4 @@: ; Betting Zone Right: [2] ÍÅ×ÅÒ mov eax, 00073014h mov edx, 001A602Ah mov ecx, 0080B090h cmp dice3d_choice, 2 jne @F mov eax, 000B441Dh mov edx, 0000FFFFh mov ecx, 0000FFFFh @@: push ecx invoke DrawBoxBorder, 216, 68, 88, 54, eax, edx, 2 pop ecx invoke DrawString8x8, 224, 74, OFFSET textDiceOdd, ecx invoke DrawString8x8, 224, 86, OFFSET textDiceOddNums, 00508060h cmp dice3d_choice, 2 jne @F invoke DrawChipStack, 248, 110, 4 @@: ; Center Dice Field invoke DrawBoxBorder, 112, 68, 96, 54, 00072E13h, 00145826h, 1 ; Rolling Animation Logic cmp dice3d_state, 1 jne dice_at_rest inc dice3d_timer ; Tumbling jitter offsets mov eax, dice3d_timer and eax, 3 sub eax, 1 mov edx, 120 add edx, eax mov d1X, edx mov edx, 76 sub edx, eax mov d1Y, edx mov edx, 164 sub edx, eax mov d2X, edx mov edx, 78 add edx, eax mov d2Y, edx test dice3d_timer, 1 jz @F invoke RandomRange3D, 6 inc eax mov dice3d_val1, eax invoke RandomRange3D, 6 inc eax mov dice3d_val2, eax @@: invoke DrawCrapsDie, d1X, d1Y, 36, dice3d_val1 invoke DrawCrapsDie, d2X, d2Y, 36, dice3d_val2 invoke DrawString8x8, 76, 138, OFFSET textDiceRolling, 0000FFFFh cmp dice3d_timer, 36 jl dice_draw_controls ; Settle dice! mov dice3d_state, 2 invoke RandomRange3D, 6 inc eax mov dice3d_val1, eax invoke RandomRange3D, 6 inc eax mov dice3d_val2, eax mov eax, dice3d_val1 add eax, dice3d_val2 mov dice3d_sum, eax ; Check choice vs sum parity mov eax, dice3d_sum test eax, 1 jz dice_sum_is_even ; Odd cmp dice3d_choice, 2 je dice_roll_won jmp dice_roll_lost dice_sum_is_even: cmp dice3d_choice, 1 je dice_roll_won dice_roll_lost: mov dice3d_win, 0 invoke PlaySoundA, OFFSET soundLose, 0, 1 jmp dice_draw_controls dice_roll_won: mov eax, dice3d_bet shl eax, 1 mov dice3d_win, eax add bankroll, eax invoke PlaySoundA, OFFSET soundVictory, 0, 1 jmp dice_draw_controls dice_at_rest: invoke DrawCrapsDie, 120, 76, 36, dice3d_val1 invoke DrawCrapsDie, 164, 76, 36, dice3d_val2 cmp dice3d_state, 2 jne dice_draw_controls ; Scoreboard Plaque invoke DrawBoxBorder, 36, 130, 248, 30, 00051D0Ch, 0000D7FFh, 1 invoke DrawString8x8, 44, 135, OFFSET textDiceSumHdr, 0000D7FFh invoke FormatNumber, dice3d_val1, OFFSET hudNumBuffer invoke DrawString8x8, 100, 135, OFFSET hudNumBuffer, 00FFFFFFh invoke DrawString8x8, 110, 135, OFFSET textDicePlus, 0000D7FFh invoke FormatNumber, dice3d_val2, OFFSET hudNumBuffer invoke DrawString8x8, 134, 135, OFFSET hudNumBuffer, 00FFFFFFh invoke DrawString8x8, 144, 135, OFFSET textDiceEqual, 0000D7FFh invoke FormatNumber, dice3d_sum, OFFSET hudNumBuffer invoke DrawString8x8, 168, 135, OFFSET hudNumBuffer, 0000FFFFh mov eax, dice3d_sum test eax, 1 jnz @F invoke DrawString8x8, 186, 135, OFFSET textDiceEvenResult, 0080FF80h jmp dice_show_win_msg @@: invoke DrawString8x8, 186, 135, OFFSET textDiceOddResult, 00FF8080h dice_show_win_msg: cmp dice3d_win, 0 je dice_show_loss invoke DrawString8x8, 68, 147, OFFSET textDiceWin, 0050FF50h invoke FormatNumber, dice3d_win, OFFSET hudNumBuffer invoke DrawString8x8, 156, 147, OFFSET hudNumBuffer, 0050FF50h invoke DrawString8x8, 188, 147, OFFSET textDiceWinMult, 0050FF50h jmp dice_draw_controls dice_show_loss: invoke DrawString8x8, 116, 147, OFFSET textDiceLose, 008080FFh dice_draw_controls: invoke DrawBox, 16, 188, 288, 1, 00104820h mov eax, 0 cmp dice3d_choice, 1 sete al invoke DrawKeycap3D, 20, 198, OFFSET textDiceKey1, eax mov eax, 0 cmp dice3d_choice, 2 sete al invoke DrawKeycap3D, 82, 198, OFFSET textDiceKey2, eax invoke DrawKeycap3D, 160, 198, OFFSET textDiceKeySpace, 1 invoke DrawKeycap3D, 274, 198, OFFSET textKeyEsc, 0 ret RenderDiceGame ENDP ; ============================================================================== ; IN-ENGINE 2.5D MINI-GAME: SKULLS & CUPS (ÍÀϨÐÑÒÊÈ) ; ============================================================================== DrawGlowingOrb PROC uses ebx esi edi, cxVal:DWORD, cyVal:DWORD invoke DrawCircle, cxVal, cyVal, 14, 00081E2Eh invoke DrawCircle, cxVal, cyVal, 11, 00103A58h invoke DrawCircle, cxVal, cyVal, 8, 001A588Ah invoke DrawCircle, cxVal, cyVal, 6, 0000B0E0h invoke DrawCircle, cxVal, cyVal, 4, 0000E0FFh mov eax, cxVal dec eax mov edx, cyVal dec edx invoke DrawCircle, eax, edx, 2, 00A0FFFFh mov eax, cxVal sub eax, 2 mov edx, cyVal sub edx, 2 invoke DrawPixel, eax, edx, 00FFFFFFh ret DrawGlowingOrb ENDP DrawGothicCup PROC uses ebx esi edi, x:DWORD, y:DWORD, cupId:DWORD, isLifted:DWORD, hasBall:DWORD LOCAL liftY:DWORD mov eax, y cmp isLifted, 0 je @F sub eax, 28 @@: mov liftY, eax ; Drop shadow on purple velvet cmp isLifted, 0 jne @F mov eax, x add eax, 6 mov edx, y add edx, 42 invoke DrawBox, eax, edx, 36, 4, 000A0410h jmp draw_cup_body @@: mov eax, x add eax, 10 mov edx, y add edx, 42 invoke DrawBox, eax, edx, 28, 2, 0012061Ah ; Draw orb if lifted and has ball cmp hasBall, 0 je draw_cup_body mov eax, x add eax, 24 mov edx, y add edx, 26 invoke DrawGlowingOrb, eax, edx draw_cup_body: ; Base mov eax, x add eax, 6 mov edx, liftY add edx, 36 invoke DrawBoxBorder, eax, edx, 36, 6, 00221A30h, 0000B0D0h, 1 ; Stem mov eax, x add eax, 18 mov edx, liftY add edx, 28 invoke DrawBox, eax, edx, 12, 8, 00332545h mov eax, x add eax, 22 mov edx, liftY add edx, 28 invoke DrawBox, eax, edx, 4, 8, 0055406Eh ; Bowl mov eax, x add eax, 8 mov edx, liftY add edx, 8 invoke DrawBoxBorder, eax, edx, 32, 20, 002D1E40h, 0000D7FFh, 1 mov eax, x add eax, 14 mov edx, liftY add edx, 10 invoke DrawBox, eax, edx, 6, 16, 00503570h mov eax, x add eax, 17 mov edx, liftY add edx, 10 invoke DrawBox, eax, edx, 3, 16, 007850A0h ; Flared Rim mov eax, x add eax, 4 mov edx, liftY add edx, 2 invoke DrawBoxBorder, eax, edx, 40, 7, 00150A20h, 0000FFFFh, 1 mov eax, x add eax, 12 mov edx, liftY add edx, 4 invoke DrawBox, eax, edx, 16, 2, 0000FFFFh ; Skull Insignia on Bowl mov eax, x add eax, 21 mov edx, liftY add edx, 12 invoke DrawBox, eax, edx, 6, 5, 0000D7FFh mov eax, x add eax, 22 mov edx, liftY add edx, 17 invoke DrawBox, eax, edx, 4, 3, 0000D7FFh mov eax, x add eax, 22 mov edx, liftY add edx, 14 invoke DrawPixel, eax, edx, 00150A20h mov eax, x add eax, 24 mov edx, liftY add edx, 14 invoke DrawPixel, eax, edx, 00150A20h ; Cup ID Badge mov eax, x add eax, 21 mov edx, liftY add edx, 24 mov ecx, cupId add ecx, '0' invoke DrawChar8x8, eax, edx, ecx, 0000FFFFh ret DrawGothicCup ENDP InitSkullsGame PROC mov skulls3d_state, 0 mov skulls3d_timer, 0 mov skulls3d_win, 0 cmp skulls3d_bet, 10 jge @F mov skulls3d_bet, 50 @@: invoke RandomRange3D, 3 mov skulls3d_ballPos, eax ret InitSkullsGame ENDP FinalizeSkullsGuess PROC uses ebx mov skulls3d_state, 4 mov eax, skulls3d_choice cmp eax, skulls3d_ballPos jne skulls_guess_lost ; Won 3x! mov eax, skulls3d_bet imul eax, 3 mov skulls3d_win, eax add bankroll, eax invoke PlaySoundA, OFFSET soundVictory, 0, 1 ret skulls_guess_lost: mov skulls3d_win, 0 invoke PlaySoundA, OFFSET soundLose, 0, 1 ret FinalizeSkullsGuess ENDP HandleSkullsInput PROC cmp skulls3d_state, 1 je skulls_input_done cmp skulls3d_state, 2 je skulls_input_done cmp skulls3d_state, 3 je check_skulls_pick ; State 0 or 4: Can start new round or adjust bet invoke Pressed3D, 20h ; SPACE test eax, eax jz check_skulls_bet_adjust mov eax, bankroll cmp eax, skulls3d_bet jl skulls_no_cash sub eax, skulls3d_bet mov bankroll, eax invoke RandomRange3D, 3 mov skulls3d_ballPos, eax invoke RandomRange3D, 3 mov skulls3d_swapPair0, eax invoke RandomRange3D, 3 mov skulls3d_swapPair1, eax invoke RandomRange3D, 3 mov skulls3d_swapPair2, eax mov skulls3d_state, 1 mov skulls3d_timer, 0 mov skulls3d_win, 0 invoke PlaySoundA, OFFSET soundShuffle, 0, 1 jmp skulls_input_done skulls_no_cash: invoke CopyString3D, OFFSET msgNeedMoney, OFFSET flashMessage mov flashTimer, 60 invoke PlaySoundA, OFFSET soundClick, 0, 1 jmp skulls_input_done check_skulls_pick: invoke Pressed3D, 31h ; '1' test eax, eax jz @F mov skulls3d_choice, 0 call FinalizeSkullsGuess jmp skulls_input_done @@: invoke Pressed3D, 32h ; '2' test eax, eax jz @F mov skulls3d_choice, 1 call FinalizeSkullsGuess jmp skulls_input_done @@: invoke Pressed3D, 33h ; '3' test eax, eax jz skulls_input_done mov skulls3d_choice, 2 call FinalizeSkullsGuess jmp skulls_input_done check_skulls_bet_adjust: invoke Pressed3D, 26h ; UP test eax, eax jnz skulls_inc_bet invoke Pressed3D, 57h ; W test eax, eax jz check_skulls_bet_down skulls_inc_bet: invoke PlaySoundA, OFFSET soundClick, 0, 1 cmp skulls3d_bet, 500 jge skulls_input_done cmp skulls3d_bet, 250 jge skulls_set_500 cmp skulls3d_bet, 100 jge skulls_set_250 cmp skulls3d_bet, 50 jge skulls_set_100 cmp skulls3d_bet, 25 jge skulls_set_50 jmp skulls_set_25 skulls_set_500: mov skulls3d_bet, 500 jmp skulls_input_done skulls_set_250: mov skulls3d_bet, 250 jmp skulls_input_done skulls_set_100: mov skulls3d_bet, 100 jmp skulls_input_done skulls_set_50: mov skulls3d_bet, 50 jmp skulls_input_done skulls_set_25: mov skulls3d_bet, 25 jmp skulls_input_done check_skulls_bet_down: invoke Pressed3D, 28h ; DOWN test eax, eax jnz skulls_dec_bet invoke Pressed3D, 53h ; S test eax, eax jz skulls_input_done skulls_dec_bet: invoke PlaySoundA, OFFSET soundClick, 0, 1 cmp skulls3d_bet, 25 jle skulls_set_10 cmp skulls3d_bet, 50 jle skulls_set_25 cmp skulls3d_bet, 100 jle skulls_set_50 cmp skulls3d_bet, 250 jle skulls_set_100 mov skulls3d_bet, 250 jmp skulls_input_done skulls_set_10: mov skulls3d_bet, 10 skulls_input_done: ret HandleSkullsInput ENDP RenderSkullsGame PROC uses ebx esi edi LOCAL passTick:DWORD, curPair:DWORD, swapSlotA:DWORD, swapSlotB:DWORD LOCAL xA:DWORD, xB:DWORD, curXA:DWORD, curXB:DWORD, curYA:DWORD, curYB:DWORD LOCAL distX:DWORD, dxVal:DWORD, archY:DWORD ; Dark Gothic Tavern Table with Royal Velvet invoke DrawBox, 0, 0, 320, 240, 000D0612h invoke DrawBoxBorder, 4, 4, 312, 232, 00160B20h, 00321845h, 3 invoke DrawBoxBorder, 8, 8, 304, 224, 00220F30h, 0000D7FFh, 1 ; Header invoke DrawBoxBorder, 24, 12, 272, 24, 0012081Ah, 0000D7FFh, 2 invoke DrawString8x8, 64, 20, OFFSET textSkullsTitle, 0000FFFFh ; Meters: Bank & Bet invoke DrawBoxBorder, 20, 42, 114, 16, 000D0616h, 00401858h, 1 invoke DrawString8x8, 24, 46, OFFSET textBankPrompt, 0050FF50h invoke FormatNumber, bankroll, OFFSET hudNumBuffer invoke DrawString8x8, 72, 46, OFFSET hudNumBuffer, 0050FF50h invoke DrawBoxBorder, 186, 42, 114, 16, 000D0616h, 00401858h, 1 invoke DrawString8x8, 190, 46, OFFSET textBetPrompt, 0000D7FFh invoke FormatNumber, skulls3d_bet, OFFSET hudNumBuffer invoke DrawString8x8, 254, 46, OFFSET hudNumBuffer, 0000D7FFh ; Velvet Table Runner invoke DrawBoxBorder, 16, 64, 288, 120, 001A0B25h, 00452060h, 1 ; Dispatch based on phase cmp skulls3d_state, 1 je skulls_render_phase1 cmp skulls3d_state, 2 je skulls_render_phase2 cmp skulls3d_state, 3 je skulls_render_phase3 cmp skulls3d_state, 4 je skulls_render_phase4 ; Phase 0: Idle / Betting invoke DrawString8x8, 56, 70, OFFSET textSkullsPhase0, 0000D7FFh invoke DrawGothicCup, 48, 108, 1, 0, 0 invoke DrawGothicCup, 136, 108, 2, 0, 0 invoke DrawGothicCup, 224, 108, 3, 0, 0 jmp skulls_draw_controls skulls_render_phase1: inc skulls3d_timer invoke DrawString8x8, 56, 70, OFFSET textSkullsPhase1, 0000FFFFh ; Draw cups with ballPos cup lifted mov eax, 0 cmp skulls3d_ballPos, 0 sete al invoke DrawGothicCup, 48, 108, 1, eax, eax mov eax, 0 cmp skulls3d_ballPos, 1 sete al invoke DrawGothicCup, 136, 108, 2, eax, eax mov eax, 0 cmp skulls3d_ballPos, 2 sete al invoke DrawGothicCup, 224, 108, 3, eax, eax cmp skulls3d_timer, 40 jl skulls_draw_controls ; Start Phase 2 (Shuffle) mov skulls3d_state, 2 mov skulls3d_timer, 0 invoke PlaySoundA, OFFSET soundShuffle, 0, 1 jmp skulls_draw_controls skulls_render_phase2: inc skulls3d_timer mov eax, skulls3d_timer cmp eax, 20 jbe pass_0 cmp eax, 40 jbe pass_1 sub eax, 41 mov passTick, eax mov eax, skulls3d_swapPair2 mov curPair, eax jmp setup_pass_pair pass_0: dec eax mov passTick, eax mov eax, skulls3d_swapPair0 mov curPair, eax jmp setup_pass_pair pass_1: sub eax, 21 mov passTick, eax mov eax, skulls3d_swapPair1 mov curPair, eax setup_pass_pair: cmp curPair, 1 je pair_1 cmp curPair, 2 je pair_2 mov swapSlotA, 0 mov swapSlotB, 1 mov xA, 48 mov xB, 136 jmp calc_swap_coords pair_1: mov swapSlotA, 1 mov swapSlotB, 2 mov xA, 136 mov xB, 224 jmp calc_swap_coords pair_2: mov swapSlotA, 0 mov swapSlotB, 2 mov xA, 48 mov xB, 224 calc_swap_coords: mov eax, xB sub eax, xA mov distX, eax mov eax, distX imul eax, passTick xor edx, edx mov ecx, 20 div ecx mov dxVal, eax mov eax, xA add eax, dxVal mov curXA, eax mov eax, xB sub eax, dxVal mov curXB, eax ; Arch height: archY = (t * (20 - t)) / 25 mov eax, passTick mov ecx, 20 sub ecx, eax imul eax, ecx xor edx, edx mov ecx, 25 div ecx mov archY, eax mov edx, 108 sub edx, archY mov curYA, edx ; upper arc mov edx, 108 add edx, archY mov curYB, edx ; lower arc invoke DrawString8x8, 56, 70, OFFSET textSkullsPhase2, 0000FFFFh ; Depth sorted rendering: Background cup (upper arc) draws FIRST, Foreground cup (lower arc) draws OVER it! invoke DrawGothicCup, curXA, curYA, 1, 0, 0 invoke DrawGothicCup, curXB, curYB, 2, 0, 0 ; Draw remaining static cup cmp curPair, 1 je draw_stat_0 cmp curPair, 2 je draw_stat_1 invoke DrawGothicCup, 224, 108, 3, 0, 0 jmp check_pass_finish draw_stat_0: invoke DrawGothicCup, 48, 108, 1, 0, 0 jmp check_pass_finish draw_stat_1: invoke DrawGothicCup, 136, 108, 2, 0, 0 check_pass_finish: cmp skulls3d_timer, 20 je do_pass_swap cmp skulls3d_timer, 40 je do_pass_swap cmp skulls3d_timer, 60 je do_pass_swap jmp skulls_draw_controls do_pass_swap: ; Update ballPos if involved in swap mov eax, skulls3d_ballPos cmp eax, swapSlotA jne check_swap_b mov eax, swapSlotB mov skulls3d_ballPos, eax jmp ball_swap_done check_swap_b: cmp eax, swapSlotB jne ball_swap_done mov eax, swapSlotA mov skulls3d_ballPos, eax ball_swap_done: invoke PlaySoundA, OFFSET soundShuffle, 0, 1 cmp skulls3d_timer, 60 jl skulls_draw_controls ; Shuffle complete -> Move to Pick phase mov skulls3d_state, 3 mov skulls3d_timer, 0 jmp skulls_draw_controls skulls_render_phase3: invoke DrawString8x8, 40, 70, OFFSET textSkullsPhase3, 0000FFFFh invoke DrawGothicCup, 48, 108, 1, 0, 0 invoke DrawGothicCup, 136, 108, 2, 0, 0 invoke DrawGothicCup, 224, 108, 3, 0, 0 jmp skulls_draw_controls skulls_render_phase4: ; Reveal phase cmp skulls3d_win, 0 je skulls_show_loss invoke DrawString8x8, 48, 70, OFFSET textSkullsWin, 0050FF50h invoke FormatNumber, skulls3d_win, OFFSET hudNumBuffer invoke DrawString8x8, 216, 70, OFFSET hudNumBuffer, 0050FF50h jmp skulls_p4_cups skulls_show_loss: invoke DrawString8x8, 40, 70, OFFSET textSkullsLose, 008080FFh skulls_p4_cups: ; Draw chosen cup lifted mov eax, 0 cmp skulls3d_choice, 0 sete al mov edx, 0 cmp skulls3d_ballPos, 0 sete dl invoke DrawGothicCup, 48, 108, 1, eax, edx mov eax, 0 cmp skulls3d_choice, 1 sete al mov edx, 0 cmp skulls3d_ballPos, 1 sete dl invoke DrawGothicCup, 136, 108, 2, eax, edx mov eax, 0 cmp skulls3d_choice, 2 sete al mov edx, 0 cmp skulls3d_ballPos, 2 sete dl invoke DrawGothicCup, 224, 108, 3, eax, edx invoke DrawString8x8, 64, 168, OFFSET textSkullsAgain, 0000D7FFh skulls_draw_controls: invoke DrawBox, 16, 190, 288, 1, 003A1850h mov eax, 0 cmp skulls3d_choice, 0 sete al invoke DrawKeycap3D, 18, 200, OFFSET textSkullsKey1, eax mov eax, 0 cmp skulls3d_choice, 1 sete al invoke DrawKeycap3D, 82, 200, OFFSET textSkullsKey2, eax mov eax, 0 cmp skulls3d_choice, 2 sete al invoke DrawKeycap3D, 146, 200, OFFSET textSkullsKey3, eax invoke DrawKeycap3D, 212, 200, OFFSET textSkullsKeySpace, 1 invoke DrawKeycap3D, 274, 200, OFFSET textKeyEsc, 0 ret RenderSkullsGame ENDP HandlePlayerInput PROC uses ebx esi edi local speed:DWORD local nextX:DWORD local nextY:DWORD mov eax, deltaTime3D imul eax, 200 mov speed, eax cmp keys3D[10h], 0 je @F shl speed, 1 @@: mov eax, deltaTime3D shr eax, 2 inc eax cmp keys3D[41h], 0 jne input_turn_left cmp keys3D[25h], 0 je input_right input_turn_left: sub playerAngle, eax input_right: cmp keys3D[44h], 0 jne input_turn_right cmp keys3D[27h], 0 je input_forward input_turn_right: add playerAngle, eax input_forward: and playerAngle, 511 call UpdateCamera3D xor edi, edi cmp keys3D[57h], 0 jne input_go_forward cmp keys3D[26h], 0 je input_back input_go_forward: inc edi input_back: cmp keys3D[53h], 0 jne input_go_back cmp keys3D[28h], 0 je input_move input_go_back: dec edi input_move: test edi, edi jz input_action imul edi, speed mov eax, playerDirX imul edi shrd eax, edx, 16 add eax, playerX mov nextX, eax mov eax, playerDirY imul edi shrd eax, edx, 16 add eax, playerY mov nextY, eax invoke CanWalk3D, nextX, playerY test eax, eax jz @F mov eax, nextX mov playerX, eax @@: invoke CanWalk3D, playerX, nextY test eax, eax jz input_action mov eax, nextY mov playerY, eax input_action: invoke Pressed3D, 45h test eax, eax jz @F call Trigger3DInteraction @@: ret HandlePlayerInput ENDP CheckInteractions PROC uses ebx esi edi local nearest:DWORD mov nearest, 262144 mov interactTargetId, 0 mov interactPromptPtr, 0 xor esi, esi interaction_scan: cmp esi, NUM_SPRITES jge interaction_done imul edi, esi, SIZEOF SpriteObject cmp [casinoSprites+edi].interactId, 0 je interaction_next mov eax, [casinoSprites+edi].posX sub eax, playerX sar eax, 8 mov ebx, eax imul eax, eax mov ecx, eax mov eax, [casinoSprites+edi].posY sub eax, playerY sar eax, 8 mov edx, eax imul eax, eax add ecx, eax cmp ecx, nearest jae interaction_next ; Only target objects in front of the camera. mov eax, playerDirX sar eax, 8 imul eax, ebx mov ebx, playerDirY sar ebx, 8 imul ebx, edx add eax, ebx cmp eax, 18000 jl interaction_next mov nearest, ecx mov eax, [casinoSprites+edi].interactId mov interactTargetId, eax mov eax, [casinoSprites+edi].promptPtr mov interactPromptPtr, eax interaction_next: inc esi jmp interaction_scan interaction_done: ret CheckInteractions ENDP ; --- RenderCabinetBezel: Îòðèñîâêà àðêàäíîãî áåçåëÿ òåðìèíàëà íà 3D ýêðàíå --- RenderCabinetBezel PROC uses ebx esi edi, pTitle:DWORD ; Çàòåìíÿåì 3D-çàë â áóôåðå êàäðà (äåëèì ÿðêîñòü ïîïîëàì) mov ecx, SCREEN_SIZE xor esi, esi dim_bezel_loop: mov eax, [screenBuffer + esi*4] shr eax, 1 and eax, 007F7F7Fh mov [screenBuffer + esi*4], eax inc esi loop dim_bezel_loop ; Âíåøíÿÿ çîëîòàÿ ðàìêà òåðìèíàëà invoke DrawBoxBorder, 10, 14, 300, 212, 000C0E14h, 00D8BC6Ah, 2 ; Øàïêà òåðìèíàëà ñ íàçâàíèåì èãðû invoke DrawBox, 12, 16, 296, 16, 00221A10h invoke DrawString8x8, 20, 20, pTitle, 00F5E2B0h ; Ïîäâàëüíàÿ ïëàøêà ñ ïîäñêàçêîé ïî âûõîäó invoke DrawBox, 12, 210, 296, 14, 00141416h invoke DrawString8x8, 20, 213, OFFSET textCabinetFooter, 00AAAAAAh ; Âûâîäèì êàäð áåçåëÿ â îêíî call Present3D ret RenderCabinetBezel ENDP ; --- LaunchClassicGame: Âñòðàèâàíèå èãðû â UI òåðìèíàëà êàçèíî --- LaunchClassicGame PROC uses ebx esi edi, pGameProc:DWORD, gameId:DWORD, pTitle:DWORD LOCAL rcClient[16]:BYTE LOCAL ptScreen[8]:BYTE LOCAL fontInfo[84]:BYTE LOCAL conWnd:DWORD LOCAL conW:DWORD, conH:DWORD, conX:DWORD, conY:DWORD LOCAL viewW:DWORD, viewH:DWORD LOCAL offsetX:DWORD, offsetY:DWORD mov eax, gameId mov currentGameId, eax ; 1. Ðèñóåì çîëîòîé áåçåëü òåðìèíàëà íà 3D ýêðàíå cmp pTitle, 0 je @F invoke RenderCabinetBezel, pTitle @@: ; 2. Âûäåëÿåì êîíñîëü invoke AllocConsole test eax, eax jz launch_ret invoke GetStdHandle, STD_OUTPUT_HANDLE mov hOut, eax invoke GetStdHandle, STD_INPUT_HANDLE mov hIn, eax invoke SetConsoleCP, 1251 invoke SetConsoleOutputCP, 1251 cmp pTitle, 0 je @F invoke SetConsoleTitleA, pTitle @@: call EnableAnsi call ConfigureConsoleSize ; 3. Íàñòðàèâàåì øðèôò Consolas Bold 16pt lea edi, fontInfo xor eax, eax mov ecx, 21 rep stosd mov dword ptr fontInfo[0], 84 ; cbSize mov word ptr fontInfo[8], 0 ; dwFontSize.X mov word ptr fontInfo[10], 16 ; dwFontSize.Y mov dword ptr fontInfo[16], 700 ; FontWeight = FW_BOLD mov word ptr fontInfo[20], 'C' mov word ptr fontInfo[22], 'o' mov word ptr fontInfo[24], 'n' mov word ptr fontInfo[26], 's' mov word ptr fontInfo[28], 'o' mov word ptr fontInfo[30], 'l' mov word ptr fontInfo[32], 'a' mov word ptr fontInfo[34], 's' mov word ptr fontInfo[36], 0 lea eax, fontInfo invoke SetCurrentConsoleFontEx, hOut, 0, eax ; 4. Ïîëó÷àåì äåñêðèïòîð îêíà êîíñîëè invoke GetConsoleWindow mov conWnd, eax test eax, eax jz run_game_body ; 5. Ñíèìàåì ñèñòåìíóþ ðàìêó Windows è çàãîëîâîê ñ êíîïêàìè çàêðûòèÿ/ñâîðà÷èâàíèÿ invoke GetWindowLongA, conWnd, -16 ; GWL_STYLE and eax, NOT (00C00000h or 00040000h or 00080000h or 00010000h or 00020000h) or eax, 80000000h ; WS_POPUP invoke SetWindowLongA, conWnd, -16, eax ; Ñâÿçûâàåì êàê äî÷åðíåå/ïðèíàäëåæàùåå îêíî ê îêíó èãðû cmp h3DWnd, 0 je show_con_fallback invoke SetWindowLongA, conWnd, -8, h3DWnd ; GWL_HWNDPARENT ; 6. Âû÷èñëÿåì òî÷íûå êîîðäèíàòû äëÿ ïîñàäêè ýêðàíà âíóòðü áåçåëÿ lea eax, rcClient invoke GetClientRect, h3DWnd, eax mov esi, dword ptr rcClient[8] ; øèðèíà êëèåíòñêîé îáëàñòè mov edi, dword ptr rcClient[12] ; âûñîòà êëèåíòñêîé îáëàñòè test esi, esi jz show_con_fallback test edi, edi jz show_con_fallback ; Ðàñ÷åò âüþïîðòà 4:3 òî÷íî êàê â Present3D mov viewW, esi mov eax, esi imul eax, 3 shr eax, 2 cmp eax, edi jle calc_view_h mov eax, edi imul eax, 4 xor edx, edx mov ecx, 3 div ecx mov viewW, eax mov eax, edi calc_view_h: mov viewH, eax mov ebx, esi sub ebx, viewW shr ebx, 1 mov offsetX, ebx mov ebx, edi sub ebx, viewH shr ebx, 1 mov offsetY, ebx ; Ýêðàííûå êîîðäèíàòû ëåâîãî âåðõíåãî óãëà êëèåíòñêîé îáëàñòè mov dword ptr ptScreen[0], 0 mov dword ptr ptScreen[4], 0 lea eax, ptScreen invoke ClientToScreen, h3DWnd, eax ; conW = viewW * 280 / 320 (âíóòðåííåå îêíî áåçåëÿ) mov eax, viewW imul eax, 280 xor edx, edx mov ecx, 320 div ecx mov conW, eax ; conH = viewH * 168 / 240 mov eax, viewH imul eax, 168 xor edx, edx mov ecx, 240 div ecx mov conH, eax ; conX = ptScreen.x + offsetX + (viewW * 20 / 320) mov eax, viewW imul eax, 20 xor edx, edx mov ecx, 320 div ecx add eax, offsetX add eax, dword ptr ptScreen[0] mov conX, eax ; conY = ptScreen.y + offsetY + (viewH * 38 / 240) mov eax, viewH imul eax, 38 xor edx, edx mov ecx, 240 div ecx add eax, offsetY add eax, dword ptr ptScreen[4] mov conY, eax ; Ïîçèöèîíèðóåì áåçðàìî÷íûé ýêðàí òî÷íî âíóòðü çîëîòîé ðàìêè áåçåëÿ invoke SetWindowPos, conWnd, 0, conX, conY, conW, conH, 20h or 40h ; SWP_FRAMECHANGED | SWP_SHOWWINDOW jmp set_con_focus show_con_fallback: invoke ShowWindow, conWnd, 5 ; SW_SHOW set_con_focus: invoke SetForegroundWindow, conWnd invoke SetFocus, conWnd run_game_body: ; Çàïóñê îðèãèíàëüíîé èãðû! call pGameProc ; Çàêðûâàåì êîíñîëü invoke FreeConsole mov hOut, 0 mov hIn, 0 ; Âîçâðàùàåì ôîêóñ â îêíî 3D èãðû cmp h3DWnd, 0 je cleanup_game_input invoke SetForegroundWindow, h3DWnd invoke SetFocus, h3DWnd cleanup_game_input: mov ecx, 256 xor eax, eax lea edi, keys3D rep stosb mov ecx, 256 lea edi, pressedKeys3D rep stosb invoke GetTickCount mov previousTick3D, eax mov frameStart3D, eax mov deltaTime3D, 0 call SaveProgress3D launch_ret: ret LaunchClassicGame ENDP Trigger3DInteraction PROC mov eax, interactTargetId test eax, eax jz trigger_done cmp eax, INTERACT_DANCER jne check_target_bj cmp bankroll, 100 jl dancer_no_cash sub bankroll, 100 inc dancerLuckBuff invoke CopyString3D, OFFSET textTips3D, OFFSET flashMessage mov flashTimer, 100 invoke PlaySoundA, OFFSET soundJackpot, 0, 1 ret dancer_no_cash: invoke CopyString3D, OFFSET msgNeedMoney, OFFSET flashMessage mov flashTimer, 60 ret check_target_bj: cmp eax, INTERACT_BLACKJACK jne check_target_poker invoke LaunchClassicGame, OFFSET Game21, 1, OFFSET szTitleBlackjack ret check_target_poker: cmp eax, INTERACT_POKER jne check_target_durak invoke LaunchClassicGame, OFFSET GamePoker, 2, OFFSET szTitlePoker ret check_target_durak: cmp eax, INTERACT_DURAK jne check_target_slots777 invoke LaunchClassicGame, OFFSET GameDurak, 10, OFFSET szTitleDurak ret check_target_slots777: cmp eax, INTERACT_SLOTS_777 jne check_target_slots_clover invoke LaunchClassicGame, OFFSET GameClassicSlot, 9, OFFSET szTitleClassicSlot ret check_target_slots_clover: cmp eax, INTERACT_SLOTS_CLOVER jne check_target_roulette invoke LaunchClassicGame, OFFSET GameSlot, 3, OFFSET szTitleCloverSlot ret check_target_roulette: cmp eax, INTERACT_ROULETTE jne check_target_dice invoke LaunchClassicGame, OFFSET GameCasinoRoulette, 8, OFFSET szTitleCasinoRoulette ret check_target_dice: cmp eax, INTERACT_DICE jne check_target_skulls call InitDiceGame mov engineMode, MODE_DICE ret check_target_skulls: cmp eax, INTERACT_SKULLS jne check_target_coin call InitSkullsGame mov engineMode, MODE_SKULLS ret check_target_coin: cmp eax, INTERACT_COIN jne check_target_skill call InitCoinGame mov engineMode, MODE_COIN ret check_target_skill: cmp eax, INTERACT_SKILL_CHECK jne check_target_buckshot invoke LaunchClassicGame, OFFSET GameSkillCheck, 11, OFFSET szTitleSkillCheck ret check_target_buckshot: cmp eax, INTERACT_BUCKSHOT jne check_target_rr invoke LaunchClassicGame, OFFSET GameBuckshot, 13, OFFSET szTitleBuckshot ret check_target_rr: cmp eax, INTERACT_RUSSIAN_ROULETTE jne check_target_online_rr invoke LaunchClassicGame, OFFSET GameRoulette, 4, OFFSET szTitleRussianRoulette ret check_target_online_rr: cmp eax, INTERACT_ONLINE_RR jne check_target_umamusume invoke LaunchClassicGame, OFFSET GameOnlineCasino, 20, OFFSET szTitleOnlineRR ret check_target_umamusume: cmp eax, INTERACT_UMAMUSUME jne check_target_hell invoke LaunchClassicGame, OFFSET GameUmamusume, 21, OFFSET szTitleUmamusume ret check_target_hell: cmp eax, INTERACT_HELL_TOWER jne check_target_shop invoke LaunchClassicGame, OFFSET GameTournament, 666, OFFSET szTitleHellTower ret check_target_shop: cmp eax, INTERACT_SHOP jne check_target_atm invoke LaunchClassicGame, OFFSET GameShop, 0, OFFSET szTitleShop ret check_target_atm: cmp eax, INTERACT_ATM jne check_target_terminal mov engineMode, MODE_ATM ret check_target_terminal: cmp eax, INTERACT_TERMINAL jne check_target_observer invoke LaunchClassicGame, OFFSET GamePlayerTerminal, 0, OFFSET szTitleTerminal ret check_target_observer: cmp eax, INTERACT_OBSERVER jne target_unported invoke LaunchClassicGame, OFFSET GameObserver, 14, OFFSET szTitleObserver ret target_unported: invoke CopyString3D, OFFSET textUnavailable3D, OFFSET flashMessage mov flashTimer, 150 trigger_done: ret Trigger3DInteraction ENDP ; --- Engine Initialization --- Init3DEngine PROC local screenCX:DWORD local screenCY:DWORD local posX:DWORD local posY:DWORD local bytesRead:DWORD push ebx push esi push edi call Create3DWindow test eax, eax jz init_failed call LoadTextures3D test eax, eax jz init_failed init_sprites_table: ; Sprite 0: VIP Dancer 1 (Stage Left) mov casinoSprites[0*SIZEOF SpriteObject].posX, (13 * FP_1 + FP_HALF) mov casinoSprites[0*SIZEOF SpriteObject].posY, (4 * FP_1) mov casinoSprites[0*SIZEOF SpriteObject].baseTexId, 10 mov casinoSprites[0*SIZEOF SpriteObject].frameCount, 12 mov casinoSprites[0*SIZEOF SpriteObject].curFrame, 0 mov casinoSprites[0*SIZEOF SpriteObject].animTimer, 0 mov casinoSprites[0*SIZEOF SpriteObject].animSpeed, 5 mov casinoSprites[0*SIZEOF SpriteObject].interactId, INTERACT_DANCER mov casinoSprites[0*SIZEOF SpriteObject].promptPtr, OFFSET promptDancer ; Sprite 1: VIP Dancer 2 (Center Stage Star) mov casinoSprites[1*SIZEOF SpriteObject].posX, (16 * FP_1 + FP_HALF) mov casinoSprites[1*SIZEOF SpriteObject].posY, (3 * FP_1 + FP_HALF) mov casinoSprites[1*SIZEOF SpriteObject].baseTexId, 10 mov casinoSprites[1*SIZEOF SpriteObject].frameCount, 12 mov casinoSprites[1*SIZEOF SpriteObject].curFrame, 2 mov casinoSprites[1*SIZEOF SpriteObject].animTimer, 0 mov casinoSprites[1*SIZEOF SpriteObject].animSpeed, 5 mov casinoSprites[1*SIZEOF SpriteObject].interactId, INTERACT_DANCER mov casinoSprites[1*SIZEOF SpriteObject].promptPtr, OFFSET promptDancer ; Sprite 2: VIP Dancer 3 (Stage Right) mov casinoSprites[2*SIZEOF SpriteObject].posX, (19 * FP_1 + FP_HALF) mov casinoSprites[2*SIZEOF SpriteObject].posY, (4 * FP_1) mov casinoSprites[2*SIZEOF SpriteObject].baseTexId, 10 mov casinoSprites[2*SIZEOF SpriteObject].frameCount, 12 mov casinoSprites[2*SIZEOF SpriteObject].curFrame, 1 mov casinoSprites[2*SIZEOF SpriteObject].animTimer, 0 mov casinoSprites[2*SIZEOF SpriteObject].animSpeed, 5 mov casinoSprites[2*SIZEOF SpriteObject].interactId, INTERACT_DANCER mov casinoSprites[2*SIZEOF SpriteObject].promptPtr, OFFSET promptDancer ; Sprite 3: VIP Blackjack (Front Center Left) mov casinoSprites[3*SIZEOF SpriteObject].posX, (12 * FP_1 + FP_HALF) mov casinoSprites[3*SIZEOF SpriteObject].posY, (8 * FP_1) mov casinoSprites[3*SIZEOF SpriteObject].baseTexId, 30 mov casinoSprites[3*SIZEOF SpriteObject].frameCount, 1 mov casinoSprites[3*SIZEOF SpriteObject].curFrame, 0 mov casinoSprites[3*SIZEOF SpriteObject].animTimer, 0 mov casinoSprites[3*SIZEOF SpriteObject].animSpeed, 1 mov casinoSprites[3*SIZEOF SpriteObject].interactId, INTERACT_BLACKJACK mov casinoSprites[3*SIZEOF SpriteObject].promptPtr, OFFSET promptBlackjack ; Sprite 4: European Roulette Table (Front Center) mov casinoSprites[4*SIZEOF SpriteObject].posX, (16 * FP_1 + FP_HALF) mov casinoSprites[4*SIZEOF SpriteObject].posY, (10 * FP_1) mov casinoSprites[4*SIZEOF SpriteObject].baseTexId, 31 mov casinoSprites[4*SIZEOF SpriteObject].frameCount, 1 mov casinoSprites[4*SIZEOF SpriteObject].curFrame, 0 mov casinoSprites[4*SIZEOF SpriteObject].animTimer, 0 mov casinoSprites[4*SIZEOF SpriteObject].animSpeed, 1 mov casinoSprites[4*SIZEOF SpriteObject].interactId, INTERACT_ROULETTE mov casinoSprites[4*SIZEOF SpriteObject].promptPtr, OFFSET promptCasinoRoulette ; Sprite 5: Texas Hold'em Poker Table (Front Center Right) mov casinoSprites[5*SIZEOF SpriteObject].posX, (20 * FP_1 + FP_HALF) mov casinoSprites[5*SIZEOF SpriteObject].posY, (8 * FP_1) mov casinoSprites[5*SIZEOF SpriteObject].baseTexId, 30 mov casinoSprites[5*SIZEOF SpriteObject].frameCount, 1 mov casinoSprites[5*SIZEOF SpriteObject].curFrame, 0 mov casinoSprites[5*SIZEOF SpriteObject].animTimer, 0 mov casinoSprites[5*SIZEOF SpriteObject].animSpeed, 1 mov casinoSprites[5*SIZEOF SpriteObject].interactId, INTERACT_POKER mov casinoSprites[5*SIZEOF SpriteObject].promptPtr, OFFSET promptPoker ; Sprite 6: Podkidnoy Durak Card Table mov casinoSprites[6*SIZEOF SpriteObject].posX, (24 * FP_1 + FP_HALF) mov casinoSprites[6*SIZEOF SpriteObject].posY, (8 * FP_1) mov casinoSprites[6*SIZEOF SpriteObject].baseTexId, 30 mov casinoSprites[6*SIZEOF SpriteObject].frameCount, 1 mov casinoSprites[6*SIZEOF SpriteObject].curFrame, 0 mov casinoSprites[6*SIZEOF SpriteObject].animTimer, 0 mov casinoSprites[6*SIZEOF SpriteObject].animSpeed, 1 mov casinoSprites[6*SIZEOF SpriteObject].interactId, INTERACT_DURAK mov casinoSprites[6*SIZEOF SpriteObject].promptPtr, OFFSET promptDurak ; Sprite 7: Classic Slots 777 (West Arcade 1) mov casinoSprites[7*SIZEOF SpriteObject].posX, (6 * FP_1) mov casinoSprites[7*SIZEOF SpriteObject].posY, (8 * FP_1) mov casinoSprites[7*SIZEOF SpriteObject].baseTexId, 24 mov casinoSprites[7*SIZEOF SpriteObject].frameCount, 3 mov casinoSprites[7*SIZEOF SpriteObject].curFrame, 0 mov casinoSprites[7*SIZEOF SpriteObject].animTimer, 0 mov casinoSprites[7*SIZEOF SpriteObject].animSpeed, 8 mov casinoSprites[7*SIZEOF SpriteObject].interactId, INTERACT_SLOTS_777 mov casinoSprites[7*SIZEOF SpriteObject].promptPtr, OFFSET promptClassicSlot ; Sprite 8: CloverPit Slots 5x3 (West Arcade 2) mov casinoSprites[8*SIZEOF SpriteObject].posX, (6 * FP_1) mov casinoSprites[8*SIZEOF SpriteObject].posY, (11 * FP_1) mov casinoSprites[8*SIZEOF SpriteObject].baseTexId, 24 mov casinoSprites[8*SIZEOF SpriteObject].frameCount, 3 mov casinoSprites[8*SIZEOF SpriteObject].curFrame, 1 mov casinoSprites[8*SIZEOF SpriteObject].animTimer, 0 mov casinoSprites[8*SIZEOF SpriteObject].animSpeed, 8 mov casinoSprites[8*SIZEOF SpriteObject].interactId, INTERACT_SLOTS_CLOVER mov casinoSprites[8*SIZEOF SpriteObject].promptPtr, OFFSET promptCloverSlot ; Sprite 9: Craps & Dice Table (West Arcade 3) mov casinoSprites[9*SIZEOF SpriteObject].posX, (6 * FP_1) mov casinoSprites[9*SIZEOF SpriteObject].posY, (14 * FP_1) mov casinoSprites[9*SIZEOF SpriteObject].baseTexId, 30 mov casinoSprites[9*SIZEOF SpriteObject].frameCount, 1 mov casinoSprites[9*SIZEOF SpriteObject].curFrame, 0 mov casinoSprites[9*SIZEOF SpriteObject].animTimer, 0 mov casinoSprites[9*SIZEOF SpriteObject].animSpeed, 1 mov casinoSprites[9*SIZEOF SpriteObject].interactId, INTERACT_DICE mov casinoSprites[9*SIZEOF SpriteObject].promptPtr, OFFSET promptDice ; Sprite 10: Skulls & Cups Table mov casinoSprites[10*SIZEOF SpriteObject].posX, (10 * FP_1) mov casinoSprites[10*SIZEOF SpriteObject].posY, (15 * FP_1) mov casinoSprites[10*SIZEOF SpriteObject].baseTexId, 30 mov casinoSprites[10*SIZEOF SpriteObject].frameCount, 1 mov casinoSprites[10*SIZEOF SpriteObject].curFrame, 0 mov casinoSprites[10*SIZEOF SpriteObject].animTimer, 0 mov casinoSprites[10*SIZEOF SpriteObject].animSpeed, 1 mov casinoSprites[10*SIZEOF SpriteObject].interactId, INTERACT_SKULLS mov casinoSprites[10*SIZEOF SpriteObject].promptPtr, OFFSET promptSkulls ; Sprite 11: Coin Toss Stand mov casinoSprites[11*SIZEOF SpriteObject].posX, (14 * FP_1) mov casinoSprites[11*SIZEOF SpriteObject].posY, (15 * FP_1) mov casinoSprites[11*SIZEOF SpriteObject].baseTexId, 30 mov casinoSprites[11*SIZEOF SpriteObject].frameCount, 1 mov casinoSprites[11*SIZEOF SpriteObject].curFrame, 0 mov casinoSprites[11*SIZEOF SpriteObject].animTimer, 0 mov casinoSprites[11*SIZEOF SpriteObject].animSpeed, 1 mov casinoSprites[11*SIZEOF SpriteObject].interactId, INTERACT_COIN mov casinoSprites[11*SIZEOF SpriteObject].promptPtr, OFFSET promptCoin ; Sprite 12: Skill Check Stand mov casinoSprites[12*SIZEOF SpriteObject].posX, (18 * FP_1) mov casinoSprites[12*SIZEOF SpriteObject].posY, (15 * FP_1) mov casinoSprites[12*SIZEOF SpriteObject].baseTexId, 30 mov casinoSprites[12*SIZEOF SpriteObject].frameCount, 1 mov casinoSprites[12*SIZEOF SpriteObject].curFrame, 0 mov casinoSprites[12*SIZEOF SpriteObject].animTimer, 0 mov casinoSprites[12*SIZEOF SpriteObject].animSpeed, 1 mov casinoSprites[12*SIZEOF SpriteObject].interactId, INTERACT_SKILL_CHECK mov casinoSprites[12*SIZEOF SpriteObject].promptPtr, OFFSET promptSkillCheck ; Sprite 13: Umamusume Derby Lounge mov casinoSprites[13*SIZEOF SpriteObject].posX, (22 * FP_1) mov casinoSprites[13*SIZEOF SpriteObject].posY, (15 * FP_1) mov casinoSprites[13*SIZEOF SpriteObject].baseTexId, 30 mov casinoSprites[13*SIZEOF SpriteObject].frameCount, 1 mov casinoSprites[13*SIZEOF SpriteObject].curFrame, 0 mov casinoSprites[13*SIZEOF SpriteObject].animTimer, 0 mov casinoSprites[13*SIZEOF SpriteObject].animSpeed, 1 mov casinoSprites[13*SIZEOF SpriteObject].interactId, INTERACT_UMAMUSUME mov casinoSprites[13*SIZEOF SpriteObject].promptPtr, OFFSET promptUmamusume ; Sprite 14: Boutique & Shop (East Wing) mov casinoSprites[14*SIZEOF SpriteObject].posX, (26 * FP_1) mov casinoSprites[14*SIZEOF SpriteObject].posY, (12 * FP_1) mov casinoSprites[14*SIZEOF SpriteObject].baseTexId, 32 mov casinoSprites[14*SIZEOF SpriteObject].frameCount, 1 mov casinoSprites[14*SIZEOF SpriteObject].curFrame, 0 mov casinoSprites[14*SIZEOF SpriteObject].animTimer, 0 mov casinoSprites[14*SIZEOF SpriteObject].animSpeed, 1 mov casinoSprites[14*SIZEOF SpriteObject].interactId, INTERACT_SHOP mov casinoSprites[14*SIZEOF SpriteObject].promptPtr, OFFSET promptShop ; Sprite 15: Cashier & ATM (East Wing) mov casinoSprites[15*SIZEOF SpriteObject].posX, (26 * FP_1) mov casinoSprites[15*SIZEOF SpriteObject].posY, (16 * FP_1) mov casinoSprites[15*SIZEOF SpriteObject].baseTexId, 33 mov casinoSprites[15*SIZEOF SpriteObject].frameCount, 1 mov casinoSprites[15*SIZEOF SpriteObject].curFrame, 0 mov casinoSprites[15*SIZEOF SpriteObject].animTimer, 0 mov casinoSprites[15*SIZEOF SpriteObject].animSpeed, 1 mov casinoSprites[15*SIZEOF SpriteObject].interactId, INTERACT_ATM mov casinoSprites[15*SIZEOF SpriteObject].promptPtr, OFFSET promptATM ; Sprite 16: Player Terminal (East Wing) mov casinoSprites[16*SIZEOF SpriteObject].posX, (26 * FP_1) mov casinoSprites[16*SIZEOF SpriteObject].posY, (20 * FP_1) mov casinoSprites[16*SIZEOF SpriteObject].baseTexId, 33 mov casinoSprites[16*SIZEOF SpriteObject].frameCount, 1 mov casinoSprites[16*SIZEOF SpriteObject].curFrame, 0 mov casinoSprites[16*SIZEOF SpriteObject].animTimer, 0 mov casinoSprites[16*SIZEOF SpriteObject].animSpeed, 1 mov casinoSprites[16*SIZEOF SpriteObject].interactId, INTERACT_TERMINAL mov casinoSprites[16*SIZEOF SpriteObject].promptPtr, OFFSET promptPlayerTerminal ; Sprite 17: Buckshot Roulette (South-West) mov casinoSprites[17*SIZEOF SpriteObject].posX, (12 * FP_1) mov casinoSprites[17*SIZEOF SpriteObject].posY, (22 * FP_1) mov casinoSprites[17*SIZEOF SpriteObject].baseTexId, 30 mov casinoSprites[17*SIZEOF SpriteObject].frameCount, 1 mov casinoSprites[17*SIZEOF SpriteObject].curFrame, 0 mov casinoSprites[17*SIZEOF SpriteObject].animTimer, 0 mov casinoSprites[17*SIZEOF SpriteObject].animSpeed, 1 mov casinoSprites[17*SIZEOF SpriteObject].interactId, INTERACT_BUCKSHOT mov casinoSprites[17*SIZEOF SpriteObject].promptPtr, OFFSET promptBuckshot ; Sprite 18: Observer Lounge (South-East) mov casinoSprites[18*SIZEOF SpriteObject].posX, (20 * FP_1) mov casinoSprites[18*SIZEOF SpriteObject].posY, (22 * FP_1) mov casinoSprites[18*SIZEOF SpriteObject].baseTexId, 30 mov casinoSprites[18*SIZEOF SpriteObject].frameCount, 1 mov casinoSprites[18*SIZEOF SpriteObject].curFrame, 0 mov casinoSprites[18*SIZEOF SpriteObject].animTimer, 0 mov casinoSprites[18*SIZEOF SpriteObject].animSpeed, 1 mov casinoSprites[18*SIZEOF SpriteObject].interactId, INTERACT_OBSERVER mov casinoSprites[18*SIZEOF SpriteObject].promptPtr, OFFSET promptObserver ; Sprite 19: Russian Roulette (Backroom Entrance) mov casinoSprites[19*SIZEOF SpriteObject].posX, (16 * FP_1) mov casinoSprites[19*SIZEOF SpriteObject].posY, (25 * FP_1) mov casinoSprites[19*SIZEOF SpriteObject].baseTexId, 34 mov casinoSprites[19*SIZEOF SpriteObject].frameCount, 1 mov casinoSprites[19*SIZEOF SpriteObject].curFrame, 0 mov casinoSprites[19*SIZEOF SpriteObject].animTimer, 0 mov casinoSprites[19*SIZEOF SpriteObject].animSpeed, 1 mov casinoSprites[19*SIZEOF SpriteObject].interactId, INTERACT_RUSSIAN_ROULETTE mov casinoSprites[19*SIZEOF SpriteObject].promptPtr, OFFSET promptRussianRoulette ; Sprite 20: Online Russian Roulette (Backroom Secret Terminal) mov casinoSprites[20*SIZEOF SpriteObject].posX, (18 * FP_1) mov casinoSprites[20*SIZEOF SpriteObject].posY, (25 * FP_1) mov casinoSprites[20*SIZEOF SpriteObject].baseTexId, 34 mov casinoSprites[20*SIZEOF SpriteObject].frameCount, 1 mov casinoSprites[20*SIZEOF SpriteObject].curFrame, 0 mov casinoSprites[20*SIZEOF SpriteObject].animTimer, 0 mov casinoSprites[20*SIZEOF SpriteObject].animSpeed, 1 mov casinoSprites[20*SIZEOF SpriteObject].interactId, INTERACT_ONLINE_RR mov casinoSprites[20*SIZEOF SpriteObject].promptPtr, OFFSET promptOnlineRR ; Sprite 21: Hell Tower Portal (South Wing Deep End) mov casinoSprites[21*SIZEOF SpriteObject].posX, (16 * FP_1 + FP_HALF) mov casinoSprites[21*SIZEOF SpriteObject].posY, (29 * FP_1) mov casinoSprites[21*SIZEOF SpriteObject].baseTexId, 4 mov casinoSprites[21*SIZEOF SpriteObject].frameCount, 1 mov casinoSprites[21*SIZEOF SpriteObject].curFrame, 0 mov casinoSprites[21*SIZEOF SpriteObject].animTimer, 0 mov casinoSprites[21*SIZEOF SpriteObject].animSpeed, 1 mov casinoSprites[21*SIZEOF SpriteObject].interactId, INTERACT_HELL_TOWER mov casinoSprites[21*SIZEOF SpriteObject].promptPtr, OFFSET promptHellTower mov eax, 1 jmp init_return init_failed: xor eax, eax init_return: pop edi pop esi pop ebx ret Init3DEngine ENDP ; --- Main Loop of the 3D Casino Engine --- StartCasino3D PROC uses ebx esi edi call Init3DEngine test eax, eax jz engine_shutdown invoke GetTickCount mov rngSeed3D, eax mov previousTick3D, eax engine_loop: invoke PeekMessageA, OFFSET msg3D, 0, 0, 0, PM_REMOVE test eax, eax jz dispatch_frame cmp msg3D.message, WM_QUIT je engine_shutdown invoke TranslateMessage, OFFSET msg3D invoke DispatchMessageA, OFFSET msg3D jmp engine_loop dispatch_frame: invoke GetTickCount mov frameStart3D, eax sub eax, previousTick3D cmp eax, 50 jbe @F mov eax, 50 @@: mov deltaTime3D, eax mov eax, frameStart3D mov previousTick3D, eax invoke GetForegroundWindow cmp eax, h3DWnd jne engine_idle invoke IsIconic, h3DWnd test eax, eax jnz engine_idle invoke Pressed3D, 7Ah test eax, eax jz @F call ToggleFullscreen3D @@: invoke Pressed3D, 1Bh test eax, eax jz engine_tick cmp engineMode, MODE_WALK jne leave_table xor paused3D, 1 jmp engine_tick leave_table: ; An already paid round cannot be skipped or settled twice. cmp slotSpinState, 1 je engine_tick cmp roulState, 1 je engine_tick cmp coin3d_state, 1 je engine_tick cmp dice3d_state, 1 je engine_tick cmp skulls3d_state, 1 je engine_tick cmp skulls3d_state, 2 je engine_tick mov engineMode, MODE_WALK engine_tick: cmp paused3D, 0 jne draw_pause mov eax, deltaTime3D add animationClock3D, eax cmp engineMode, MODE_WALK jne check_slots_mode call UpdateCamera3D call CheckInteractions call HandlePlayerInput call UpdateCamera3D call RenderCeilingAndFloor call RenderWalls call RenderSprites call RenderHUD call RenderMinimap jmp present_frame check_slots_mode: cmp engineMode, MODE_SLOTS jne check_bj_mode call HandleSlotsInput call RenderSlotsGame jmp present_frame check_bj_mode: cmp engineMode, MODE_BLACKJACK jne check_roul_mode call HandleBlackjackInput call RenderBlackjackGame jmp present_frame check_roul_mode: cmp engineMode, MODE_ROULETTE jne check_shop_mode call HandleRouletteInput call RenderRouletteGame jmp present_frame check_shop_mode: cmp engineMode, MODE_SHOP jne check_atm_mode call HandleShopInput call RenderShopGame jmp present_frame check_atm_mode: cmp engineMode, MODE_ATM jne check_coin_mode call HandleATMInput call RenderATMGame jmp present_frame check_coin_mode: cmp engineMode, MODE_COIN jne check_dice_mode call HandleCoinInput call RenderCoinGame jmp present_frame check_dice_mode: cmp engineMode, MODE_DICE jne check_skulls_mode call HandleDiceInput call RenderDiceGame jmp present_frame check_skulls_mode: cmp engineMode, MODE_SKULLS jne present_frame call HandleSkullsInput call RenderSkullsGame jmp present_frame draw_pause: invoke DrawBoxBorder, 65, 75, 190, 85, 00151C21h, 00D8BC6Ah, 2 invoke DrawString8x8, 86, 88, OFFSET textPause3D, 00FFFFFFh invoke DrawString8x8, 78, 111, OFFSET textResume3D, 00D8BC6Ah invoke DrawString8x8, 78, 131, OFFSET textQuit3D, 00BBBBBBh invoke Pressed3D, 51h test eax, eax jnz engine_shutdown present_frame: call Present3D lea edi, pressedKeys3D xor eax, eax mov ecx, 64 rep stosd invoke GetTickCount sub eax, frameStart3D cmp eax, 16 jae engine_loop mov ecx, 16 sub ecx, eax invoke Sleep, ecx jmp engine_loop engine_idle: invoke Sleep, 50 jmp engine_loop engine_shutdown: call SaveProgress3D cmp h3DDC, 0 je @F invoke ReleaseDC, h3DWnd, h3DDC mov h3DDC, 0 @@: cmp h3DWnd, 0 je @F invoke DestroyWindow, h3DWnd mov h3DWnd, 0 @@: ret StartCasino3D ENDP include src_graphics\platform_code.inc