diff --git a/build/graphics/poker.exe b/build/graphics/poker.exe index f017cf7..2f4481c 100644 Binary files a/build/graphics/poker.exe and b/build/graphics/poker.exe differ diff --git a/casino3d.inc b/casino3d.inc index 628a60e..72afffe 100644 --- a/casino3d.inc +++ b/casino3d.inc @@ -1,5517 +1,5614 @@ - -; ============================================================================== -; 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 -CopyFileA PROTO :DWORD,:DWORD,:DWORD -lstrcmpiA PROTO :DWORD,:DWORD -GetFileSize PROTO :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 -MODE_SKILL equ 9 - -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 -include src_graphics\casino_actions_data.inc -include src_graphics\audio_data.inc -include src_graphics\startup_data.inc -include src_graphics\card_tables_data.inc -include src_graphics\native_durak_data.inc -include src_graphics\scene_animation_data.inc -include src_graphics\arrival_data.inc -include src_graphics\city_arrival_data.inc -include src_graphics\merchant_data.inc -include src_graphics\hall_data.inc -include src_graphics\npc_mind_data.inc -include src_graphics\npc_life_data.inc -include src_graphics\native_wheel_data.inc -include src_graphics\billiards_data.inc -include src_graphics\buckshot_data.inc -include src_graphics\russian_view_data.inc -include src_graphics\unavailable_data.inc -include src_graphics\native_slots_data.inc -include src_graphics\native_clover_data.inc -include src_graphics\native_coin_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 192,241,241,229,236,225,235,229,240,32,202,224,231,232,237,238,32,45,32,50,46,53,68,0 -szTexturesRelPath db "assets\textures\casino3d-hd.bin",0 -szTexturesFullPath db 260 dup(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 91,69,93,32,207,206,202,197,208,32,40,210,197,213,192,209,209,202,200,201,32,213,206,203,196,197,204,41,0 -promptDurak db "[E] ÊÀÐÒÛ: ÏÎÄÊÈÄÍÎÉ ÄÓÐÀÊ",0 -promptCasinoRoulette db "[E] ÅÂÐÎÏÅÉÑÊÀß ÐÓËÅÒÊÀ",0 -promptClassicSlot db "[E] ÊËÀÑÑÈ×ÅÑÊÈÅ ÑËÎÒÛ 777",0 -promptCloverSlot db "[E] ÑËÎÒÛ CLOVERPIT (5x3)",0 -promptDice db 91,69,93,32,200,195,208,192,32,194,32,202,206,209,210,200,0 -promptSkulls db "[E] ÍÀϨÐÑÒÊÈ (×ÅÐÅÏÀ)",0 -promptCoin db "[E] ÌÎÍÅÒÊÀ (ÎШË/ÐÅØÊÀ)",0 -promptSkillCheck db "[E] ÒÐÅÍÈÐÎÂÊÀ ÐÅÀÊÖÈÈ",0 -promptBuckshot db 91,69,93,32,193,192,202,216,206,210,32,208,211,203,197,210,202,192,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 202,192,199,200,202,32,51,68,32,45,32,193,203,221,202,196,198,197,202,32,40,50,49,41,0 -szTitlePoker db 202,192,199,200,202,32,51,68,32,45,32,207,206,202,197,208,32,40,210,197,213,192,209,209,202,200,201,32,213,206,203,196 - db 197,204,41,0 -szTitleDurak db 202,192,199,200,202,32,51,68,32,45,32,207,197,208,197,194,206,196,205,206,201,32,196,211,208,192,202,0 -szTitleCasinoRoulette db 202,192,199,200,202,32,51,68,32,45,32,197,194,208,206,207,197,201,209,202,192,223,32,208,211,203,197,210,202,192,0 -szTitleClassicSlot db 202,192,199,200,202,32,51,68,32,45,32,192,194,210,206,204,192,210,32,55,55,55,0 -szTitleCloverSlot db 202,192,199,200,202,32,51,68,32,45,32,202,203,197,194,197,208,205,192,223,32,223,204,192,32,40,53,120,51,41,0 -szTitleDice db 202,192,199,200,202,32,51,68,32,45,32,200,195,208,192,32,194,32,202,206,209,210,200,0 -szTitleSkulls db 202,192,199,200,202,32,51,68,32,45,32,205,192,207,168,208,209,210,202,200,0 -szTitleCoin db 202,192,199,200,202,32,51,68,32,45,32,204,206,205,197,210,202,192,32,40,206,208,168,203,47,208,197,216,202,192,41,0 -szTitleSkillCheck db 202,192,199,200,202,32,51,68,32,45,32,207,208,206,194,197,208,202,192,32,205,192,194,219,202,192,0 -szTitleBuckshot db 202,192,199,200,202,32,51,68,32,45,32,193,192,202,216,206,210,32,208,211,203,197,210,202,192,0 -szTitleRussianRoulette db 202,192,199,200,202,32,51,68,32,45,32,208,211,209,209,202,192,223,32,208,211,203,197,210,202,192,0 -szTitleOnlineRR db 202,192,199,200,202,32,51,68,32,45,32,209,197,210,197,194,192,223,32,208,211,209,209,202,192,223,32,208,211,203,197,210 - db 202,192,0 -szTitleUmamusume db 202,192,199,200,202,32,51,68,32,45,32,195,206,205,202,200,32,211,204,192,204,211,209,211,204,197,0 -szTitleHellTower db 202,192,199,200,202,32,51,68,32,45,32,192,196,209,202,192,223,32,193,192,216,205,223,0 -szTitleShop db 202,192,199,200,202,32,51,68,32,45,32,202,192,208,210,219,32,200,32,210,192,203,200,209,204,192,205,219,0 -szTitleATM db 202,192,199,200,202,32,51,68,32,45,32,193,192,205,202,206,204,192,210,0 -szTitleTerminal db 202,192,199,200,202,32,51,68,32,45,32,203,206,202,192,203,220,205,219,197,32,207,208,206,212,200,203,200,0 -szTitleObserver db 202,192,199,200,202,32,51,68,32,45,32,205,192,193,203,222,196,192,210,197,203,220,32,40,200,200,41,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) - -coinRxAnimTable db 26, 22, 16, 6, 16, 22, 26, 22, 16, 6 - -; --- Native 2.5D Coin Flip --- -coin3d_bet dd 50 -coin3d_choice 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 - -textCoinTitle db "* * * Ç Î Ë Î Ò À ß Ì Î Í Å Ò À * * *",0 -textCoinHeads db "ÎШË",0 -textCoinTails db "ÐÅØÊÀ",0 -textCoinSide1 db "[1] ÎШË",0 -textCoinSide2 db "[2] ÐÅØÊÀ",0 -textCoinFlipping db "ÌÎÍÅÒÀ  ÏÎ˨ÒÅ...",0 -textCoinWin db "ÏÎÁÅÄÀ: +$",0 -textCoinLose db "ÍÅ ÓÃÀÄÀËÈ!",0 -textCoinStreakFmt db "ÑÅÐÈß ÏÎÁÅÄ: x",0 -textCoinSelected db "ÂÛÁÐÀÍÎ",0 -textCoinKey1 db "[1] ÎШË",0 -textCoinKey2 db "[2] ÐÅØÊÀ",0 -textCoinKeySpace db "[SPACE]",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 200,195,208,192,32,194,32,202,206,209,210,200,0 -textDiceEven db "[1] רÒ",0 -textDiceOdd db "[2] ÍÅ×ÅÒ",0 -textDiceEvenNums db "2 4 6 ...",0 -textDiceOddNums db "3 5 7 ...",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 "[SPACE]",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 -skulls3d_cup0 dd 0 -skulls3d_cup1 dd 1 -skulls3d_cup2 dd 2 - -textSkullsTitle db "* * * Í À Ï ¨ Ð Ñ Ò Ê È * * *",0 -textSkullsPhase0 db "ÄÅËÀÉ ÑÒÀÂÊÓ È ÆÌÈ [ÏÐÎÁÅË]",0 -textSkullsPhase1 db "ÑÌÎÒÐÈ, ÃÄÅ ÇÎËÎÒÎÉ ØÀÐ...",0 -textSkullsPhase2 db "ÊÐÓ×Ó, ÂÅÐ×Ó, ÇÀÏÓÒÀÒÜ ÕÎ×Ó...",0 -textSkullsPhase3 db "ÃÄÅ ØÀÐ? ÂÛÁÈÐÀÉ: [1], [2] ÈËÈ [3]!",0 -textSkullsWin db "ÂÛÈÃÐÛØ: +$",0 -textSkullsWinMult db "! (x3) ÂÛ ÓÃÀÄÀËÈ!",0 -textSkullsLose db "ÌÈÌÎ! ØÀÐ ÁÛË Â ÄÐÓÃÎÌ ÌÅÑÒÅ!",0 -textSkullsAgain db "[ÏÐÎÁÅË] - ÑÛÃÐÀÒÜ ÅÙ¨ ÐÀÇ",0 -textSkullsKey1 db "[1]",0 -textSkullsKey2 db "[2]",0 -textSkullsKey3 db "[3]",0 -textSkullsKeySpace db "[SPACE] ÑÒÀÐÒ",0 - -; --- Native 2.5D Skill Check (Dead by Daylight Survivor Check) --- -skill3d_bet dd 50 -skill3d_state dd 0 ; 0=Ready, 1=Active, 2=Hit Result, 3=Miss Result, 4=Escaped, 5=Defeated -skill3d_timer dd 0 -skill3d_needle dd 55 ; Needle X (52..268) -skill3d_speed dd 4 -skill3d_dir dd 1 ; 1=Right, -1=Left -skill3d_zone_start dd 140 -skill3d_zone_width dd 48 -skill3d_great_start dd 176 -skill3d_great_width dd 12 -skill3d_hits dd 0 -skill3d_misses dd 0 -skill3d_last_result dd 0 -skill3d_win_amount dd 0 - -textSkillTitle db 61,61,61,32,207,208,206,194,197,208,202,192,32,205,192,194,219,202,192,32,61,61,61,0 -textSkillHitsHdr db "ÕÈÒ: ",0 -textSkillMissHdr db "ÏÐÎÌÀÕ: ",0 -textSkillReadyMsg db "ÍÀÆÌÈÒÅ [ÏÐÎÁÅË] ÄËß ÑÒÀÐÒÀ",0 -textSkillPrompt db "ÍÀÆÌÈÒÅ [ÏÐÎÁÅË]  ÇÎÍÅ!",0 -textSkillHitMsg db "ÕÈÒ! ÒÎ×ÍÎÅ ÏÎÏÀÄÀÍÈÅ!",0 -textSkillGreatMsg db 206,210,203,200,215,205,206,33,32,43,193,206,205,211,209,33,0 -textSkillMissMsg db "ÏÐÎÌÀÕ! ÒÐÅÂÎÃÀ!",0 -textSkillEscape db "ÏÎÁÅà ÓÑÏÅØÅÍ! ÂÛÈÃÐÛØ: +$",0 -textSkillLost db "ÂÛ ÏÎÉÌÀÍÛ! ÏÐÎÈÃÐÛØ ÑÒÀÂÊÈ!",0 -textSkillKeySpace db "[SPACE] ÐÅÀÊÖÈß",0 -textSkillKeyBet 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 205,200,215,220,223,0 -strDealerBust db "ÄÈËÅÐ ÏÅÐÅÁÐÀË! ÏÎÁÅÄÀ! +$",0 -strPlayerBust db "ÏÅÐÅÁÎÐ (>21)! ÏÐÎÈÃÐÛØ",0 - -sym7 db " 777 ",0 -symBar db " BAR ",0 -symBell db 32,199,194,206,205,0 -symCherry db 194,200,216,205,223,0 -symClover db 202,203,197,194,197,208,0 -symGem db 192,203,204,192,199,0 -symCrown db 202,206,208,206,205,192,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 (104 * 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 --- - -; --- DDA Raycasting Walls --- -RenderWalls PROC - local col:DWORD - local originalStart: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 texXHD:DWORD - local pixelMaterial: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 wall_map_boundary - - 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 wall_map_boundary - cmp mapX, MAP_WIDTH - jge wall_map_boundary - cmp mapY, 0 - jl wall_map_boundary - cmp mapY, MAP_HEIGHT - jge wall_map_boundary - - mov eax, mapY - shl eax, 5 - add eax, mapX - mov edx, worldMap3D - movzx eax, BYTE PTR [edx + eax] - test eax, eax - jnz hit_wall - jmp dda_step_loop - -wall_map_boundary: - cmp outdoorRender3D, 0 - je hit_wall - mov eax, col - mov zBuffer[eax*4], 7FFFFFFFh - jmp next_col - -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 - - ; Unit projection is shared by indoor room height and outdoor storeys. - mov eax, SCREEN_H - imul eax, FP_1 - cdq - idiv perpWallDist - mov lineH, eax - - mov eax, lineH - imul viewEye3D - shrd eax, edx, 16 - add eax, viewHorizon3D - mov drawEnd, eax - mov ebx, lineH - mov eax, viewCeiling3D - cmp outdoorRender3D, 0 - je @F - mov eax, CITY_STOREY_HEIGHT -@@: - imul ebx - shrd eax, edx, 16 - mov ebx, eax - mov lineH, ebx - mov eax, drawEnd - sub eax, ebx - mov drawStart, eax - cmp outdoorRender3D, 0 - je wall_store_original_start - ; Floor height is independent of storey height. - mov eax, drawEnd - sub eax, lineH - mov drawStart, eax - mov eax, mapY - shl eax, 5 - add eax, mapX - mov edx, worldMap3D - movzx eax, BYTE PTR [edx+eax] -wall_exterior_tall: - ; Roof projection and texture sampling use the same storey count. - mov eax, lineH - imul eax, CITY_BUILDING_STOREYS-1 - sub drawStart, eax - mov eax, lineH - imul eax, CITY_BUILDING_STOREYS - mov lineH, eax -wall_store_original_start: - mov eax, drawStart - mov originalStart, eax - - 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 - mov texXHD, eax - 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 - xor texXHD, 0FFFFh -@@: - cmp side, 1 - jne select_tex - cmp rayDirY, 0 - jge select_tex - mov eax, 127 - sub eax, texX - mov texX, eax - xor texXHD, 0FFFFh - -select_tex: - mov eax, mapY - shl eax, 5 - add eax, mapX - mov edx, worldMap3D - movzx eax, BYTE PTR [edx + 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, drawStart - sub eax, originalStart - 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 - mov edx, texId - cmp outdoorRender3D, 0 - je wall_sample_material - imul eax, CITY_BUILDING_STOREYS - cmp eax, 128*(CITY_BUILDING_STOREYS-1) - jae wall_lower_storey - push eax - shr eax, 7 - add eax, mapX - add eax, mapY - xor edx, edx - mov ebx, 3 - div ebx - add edx, 65 - pop eax - and eax, 127 - jmp wall_sample_material -wall_lower_storey: - sub eax, 128*(CITY_BUILDING_STOREYS-1) -wall_sample_material: - mov pixelMaterial, edx - cmp outdoorRender3D, 0 - je wall_sample_indoor_hd - cmp hallCityDetail3D.pixels, 0 - je wall_sample_standard - cmp edx, 57 - jb wall_sample_standard - cmp edx, 72 - ja wall_sample_standard - cmp perpWallDist, 6*FP_1 - ja wall_sample_standard - ; Preserve subtexel detail near facades; retain the 128px mip at distance. - push edx - mov eax, edi - shr eax, 15 - imul eax, CITY_BUILDING_STOREYS - and eax, 255 - shl eax, 8 - mov ebx, texXHD - shr ebx, 8 - add eax, ebx - pop edx - sub edx, 57 - shl edx, 16 - add eax, edx - mov ebx, hallCityDetail3D.pixels - mov eax, [ebx+eax*4] - jmp wall_shade_pixel -wall_sample_indoor_hd: - cmp edx, 80 - jb wall_sample_standard - cmp edx, 103 - ja wall_sample_standard - mov ebx, hallRoomHD3D.pixels - cmp edx, 92 - jb wall_sample_room_hd - mov ebx, hallArchitectureHD3D.pixels - sub edx, 12 -wall_sample_room_hd: - test ebx, ebx - jz wall_sample_standard_restore - sub edx, 80 - shl edx, 18 - add ebx, edx - mov eax, edi - shr eax, 15 - and eax, 255 - shl eax, 8 - mov edx, texXHD - shr edx, 8 - add eax, edx - mov eax, [ebx+eax*4] - jmp wall_shade_pixel -wall_sample_standard_restore: - mov edx, texId - mov eax, edi - shr eax, 16 - and eax, 127 -wall_sample_standard: - shl eax, 7 - add eax, texX - - shl edx, 14 - add eax, edx - mov eax, [texturesBuffer + eax*4] - - ; Shade wall pixel -wall_shade_pixel: - mov ebx, shade - cmp outdoorRender3D, 0 - je wall_ambient_shade - push eax - push ecx - invoke IsCityEmissive3D, eax, pixelMaterial - pop ecx - test eax, eax - pop eax - jz wall_ambient_shade - mov ebx, 256 -wall_ambient_shade: - cmp hallLevel3D, 0 - je @F - imul ebx, 7 - shr ebx, 3 -@@: - 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 --- - -; --- 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, 00FFD700h, 1 - - ; Draw Sprites on radar - cmp hallLevel3D, 0 - jne draw_player_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, 00FF2020h - 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 PlayCasinoSound3D, OFFSET soundSlotSpin, 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, 00FFD700h, 3 - - ; Illuminated Top Marquee - invoke DrawBoxBorder, 25, 20, 270, 32, 000A0505h, 00FFFF00h, 2 - invoke DrawString8x8, 55, 32, OFFSET textSlots3D, 00FFD700h - - ; 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 PlayCasinoSound3D, 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 PlayCasinoSound3D, OFFSET soundJackpot, 0, 1 - jmp draw_reels -@@: - mov eax, slotBet - imul eax, 10 - mov slotWinAmount, eax - add bankroll, eax - invoke PlayCasinoSound3D, OFFSET soundRoundWin, 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 PlayCasinoSound3D, OFFSET soundRoundWin, 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, 00FFD700h, 1 - - invoke DrawString8x8, 28, 172, OFFSET textBank3D, 00FFD700h - invoke FormatNumber, bankroll, OFFSET hudNumBuffer - invoke DrawString8x8, 110, 172, OFFSET hudNumBuffer, 00FFFF00h - - invoke DrawString8x8, 175, 172, OFFSET textBet3D, 00FFD700h - 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, 00FFFF00h - invoke FormatNumber, slotWinAmount, OFFSET hudNumBuffer - invoke DrawString8x8, 110, 187, OFFSET hudNumBuffer, 00FFFF00h - -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, 00FF2020h - 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, 00FFD700h - 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, 00FFD700h - ret -DrawReelSymbolAt1 ENDP - -DrawReelSymbolAt2 PROC - cmp eax, 0 - jne @F - invoke DrawString8x8, 135, 105, OFFSET sym7, 00FF2020h - 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, 00FFD700h - 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, 00FFD700h - ret -DrawReelSymbolAt2 ENDP - -DrawReelSymbolAt3 PROC - cmp eax, 0 - jne @F - invoke DrawString8x8, 218, 105, OFFSET sym7, 00FF2020h - 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, 00FFD700h - 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, 00FFD700h - 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 PlayCasinoSound3D, 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 PlayCasinoSound3D, OFFSET soundRoundWin, 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 PlayCasinoSound3D, 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 PlayCasinoSound3D, OFFSET soundRoundWin, 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 PlayCasinoSound3D, OFFSET soundRoundWin, 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, 00FFD700h, 3 - - ; Dealer Area Top - invoke DrawString8x8, 25, 20, OFFSET textBJ3D, 00FFD700h - invoke DrawString8x8, 25, 35, OFFSET textDealer3D, 00FFFFFFh - invoke FormatNumber, bjDealerScore, OFFSET hudNumBuffer - invoke DrawString8x8, 120, 35, OFFSET hudNumBuffer, 00FFFF00h - - ; 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, 00FFD700h, 1 - cmp BYTE PTR [bjOutcomeMsg], 0 - je draw_bj_controls - invoke DrawString8x8, 28, 188, OFFSET bjOutcomeMsg, 00FFFF00h - 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 PlayCasinoSound3D, 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, 00FFD700h, 3 - - ; 2.5D Rotating Wheel on Left - invoke DrawCircle, 85, 110, 65, 00102550h - invoke DrawCircle, 85, 110, 60, 00FFD700h - invoke DrawCircle, 85, 110, 52, 00101010h - invoke DrawCircle, 85, 110, 22, 00FFD700h ; 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 PlayCasinoSound3D, OFFSET soundRoundWin, 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 PlayCasinoSound3D, OFFSET soundRoundWin, 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 PlayCasinoSound3D, 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 PlayCasinoSound3D, OFFSET soundRoundWin, 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 PlayCasinoSound3D, OFFSET soundRoundWin, 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, 00FFFF00h, 2 -@@: - cmp roulBetType, 2 - jne @F - invoke DrawBoxBorder, 173, 58, 129, 32, 0, 00FFFF00h, 2 -@@: - cmp roulBetType, 3 - jne @F - invoke DrawBoxBorder, 173, 93, 129, 32, 0, 00FFFF00h, 2 -@@: - cmp roulBetType, 4 - jne @F - invoke DrawBoxBorder, 173, 128, 64, 30, 0, 00FFFF00h, 2 -@@: - cmp roulBetType, 5 - jne draw_ro_footer - invoke DrawBoxBorder, 238, 128, 64, 30, 0, 00FFFF00h, 2 - -draw_ro_footer: - invoke DrawBoxBorder, 20, 180, 280, 42, 00101015h, 00FFD700h, 1 - - cmp roulState, 2 - jne @F - invoke DrawString8x8, 28, 186, OFFSET textResult3D, 00FFD700h - invoke FormatNumber, roulWinningNum, OFFSET hudNumBuffer - invoke DrawString8x8, 85, 186, OFFSET hudNumBuffer, 00FFFF00h - 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, 00FFD700h, 3 - invoke DrawString8x8, 25, 20, OFFSET textShop3D, 00FFD700h - - invoke DrawBoxBorder, 20, 40, 280, 32, 001A1010h, 00FFFFFFh, 1 - invoke DrawString8x8, 28, 46, OFFSET textItem1_3D, 00FFFF00h - invoke DrawString8x8, 28, 58, OFFSET textShopHint3D, 00A0A0A0h - - invoke DrawBoxBorder, 20, 80, 280, 32, 001A1010h, 00FFFFFFh, 1 - invoke DrawString8x8, 28, 86, OFFSET textItem2_3D, 00FFFF00h - invoke DrawString8x8, 28, 98, OFFSET textShopHint3D, 00A0A0A0h - - invoke DrawBoxBorder, 20, 120, 280, 32, 001A1010h, 00FFFFFFh, 1 - invoke DrawString8x8, 28, 126, OFFSET textItem3_3D, 00FFFF00h - invoke DrawString8x8, 28, 138, OFFSET textShopHint3D, 00A0A0A0h - - invoke DrawBoxBorder, 20, 165, 280, 55, 00100A0Ah, 00FFD700h, 1 - invoke DrawString8x8, 28, 172, OFFSET textBank3D, 00FFD700h - invoke FormatNumber, bankroll, OFFSET hudNumBuffer - invoke DrawString8x8, 110, 172, OFFSET hudNumBuffer, 00FFFF00h - - 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 keyW:DWORD - mov esi, strPtr - xor ecx, ecx -keycap_len: - mov al, [esi+ecx] - test al, al - jz keycap_len_done - inc ecx - jmp keycap_len -keycap_len_done: - shl ecx, 3 - add ecx, 8 - mov keyW, ecx - - ; Drop shadow - mov eax, y - add eax, 2 - invoke DrawBox, x, eax, keyW, 13, 0008080Ch - - ; Border and Fill - cmp isActive, 0 - je keycap_inactive - mov eax, 00FFFF00h ; Bright Yellow active border - mov edx, 001B4B22h ; Casino Green active fill - mov ebx, 00FFFF00h ; Bright Yellow active text - jmp keycap_draw_box -keycap_inactive: - mov eax, 00606870h ; Slate inactive border - mov edx, 001A1C22h ; Charcoal inactive fill - mov ebx, 00D0D8E0h ; Silver inactive text - -keycap_draw_box: - push ebx - invoke DrawBoxBorder, x, y, keyW, 13, edx, eax, 1 - pop ebx - - ; Text label - mov eax, x - add eax, 4 - mov edx, y - add edx, 3 - invoke DrawString8x8, eax, edx, strPtr, ebx - - mov eax, keyW - add eax, 4 - ret -DrawKeycap3D ENDP - -DrawChipStack PROC uses ebx esi edi, x:DWORD, y:DWORD, chipCount:DWORD - mov edi, chipCount - xor esi, esi -chip_loop: - cmp esi, edi - jge chip_done - mov eax, esi - shl eax, 2 - mov edx, y - sub edx, eax - - ; Shadow - mov eax, x - add eax, 2 - mov ecx, edx - add ecx, 5 - invoke DrawBox, eax, ecx, 20, 2, 00061004h - - ; Red Clay Chip body with white rim - invoke DrawBoxBorder, x, edx, 24, 6, 00B81515h, 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 - mov ecx, edx - add ecx, 1 - invoke DrawBox, eax, ecx, 3, 4, 00FFFFFFh - - inc esi - jmp chip_loop -chip_done: - ret -DrawChipStack ENDP - -DrawDetailedCoin PROC uses ebx esi edi, cxVal:DWORD, cyVal:DWORD, rxVal:DWORD, ryVal:DWORD, outerColor:DWORD, innerColor:DWORD, reliefType:DWORD - local rxSq:DWORD - local rySq:DWORD - local rxRySq:DWORD - local threshSq:DWORD - local curDy:DWORD - local curDx:DWORD - local curX:DWORD - local curY:DWORD - - mov eax, rxVal - cmp eax, 0 - jle coin_draw_done - mov eax, ryVal - cmp eax, 0 - jle coin_draw_done - - mov eax, rxVal - imul eax, rxVal - mov rxSq, eax - - mov eax, ryVal - imul eax, ryVal - mov rySq, eax - - imul eax, rxSq - mov rxRySq, eax - - ; 3/4 threshold for rim bevel - mov ecx, 3 - imul eax, ecx - shr eax, 2 - mov threshSq, eax - - ; Scan rows - mov eax, ryVal - neg eax - mov curDy, eax -coin_row_loop: - mov eax, curDy - cmp eax, ryVal - jg coin_relief_check - - mov edx, cyVal - add edx, curDy - mov curY, edx - - ; Scan columns - mov eax, rxVal - neg eax - mov curDx, eax -coin_col_loop: - mov eax, curDx - cmp eax, rxVal - jg coin_col_next_row - - mov ecx, cxVal - add ecx, curDx - mov curX, ecx - - ; val = dx*dx*rySq + dy*dy*rxSq - mov eax, curDx - imul eax, curDx - imul eax, rySq - mov ebx, eax - - mov eax, curDy - imul eax, curDy - imul eax, rxSq - add eax, ebx - - cmp eax, rxRySq - ja coin_pixel_outside - - cmp eax, threshSq - jb coin_draw_inner - invoke DrawPixel, curX, curY, outerColor - jmp coin_pixel_outside -coin_draw_inner: - invoke DrawPixel, curX, curY, innerColor - -coin_pixel_outside: - inc curDx - jmp coin_col_loop - -coin_col_next_row: - inc curDy - jmp coin_row_loop - -coin_relief_check: - cmp rxVal, 14 - jl coin_draw_done - - cmp reliefType, 1 - je coin_draw_eagle - cmp reliefType, 2 - je coin_draw_numeral - jmp coin_draw_done - -coin_draw_eagle: - ; Imperial Eagle relief (Dark Gold 009A7A00h / Bright 00FFD700h) - mov eax, cxVal - sub eax, 3 - mov edx, cyVal - sub edx, 14 - invoke DrawBox, eax, edx, 7, 2, 009A7A00h - - mov eax, cxVal - sub eax, 4 - mov edx, cyVal - sub edx, 12 - invoke DrawBox, eax, edx, 9, 2, 009A7A00h - - mov eax, cxVal - sub eax, 2 - mov edx, cyVal - sub edx, 9 - invoke DrawBox, eax, edx, 5, 12, 009A7A00h - - mov eax, cxVal - sub eax, 1 - mov edx, cyVal - sub edx, 8 - invoke DrawBox, eax, edx, 3, 10, 00FFD700h - - mov eax, cxVal - sub eax, 10 - mov edx, cyVal - sub edx, 8 - invoke DrawBox, eax, edx, 7, 3, 009A7A00h - - mov eax, cxVal - sub eax, 13 - mov edx, cyVal - sub edx, 5 - invoke DrawBox, eax, edx, 10, 3, 009A7A00h - - mov eax, cxVal - sub eax, 11 - mov edx, cyVal - sub edx, 2 - invoke DrawBox, eax, edx, 7, 3, 009A7A00h - - mov eax, cxVal - add eax, 4 - mov edx, cyVal - sub edx, 8 - invoke DrawBox, eax, edx, 7, 3, 009A7A00h - - mov eax, cxVal - add eax, 4 - mov edx, cyVal - sub edx, 5 - invoke DrawBox, eax, edx, 10, 3, 009A7A00h - - mov eax, cxVal - add eax, 5 - mov edx, cyVal - sub edx, 2 - invoke DrawBox, eax, edx, 7, 3, 009A7A00h - - mov eax, cxVal - sub eax, 4 - mov edx, cyVal - add edx, 4 - invoke DrawBox, eax, edx, 9, 3, 009A7A00h - - mov eax, cxVal - sub eax, 3 - mov edx, cyVal - add edx, 7 - invoke DrawBox, eax, edx, 7, 3, 009A7A00h - jmp coin_draw_done - -coin_draw_numeral: - ; Roman numeral 'I' & laurel - mov eax, cxVal - sub eax, 5 - mov edx, cyVal - sub edx, 10 - invoke DrawBox, eax, edx, 11, 3, 009A7A00h - - mov eax, cxVal - sub eax, 2 - mov edx, cyVal - sub edx, 7 - invoke DrawBox, eax, edx, 5, 14, 009A7A00h - - mov eax, cxVal - sub eax, 1 - mov edx, cyVal - sub edx, 6 - invoke DrawBox, eax, edx, 3, 12, 00FFD700h - - mov eax, cxVal - sub eax, 6 - mov edx, cyVal - add edx, 7 - invoke DrawBox, eax, edx, 13, 3, 009A7A00h - - ; Laurel dots - mov eax, cxVal - sub eax, 12 - mov edx, cyVal - sub edx, 8 - invoke DrawBox, eax, edx, 2, 2, 009A7A00h - - mov eax, cxVal - add eax, 11 - mov edx, cyVal - sub edx, 8 - invoke DrawBox, eax, edx, 2, 2, 009A7A00h - - mov eax, cxVal - sub eax, 12 - mov edx, cyVal - invoke DrawBox, eax, edx, 2, 2, 009A7A00h - - mov eax, cxVal - add eax, 11 - mov edx, cyVal - invoke DrawBox, eax, edx, 2, 2, 009A7A00h - - mov eax, cxVal - sub eax, 12 - mov edx, cyVal - add edx, 8 - invoke DrawBox, eax, edx, 2, 2, 009A7A00h - - mov eax, cxVal - add eax, 11 - mov edx, cyVal - add edx, 8 - invoke DrawBox, eax, edx, 2, 2, 009A7A00h - -coin_draw_done: - ret -DrawDetailedCoin ENDP - -; ============================================================================== -; IN-ENGINE 2.5D MINI-GAME: COIN FLIP -; ============================================================================== -InitCoinGame PROC - call InitNativeCoin3D - ret -InitCoinGame ENDP - -HandleCoinInput PROC - call HandleNativeCoin3D - ret -; Retained legacy frame-count prototype, excluded from the executable. -IF 0 - cmp coin3d_state, 0 - je coin_handle_idle - cmp coin3d_state, 1 - je coin_handle_flipping - cmp coin3d_state, 2 - je coin_handle_result - ret - -coin_handle_idle: - invoke Pressed3D, 26h ; UP - test eax, eax - jnz coin_bet_up - invoke Pressed3D, 57h ; 'W' - test eax, eax - jnz coin_bet_up - invoke Pressed3D, 28h ; DOWN - test eax, eax - jnz coin_bet_down - invoke Pressed3D, 53h ; 'S' - test eax, eax - jnz coin_bet_down - invoke Pressed3D, 31h ; '1' - test eax, eax - jnz coin_pick_1 - invoke Pressed3D, 32h ; '2' - test eax, eax - jnz coin_pick_2 - invoke Pressed3D, 20h ; SPACE - test eax, eax - jnz coin_start_flip - ret - -coin_bet_up: - mov eax, coin3d_bet - add eax, 50 - cmp eax, bankroll - jle @F - mov eax, bankroll -@@: - cmp eax, 5000 - jle @F - mov eax, 5000 -@@: - mov coin3d_bet, eax - invoke PlayCasinoSound3D, OFFSET soundClick, 0, 1 - ret - -coin_bet_down: - mov eax, coin3d_bet - sub eax, 50 - cmp eax, 50 - jge @F - mov eax, 50 -@@: - mov coin3d_bet, eax - invoke PlayCasinoSound3D, OFFSET soundClick, 0, 1 - ret - -coin_pick_1: - mov coin3d_choice, 1 - invoke PlayCasinoSound3D, OFFSET soundClick, 0, 1 - ret - -coin_pick_2: - mov coin3d_choice, 2 - invoke PlayCasinoSound3D, OFFSET soundClick, 0, 1 - ret - -coin_start_flip: - mov eax, coin3d_bet - cmp eax, bankroll - jle @F - mov eax, bankroll - mov coin3d_bet, eax - test eax, eax - jz coin_done -@@: - mov eax, coin3d_bet - sub bankroll, eax - mov coin3d_state, 1 - mov coin3d_timer, 40 - invoke PlayCasinoSound3D, OFFSET soundCoin, 0, 1 - ret - -coin_handle_flipping: - dec coin3d_timer - cmp coin3d_timer, 0 - jg coin_done - invoke RandomRange3D, 2 - inc eax - mov coin3d_result, eax - mov edx, coin3d_choice - cmp eax, edx - jne coin_flip_lost - - ; Won! - inc coin3d_streak - mov eax, coin3d_bet - shl eax, 1 - add bankroll, eax - mov coin3d_win, eax - mov coin3d_state, 2 - invoke PlayCasinoSound3D, OFFSET soundCoinDing, 0, 1 - ret - -coin_flip_lost: - mov coin3d_streak, 0 - mov coin3d_win, 0 - mov coin3d_state, 2 - invoke PlayCasinoSound3D, OFFSET soundLose, 0, 1 - ret - -coin_handle_result: - invoke Pressed3D, 20h - test eax, eax - jz coin_done - mov coin3d_state, 0 - invoke PlayCasinoSound3D, OFFSET soundClick, 0, 1 -coin_done: - ret -ENDIF -HandleCoinInput ENDP - -RenderCoinGame PROC uses ebx esi edi - local cyVal:DWORD - local rxVal:DWORD - local kx:DWORD - - call RenderNativeCoin3D - ret -IF 0 - ; Background & Cabinet border - invoke DrawBox, 0, 0, 320, 240, 00140906h - invoke DrawBoxBorder, 6, 6, 308, 228, 0022150Fh, 00482E1Bh, 3 - - ; Header - invoke DrawBoxBorder, 20, 12, 280, 26, 001C100Ah, 00FFD700h, 2 - invoke DrawString8x8, 44, 21, OFFSET textCoinTitle, 00FFFF00h - - ; Corner rivets - invoke DrawBox, 12, 12, 3, 3, 00FFD700h - invoke DrawBox, 306, 12, 3, 3, 00FFD700h - invoke DrawBox, 12, 226, 3, 3, 00FFD700h - invoke DrawBox, 306, 226, 3, 3, 00FFD700h - - ; Status meters - invoke DrawBoxBorder, 20, 44, 110, 18, 000E1A0Ah, 00224B1Ah, 1 - invoke DrawString8x8, 24, 49, OFFSET textBankPrompt, 003CFF3Ch - invoke FormatNumber, bankroll, OFFSET hudNumBuffer - invoke DrawString8x8, 72, 49, OFFSET hudNumBuffer, 003CFF3Ch - - invoke DrawBoxBorder, 190, 44, 110, 18, 001A100Ah, 003A2814h, 1 - invoke DrawString8x8, 194, 49, OFFSET textBetPrompt, 00FFD700h - invoke FormatNumber, coin3d_bet, OFFSET hudNumBuffer - invoke DrawString8x8, 254, 49, OFFSET hudNumBuffer, 00FFD700h - - ; Left: Heads - cmp coin3d_choice, 1 - jne coin_left_inactive - invoke DrawBoxBorder, 20, 72, 76, 68, 00101828h, 00FFFF00h, 2 - invoke DrawString8x8, 30, 78, OFFSET textCoinSide1, 00FFFF00h - invoke DrawDetailedCoin, 58, 106, 14, 14, 00D0A000h, 00FFD700h, 1 - invoke DrawString8x8, 24, 126, OFFSET textCoinSelected, 003CFF3Ch - jmp coin_right_side -coin_left_inactive: - invoke DrawBoxBorder, 20, 72, 76, 68, 000A101Ch, 00404855h, 1 - invoke DrawString8x8, 30, 78, OFFSET textCoinSide1, 00D0D8E0h - invoke DrawDetailedCoin, 58, 106, 14, 14, 009A7A00h, 00D0A000h, 1 - -coin_right_side: - ; Right: Tails - cmp coin3d_choice, 2 - jne coin_right_inactive - invoke DrawBoxBorder, 224, 72, 76, 68, 00101828h, 00FFFF00h, 2 - invoke DrawString8x8, 234, 78, OFFSET textCoinSide2, 00FFFF00h - invoke DrawDetailedCoin, 262, 106, 14, 14, 00D0A000h, 00FFD700h, 2 - invoke DrawString8x8, 228, 126, OFFSET textCoinSelected, 003CFF3Ch - jmp coin_center_area -coin_right_inactive: - invoke DrawBoxBorder, 224, 72, 76, 68, 000A101Ch, 00404855h, 1 - invoke DrawString8x8, 234, 78, OFFSET textCoinSide2, 00D0D8E0h - invoke DrawDetailedCoin, 262, 106, 14, 14, 009A7A00h, 00D0A000h, 2 - -coin_center_area: - ; Center spotlight - invoke DrawCircle, 160, 110, 48, 00121620h - invoke DrawCircle, 160, 110, 44, 00FFD700h - invoke DrawCircle, 160, 110, 42, 000E141Eh - - cmp coin3d_state, 1 - je coin_render_flipping - cmp coin3d_state, 2 - je coin_render_result - - ; Idle coin - invoke DrawDetailedCoin, 160, 110, 26, 26, 00D0A000h, 00FFD700h, coin3d_choice - jmp coin_render_keys - -coin_render_flipping: - mov eax, coin3d_timer - and eax, 7 - movzx eax, byte ptr [coinRxAnimTable + eax] - mov rxVal, eax - invoke DrawDetailedCoin, 160, 110, rxVal, 26, 00D0A000h, 00FFD700h, 0 - invoke DrawString8x8, 88, 160, OFFSET textCoinFlipping, 00FFFF00h - jmp coin_render_keys - -coin_render_result: - invoke DrawDetailedCoin, 160, 110, 26, 26, 00D0A000h, 00FFD700h, coin3d_result - mov eax, coin3d_result - cmp eax, coin3d_choice - jne coin_render_loss_msg - - ; Win banner - invoke DrawBoxBorder, 44, 154, 232, 22, 000E141Eh, 003CFF3Ch, 1 - invoke DrawString8x8, 64, 161, OFFSET textCoinWin, 003CFF3Ch - invoke FormatNumber, coin3d_win, OFFSET hudNumBuffer - invoke DrawString8x8, 152, 161, OFFSET hudNumBuffer, 003CFF3Ch - jmp coin_render_keys - -coin_render_loss_msg: - invoke DrawBoxBorder, 44, 154, 232, 22, 000E141Eh, 00C81414h, 1 - invoke DrawString8x8, 114, 161, OFFSET textCoinLose, 00FF6464h - -coin_render_keys: - mov kx, 16 - xor eax, eax - cmp coin3d_choice, 1 - sete al - invoke DrawKeycap3D, kx, 192, OFFSET textCoinKey1, eax - add kx, eax - - xor eax, eax - cmp coin3d_choice, 2 - sete al - invoke DrawKeycap3D, kx, 192, OFFSET textCoinKey2, eax - add kx, eax - - invoke DrawKeycap3D, kx, 192, OFFSET textCoinKeySpace, 1 - add kx, eax - - invoke DrawKeycap3D, kx, 192, OFFSET textKeyEsc, 0 - ret -ENDIF -RenderCoinGame ENDP - -; ============================================================================== -; IN-ENGINE 2.5D MINI-GAME: CRAPS / DICE -; ============================================================================== -DrawCrapsDie PROC uses ebx esi edi, x:DWORD, y:DWORD, sizeVal:DWORD, valNum:DWORD - ; Drop shadow - mov eax, x - add eax, 3 - mov edx, y - add edx, sizeVal - invoke DrawBox, eax, edx, sizeVal, 3, 00081403h - - mov eax, x - add eax, sizeVal - mov edx, y - add edx, 3 - invoke DrawBox, eax, edx, 3, sizeVal, 00081403h - - ; Ivory body & bevel - invoke DrawBoxBorder, x, y, sizeVal, sizeVal, 00FAF4F0h, 00403535h, 1 - mov eax, x - inc eax - mov edx, y - inc edx - mov ecx, sizeVal - sub ecx, 2 - invoke DrawBox, eax, edx, ecx, 1, 00FFFFFFh - invoke DrawBox, eax, edx, 1, ecx, 00FFFFFFh - - ; Ruby pips (00C81515h) - mov eax, valNum - test al, 1 - jz @F - ; Center pip - mov eax, x - add eax, 18 - mov edx, y - add edx, 18 - invoke DrawCircle, eax, edx, 3, 00C81515h - dec eax - dec edx - invoke DrawPixel, eax, edx, 00FFFFFFh -@@: - cmp valNum, 2 - jl die_pips_done - mov eax, x - add eax, 9 - mov edx, y - add edx, 9 - invoke DrawCircle, eax, edx, 3, 00C81515h - mov eax, x - add eax, 27 - mov edx, y - add edx, 27 - invoke DrawCircle, eax, edx, 3, 00C81515h - - cmp valNum, 4 - jl die_pips_done - mov eax, x - add eax, 27 - mov edx, y - add edx, 9 - invoke DrawCircle, eax, edx, 3, 00C81515h - mov eax, x - add eax, 9 - mov edx, y - add edx, 27 - invoke DrawCircle, eax, edx, 3, 00C81515h - - cmp valNum, 6 - jl die_pips_done - mov eax, x - add eax, 9 - mov edx, y - add edx, 18 - invoke DrawCircle, eax, edx, 3, 00C81515h - mov eax, x - add eax, 27 - mov edx, y - add edx, 18 - invoke DrawCircle, eax, edx, 3, 00C81515h - -die_pips_done: - ret -DrawCrapsDie ENDP - -InitDiceGame PROC - mov dice3d_state, 0 - mov dice3d_timer, 0 - mov dice3d_win, 0 - ret -InitDiceGame ENDP - -HandleDiceInput PROC - cmp dice3d_state, 0 - je dice_handle_idle - cmp dice3d_state, 1 - je dice_handle_rolling - cmp dice3d_state, 2 - je dice_handle_result - ret - -dice_handle_idle: - invoke Pressed3D, 26h ; UP - test eax, eax - jnz dice_bet_up - invoke Pressed3D, 57h ; 'W' - test eax, eax - jnz dice_bet_up - invoke Pressed3D, 28h ; DOWN - test eax, eax - jnz dice_bet_down - invoke Pressed3D, 53h ; 'S' - test eax, eax - jnz dice_bet_down - invoke Pressed3D, 31h ; '1' - test eax, eax - jnz dice_pick_1 - invoke Pressed3D, 32h ; '2' - test eax, eax - jnz dice_pick_2 - invoke Pressed3D, 20h ; SPACE - test eax, eax - jnz dice_start_roll - ret - -dice_bet_up: - mov eax, dice3d_bet - add eax, 50 - cmp eax, bankroll - jle @F - mov eax, bankroll -@@: - cmp eax, 5000 - jle @F - mov eax, 5000 -@@: - mov dice3d_bet, eax - invoke PlayCasinoSound3D, OFFSET soundClick, 0, 1 - ret - -dice_bet_down: - mov eax, dice3d_bet - sub eax, 50 - cmp eax, 50 - jge @F - mov eax, 50 -@@: - mov dice3d_bet, eax - invoke PlayCasinoSound3D, OFFSET soundClick, 0, 1 - ret - -dice_pick_1: - mov dice3d_choice, 1 - invoke PlayCasinoSound3D, OFFSET soundClick, 0, 1 - ret - -dice_pick_2: - mov dice3d_choice, 2 - invoke PlayCasinoSound3D, OFFSET soundClick, 0, 1 - ret - -dice_start_roll: - mov eax, dice3d_bet - cmp eax, bankroll - jle @F - mov eax, bankroll - mov dice3d_bet, eax - test eax, eax - jz dice_done -@@: - mov eax, dice3d_bet - test eax, eax - jle dice_done - sub bankroll, eax - mov dice3d_state, 1 - mov dice3d_timer, 0 - invoke RandomRange3D, 6 - inc eax - mov dice3d_val1, eax - invoke RandomRange3D, 6 - inc eax - mov dice3d_val2, eax - invoke PlayCasinoSound3D, OFFSET soundDiceRoll, 0, 1 - call SaveProgress3D - ret - -dice_handle_rolling: - mov eax, deltaTime3D - add dice3d_timer, eax - cmp dice3d_timer, 1600 - jb dice_done - mov dice3d_timer, 1600 - mov eax, dice3d_val2 - mov edx, dice3d_val1 - add edx, eax - mov dice3d_sum, edx - - ; Parity check - mov eax, edx - and eax, 1 - jnz dice_sum_is_odd - ; Even - mov eax, 1 - jmp dice_check_win -dice_sum_is_odd: - mov eax, 2 - -dice_check_win: - cmp eax, dice3d_choice - jne dice_roll_lost - - ; Won! - mov eax, dice3d_bet - shl eax, 1 - add bankroll, eax - mov dice3d_win, eax - mov dice3d_state, 2 - invoke PlayCasinoSound3D, OFFSET soundRoundWin, 0, 1 - invoke NpcRecordRound3D,8,1 - call SaveProgress3D - ret - -dice_roll_lost: - mov dice3d_win, 0 - mov dice3d_state, 2 - invoke PlayCasinoSound3D, OFFSET soundLose, 0, 1 - invoke NpcRecordRound3D,8,0 - call SaveProgress3D - ret - -dice_handle_result: - invoke Pressed3D, 20h - test eax, eax - jz dice_done - mov dice3d_state, 0 - invoke PlayCasinoSound3D, OFFSET soundClick, 0, 1 -dice_done: - ret -HandleDiceInput ENDP - -RenderDiceGame PROC uses ebx esi edi - local kx:DWORD - - ; Mahogany frame & Deep Felt Green table - invoke DrawBox, 0, 0, 320, 240, 00140906h - invoke DrawBoxBorder, 6, 6, 308, 228, 000A3816h, 00FFD700h, 2 - - ; Header - invoke DrawBoxBorder, 20, 12, 280, 26, 00072E13h, 00FFD700h, 2 - invoke DrawString8x8, 116, 21, OFFSET textDiceTitle, 00FFFF00h - - ; Status - invoke DrawBoxBorder, 20, 44, 110, 18, 00072E13h, 001B4B22h, 1 - invoke DrawString8x8, 24, 49, OFFSET textBankPrompt, 003CFF3Ch - invoke FormatNumber, bankroll, OFFSET hudNumBuffer - invoke DrawString8x8, 72, 49, OFFSET hudNumBuffer, 003CFF3Ch - - invoke DrawBoxBorder, 190, 44, 110, 18, 00072E13h, 001B4B22h, 1 - invoke DrawString8x8, 194, 49, OFFSET textBetPrompt, 00FFD700h - invoke FormatNumber, dice3d_bet, OFFSET hudNumBuffer - invoke DrawString8x8, 258, 49, OFFSET hudNumBuffer, 00FFD700h - - ; [1] ×¨Ò - cmp dice3d_choice, 1 - jne dice_even_inactive - invoke DrawBoxBorder, 16, 70, 88, 48, 00072E13h, 00FFFF00h, 2 - invoke DrawString8x8, 30, 76, OFFSET textDiceEven, 00FFFF00h - invoke DrawString8x8, 22, 90, OFFSET textDiceEvenNums, 00FFD700h - invoke DrawString8x8, 26, 104, OFFSET textCoinSelected, 003CFF3Ch - jmp dice_odd_side -dice_even_inactive: - invoke DrawBoxBorder, 16, 70, 88, 48, 00072E13h, 001B4B22h, 1 - invoke DrawString8x8, 30, 76, OFFSET textDiceEven, 00D0D8E0h - invoke DrawString8x8, 22, 90, OFFSET textDiceEvenNums, 0080B090h - -dice_odd_side: - ; [2] ÍÅ×ÅÒ - cmp dice3d_choice, 2 - jne dice_odd_inactive - invoke DrawBoxBorder, 216, 70, 88, 48, 00072E13h, 00FFFF00h, 2 - invoke DrawString8x8, 226, 76, OFFSET textDiceOdd, 00FFFF00h - invoke DrawString8x8, 224, 90, OFFSET textDiceOddNums, 00FFD700h - invoke DrawString8x8, 226, 104, OFFSET textCoinSelected, 003CFF3Ch - jmp dice_center_cubes -dice_odd_inactive: - invoke DrawBoxBorder, 216, 70, 88, 48, 00072E13h, 001B4B22h, 1 - invoke DrawString8x8, 226, 76, OFFSET textDiceOdd, 00D0D8E0h - invoke DrawString8x8, 224, 90, OFFSET textDiceOddNums, 0080B090h - -dice_center_cubes: - call RenderDiceThrow3D - - cmp dice3d_state, 1 - je dice_render_rolling - cmp dice3d_state, 2 - je dice_render_result - jmp dice_render_keys - -dice_render_rolling: - invoke DrawString8x8, 76, 138, OFFSET textDiceRolling, 00FFFF00h - jmp dice_render_keys - -dice_render_result: - invoke DrawBoxBorder, 36, 130, 248, 36, 00072E13h, 00FFD700h, 1 - invoke DrawString8x8, 44, 135, OFFSET textDiceSumHdr, 00FFD700h - invoke FormatNumber, dice3d_val1, OFFSET hudNumBuffer - invoke DrawString8x8, 92, 135, OFFSET hudNumBuffer, 00FFFF00h - invoke DrawString8x8, 110, 135, OFFSET textDicePlus, 00FFD700h - invoke FormatNumber, dice3d_val2, OFFSET hudNumBuffer - invoke DrawString8x8, 126, 135, OFFSET hudNumBuffer, 00FFFF00h - invoke DrawString8x8, 144, 135, OFFSET textDiceEqual, 00FFD700h - invoke FormatNumber, dice3d_sum, OFFSET hudNumBuffer - invoke DrawString8x8, 168, 135, OFFSET hudNumBuffer, 00FFFF00h - - mov eax, dice3d_sum - and eax, 1 - jnz dice_render_odd_res - invoke DrawString8x8, 186, 135, OFFSET textDiceEvenResult, 003CFF3Ch - jmp dice_render_outcome -dice_render_odd_res: - invoke DrawString8x8, 186, 135, OFFSET textDiceOddResult, 003CFF3Ch - -dice_render_outcome: - mov eax, dice3d_win - test eax, eax - jz dice_render_loss_outcome - invoke DrawString8x8, 68, 150, OFFSET textDiceWin, 003CFF3Ch - invoke FormatNumber, dice3d_win, OFFSET hudNumBuffer - invoke DrawString8x8, 156, 150, OFFSET hudNumBuffer, 003CFF3Ch - invoke DrawString8x8, 188, 150, OFFSET textDiceWinMult, 003CFF3Ch - jmp dice_render_keys - -dice_render_loss_outcome: - invoke DrawString8x8, 116, 150, OFFSET textDiceLose, 00FF6464h - -dice_render_keys: - mov kx, 16 - xor eax, eax - cmp dice3d_choice, 1 - sete al - invoke DrawKeycap3D, kx, 192, OFFSET textDiceKey1, eax - add kx, eax - - xor eax, eax - cmp dice3d_choice, 2 - sete al - invoke DrawKeycap3D, kx, 192, OFFSET textDiceKey2, eax - add kx, eax - - invoke DrawKeycap3D, kx, 192, OFFSET textDiceKeySpace, 1 - add kx, eax - - invoke DrawKeycap3D, kx, 192, 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, 002E1E08h - invoke DrawCircle, cxVal, cyVal, 11, 00583A10h - invoke DrawCircle, cxVal, cyVal, 8, 008A581Ah - invoke DrawCircle, cxVal, cyVal, 6, 00D0B000h - invoke DrawCircle, cxVal, cyVal, 4, 00FFE000h - mov eax, cxVal - dec eax - mov edx, cyVal - dec edx - invoke DrawCircle, eax, edx, 2, 00FFFF80h - dec eax - dec edx - 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, 36 -@@: - mov liftY, eax - - ; Drop shadow - cmp isLifted, 0 - jne cup_shadow_lifted - mov eax, x - add eax, 6 - mov edx, y - add edx, 42 - invoke DrawBox, eax, edx, 36, 4, 0010040Ah - jmp cup_ball_check -cup_shadow_lifted: - mov eax, x - add eax, 10 - mov edx, y - add edx, 42 - invoke DrawBox, eax, edx, 28, 2, 001A0612h - -cup_ball_check: - cmp isLifted, 0 - je cup_body_draw - cmp hasBall, 0 - je cup_body_draw - mov eax, x - add eax, 24 - mov edx, y - add edx, 26 - invoke DrawGlowingOrb, eax, edx - -cup_body_draw: - ; Base pedestal - mov eax, x - add eax, 6 - mov edx, liftY - add edx, 36 - invoke DrawBoxBorder, eax, edx, 36, 6, 00301A22h, 00D0B000h, 1 - - ; Stem - mov eax, x - add eax, 18 - mov edx, liftY - add edx, 28 - invoke DrawBox, eax, edx, 12, 8, 00452533h - mov eax, x - add eax, 22 - invoke DrawBox, eax, edx, 4, 8, 006E4055h - - ; Goblet Bowl - mov eax, x - add eax, 8 - mov edx, liftY - add edx, 8 - invoke DrawBoxBorder, eax, edx, 32, 20, 00401E2Dh, 00FFD700h, 1 - - mov eax, x - add eax, 14 - mov edx, liftY - add edx, 10 - invoke DrawBox, eax, edx, 6, 16, 00703550h - mov eax, x - add eax, 17 - invoke DrawBox, eax, edx, 3, 16, 00A05078h - - ; Golden Rim - mov eax, x - add eax, 4 - mov edx, liftY - add edx, 2 - invoke DrawBoxBorder, eax, edx, 40, 7, 00200A15h, 00FFFF00h, 1 - mov eax, x - add eax, 12 - mov edx, liftY - add edx, 4 - invoke DrawBox, eax, edx, 16, 2, 00FFFF00h - - ; Skull face emblem - mov eax, x - add eax, 21 - mov edx, liftY - add edx, 12 - invoke DrawBox, eax, edx, 6, 5, 00FFD700h - mov eax, x - add eax, 22 - mov edx, liftY - add edx, 17 - invoke DrawBox, eax, edx, 4, 3, 00FFD700h - mov eax, x - add eax, 22 - mov edx, liftY - add edx, 14 - invoke DrawPixel, eax, edx, 00200A15h - mov eax, x - add eax, 24 - invoke DrawPixel, eax, edx, 00200A15h - - ; Cup number label - mov eax, x - add eax, 21 - mov edx, liftY - add edx, 24 - mov ecx, cupId - add ecx, '1' - invoke DrawChar8x8, eax, edx, ecx, 00FFFF00h - ret -DrawGothicCup ENDP - -InitSkullsGame PROC - mov skulls3d_state, 0 - mov skulls3d_timer, 0 - mov skulls3d_win, 0 - mov skulls3d_choice, 1 - mov skulls3d_cup0, 0 - mov skulls3d_cup1, 1 - mov skulls3d_cup2, 2 - invoke RandomRange3D, 3 - mov skulls3d_ballPos, eax - ret -InitSkullsGame ENDP - -FinalizeSkullsGuess PROC uses ebx - cmp skulls3d_state,3 - jne skulls_guess_done - mov eax, skulls3d_choice - cmp eax, skulls3d_ballPos - jne skulls_guess_wrong - - ; Correct! 3x payout - mov eax, skulls3d_bet - imul eax, 3 - add bankroll, eax - mov skulls3d_win, eax - mov skulls3d_state, 4 - invoke PlayCasinoSound3D, OFFSET soundRoundWin, 0, 1 - invoke NpcRecordRound3D,9,1 - call SaveProgress3D - ret - -skulls_guess_wrong: - mov skulls3d_win, 0 - mov skulls3d_state, 4 - invoke PlayCasinoSound3D, OFFSET soundLose, 0, 1 - invoke NpcRecordRound3D,9,0 - call SaveProgress3D -skulls_guess_done: - ret -FinalizeSkullsGuess ENDP - -HandleSkullsInput PROC - cmp skulls3d_state, 0 - je skulls_handle_idle - cmp skulls3d_state, 1 - je skulls_handle_show - cmp skulls3d_state, 2 - je skulls_handle_shuffle - cmp skulls3d_state, 3 - je skulls_handle_pick - cmp skulls3d_state, 4 - je skulls_handle_reveal - ret - -skulls_handle_idle: - invoke Pressed3D, 26h ; UP - test eax, eax - jnz skulls_bet_up - invoke Pressed3D, 57h ; 'W' - test eax, eax - jnz skulls_bet_up - invoke Pressed3D, 28h ; DOWN - test eax, eax - jnz skulls_bet_down - invoke Pressed3D, 53h ; 'S' - test eax, eax - jnz skulls_bet_down - invoke Pressed3D, 20h ; SPACE - test eax, eax - jnz skulls_start_game - ret - -skulls_bet_up: - mov eax, skulls3d_bet - add eax, 50 - cmp eax, bankroll - jle @F - mov eax, bankroll -@@: - cmp eax, 5000 - jle @F - mov eax, 5000 -@@: - mov skulls3d_bet, eax - invoke PlayCasinoSound3D, OFFSET soundClick, 0, 1 - ret - -skulls_bet_down: - mov eax, skulls3d_bet - sub eax, 50 - cmp eax, 50 - jge @F - mov eax, 50 -@@: - mov skulls3d_bet, eax - invoke PlayCasinoSound3D, OFFSET soundClick, 0, 1 - ret - -skulls_start_game: - mov eax, skulls3d_bet - cmp eax, bankroll - jle @F - mov eax, bankroll - mov skulls3d_bet, eax - test eax, eax - jz skulls_input_done -@@: - mov eax, skulls3d_bet - sub bankroll, eax - invoke RandomRange3D, 3 - mov skulls3d_ballPos, eax - mov skulls3d_cup0, 0 - mov skulls3d_cup1, 1 - mov skulls3d_cup2, 2 - - ; Pre-generate 3 dynamic swap pairs - 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 - invoke PlayCasinoSound3D, OFFSET soundClick, 0, 1 - ret - -skulls_handle_show: - inc skulls3d_timer - cmp skulls3d_timer, 45 - jl skulls_input_done - ; Transition to Phase 2: Active Shuffle Animation - mov skulls3d_state, 2 - mov skulls3d_timer, 0 - invoke PlayCasinoSound3D, OFFSET soundShuffle, 0, 1 - ret - -skulls_handle_shuffle: - inc skulls3d_timer - cmp skulls3d_timer, 60 - jl skulls_input_done - ; Transition to Phase 3: Pick cup - mov skulls3d_state, 3 - mov skulls3d_timer, 0 - ret - -skulls_handle_pick: - invoke Pressed3D, 31h ; '1' - test eax, eax - jnz skulls_pick_1 - invoke Pressed3D, 32h ; '2' - test eax, eax - jnz skulls_pick_2 - invoke Pressed3D, 33h ; '3' - test eax, eax - jnz skulls_pick_3 - ret - -skulls_pick_1: - mov skulls3d_choice, 0 - call FinalizeSkullsGuess - ret - -skulls_pick_2: - mov skulls3d_choice, 1 - call FinalizeSkullsGuess - ret - -skulls_pick_3: - mov skulls3d_choice, 2 - call FinalizeSkullsGuess - ret - -skulls_handle_reveal: - invoke Pressed3D, 20h - test eax, eax - jz skulls_input_done - mov skulls3d_state, 0 - invoke PlayCasinoSound3D, OFFSET soundClick, 0, 1 -skulls_input_done: - ret -HandleSkullsInput ENDP - -RenderSkullsGame PROC uses ebx esi edi - local kx:DWORD - 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 - - ; Mahogany & Gothic Purple table - invoke DrawBox, 0, 0, 320, 240, 00140906h - invoke DrawBoxBorder, 6, 6, 308, 228, 00300F22h, 00FFD700h, 2 - - ; Header - invoke DrawBoxBorder, 20, 12, 280, 26, 001A0812h, 00FFD700h, 2 - invoke DrawString8x8, 44, 21, OFFSET textSkullsTitle, 00FFFF00h - - ; Status - invoke DrawBoxBorder, 20, 44, 110, 18, 001A0812h, 00452033h, 1 - invoke DrawString8x8, 24, 49, OFFSET textBankPrompt, 003CFF3Ch - invoke FormatNumber, bankroll, OFFSET hudNumBuffer - invoke DrawString8x8, 72, 49, OFFSET hudNumBuffer, 003CFF3Ch - - invoke DrawBoxBorder, 190, 44, 110, 18, 001A0812h, 00452033h, 1 - invoke DrawString8x8, 194, 49, OFFSET textBetPrompt, 00FFD700h - invoke FormatNumber, skulls3d_bet, OFFSET hudNumBuffer - invoke DrawString8x8, 254, 49, OFFSET hudNumBuffer, 00FFD700h - - ; Phase Prompts - cmp skulls3d_state, 0 - jne @F - invoke DrawString8x8, 56, 62, OFFSET textSkullsPhase0, 00FFD700h - jmp skulls_draw_idle_cups -@@: - cmp skulls3d_state, 1 - jne @F - invoke DrawString8x8, 56, 62, OFFSET textSkullsPhase1, 00FFFF00h - jmp skulls_draw_phase1_cups -@@: - cmp skulls3d_state, 2 - jne @F - invoke DrawString8x8, 44, 62, OFFSET textSkullsPhase2, 00FFFF00h - jmp skulls_draw_animated_cups -@@: - cmp skulls3d_state, 3 - jne @F - invoke DrawString8x8, 28, 62, OFFSET textSkullsPhase3, 00FFFF00h - jmp skulls_draw_idle_cups -@@: - ; Phase 4: Reveal outcome - mov eax, skulls3d_win - test eax, eax - jz skulls_reveal_loss_text - invoke DrawString8x8, 40, 62, OFFSET textSkullsWin, 003CFF3Ch - invoke FormatNumber, skulls3d_win, OFFSET hudNumBuffer - invoke DrawString8x8, 136, 62, OFFSET hudNumBuffer, 003CFF3Ch - invoke DrawString8x8, 168, 62, OFFSET textSkullsWinMult, 003CFF3Ch - jmp skulls_draw_reveal_cups - -skulls_reveal_loss_text: - invoke DrawString8x8, 40, 62, OFFSET textSkullsLose, 00FF6464h - jmp skulls_draw_reveal_cups - -skulls_draw_idle_cups: - ; Draw resting cups at static slots: Slot 0 (X=36), Slot 1 (X=136), Slot 2 (X=236) - invoke DrawGothicCup, 36, 114, skulls3d_cup0, 0, 0 - invoke DrawGothicCup, 136, 114, skulls3d_cup1, 0, 0 - invoke DrawGothicCup, 236, 114, skulls3d_cup2, 0, 0 - jmp skulls_render_controls - -skulls_draw_phase1_cups: - ; Draw with golden ball showing under starting cup - mov ebx, 0 - mov edx, 0 - cmp skulls3d_ballPos, 0 - jne @F - mov ebx, 1 - mov edx, 1 -@@: - invoke DrawGothicCup, 36, 114, skulls3d_cup0, ebx, edx - - mov ebx, 0 - mov edx, 0 - cmp skulls3d_ballPos, 1 - jne @F - mov ebx, 1 - mov edx, 1 -@@: - invoke DrawGothicCup, 136, 114, skulls3d_cup1, ebx, edx - - mov ebx, 0 - mov edx, 0 - cmp skulls3d_ballPos, 2 - jne @F - mov ebx, 1 - mov edx, 1 -@@: - invoke DrawGothicCup, 236, 114, skulls3d_cup2, ebx, edx - jmp skulls_render_controls - -skulls_draw_animated_cups: - ; 60 frames = 3 passes of 20 frames - 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 - -pass_0: - dec eax - mov passTick, eax - mov eax, skulls3d_swapPair0 - mov curPair, eax - jmp setup_pass - -pass_1: - sub eax, 21 - mov passTick, eax - mov eax, skulls3d_swapPair1 - mov curPair, eax - -setup_pass: - ; curPair determines swap pair: - ; 0: swap slot 0 (X=36) and slot 1 (X=136) - ; 1: swap slot 1 (X=136) and slot 2 (X=236) - ; 2: swap slot 0 (X=36) and slot 2 (X=236) - cmp curPair, 1 - je pair_1 - cmp curPair, 2 - je pair_2 - mov swapSlotA, 0 - mov swapSlotB, 1 - mov xA, 36 - mov xB, 136 - jmp calc_coords -pair_1: - mov swapSlotA, 1 - mov swapSlotB, 2 - mov xA, 136 - mov xB, 236 - jmp calc_coords -pair_2: - mov swapSlotA, 0 - mov swapSlotB, 2 - mov xA, 36 - mov xB, 236 - -calc_coords: - ; distX = xB - xA - mov eax, xB - sub eax, xA - mov distX, eax - - ; dxVal = (distX * passTick) / 20 - mov eax, distX - imul eax, passTick - xor edx, edx - mov ecx, 20 - div ecx - mov dxVal, eax - - ; curXA = xA + dxVal - mov eax, xA - add eax, dxVal - mov curXA, eax - - ; curXB = xB - dxVal - mov eax, xB - sub eax, dxVal - mov curXB, eax - - ; archY = (passTick * (20 - passTick)) / 10 - mov eax, passTick - mov ecx, 20 - sub ecx, eax - imul eax, ecx - xor edx, edx - mov ecx, 10 - div ecx - mov archY, eax - - ; Cup A hops UP: 114 - archY - mov eax, 114 - sub eax, archY - mov curYA, eax - - ; Cup B hops DOWN: 114 + archY - mov eax, 114 - add eax, archY - mov curYB, eax - - ; Check if pass ended (frame 19): swap ball position and cups - cmp passTick, 19 - jne draw_active_shuffle - - ; Swap ball position if involved - mov eax, skulls3d_ballPos - cmp eax, swapSlotA - jne check_ball_b - mov edx, swapSlotB - mov skulls3d_ballPos, edx - jmp swap_slot_identities -check_ball_b: - cmp eax, swapSlotB - jne swap_slot_identities - mov edx, swapSlotA - mov skulls3d_ballPos, edx - -swap_slot_identities: - cmp curPair, 1 - je swap_ids_1_2 - cmp curPair, 2 - je swap_ids_0_2 - ; swap 0 and 1 - mov eax, skulls3d_cup0 - xchg eax, skulls3d_cup1 - mov skulls3d_cup0, eax - jmp swap_sound_tick -swap_ids_1_2: - mov eax, skulls3d_cup1 - xchg eax, skulls3d_cup2 - mov skulls3d_cup1, eax - jmp swap_sound_tick -swap_ids_0_2: - mov eax, skulls3d_cup0 - xchg eax, skulls3d_cup2 - mov skulls3d_cup0, eax - -swap_sound_tick: - invoke PlayCasinoSound3D, OFFSET soundShuffle, 0, 1 - -draw_active_shuffle: - ; Draw stationary cup - cmp curPair, 1 - je draw_stat_cup0 - cmp curPair, 2 - je draw_stat_cup1 - ; Stationary cup is slot 2 (X=236) - invoke DrawGothicCup, 236, 114, skulls3d_cup2, 0, 0 - jmp draw_moving_cups -draw_stat_cup0: - ; Stationary cup is slot 0 (X=36) - invoke DrawGothicCup, 36, 114, skulls3d_cup0, 0, 0 - jmp draw_moving_cups -draw_stat_cup1: - ; Stationary cup is slot 1 (X=136) - invoke DrawGothicCup, 136, 114, skulls3d_cup1, 0, 0 - -draw_moving_cups: - ; Moving Cup A and Moving Cup B - cmp curPair, 1 - je ids_pair_1 - cmp curPair, 2 - je ids_pair_2 - mov eax, skulls3d_cup0 - mov ebx, skulls3d_cup1 - jmp draw_the_pair -ids_pair_1: - mov eax, skulls3d_cup1 - mov ebx, skulls3d_cup2 - jmp draw_the_pair -ids_pair_2: - mov eax, skulls3d_cup0 - mov ebx, skulls3d_cup2 - -draw_the_pair: - push ebx - invoke DrawGothicCup, curXA, curYA, eax, 0, 0 - pop ebx - invoke DrawGothicCup, curXB, curYB, ebx, 0, 0 - jmp skulls_render_controls - -skulls_draw_reveal_cups: - ; Reveal Phase: lift chosen cup and lift actual ball cup if different - ; Slot 0 - mov ebx, 0 - mov edx, 0 - cmp skulls3d_choice, 0 - je slot0_is_lifted - cmp skulls3d_ballPos, 0 - jne @F -slot0_is_lifted: - mov ebx, 1 - cmp skulls3d_ballPos, 0 - sete dl -@@: - invoke DrawGothicCup, 36, 114, skulls3d_cup0, ebx, edx - - ; Slot 1 - mov ebx, 0 - mov edx, 0 - cmp skulls3d_choice, 1 - je slot1_is_lifted - cmp skulls3d_ballPos, 1 - jne @F -slot1_is_lifted: - mov ebx, 1 - cmp skulls3d_ballPos, 1 - sete dl -@@: - invoke DrawGothicCup, 136, 114, skulls3d_cup1, ebx, edx - - ; Slot 2 - mov ebx, 0 - mov edx, 0 - cmp skulls3d_choice, 2 - je slot2_is_lifted - cmp skulls3d_ballPos, 2 - jne @F -slot2_is_lifted: - mov ebx, 1 - cmp skulls3d_ballPos, 2 - sete dl -@@: - invoke DrawGothicCup, 236, 114, skulls3d_cup2, ebx, edx - -skulls_render_controls: - ; Cup selection slot labels [1], [2], [3] - invoke DrawString8x8, 54, 168, OFFSET textSkullsKey1, 00D0D8E0h - invoke DrawString8x8, 150, 168, OFFSET textSkullsKey2, 00D0D8E0h - invoke DrawString8x8, 250, 168, OFFSET textSkullsKey3, 00D0D8E0h - - ; Keycaps - mov kx, 16 - xor eax, eax - cmp skulls3d_state, 3 - je key1_active - cmp skulls3d_choice, 0 - sete al - jmp draw_key1 -key1_active: - mov eax, 1 -draw_key1: - invoke DrawKeycap3D, kx, 192, OFFSET textSkullsKey1, eax - add kx, eax - - xor eax, eax - cmp skulls3d_state, 3 - je key2_active - cmp skulls3d_choice, 1 - sete al - jmp draw_key2 -key2_active: - mov eax, 1 -draw_key2: - invoke DrawKeycap3D, kx, 192, OFFSET textSkullsKey2, eax - add kx, eax - - xor eax, eax - cmp skulls3d_state, 3 - je key3_active - cmp skulls3d_choice, 2 - sete al - jmp draw_key3 -key3_active: - mov eax, 1 -draw_key3: - invoke DrawKeycap3D, kx, 192, OFFSET textSkullsKey3, eax - add kx, eax - - xor eax, eax - cmp skulls3d_state, 0 - je start_active - cmp skulls3d_state, 4 - je start_active - jmp draw_start_key -start_active: - mov eax, 1 -draw_start_key: - invoke DrawKeycap3D, kx, 192, OFFSET textSkullsKeySpace, eax - add kx, eax - - invoke DrawKeycap3D, kx, 192, OFFSET textKeyEsc, 0 - ret -RenderSkullsGame ENDP - -InitSkillGame PROC - mov skill3d_state, 0 - mov skill3d_timer, 0 - mov skill3d_hits, 0 - mov skill3d_misses, 0 - mov skill3d_needle, 55 - mov skill3d_speed, 4 - mov skill3d_dir, 1 - mov skill3d_last_result, 0 - mov skill3d_win_amount, 0 - - ; Randomize initial zone: 80 + RandomRange(90) -> 80..170 - invoke RandomRange3D, 90 - add eax, 80 - mov skill3d_zone_start, eax - - ; Great zone: start + 20 + RandomRange(12) - invoke RandomRange3D, 12 - add eax, skill3d_zone_start - add eax, 20 - mov skill3d_great_start, eax - ret -InitSkillGame ENDP - -HandleSkillInput PROC uses ebx esi - mov eax, skill3d_state - cmp eax, 0 - je skill_handle_ready - cmp eax, 1 - je skill_handle_active - cmp eax, 2 - je skill_handle_round_wait - cmp eax, 3 - je skill_handle_round_wait - cmp eax, 4 - je skill_handle_end_wait - cmp eax, 5 - je skill_handle_end_wait - ret - -skill_handle_ready: - invoke Pressed3D, 26h ; UP - test eax, eax - jnz skill_bet_up - invoke Pressed3D, 57h ; 'W' - test eax, eax - jnz skill_bet_up - invoke Pressed3D, 28h ; DOWN - test eax, eax - jnz skill_bet_down - invoke Pressed3D, 53h ; 'S' - test eax, eax - jnz skill_bet_down - jmp skill_check_start - -skill_bet_up: - mov eax, skill3d_bet - add eax, 50 - cmp eax, bankroll - jle @F - mov eax, bankroll -@@: - cmp eax, 5000 - jle @F - mov eax, 5000 -@@: - mov skill3d_bet, eax - invoke PlayCasinoSound3D, OFFSET soundClick, 0, 1 - ret - -skill_bet_down: - mov eax, skill3d_bet - sub eax, 50 - cmp eax, 50 - jge @F - mov eax, 50 -@@: - mov skill3d_bet, eax - invoke PlayCasinoSound3D, OFFSET soundClick, 0, 1 - ret - -skill_check_start: - invoke Pressed3D, 20h ; SPACE - test eax, eax - jz skill_input_done - - ; Deduct bet on game start if beginning of run - mov eax, skill3d_hits - or eax, skill3d_misses - jnz @F - mov eax, skill3d_bet - cmp eax, bankroll - jle skill_has_funds - mov eax, bankroll - mov skill3d_bet, eax - test eax, eax - jz skill_input_done -skill_has_funds: - mov eax, skill3d_bet - sub bankroll, eax -@@: - mov skill3d_state, 1 - mov skill3d_needle, 55 - mov skill3d_dir, 1 - invoke PlayCasinoSound3D, OFFSET soundClick, 0, 1 - ret - -skill_handle_active: - ; Move needle smoothly - mov eax, skill3d_needle - mov edx, skill3d_speed - cmp skill3d_dir, 1 - je skill_move_right - sub eax, edx - cmp eax, 52 - jge skill_update_needle - mov eax, 52 - mov skill3d_dir, 1 - jmp skill_update_needle -skill_move_right: - add eax, edx - cmp eax, 268 - jle skill_update_needle - mov eax, 268 - mov skill3d_dir, -1 -skill_update_needle: - mov skill3d_needle, eax - - ; Check SPACE pressed (Reaction Hit Attempt!) - invoke Pressed3D, 20h - test eax, eax - jz skill_input_done - - ; Is needle in Great Sweet Spot? - mov eax, skill3d_needle - mov edx, skill3d_great_start - cmp eax, edx - jl check_success_zone - add edx, skill3d_great_width - cmp eax, edx - jg check_success_zone - - ; GREAT HIT! - mov skill3d_last_result, 2 - add skill3d_hits, 2 - mov skill3d_state, 2 - mov skill3d_timer, 40 - invoke PlayCasinoSound3D, OFFSET soundSkillPerfect, 0, 1 - jmp skill_check_finish_round - -check_success_zone: - mov eax, skill3d_needle - mov edx, skill3d_zone_start - cmp eax, edx - jl skill_was_miss - add edx, skill3d_zone_width - cmp eax, edx - jg skill_was_miss - - ; NORMAL HIT! - mov skill3d_last_result, 1 - inc skill3d_hits - mov skill3d_state, 2 - mov skill3d_timer, 40 - invoke PlayCasinoSound3D, OFFSET soundSkillHit, 0, 1 - jmp skill_check_finish_round - -skill_was_miss: - ; MISS! - mov skill3d_last_result, 0 - inc skill3d_misses - mov skill3d_state, 3 - mov skill3d_timer, 45 - invoke PlayCasinoSound3D, OFFSET soundSkillMiss, 0, 1 - -skill_check_finish_round: - cmp skill3d_hits, 5 - jge skill_game_escaped - cmp skill3d_misses, 3 - jge skill_game_lost - ret - -skill_game_escaped: - mov skill3d_state, 4 - mov skill3d_timer, 0 - ; Payout: 3x total return (+$2x bet profit) - mov eax, skill3d_bet - imul eax, 3 - add bankroll, eax - mov eax, skill3d_bet - shl eax, 1 - mov skill3d_win_amount, eax - invoke NpcRecordRound3D,10,1 - call SaveProgress3D - invoke PlayCasinoSound3D, OFFSET soundRoundWin, 0, 1 - ret - -skill_game_lost: - mov skill3d_state, 5 - mov skill3d_timer, 0 - invoke NpcRecordRound3D,10,0 - call SaveProgress3D - invoke PlayCasinoSound3D, OFFSET soundLose, 0, 1 - ret - -skill_handle_round_wait: - dec skill3d_timer - cmp skill3d_timer, 0 - jg skill_input_done - - ; Next round setup - invoke RandomRange3D, 90 - add eax, 80 - mov skill3d_zone_start, eax - - invoke RandomRange3D, 12 - add eax, skill3d_zone_start - add eax, 20 - mov skill3d_great_start, eax - - mov eax, skill3d_hits - shr eax, 1 - add eax, 4 - mov skill3d_speed, eax - mov skill3d_state, 1 - ret - -skill_handle_end_wait: - invoke Pressed3D, 20h - test eax, eax - jz skill_input_done - call InitSkillGame - ret - -skill_input_done: - ret -HandleSkillInput ENDP - -RenderSkillGame PROC uses ebx esi edi - local kx:DWORD - local tx:DWORD - - ; Industrial Steel bezel - invoke DrawBox, 0, 0, 320, 240, 00121416h - invoke DrawBoxBorder, 6, 6, 308, 228, 001A1D20h, 00FFD700h, 2 - - ; Header - invoke DrawBoxBorder, 20, 12, 280, 26, 00121418h, 00FFD700h, 2 - invoke DrawString8x8, 40, 21, OFFSET textSkillTitle, 00FFFF00h - - ; Status - invoke DrawBoxBorder, 20, 44, 110, 18, 00121418h, 002A3540h, 1 - invoke DrawString8x8, 24, 49, OFFSET textBankPrompt, 003CFF3Ch - invoke FormatNumber, bankroll, OFFSET hudNumBuffer - invoke DrawString8x8, 72, 49, OFFSET hudNumBuffer, 003CFF3Ch - - invoke DrawBoxBorder, 190, 44, 110, 18, 00121418h, 002A3540h, 1 - invoke DrawString8x8, 194, 49, OFFSET textBetPrompt, 00FFD700h - invoke FormatNumber, skill3d_bet, OFFSET hudNumBuffer - invoke DrawString8x8, 254, 49, OFFSET hudNumBuffer, 00FFD700h - - ; Survivor Progress - invoke DrawString8x8, 24, 70, OFFSET textSkillHitsHdr, 003CFF3Ch - invoke FormatNumber, skill3d_hits, OFFSET hudNumBuffer - invoke DrawString8x8, 64, 70, OFFSET hudNumBuffer, 003CFF3Ch - - invoke DrawString8x8, 180, 70, OFFSET textSkillMissHdr, 00FF6464h - invoke FormatNumber, skill3d_misses, OFFSET hudNumBuffer - invoke DrawString8x8, 240, 70, OFFSET hudNumBuffer, 00FF6464h - - ; Dial Frame (Track: X=50..270, Y=102..134) - invoke DrawBoxBorder, 50, 102, 220, 32, 000F1114h, 00404855h, 2 - - ; Calibrated ticks - mov tx, 60 -skill_ticks_loop: - cmp tx, 260 - jge skill_draw_zones - invoke DrawBox, tx, 104, 1, 6, 00303845h - invoke DrawBox, tx, 126, 1, 6, 00303845h - add tx, 12 - jmp skill_ticks_loop - -skill_draw_zones: - ; Normal Success Zone (Green) - invoke DrawBoxBorder, skill3d_zone_start, 106, skill3d_zone_width, 24, 00155020h, 003CFF3Ch, 1 - - ; Great Zone (Gold) - invoke DrawBoxBorder, skill3d_great_start, 106, skill3d_great_width, 24, 00FFD700h, 00FFFF00h, 1 - - ; Pointer / Needle at skill3d_needle - mov eax, skill3d_needle - dec eax - invoke DrawBox, eax, 98, 3, 40, 00FFFFFFh - mov eax, skill3d_needle - sub eax, 2 - invoke DrawBox, eax, 96, 5, 2, 00FF3030h - invoke DrawBox, eax, 138, 5, 2, 00FF3030h - - ; Center prompts / outcome - cmp skill3d_state, 0 - jne @F - invoke DrawString8x8, 52, 150, OFFSET textSkillReadyMsg, 00FFD700h - invoke DrawString8x8, 76, 166, OFFSET textSkillPrompt, 00D0D8E0h - jmp skill_render_keys -@@: - cmp skill3d_state, 1 - jne @F - invoke DrawString8x8, 76, 150, OFFSET textSkillPrompt, 00FFFF00h - jmp skill_render_keys -@@: - cmp skill3d_state, 2 - jne @F - cmp skill3d_last_result, 2 - jne skill_normal_hit_text - invoke DrawString8x8, 36, 150, OFFSET textSkillGreatMsg, 00FFFF00h - jmp skill_render_keys -skill_normal_hit_text: - invoke DrawString8x8, 64, 150, OFFSET textSkillHitMsg, 003CFF3Ch - jmp skill_render_keys -@@: - cmp skill3d_state, 3 - jne @F - invoke DrawString8x8, 88, 150, OFFSET textSkillMissMsg, 00FF6464h - jmp skill_render_keys -@@: - cmp skill3d_state, 4 - jne @F - invoke DrawString8x8, 48, 150, OFFSET textSkillEscape, 003CFF3Ch - invoke FormatNumber, skill3d_win_amount, OFFSET hudNumBuffer - invoke DrawString8x8, 240, 150, OFFSET hudNumBuffer, 003CFF3Ch - invoke DrawString8x8, 64, 166, OFFSET textSkullsAgain, 00FFD700h - jmp skill_render_keys -@@: - invoke DrawString8x8, 44, 150, OFFSET textSkillLost, 00FF6464h - invoke DrawString8x8, 64, 166, OFFSET textSkullsAgain, 00FFD700h - -skill_render_keys: - mov kx, 16 - invoke DrawKeycap3D, kx, 192, OFFSET textSkillKeySpace, 1 - add kx, eax - - invoke DrawKeycap3D, kx, 192, OFFSET textSkillKeyBet, 0 - add kx, eax - - invoke DrawKeycap3D, kx, 192, OFFSET textKeyEsc, 0 - ret -RenderSkillGame 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: - call CheckHallInteractions3D - 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: - invoke PlayCasinoSound3D, 0, 0, 0 - call InitSounds - ; Çàïóñê îðèãèíàëüíîé èãðû! - call pGameProc - call CloseLegacySounds3D - - ; Çàêðûâàåì êîíñîëü - 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 - call TriggerHallInteraction3D - test eax, eax - jnz trigger_done - 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 PlayCasinoSound3D, OFFSET soundClick, 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 - call InitNativeBlackjack3D - mov engineMode, MODE_BLACKJACK - ret - -check_target_poker: - cmp eax, INTERACT_POKER - jne check_target_durak - call InitNativePoker3D - test eax, eax - jz target_unported - mov engineMode, MODE_POKER - ret - -check_target_durak: - cmp eax, INTERACT_DURAK - jne check_target_slots777 - call InitNativeDurak3D - mov engineMode, MODE_DURAK - ret - -check_target_slots777: - cmp eax, INTERACT_SLOTS_777 - jne check_target_slots_clover - call InitNativeSlots3D - test eax,eax - jz target_unported - mov engineMode,MODE_SLOTS - ret - -check_target_slots_clover: - cmp eax, INTERACT_SLOTS_CLOVER - jne check_target_roulette - call InitNativeClover3D - test eax,eax - jz target_unported - mov engineMode,MODE_CLOVER - ret - -check_target_roulette: - cmp eax, INTERACT_ROULETTE - jne check_target_dice - call InitNativeWheel3D - mov engineMode, MODE_ROULETTE - 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 - call InitSkillGame - mov engineMode, MODE_SKILL - ret - -check_target_buckshot: - cmp eax, INTERACT_BUCKSHOT - jne check_target_rr - call InitBuckshot3D - mov engineMode, MODE_BUCKSHOT - ret - -check_target_rr: - cmp eax, INTERACT_RUSSIAN_ROULETTE - jne check_target_online_rr - call InitRussianGame3D - test eax, eax - jz @F - mov engineMode, MODE_RUSSIAN -@@: - ret - -check_target_online_rr: - cmp eax, INTERACT_ONLINE_RR - jne check_target_umamusume - call BeginUnavailable3D - ret - -check_target_umamusume: - cmp eax, INTERACT_UMAMUSUME - jne check_target_hell - call BeginUnavailable3D - ret - -check_target_hell: - cmp eax, INTERACT_HELL_TOWER - jne check_target_shop - call BeginUnavailable3D - ret - -check_target_shop: - cmp eax, INTERACT_SHOP - jne check_target_atm - call BeginMerchant3D - 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 - call BeginUnavailable3D - ret - -check_target_observer: - cmp eax, INTERACT_OBSERVER - jne target_unported - call BeginUnavailable3D - ret - -target_unported: - call BeginUnavailable3D -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 LoadDisplaySettings3D - call Create3DWindow - test eax, eax - jz init_failed - call LoadTextures3D - test eax, eax - jz init_failed - - call InitializeCasinoSprites3D - - call InitHall3D - call BeginStartup3D - call RenderStartup3D - invoke ShowWindow, h3DWnd, SW_SHOW - invoke UpdateWindow, h3DWnd - invoke SetForegroundWindow, h3DWnd - mov eax, 1 - jmp init_return -init_failed: - xor eax, eax -init_return: - pop edi - pop esi - pop ebx - ret -Init3DEngine ENDP - -InitializeCasinoSprites3D PROC -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 - ret -InitializeCasinoSprites3D ENDP - -include src_graphics\audio_code.inc -include src_graphics\dice_animation.inc -include src_graphics\russian_roulette.inc -include src_graphics\startup_code.inc -include src_graphics\card_table_assets.inc -include src_graphics\poker_evaluator.inc -include src_graphics\native_poker.inc -include src_graphics\native_blackjack.inc -include src_graphics\native_durak.inc -include src_graphics\card_tables_render.inc -include src_graphics\durak_render.inc -include src_graphics\card_table_input.inc -include src_graphics\scene_animation.inc -include src_graphics\native_slots.inc -include src_graphics\native_clover.inc -include src_graphics\native_coin.inc -include src_graphics\graphic_profiles.inc -include src_graphics\city_arrival_scene.inc -include src_graphics\arrival_scene.inc -include src_graphics\merchant_scene.inc -include src_graphics\hall_scene.inc -include src_graphics\npc_mind.inc -include src_graphics\npc_life.inc -include src_graphics\npc_contracts.inc -include src_graphics\native_wheel.inc -include src_graphics\billiards.inc -include src_graphics\buckshot.inc -include src_graphics\russian_table.inc -include src_graphics\unavailable.inc - -; --- 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_INTRO - jne @F - call FinishStartup3D - jmp engine_tick -@@: - cmp engineMode, MODE_ARRIVAL - jne @F - call ArrivalEscape3D - jmp engine_tick -@@: - cmp engineMode, MODE_WALK - jne leave_table - xor paused3D, 1 - jmp engine_tick -leave_table: - call CardTableEscape3D - test eax, eax - jnz engine_tick - call TableBusy3D - test eax, eax - jz leave_idle_table - xor paused3D, 1 - call ClearKeys3D - jmp engine_tick -leave_idle_table: - mov paused3D, 0 - mov engineMode, MODE_WALK - call ClearKeys3D - invoke PlayCasinoSound3D, 0, 0, 0 -engine_tick: - cmp paused3D, 0 - jne draw_pause - mov eax, deltaTime3D - add animationClock3D, eax - cmp engineMode, MODE_INTRO - jne check_arrival_mode - call HandleStartupInput3D - cmp engineMode, MODE_INTRO - jne check_arrival_mode - call RenderStartup3D - jmp present_frame -check_arrival_mode: - cmp engineMode, MODE_ARRIVAL - jne check_walk_mode - call HandleArrival3D - cmp engineMode, MODE_WALK - je check_walk_mode - call RenderArrival3D - jmp present_frame -check_walk_mode: - cmp engineMode, MODE_WALK - jne check_slots_mode - call UpdateHall3D - call UpdateCamera3D - call CheckInteractions - call HandlePlayerInput - call UpdateCamera3D - call RenderCeilingAndFloor - call RenderWalls - call PrepareCityDepth3D - call RenderSprites - call RenderHall3D - call RenderHUD - call RenderMinimap - jmp present_frame -check_slots_mode: - cmp engineMode,MODE_CLOVER - jne @F - call HandleNativeClover3D - call RenderNativeClover3D - jmp present_frame -@@: - cmp engineMode,MODE_NPC_DIALOG - jne @F - call HandleNpcDialog3D - call RenderNpcDialog3D - jmp present_frame -@@: - cmp engineMode, MODE_UNAVAILABLE - jne @F - call HandleUnavailable3D - call RenderUnavailable3D - jmp present_frame -@@: - cmp engineMode, MODE_POOL - jne @F - call HandlePool3D - call RenderPool3D - jmp present_frame -@@: - cmp engineMode, MODE_BAR - jne @F - call HandleBar3D - call RenderBar3D - jmp present_frame -@@: - cmp engineMode, MODE_STAIRS - jne @F - call HandleStairs3D - call RenderStairs3D - jmp present_frame -@@: - cmp engineMode, MODE_SLOTS - jne check_bj_mode - call HandleNativeSlots3D - cmp engineMode,MODE_WALK - je check_walk_mode - call RenderNativeSlots3D - jmp present_frame -check_bj_mode: - cmp engineMode, MODE_BLACKJACK - jne check_poker_mode - call HandleNativeBlackjack3D - cmp engineMode, MODE_WALK - je check_walk_mode - call RenderNativeBlackjack3D - jmp present_frame -check_poker_mode: - cmp engineMode, MODE_POKER - jne check_durak_mode - call HandleNativePoker3D - cmp engineMode, MODE_WALK - je check_walk_mode - call RenderNativePoker3D - jmp present_frame -check_durak_mode: - cmp engineMode, MODE_DURAK - jne check_roul_mode - call HandleNativeDurak3D - cmp engineMode, MODE_WALK - je check_walk_mode - call RenderNativeDurak3D - jmp present_frame -check_roul_mode: - cmp engineMode, MODE_ROULETTE - jne check_shop_mode - call HandleNativeWheel3D - call RenderNativeWheel3D - jmp present_frame -check_shop_mode: - cmp engineMode, MODE_SHOP - jne check_atm_mode - call HandleMerchant3D - call RenderMerchant3D - 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 check_skill_mode - call HandleSkullsInput - call RenderSkullsGame - jmp present_frame -check_skill_mode: - cmp engineMode, MODE_SKILL - jne check_buckshot_mode - call HandleSkillInput - call RenderSkillGame - jmp present_frame -check_buckshot_mode: - cmp engineMode, MODE_BUCKSHOT - jne check_russian_mode - call HandleBuckshot3D - call RenderBuckshot3D - jmp present_frame -check_russian_mode: - cmp engineMode, MODE_RUSSIAN - jne present_frame - call HandleRussianInput3D - call RenderRussianGame3D - jmp present_frame -draw_pause: - invoke DrawBoxBorder, 28, 36, 264, 168, 00151C21h, 00D8BC6Ah, 2 - invoke DrawString8x8, 44, 48, OFFSET textPause3D, 00FFFFFFh - cmp displayFill3D, 0 - je @F - invoke DrawString8x8, 44, 72, OFFSET textDisplayFill3D, 00D8BC6Ah - jmp pause_draw_quality -@@: - invoke DrawString8x8, 44, 72, OFFSET textDisplayFit3D, 00D8BC6Ah -pause_draw_quality: - invoke DrawString8x8, 44, 92, OFFSET textLowSpec3D, 00D8BC6Ah - mov eax, settingsLowSpec - cmp eax, 0 - jne @F - mov edx, OFFSET textLowSpecOff3D - jmp pause_draw_quality_value -@@: - cmp eax, 1 - jne @F - mov edx, OFFSET textLowSpecEco3D - jmp pause_draw_quality_value -@@: - mov edx, OFFSET textLowSpecQuiet3D -pause_draw_quality_value: - invoke DrawString8x8, 208, 92, edx, 00FFFFFFh - invoke DrawString8x8, 44, 112, OFFSET textVolumeKeys3D, 00D8BC6Ah - invoke DrawString8x8, 44, 130, OFFSET textSoundLevel3D, 00BBBBBBh - invoke FormatNumber, settingsVolume, OFFSET hudNumBuffer - invoke DrawString8x8, 124, 130, OFFSET hudNumBuffer, 00FFFFFFh - invoke DrawString8x8, 44, 150, OFFSET textFullscreenKey3D, 00A0A0A0h - invoke DrawString8x8, 44, 170, OFFSET textResume3D, 00D8BC6Ah - invoke DrawString8x8, 44, 188, OFFSET textQuit3D, 00BBBBBBh - invoke Pressed3D, 31h - test eax, eax - jz @F - xor displayFill3D, 1 - call SaveDisplaySettings3D -@@: - invoke Pressed3D, 32h - test eax, eax - jz @F - inc settingsLowSpec - cmp settingsLowSpec, 3 - jb pause_low_spec_saved - mov settingsLowSpec, 0 -pause_low_spec_saved: - call SaveProgress3D -@@: - invoke Pressed3D, 0BBh - test eax, eax - jz @F - cmp settingsVolume, 10 - jae @F - inc settingsVolume - call ApplySoundVolume - call SaveProgress3D -@@: - invoke Pressed3D, 0BDh - test eax, eax - jz @F - mov eax, settingsVolume - test eax, eax - jz @F - dec settingsVolume - call ApplySoundVolume - call SaveProgress3D -@@: - invoke Pressed3D, 51h - test eax, eax - jz @F - call SaveProgress3D - jmp engine_shutdown -present_frame: - mov eax, engineMode - cmp eax, lastPersistMode3D - je @F - cmp eax, MODE_WALK - jne @F - call SaveProgress3D -@@: - mov eax, engineMode - mov lastPersistMode3D, eax - call Present3D - mov mouseClick3D, 0 - lea edi, pressedKeys3D - xor eax, eax - mov ecx, 64 - rep stosd - invoke GetTickCount - sub eax, frameStart3D - mov ecx, 16 - cmp settingsLowSpec, 1 - jne @F - mov ecx, 24 -@@: - cmp settingsLowSpec, 2 - jne @F - mov ecx, 33 -@@: - cmp eax, ecx - jae engine_loop - sub ecx, eax - invoke Sleep, ecx - jmp engine_loop -engine_idle: - invoke Sleep, 50 - jmp engine_loop -engine_shutdown: - call SaveProgress3D - invoke PlayCasinoSound3D, 0, 0, 0 - call FreeRussianAssets3D - call FreeStartupAssets3D - call FreeCardTableAssets3D - call FreeBuckshotAssets3D - call FreeNativeSlots3D - call FreeNativeClover3D - call FreePyramidAssets3D - call FreeArrivalAssets3D - 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 - -IFDEF CASINO_ACTION_TEST -include tools\tests\casino_actions_test.inc -ENDIF + +; ============================================================================== +; 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 +CopyFileA PROTO :DWORD,:DWORD,:DWORD +lstrcmpiA PROTO :DWORD,:DWORD +GetFileSize PROTO :DWORD,:DWORD +Sleep PROTO :DWORD +CreateThread PROTO :DWORD,:DWORD,:DWORD,:DWORD,:DWORD,:DWORD +CreateEventA PROTO :DWORD,:DWORD,:DWORD,:DWORD +SetEvent PROTO :DWORD +WaitForSingleObject PROTO :DWORD,: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 +MODE_SKILL equ 9 + +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 +include src_graphics\casino_actions_data.inc +include src_graphics\audio_data.inc +include src_graphics\startup_data.inc +include src_graphics\card_tables_data.inc +include src_graphics\native_durak_data.inc +include src_graphics\scene_animation_data.inc +include src_graphics\arrival_data.inc +include src_graphics\city_arrival_data.inc +include src_graphics\merchant_data.inc +include src_graphics\hall_data.inc +include src_graphics\npc_mind_data.inc +include src_graphics\npc_life_data.inc +include src_graphics\native_wheel_data.inc +include src_graphics\billiards_data.inc +include src_graphics\buckshot_data.inc +include src_graphics\russian_view_data.inc +include src_graphics\unavailable_data.inc +include src_graphics\native_slots_data.inc +include src_graphics\native_clover_data.inc +include src_graphics\native_coin_data.inc + +.data +ALIGN 4 +h3DInst dd 0 +h3DWnd dd 0 +h3DDC dd 0 +hCasinoConsole dd 0 + +ALIGN 4 +hRaycastThread dd 0 +hRaycastStartEvent dd 0 +hRaycastDoneEvent dd 0 +bRaycastQuit dd 0 +raycastThreadId dd 0 + +bmi3D C3D_BITMAPINFO <> +msg3D C3D_MSG <> +wc3D C3D_WNDCLASSEX <> + +sz3DClassName db "Casino3DRetroClass",0 +sz3DWindowTitle db 192,241,241,229,236,225,235,229,240,32,202,224,231,232,237,238,32,45,32,50,46,53,68,0 +szTexturesRelPath db "assets\textures\casino3d-hd.bin",0 +szTexturesFullPath db 260 dup(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 91,69,93,32,207,206,202,197,208,32,40,210,197,213,192,209,209,202,200,201,32,213,206,203,196,197,204,41,0 +promptDurak db "[E] ÊÀÐÒÛ: ÏÎÄÊÈÄÍÎÉ ÄÓÐÀÊ",0 +promptCasinoRoulette db "[E] ÅÂÐÎÏÅÉÑÊÀß ÐÓËÅÒÊÀ",0 +promptClassicSlot db "[E] ÊËÀÑÑÈ×ÅÑÊÈÅ ÑËÎÒÛ 777",0 +promptCloverSlot db "[E] ÑËÎÒÛ CLOVERPIT (5x3)",0 +promptDice db 91,69,93,32,200,195,208,192,32,194,32,202,206,209,210,200,0 +promptSkulls db "[E] ÍÀϨÐÑÒÊÈ (×ÅÐÅÏÀ)",0 +promptCoin db "[E] ÌÎÍÅÒÊÀ (ÎШË/ÐÅØÊÀ)",0 +promptSkillCheck db "[E] ÒÐÅÍÈÐÎÂÊÀ ÐÅÀÊÖÈÈ",0 +promptBuckshot db 91,69,93,32,193,192,202,216,206,210,32,208,211,203,197,210,202,192,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 202,192,199,200,202,32,51,68,32,45,32,193,203,221,202,196,198,197,202,32,40,50,49,41,0 +szTitlePoker db 202,192,199,200,202,32,51,68,32,45,32,207,206,202,197,208,32,40,210,197,213,192,209,209,202,200,201,32,213,206,203,196 + db 197,204,41,0 +szTitleDurak db 202,192,199,200,202,32,51,68,32,45,32,207,197,208,197,194,206,196,205,206,201,32,196,211,208,192,202,0 +szTitleCasinoRoulette db 202,192,199,200,202,32,51,68,32,45,32,197,194,208,206,207,197,201,209,202,192,223,32,208,211,203,197,210,202,192,0 +szTitleClassicSlot db 202,192,199,200,202,32,51,68,32,45,32,192,194,210,206,204,192,210,32,55,55,55,0 +szTitleCloverSlot db 202,192,199,200,202,32,51,68,32,45,32,202,203,197,194,197,208,205,192,223,32,223,204,192,32,40,53,120,51,41,0 +szTitleDice db 202,192,199,200,202,32,51,68,32,45,32,200,195,208,192,32,194,32,202,206,209,210,200,0 +szTitleSkulls db 202,192,199,200,202,32,51,68,32,45,32,205,192,207,168,208,209,210,202,200,0 +szTitleCoin db 202,192,199,200,202,32,51,68,32,45,32,204,206,205,197,210,202,192,32,40,206,208,168,203,47,208,197,216,202,192,41,0 +szTitleSkillCheck db 202,192,199,200,202,32,51,68,32,45,32,207,208,206,194,197,208,202,192,32,205,192,194,219,202,192,0 +szTitleBuckshot db 202,192,199,200,202,32,51,68,32,45,32,193,192,202,216,206,210,32,208,211,203,197,210,202,192,0 +szTitleRussianRoulette db 202,192,199,200,202,32,51,68,32,45,32,208,211,209,209,202,192,223,32,208,211,203,197,210,202,192,0 +szTitleOnlineRR db 202,192,199,200,202,32,51,68,32,45,32,209,197,210,197,194,192,223,32,208,211,209,209,202,192,223,32,208,211,203,197,210 + db 202,192,0 +szTitleUmamusume db 202,192,199,200,202,32,51,68,32,45,32,195,206,205,202,200,32,211,204,192,204,211,209,211,204,197,0 +szTitleHellTower db 202,192,199,200,202,32,51,68,32,45,32,192,196,209,202,192,223,32,193,192,216,205,223,0 +szTitleShop db 202,192,199,200,202,32,51,68,32,45,32,202,192,208,210,219,32,200,32,210,192,203,200,209,204,192,205,219,0 +szTitleATM db 202,192,199,200,202,32,51,68,32,45,32,193,192,205,202,206,204,192,210,0 +szTitleTerminal db 202,192,199,200,202,32,51,68,32,45,32,203,206,202,192,203,220,205,219,197,32,207,208,206,212,200,203,200,0 +szTitleObserver db 202,192,199,200,202,32,51,68,32,45,32,205,192,193,203,222,196,192,210,197,203,220,32,40,200,200,41,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) + +coinRxAnimTable db 26, 22, 16, 6, 16, 22, 26, 22, 16, 6 + +; --- Native 2.5D Coin Flip --- +coin3d_bet dd 50 +coin3d_choice 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 + +textCoinTitle db "* * * Ç Î Ë Î Ò À ß Ì Î Í Å Ò À * * *",0 +textCoinHeads db "ÎШË",0 +textCoinTails db "ÐÅØÊÀ",0 +textCoinSide1 db "[1] ÎШË",0 +textCoinSide2 db "[2] ÐÅØÊÀ",0 +textCoinFlipping db "ÌÎÍÅÒÀ  ÏÎ˨ÒÅ...",0 +textCoinWin db "ÏÎÁÅÄÀ: +$",0 +textCoinLose db "ÍÅ ÓÃÀÄÀËÈ!",0 +textCoinStreakFmt db "ÑÅÐÈß ÏÎÁÅÄ: x",0 +textCoinSelected db "ÂÛÁÐÀÍÎ",0 +textCoinKey1 db "[1] ÎШË",0 +textCoinKey2 db "[2] ÐÅØÊÀ",0 +textCoinKeySpace db "[SPACE]",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 200,195,208,192,32,194,32,202,206,209,210,200,0 +textDiceEven db "[1] רÒ",0 +textDiceOdd db "[2] ÍÅ×ÅÒ",0 +textDiceEvenNums db "2 4 6 ...",0 +textDiceOddNums db "3 5 7 ...",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 "[SPACE]",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 +skulls3d_cup0 dd 0 +skulls3d_cup1 dd 1 +skulls3d_cup2 dd 2 + +textSkullsTitle db "* * * Í À Ï ¨ Ð Ñ Ò Ê È * * *",0 +textSkullsPhase0 db "ÄÅËÀÉ ÑÒÀÂÊÓ È ÆÌÈ [ÏÐÎÁÅË]",0 +textSkullsPhase1 db "ÑÌÎÒÐÈ, ÃÄÅ ÇÎËÎÒÎÉ ØÀÐ...",0 +textSkullsPhase2 db "ÊÐÓ×Ó, ÂÅÐ×Ó, ÇÀÏÓÒÀÒÜ ÕÎ×Ó...",0 +textSkullsPhase3 db "ÃÄÅ ØÀÐ? ÂÛÁÈÐÀÉ: [1], [2] ÈËÈ [3]!",0 +textSkullsWin db "ÂÛÈÃÐÛØ: +$",0 +textSkullsWinMult db "! (x3) ÂÛ ÓÃÀÄÀËÈ!",0 +textSkullsLose db "ÌÈÌÎ! ØÀÐ ÁÛË Â ÄÐÓÃÎÌ ÌÅÑÒÅ!",0 +textSkullsAgain db "[ÏÐÎÁÅË] - ÑÛÃÐÀÒÜ ÅÙ¨ ÐÀÇ",0 +textSkullsKey1 db "[1]",0 +textSkullsKey2 db "[2]",0 +textSkullsKey3 db "[3]",0 +textSkullsKeySpace db "[SPACE] ÑÒÀÐÒ",0 + +; --- Native 2.5D Skill Check (Dead by Daylight Survivor Check) --- +skill3d_bet dd 50 +skill3d_state dd 0 ; 0=Ready, 1=Active, 2=Hit Result, 3=Miss Result, 4=Escaped, 5=Defeated +skill3d_timer dd 0 +skill3d_needle dd 55 ; Needle X (52..268) +skill3d_speed dd 4 +skill3d_dir dd 1 ; 1=Right, -1=Left +skill3d_zone_start dd 140 +skill3d_zone_width dd 48 +skill3d_great_start dd 176 +skill3d_great_width dd 12 +skill3d_hits dd 0 +skill3d_misses dd 0 +skill3d_last_result dd 0 +skill3d_win_amount dd 0 + +textSkillTitle db 61,61,61,32,207,208,206,194,197,208,202,192,32,205,192,194,219,202,192,32,61,61,61,0 +textSkillHitsHdr db "ÕÈÒ: ",0 +textSkillMissHdr db "ÏÐÎÌÀÕ: ",0 +textSkillReadyMsg db "ÍÀÆÌÈÒÅ [ÏÐÎÁÅË] ÄËß ÑÒÀÐÒÀ",0 +textSkillPrompt db "ÍÀÆÌÈÒÅ [ÏÐÎÁÅË]  ÇÎÍÅ!",0 +textSkillHitMsg db "ÕÈÒ! ÒÎ×ÍÎÅ ÏÎÏÀÄÀÍÈÅ!",0 +textSkillGreatMsg db 206,210,203,200,215,205,206,33,32,43,193,206,205,211,209,33,0 +textSkillMissMsg db "ÏÐÎÌÀÕ! ÒÐÅÂÎÃÀ!",0 +textSkillEscape db "ÏÎÁÅà ÓÑÏÅØÅÍ! ÂÛÈÃÐÛØ: +$",0 +textSkillLost db "ÂÛ ÏÎÉÌÀÍÛ! ÏÐÎÈÃÐÛØ ÑÒÀÂÊÈ!",0 +textSkillKeySpace db "[SPACE] ÐÅÀÊÖÈß",0 +textSkillKeyBet 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 205,200,215,220,223,0 +strDealerBust db "ÄÈËÅÐ ÏÅÐÅÁÐÀË! ÏÎÁÅÄÀ! +$",0 +strPlayerBust db "ÏÅÐÅÁÎÐ (>21)! ÏÐÎÈÃÐÛØ",0 + +sym7 db " 777 ",0 +symBar db " BAR ",0 +symBell db 32,199,194,206,205,0 +symCherry db 194,200,216,205,223,0 +symClover db 202,203,197,194,197,208,0 +symGem db 192,203,204,192,199,0 +symCrown db 202,206,208,206,205,192,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 (104 * 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 --- + +; --- DDA Raycasting Walls --- +RenderWallsRange PROC colStart:DWORD, colLimit:DWORD + local col:DWORD + local originalStart: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 texXHD:DWORD + local pixelMaterial: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 eax, colStart + mov col, eax +col_loop: + mov eax, colLimit + cmp col, eax + 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 wall_map_boundary + + 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 wall_map_boundary + cmp mapX, MAP_WIDTH + jge wall_map_boundary + cmp mapY, 0 + jl wall_map_boundary + cmp mapY, MAP_HEIGHT + jge wall_map_boundary + + mov eax, mapY + shl eax, 5 + add eax, mapX + mov edx, worldMap3D + movzx eax, BYTE PTR [edx + eax] + test eax, eax + jnz hit_wall + jmp dda_step_loop + +wall_map_boundary: + cmp outdoorRender3D, 0 + je hit_wall + mov eax, col + mov zBuffer[eax*4], 7FFFFFFFh + jmp next_col + +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 + + ; Unit projection is shared by indoor room height and outdoor storeys. + mov eax, SCREEN_H + imul eax, FP_1 + cdq + idiv perpWallDist + mov lineH, eax + + mov eax, lineH + imul viewEye3D + shrd eax, edx, 16 + add eax, viewHorizon3D + mov drawEnd, eax + mov ebx, lineH + mov eax, viewCeiling3D + cmp outdoorRender3D, 0 + je @F + mov eax, CITY_STOREY_HEIGHT +@@: + imul ebx + shrd eax, edx, 16 + mov ebx, eax + mov lineH, ebx + mov eax, drawEnd + sub eax, ebx + mov drawStart, eax + cmp outdoorRender3D, 0 + je wall_store_original_start + ; Floor height is independent of storey height. + mov eax, drawEnd + sub eax, lineH + mov drawStart, eax + mov eax, mapY + shl eax, 5 + add eax, mapX + mov edx, worldMap3D + movzx eax, BYTE PTR [edx+eax] +wall_exterior_tall: + ; Roof projection and texture sampling use the same storey count. + mov eax, lineH + imul eax, CITY_BUILDING_STOREYS-1 + sub drawStart, eax + mov eax, lineH + imul eax, CITY_BUILDING_STOREYS + mov lineH, eax +wall_store_original_start: + mov eax, drawStart + mov originalStart, eax + + 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 + mov texXHD, eax + 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 + xor texXHD, 0FFFFh +@@: + cmp side, 1 + jne select_tex + cmp rayDirY, 0 + jge select_tex + mov eax, 127 + sub eax, texX + mov texX, eax + xor texXHD, 0FFFFh + +select_tex: + mov eax, mapY + shl eax, 5 + add eax, mapX + mov edx, worldMap3D + movzx eax, BYTE PTR [edx + 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, drawStart + sub eax, originalStart + 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 + mov edx, texId + cmp outdoorRender3D, 0 + je wall_sample_material + imul eax, CITY_BUILDING_STOREYS + cmp eax, 128*(CITY_BUILDING_STOREYS-1) + jae wall_lower_storey + push eax + shr eax, 7 + add eax, mapX + add eax, mapY + xor edx, edx + mov ebx, 3 + div ebx + add edx, 65 + pop eax + and eax, 127 + jmp wall_sample_material +wall_lower_storey: + sub eax, 128*(CITY_BUILDING_STOREYS-1) +wall_sample_material: + mov pixelMaterial, edx + cmp outdoorRender3D, 0 + je wall_sample_indoor_hd + cmp hallCityDetail3D.pixels, 0 + je wall_sample_standard + cmp edx, 57 + jb wall_sample_standard + cmp edx, 72 + ja wall_sample_standard + cmp perpWallDist, 6*FP_1 + ja wall_sample_standard + ; Preserve subtexel detail near facades; retain the 128px mip at distance. + push edx + mov eax, edi + shr eax, 15 + imul eax, CITY_BUILDING_STOREYS + and eax, 255 + shl eax, 8 + mov ebx, texXHD + shr ebx, 8 + add eax, ebx + pop edx + sub edx, 57 + shl edx, 16 + add eax, edx + mov ebx, hallCityDetail3D.pixels + mov eax, [ebx+eax*4] + jmp wall_shade_pixel +wall_sample_indoor_hd: + cmp edx, 80 + jb wall_sample_standard + cmp edx, 103 + ja wall_sample_standard + mov ebx, hallRoomHD3D.pixels + cmp edx, 92 + jb wall_sample_room_hd + mov ebx, hallArchitectureHD3D.pixels + sub edx, 12 +wall_sample_room_hd: + test ebx, ebx + jz wall_sample_standard_restore + sub edx, 80 + shl edx, 18 + add ebx, edx + mov eax, edi + shr eax, 15 + and eax, 255 + shl eax, 8 + mov edx, texXHD + shr edx, 8 + add eax, edx + mov eax, [ebx+eax*4] + jmp wall_shade_pixel +wall_sample_standard_restore: + mov edx, texId + mov eax, edi + shr eax, 16 + and eax, 127 +wall_sample_standard: + shl eax, 7 + add eax, texX + + shl edx, 14 + add eax, edx + mov eax, [texturesBuffer + eax*4] + + ; Shade wall pixel +wall_shade_pixel: + mov ebx, shade + cmp outdoorRender3D, 0 + je wall_ambient_shade + push eax + push ecx + invoke IsCityEmissive3D, eax, pixelMaterial + pop ecx + test eax, eax + pop eax + jz wall_ambient_shade + mov ebx, 256 +wall_ambient_shade: + cmp hallLevel3D, 0 + je @F + imul ebx, 7 + shr ebx, 3 +@@: + 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 +RenderWallsRange ENDP + +; --- Raycasting Background Worker Thread --- +RaycastWorkerProc PROC uses ebx esi edi lpParam:DWORD +worker_loop: + invoke WaitForSingleObject, hRaycastStartEvent, 0FFFFFFFFh + cmp bRaycastQuit, 1 + je worker_exit + invoke RenderWallsRange, 320, 640 + invoke SetEvent, hRaycastDoneEvent + jmp worker_loop +worker_exit: + xor eax, eax + ret +RaycastWorkerProc ENDP + +; --- Multi-Threaded DDA Raycasting Walls Dispatcher --- +RenderWalls PROC + 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 + + cmp hRaycastStartEvent, 0 + je single_thread_fallback + + ; Signal background worker to render columns [320..640) + invoke SetEvent, hRaycastStartEvent + + ; Main thread processes columns [0..320) in parallel + invoke RenderWallsRange, 0, 320 + + ; Synchronize with worker completion + invoke WaitForSingleObject, hRaycastDoneEvent, 0FFFFFFFFh + jmp walls_finished + +single_thread_fallback: + invoke RenderWallsRange, 0, SCREEN_W + +walls_finished: + pop edi + pop esi + pop ebx + ret +RenderWalls ENDP + +; --- Render 3D Billboard Sprites --- + +; --- 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, 00FFD700h, 1 + + ; Draw Sprites on radar + cmp hallLevel3D, 0 + jne draw_player_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, 00FF2020h + 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 PlayCasinoSound3D, OFFSET soundSlotSpin, 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, 00FFD700h, 3 + + ; Illuminated Top Marquee + invoke DrawBoxBorder, 25, 20, 270, 32, 000A0505h, 00FFFF00h, 2 + invoke DrawString8x8, 55, 32, OFFSET textSlots3D, 00FFD700h + + ; 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 PlayCasinoSound3D, 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 PlayCasinoSound3D, OFFSET soundJackpot, 0, 1 + jmp draw_reels +@@: + mov eax, slotBet + imul eax, 10 + mov slotWinAmount, eax + add bankroll, eax + invoke PlayCasinoSound3D, OFFSET soundRoundWin, 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 PlayCasinoSound3D, OFFSET soundRoundWin, 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, 00FFD700h, 1 + + invoke DrawString8x8, 28, 172, OFFSET textBank3D, 00FFD700h + invoke FormatNumber, bankroll, OFFSET hudNumBuffer + invoke DrawString8x8, 110, 172, OFFSET hudNumBuffer, 00FFFF00h + + invoke DrawString8x8, 175, 172, OFFSET textBet3D, 00FFD700h + 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, 00FFFF00h + invoke FormatNumber, slotWinAmount, OFFSET hudNumBuffer + invoke DrawString8x8, 110, 187, OFFSET hudNumBuffer, 00FFFF00h + +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, 00FF2020h + 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, 00FFD700h + 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, 00FFD700h + ret +DrawReelSymbolAt1 ENDP + +DrawReelSymbolAt2 PROC + cmp eax, 0 + jne @F + invoke DrawString8x8, 135, 105, OFFSET sym7, 00FF2020h + 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, 00FFD700h + 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, 00FFD700h + ret +DrawReelSymbolAt2 ENDP + +DrawReelSymbolAt3 PROC + cmp eax, 0 + jne @F + invoke DrawString8x8, 218, 105, OFFSET sym7, 00FF2020h + 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, 00FFD700h + 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, 00FFD700h + 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 PlayCasinoSound3D, 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 PlayCasinoSound3D, OFFSET soundRoundWin, 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 PlayCasinoSound3D, 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 PlayCasinoSound3D, OFFSET soundRoundWin, 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 PlayCasinoSound3D, OFFSET soundRoundWin, 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, 00FFD700h, 3 + + ; Dealer Area Top + invoke DrawString8x8, 25, 20, OFFSET textBJ3D, 00FFD700h + invoke DrawString8x8, 25, 35, OFFSET textDealer3D, 00FFFFFFh + invoke FormatNumber, bjDealerScore, OFFSET hudNumBuffer + invoke DrawString8x8, 120, 35, OFFSET hudNumBuffer, 00FFFF00h + + ; 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, 00FFD700h, 1 + cmp BYTE PTR [bjOutcomeMsg], 0 + je draw_bj_controls + invoke DrawString8x8, 28, 188, OFFSET bjOutcomeMsg, 00FFFF00h + 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 PlayCasinoSound3D, 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, 00FFD700h, 3 + + ; 2.5D Rotating Wheel on Left + invoke DrawCircle, 85, 110, 65, 00102550h + invoke DrawCircle, 85, 110, 60, 00FFD700h + invoke DrawCircle, 85, 110, 52, 00101010h + invoke DrawCircle, 85, 110, 22, 00FFD700h ; 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 PlayCasinoSound3D, OFFSET soundRoundWin, 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 PlayCasinoSound3D, OFFSET soundRoundWin, 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 PlayCasinoSound3D, 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 PlayCasinoSound3D, OFFSET soundRoundWin, 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 PlayCasinoSound3D, OFFSET soundRoundWin, 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, 00FFFF00h, 2 +@@: + cmp roulBetType, 2 + jne @F + invoke DrawBoxBorder, 173, 58, 129, 32, 0, 00FFFF00h, 2 +@@: + cmp roulBetType, 3 + jne @F + invoke DrawBoxBorder, 173, 93, 129, 32, 0, 00FFFF00h, 2 +@@: + cmp roulBetType, 4 + jne @F + invoke DrawBoxBorder, 173, 128, 64, 30, 0, 00FFFF00h, 2 +@@: + cmp roulBetType, 5 + jne draw_ro_footer + invoke DrawBoxBorder, 238, 128, 64, 30, 0, 00FFFF00h, 2 + +draw_ro_footer: + invoke DrawBoxBorder, 20, 180, 280, 42, 00101015h, 00FFD700h, 1 + + cmp roulState, 2 + jne @F + invoke DrawString8x8, 28, 186, OFFSET textResult3D, 00FFD700h + invoke FormatNumber, roulWinningNum, OFFSET hudNumBuffer + invoke DrawString8x8, 85, 186, OFFSET hudNumBuffer, 00FFFF00h + 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, 00FFD700h, 3 + invoke DrawString8x8, 25, 20, OFFSET textShop3D, 00FFD700h + + invoke DrawBoxBorder, 20, 40, 280, 32, 001A1010h, 00FFFFFFh, 1 + invoke DrawString8x8, 28, 46, OFFSET textItem1_3D, 00FFFF00h + invoke DrawString8x8, 28, 58, OFFSET textShopHint3D, 00A0A0A0h + + invoke DrawBoxBorder, 20, 80, 280, 32, 001A1010h, 00FFFFFFh, 1 + invoke DrawString8x8, 28, 86, OFFSET textItem2_3D, 00FFFF00h + invoke DrawString8x8, 28, 98, OFFSET textShopHint3D, 00A0A0A0h + + invoke DrawBoxBorder, 20, 120, 280, 32, 001A1010h, 00FFFFFFh, 1 + invoke DrawString8x8, 28, 126, OFFSET textItem3_3D, 00FFFF00h + invoke DrawString8x8, 28, 138, OFFSET textShopHint3D, 00A0A0A0h + + invoke DrawBoxBorder, 20, 165, 280, 55, 00100A0Ah, 00FFD700h, 1 + invoke DrawString8x8, 28, 172, OFFSET textBank3D, 00FFD700h + invoke FormatNumber, bankroll, OFFSET hudNumBuffer + invoke DrawString8x8, 110, 172, OFFSET hudNumBuffer, 00FFFF00h + + 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 keyW:DWORD + mov esi, strPtr + xor ecx, ecx +keycap_len: + mov al, [esi+ecx] + test al, al + jz keycap_len_done + inc ecx + jmp keycap_len +keycap_len_done: + shl ecx, 3 + add ecx, 8 + mov keyW, ecx + + ; Drop shadow + mov eax, y + add eax, 2 + invoke DrawBox, x, eax, keyW, 13, 0008080Ch + + ; Border and Fill + cmp isActive, 0 + je keycap_inactive + mov eax, 00FFFF00h ; Bright Yellow active border + mov edx, 001B4B22h ; Casino Green active fill + mov ebx, 00FFFF00h ; Bright Yellow active text + jmp keycap_draw_box +keycap_inactive: + mov eax, 00606870h ; Slate inactive border + mov edx, 001A1C22h ; Charcoal inactive fill + mov ebx, 00D0D8E0h ; Silver inactive text + +keycap_draw_box: + push ebx + invoke DrawBoxBorder, x, y, keyW, 13, edx, eax, 1 + pop ebx + + ; Text label + mov eax, x + add eax, 4 + mov edx, y + add edx, 3 + invoke DrawString8x8, eax, edx, strPtr, ebx + + mov eax, keyW + add eax, 4 + ret +DrawKeycap3D ENDP + +DrawChipStack PROC uses ebx esi edi, x:DWORD, y:DWORD, chipCount:DWORD + mov edi, chipCount + xor esi, esi +chip_loop: + cmp esi, edi + jge chip_done + mov eax, esi + shl eax, 2 + mov edx, y + sub edx, eax + + ; Shadow + mov eax, x + add eax, 2 + mov ecx, edx + add ecx, 5 + invoke DrawBox, eax, ecx, 20, 2, 00061004h + + ; Red Clay Chip body with white rim + invoke DrawBoxBorder, x, edx, 24, 6, 00B81515h, 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 + mov ecx, edx + add ecx, 1 + invoke DrawBox, eax, ecx, 3, 4, 00FFFFFFh + + inc esi + jmp chip_loop +chip_done: + ret +DrawChipStack ENDP + +DrawDetailedCoin PROC uses ebx esi edi, cxVal:DWORD, cyVal:DWORD, rxVal:DWORD, ryVal:DWORD, outerColor:DWORD, innerColor:DWORD, reliefType:DWORD + local rxSq:DWORD + local rySq:DWORD + local rxRySq:DWORD + local threshSq:DWORD + local curDy:DWORD + local curDx:DWORD + local curX:DWORD + local curY:DWORD + + mov eax, rxVal + cmp eax, 0 + jle coin_draw_done + mov eax, ryVal + cmp eax, 0 + jle coin_draw_done + + mov eax, rxVal + imul eax, rxVal + mov rxSq, eax + + mov eax, ryVal + imul eax, ryVal + mov rySq, eax + + imul eax, rxSq + mov rxRySq, eax + + ; 3/4 threshold for rim bevel + mov ecx, 3 + imul eax, ecx + shr eax, 2 + mov threshSq, eax + + ; Scan rows + mov eax, ryVal + neg eax + mov curDy, eax +coin_row_loop: + mov eax, curDy + cmp eax, ryVal + jg coin_relief_check + + mov edx, cyVal + add edx, curDy + mov curY, edx + + ; Scan columns + mov eax, rxVal + neg eax + mov curDx, eax +coin_col_loop: + mov eax, curDx + cmp eax, rxVal + jg coin_col_next_row + + mov ecx, cxVal + add ecx, curDx + mov curX, ecx + + ; val = dx*dx*rySq + dy*dy*rxSq + mov eax, curDx + imul eax, curDx + imul eax, rySq + mov ebx, eax + + mov eax, curDy + imul eax, curDy + imul eax, rxSq + add eax, ebx + + cmp eax, rxRySq + ja coin_pixel_outside + + cmp eax, threshSq + jb coin_draw_inner + invoke DrawPixel, curX, curY, outerColor + jmp coin_pixel_outside +coin_draw_inner: + invoke DrawPixel, curX, curY, innerColor + +coin_pixel_outside: + inc curDx + jmp coin_col_loop + +coin_col_next_row: + inc curDy + jmp coin_row_loop + +coin_relief_check: + cmp rxVal, 14 + jl coin_draw_done + + cmp reliefType, 1 + je coin_draw_eagle + cmp reliefType, 2 + je coin_draw_numeral + jmp coin_draw_done + +coin_draw_eagle: + ; Imperial Eagle relief (Dark Gold 009A7A00h / Bright 00FFD700h) + mov eax, cxVal + sub eax, 3 + mov edx, cyVal + sub edx, 14 + invoke DrawBox, eax, edx, 7, 2, 009A7A00h + + mov eax, cxVal + sub eax, 4 + mov edx, cyVal + sub edx, 12 + invoke DrawBox, eax, edx, 9, 2, 009A7A00h + + mov eax, cxVal + sub eax, 2 + mov edx, cyVal + sub edx, 9 + invoke DrawBox, eax, edx, 5, 12, 009A7A00h + + mov eax, cxVal + sub eax, 1 + mov edx, cyVal + sub edx, 8 + invoke DrawBox, eax, edx, 3, 10, 00FFD700h + + mov eax, cxVal + sub eax, 10 + mov edx, cyVal + sub edx, 8 + invoke DrawBox, eax, edx, 7, 3, 009A7A00h + + mov eax, cxVal + sub eax, 13 + mov edx, cyVal + sub edx, 5 + invoke DrawBox, eax, edx, 10, 3, 009A7A00h + + mov eax, cxVal + sub eax, 11 + mov edx, cyVal + sub edx, 2 + invoke DrawBox, eax, edx, 7, 3, 009A7A00h + + mov eax, cxVal + add eax, 4 + mov edx, cyVal + sub edx, 8 + invoke DrawBox, eax, edx, 7, 3, 009A7A00h + + mov eax, cxVal + add eax, 4 + mov edx, cyVal + sub edx, 5 + invoke DrawBox, eax, edx, 10, 3, 009A7A00h + + mov eax, cxVal + add eax, 5 + mov edx, cyVal + sub edx, 2 + invoke DrawBox, eax, edx, 7, 3, 009A7A00h + + mov eax, cxVal + sub eax, 4 + mov edx, cyVal + add edx, 4 + invoke DrawBox, eax, edx, 9, 3, 009A7A00h + + mov eax, cxVal + sub eax, 3 + mov edx, cyVal + add edx, 7 + invoke DrawBox, eax, edx, 7, 3, 009A7A00h + jmp coin_draw_done + +coin_draw_numeral: + ; Roman numeral 'I' & laurel + mov eax, cxVal + sub eax, 5 + mov edx, cyVal + sub edx, 10 + invoke DrawBox, eax, edx, 11, 3, 009A7A00h + + mov eax, cxVal + sub eax, 2 + mov edx, cyVal + sub edx, 7 + invoke DrawBox, eax, edx, 5, 14, 009A7A00h + + mov eax, cxVal + sub eax, 1 + mov edx, cyVal + sub edx, 6 + invoke DrawBox, eax, edx, 3, 12, 00FFD700h + + mov eax, cxVal + sub eax, 6 + mov edx, cyVal + add edx, 7 + invoke DrawBox, eax, edx, 13, 3, 009A7A00h + + ; Laurel dots + mov eax, cxVal + sub eax, 12 + mov edx, cyVal + sub edx, 8 + invoke DrawBox, eax, edx, 2, 2, 009A7A00h + + mov eax, cxVal + add eax, 11 + mov edx, cyVal + sub edx, 8 + invoke DrawBox, eax, edx, 2, 2, 009A7A00h + + mov eax, cxVal + sub eax, 12 + mov edx, cyVal + invoke DrawBox, eax, edx, 2, 2, 009A7A00h + + mov eax, cxVal + add eax, 11 + mov edx, cyVal + invoke DrawBox, eax, edx, 2, 2, 009A7A00h + + mov eax, cxVal + sub eax, 12 + mov edx, cyVal + add edx, 8 + invoke DrawBox, eax, edx, 2, 2, 009A7A00h + + mov eax, cxVal + add eax, 11 + mov edx, cyVal + add edx, 8 + invoke DrawBox, eax, edx, 2, 2, 009A7A00h + +coin_draw_done: + ret +DrawDetailedCoin ENDP + +; ============================================================================== +; IN-ENGINE 2.5D MINI-GAME: COIN FLIP +; ============================================================================== +InitCoinGame PROC + call InitNativeCoin3D + ret +InitCoinGame ENDP + +HandleCoinInput PROC + call HandleNativeCoin3D + ret +; Retained legacy frame-count prototype, excluded from the executable. +IF 0 + cmp coin3d_state, 0 + je coin_handle_idle + cmp coin3d_state, 1 + je coin_handle_flipping + cmp coin3d_state, 2 + je coin_handle_result + ret + +coin_handle_idle: + invoke Pressed3D, 26h ; UP + test eax, eax + jnz coin_bet_up + invoke Pressed3D, 57h ; 'W' + test eax, eax + jnz coin_bet_up + invoke Pressed3D, 28h ; DOWN + test eax, eax + jnz coin_bet_down + invoke Pressed3D, 53h ; 'S' + test eax, eax + jnz coin_bet_down + invoke Pressed3D, 31h ; '1' + test eax, eax + jnz coin_pick_1 + invoke Pressed3D, 32h ; '2' + test eax, eax + jnz coin_pick_2 + invoke Pressed3D, 20h ; SPACE + test eax, eax + jnz coin_start_flip + ret + +coin_bet_up: + mov eax, coin3d_bet + add eax, 50 + cmp eax, bankroll + jle @F + mov eax, bankroll +@@: + cmp eax, 5000 + jle @F + mov eax, 5000 +@@: + mov coin3d_bet, eax + invoke PlayCasinoSound3D, OFFSET soundClick, 0, 1 + ret + +coin_bet_down: + mov eax, coin3d_bet + sub eax, 50 + cmp eax, 50 + jge @F + mov eax, 50 +@@: + mov coin3d_bet, eax + invoke PlayCasinoSound3D, OFFSET soundClick, 0, 1 + ret + +coin_pick_1: + mov coin3d_choice, 1 + invoke PlayCasinoSound3D, OFFSET soundClick, 0, 1 + ret + +coin_pick_2: + mov coin3d_choice, 2 + invoke PlayCasinoSound3D, OFFSET soundClick, 0, 1 + ret + +coin_start_flip: + mov eax, coin3d_bet + cmp eax, bankroll + jle @F + mov eax, bankroll + mov coin3d_bet, eax + test eax, eax + jz coin_done +@@: + mov eax, coin3d_bet + sub bankroll, eax + mov coin3d_state, 1 + mov coin3d_timer, 40 + invoke PlayCasinoSound3D, OFFSET soundCoin, 0, 1 + ret + +coin_handle_flipping: + dec coin3d_timer + cmp coin3d_timer, 0 + jg coin_done + invoke RandomRange3D, 2 + inc eax + mov coin3d_result, eax + mov edx, coin3d_choice + cmp eax, edx + jne coin_flip_lost + + ; Won! + inc coin3d_streak + mov eax, coin3d_bet + shl eax, 1 + add bankroll, eax + mov coin3d_win, eax + mov coin3d_state, 2 + invoke PlayCasinoSound3D, OFFSET soundCoinDing, 0, 1 + ret + +coin_flip_lost: + mov coin3d_streak, 0 + mov coin3d_win, 0 + mov coin3d_state, 2 + invoke PlayCasinoSound3D, OFFSET soundLose, 0, 1 + ret + +coin_handle_result: + invoke Pressed3D, 20h + test eax, eax + jz coin_done + mov coin3d_state, 0 + invoke PlayCasinoSound3D, OFFSET soundClick, 0, 1 +coin_done: + ret +ENDIF +HandleCoinInput ENDP + +RenderCoinGame PROC uses ebx esi edi + local cyVal:DWORD + local rxVal:DWORD + local kx:DWORD + + call RenderNativeCoin3D + ret +IF 0 + ; Background & Cabinet border + invoke DrawBox, 0, 0, 320, 240, 00140906h + invoke DrawBoxBorder, 6, 6, 308, 228, 0022150Fh, 00482E1Bh, 3 + + ; Header + invoke DrawBoxBorder, 20, 12, 280, 26, 001C100Ah, 00FFD700h, 2 + invoke DrawString8x8, 44, 21, OFFSET textCoinTitle, 00FFFF00h + + ; Corner rivets + invoke DrawBox, 12, 12, 3, 3, 00FFD700h + invoke DrawBox, 306, 12, 3, 3, 00FFD700h + invoke DrawBox, 12, 226, 3, 3, 00FFD700h + invoke DrawBox, 306, 226, 3, 3, 00FFD700h + + ; Status meters + invoke DrawBoxBorder, 20, 44, 110, 18, 000E1A0Ah, 00224B1Ah, 1 + invoke DrawString8x8, 24, 49, OFFSET textBankPrompt, 003CFF3Ch + invoke FormatNumber, bankroll, OFFSET hudNumBuffer + invoke DrawString8x8, 72, 49, OFFSET hudNumBuffer, 003CFF3Ch + + invoke DrawBoxBorder, 190, 44, 110, 18, 001A100Ah, 003A2814h, 1 + invoke DrawString8x8, 194, 49, OFFSET textBetPrompt, 00FFD700h + invoke FormatNumber, coin3d_bet, OFFSET hudNumBuffer + invoke DrawString8x8, 254, 49, OFFSET hudNumBuffer, 00FFD700h + + ; Left: Heads + cmp coin3d_choice, 1 + jne coin_left_inactive + invoke DrawBoxBorder, 20, 72, 76, 68, 00101828h, 00FFFF00h, 2 + invoke DrawString8x8, 30, 78, OFFSET textCoinSide1, 00FFFF00h + invoke DrawDetailedCoin, 58, 106, 14, 14, 00D0A000h, 00FFD700h, 1 + invoke DrawString8x8, 24, 126, OFFSET textCoinSelected, 003CFF3Ch + jmp coin_right_side +coin_left_inactive: + invoke DrawBoxBorder, 20, 72, 76, 68, 000A101Ch, 00404855h, 1 + invoke DrawString8x8, 30, 78, OFFSET textCoinSide1, 00D0D8E0h + invoke DrawDetailedCoin, 58, 106, 14, 14, 009A7A00h, 00D0A000h, 1 + +coin_right_side: + ; Right: Tails + cmp coin3d_choice, 2 + jne coin_right_inactive + invoke DrawBoxBorder, 224, 72, 76, 68, 00101828h, 00FFFF00h, 2 + invoke DrawString8x8, 234, 78, OFFSET textCoinSide2, 00FFFF00h + invoke DrawDetailedCoin, 262, 106, 14, 14, 00D0A000h, 00FFD700h, 2 + invoke DrawString8x8, 228, 126, OFFSET textCoinSelected, 003CFF3Ch + jmp coin_center_area +coin_right_inactive: + invoke DrawBoxBorder, 224, 72, 76, 68, 000A101Ch, 00404855h, 1 + invoke DrawString8x8, 234, 78, OFFSET textCoinSide2, 00D0D8E0h + invoke DrawDetailedCoin, 262, 106, 14, 14, 009A7A00h, 00D0A000h, 2 + +coin_center_area: + ; Center spotlight + invoke DrawCircle, 160, 110, 48, 00121620h + invoke DrawCircle, 160, 110, 44, 00FFD700h + invoke DrawCircle, 160, 110, 42, 000E141Eh + + cmp coin3d_state, 1 + je coin_render_flipping + cmp coin3d_state, 2 + je coin_render_result + + ; Idle coin + invoke DrawDetailedCoin, 160, 110, 26, 26, 00D0A000h, 00FFD700h, coin3d_choice + jmp coin_render_keys + +coin_render_flipping: + mov eax, coin3d_timer + and eax, 7 + movzx eax, byte ptr [coinRxAnimTable + eax] + mov rxVal, eax + invoke DrawDetailedCoin, 160, 110, rxVal, 26, 00D0A000h, 00FFD700h, 0 + invoke DrawString8x8, 88, 160, OFFSET textCoinFlipping, 00FFFF00h + jmp coin_render_keys + +coin_render_result: + invoke DrawDetailedCoin, 160, 110, 26, 26, 00D0A000h, 00FFD700h, coin3d_result + mov eax, coin3d_result + cmp eax, coin3d_choice + jne coin_render_loss_msg + + ; Win banner + invoke DrawBoxBorder, 44, 154, 232, 22, 000E141Eh, 003CFF3Ch, 1 + invoke DrawString8x8, 64, 161, OFFSET textCoinWin, 003CFF3Ch + invoke FormatNumber, coin3d_win, OFFSET hudNumBuffer + invoke DrawString8x8, 152, 161, OFFSET hudNumBuffer, 003CFF3Ch + jmp coin_render_keys + +coin_render_loss_msg: + invoke DrawBoxBorder, 44, 154, 232, 22, 000E141Eh, 00C81414h, 1 + invoke DrawString8x8, 114, 161, OFFSET textCoinLose, 00FF6464h + +coin_render_keys: + mov kx, 16 + xor eax, eax + cmp coin3d_choice, 1 + sete al + invoke DrawKeycap3D, kx, 192, OFFSET textCoinKey1, eax + add kx, eax + + xor eax, eax + cmp coin3d_choice, 2 + sete al + invoke DrawKeycap3D, kx, 192, OFFSET textCoinKey2, eax + add kx, eax + + invoke DrawKeycap3D, kx, 192, OFFSET textCoinKeySpace, 1 + add kx, eax + + invoke DrawKeycap3D, kx, 192, OFFSET textKeyEsc, 0 + ret +ENDIF +RenderCoinGame ENDP + +; ============================================================================== +; IN-ENGINE 2.5D MINI-GAME: CRAPS / DICE +; ============================================================================== +DrawCrapsDie PROC uses ebx esi edi, x:DWORD, y:DWORD, sizeVal:DWORD, valNum:DWORD + ; Drop shadow + mov eax, x + add eax, 3 + mov edx, y + add edx, sizeVal + invoke DrawBox, eax, edx, sizeVal, 3, 00081403h + + mov eax, x + add eax, sizeVal + mov edx, y + add edx, 3 + invoke DrawBox, eax, edx, 3, sizeVal, 00081403h + + ; Ivory body & bevel + invoke DrawBoxBorder, x, y, sizeVal, sizeVal, 00FAF4F0h, 00403535h, 1 + mov eax, x + inc eax + mov edx, y + inc edx + mov ecx, sizeVal + sub ecx, 2 + invoke DrawBox, eax, edx, ecx, 1, 00FFFFFFh + invoke DrawBox, eax, edx, 1, ecx, 00FFFFFFh + + ; Ruby pips (00C81515h) + mov eax, valNum + test al, 1 + jz @F + ; Center pip + mov eax, x + add eax, 18 + mov edx, y + add edx, 18 + invoke DrawCircle, eax, edx, 3, 00C81515h + dec eax + dec edx + invoke DrawPixel, eax, edx, 00FFFFFFh +@@: + cmp valNum, 2 + jl die_pips_done + mov eax, x + add eax, 9 + mov edx, y + add edx, 9 + invoke DrawCircle, eax, edx, 3, 00C81515h + mov eax, x + add eax, 27 + mov edx, y + add edx, 27 + invoke DrawCircle, eax, edx, 3, 00C81515h + + cmp valNum, 4 + jl die_pips_done + mov eax, x + add eax, 27 + mov edx, y + add edx, 9 + invoke DrawCircle, eax, edx, 3, 00C81515h + mov eax, x + add eax, 9 + mov edx, y + add edx, 27 + invoke DrawCircle, eax, edx, 3, 00C81515h + + cmp valNum, 6 + jl die_pips_done + mov eax, x + add eax, 9 + mov edx, y + add edx, 18 + invoke DrawCircle, eax, edx, 3, 00C81515h + mov eax, x + add eax, 27 + mov edx, y + add edx, 18 + invoke DrawCircle, eax, edx, 3, 00C81515h + +die_pips_done: + ret +DrawCrapsDie ENDP + +InitDiceGame PROC + mov dice3d_state, 0 + mov dice3d_timer, 0 + mov dice3d_win, 0 + ret +InitDiceGame ENDP + +HandleDiceInput PROC + cmp dice3d_state, 0 + je dice_handle_idle + cmp dice3d_state, 1 + je dice_handle_rolling + cmp dice3d_state, 2 + je dice_handle_result + ret + +dice_handle_idle: + invoke Pressed3D, 26h ; UP + test eax, eax + jnz dice_bet_up + invoke Pressed3D, 57h ; 'W' + test eax, eax + jnz dice_bet_up + invoke Pressed3D, 28h ; DOWN + test eax, eax + jnz dice_bet_down + invoke Pressed3D, 53h ; 'S' + test eax, eax + jnz dice_bet_down + invoke Pressed3D, 31h ; '1' + test eax, eax + jnz dice_pick_1 + invoke Pressed3D, 32h ; '2' + test eax, eax + jnz dice_pick_2 + invoke Pressed3D, 20h ; SPACE + test eax, eax + jnz dice_start_roll + ret + +dice_bet_up: + mov eax, dice3d_bet + add eax, 50 + cmp eax, bankroll + jle @F + mov eax, bankroll +@@: + cmp eax, 5000 + jle @F + mov eax, 5000 +@@: + mov dice3d_bet, eax + invoke PlayCasinoSound3D, OFFSET soundClick, 0, 1 + ret + +dice_bet_down: + mov eax, dice3d_bet + sub eax, 50 + cmp eax, 50 + jge @F + mov eax, 50 +@@: + mov dice3d_bet, eax + invoke PlayCasinoSound3D, OFFSET soundClick, 0, 1 + ret + +dice_pick_1: + mov dice3d_choice, 1 + invoke PlayCasinoSound3D, OFFSET soundClick, 0, 1 + ret + +dice_pick_2: + mov dice3d_choice, 2 + invoke PlayCasinoSound3D, OFFSET soundClick, 0, 1 + ret + +dice_start_roll: + mov eax, dice3d_bet + cmp eax, bankroll + jle @F + mov eax, bankroll + mov dice3d_bet, eax + test eax, eax + jz dice_done +@@: + mov eax, dice3d_bet + test eax, eax + jle dice_done + sub bankroll, eax + mov dice3d_state, 1 + mov dice3d_timer, 0 + invoke RandomRange3D, 6 + inc eax + mov dice3d_val1, eax + invoke RandomRange3D, 6 + inc eax + mov dice3d_val2, eax + invoke PlayCasinoSound3D, OFFSET soundDiceRoll, 0, 1 + call SaveProgress3D + ret + +dice_handle_rolling: + mov eax, deltaTime3D + add dice3d_timer, eax + cmp dice3d_timer, 1600 + jb dice_done + mov dice3d_timer, 1600 + mov eax, dice3d_val2 + mov edx, dice3d_val1 + add edx, eax + mov dice3d_sum, edx + + ; Parity check + mov eax, edx + and eax, 1 + jnz dice_sum_is_odd + ; Even + mov eax, 1 + jmp dice_check_win +dice_sum_is_odd: + mov eax, 2 + +dice_check_win: + cmp eax, dice3d_choice + jne dice_roll_lost + + ; Won! + mov eax, dice3d_bet + shl eax, 1 + add bankroll, eax + mov dice3d_win, eax + mov dice3d_state, 2 + invoke PlayCasinoSound3D, OFFSET soundRoundWin, 0, 1 + invoke NpcRecordRound3D,8,1 + call SaveProgress3D + ret + +dice_roll_lost: + mov dice3d_win, 0 + mov dice3d_state, 2 + invoke PlayCasinoSound3D, OFFSET soundLose, 0, 1 + invoke NpcRecordRound3D,8,0 + call SaveProgress3D + ret + +dice_handle_result: + invoke Pressed3D, 20h + test eax, eax + jz dice_done + mov dice3d_state, 0 + invoke PlayCasinoSound3D, OFFSET soundClick, 0, 1 +dice_done: + ret +HandleDiceInput ENDP + +RenderDiceGame PROC uses ebx esi edi + local kx:DWORD + + ; Mahogany frame & Deep Felt Green table + invoke DrawBox, 0, 0, 320, 240, 00140906h + invoke DrawBoxBorder, 6, 6, 308, 228, 000A3816h, 00FFD700h, 2 + + ; Header + invoke DrawBoxBorder, 20, 12, 280, 26, 00072E13h, 00FFD700h, 2 + invoke DrawString8x8, 116, 21, OFFSET textDiceTitle, 00FFFF00h + + ; Status + invoke DrawBoxBorder, 20, 44, 110, 18, 00072E13h, 001B4B22h, 1 + invoke DrawString8x8, 24, 49, OFFSET textBankPrompt, 003CFF3Ch + invoke FormatNumber, bankroll, OFFSET hudNumBuffer + invoke DrawString8x8, 72, 49, OFFSET hudNumBuffer, 003CFF3Ch + + invoke DrawBoxBorder, 190, 44, 110, 18, 00072E13h, 001B4B22h, 1 + invoke DrawString8x8, 194, 49, OFFSET textBetPrompt, 00FFD700h + invoke FormatNumber, dice3d_bet, OFFSET hudNumBuffer + invoke DrawString8x8, 258, 49, OFFSET hudNumBuffer, 00FFD700h + + ; [1] ×¨Ò + cmp dice3d_choice, 1 + jne dice_even_inactive + invoke DrawBoxBorder, 16, 70, 88, 48, 00072E13h, 00FFFF00h, 2 + invoke DrawString8x8, 30, 76, OFFSET textDiceEven, 00FFFF00h + invoke DrawString8x8, 22, 90, OFFSET textDiceEvenNums, 00FFD700h + invoke DrawString8x8, 26, 104, OFFSET textCoinSelected, 003CFF3Ch + jmp dice_odd_side +dice_even_inactive: + invoke DrawBoxBorder, 16, 70, 88, 48, 00072E13h, 001B4B22h, 1 + invoke DrawString8x8, 30, 76, OFFSET textDiceEven, 00D0D8E0h + invoke DrawString8x8, 22, 90, OFFSET textDiceEvenNums, 0080B090h + +dice_odd_side: + ; [2] ÍÅ×ÅÒ + cmp dice3d_choice, 2 + jne dice_odd_inactive + invoke DrawBoxBorder, 216, 70, 88, 48, 00072E13h, 00FFFF00h, 2 + invoke DrawString8x8, 226, 76, OFFSET textDiceOdd, 00FFFF00h + invoke DrawString8x8, 224, 90, OFFSET textDiceOddNums, 00FFD700h + invoke DrawString8x8, 226, 104, OFFSET textCoinSelected, 003CFF3Ch + jmp dice_center_cubes +dice_odd_inactive: + invoke DrawBoxBorder, 216, 70, 88, 48, 00072E13h, 001B4B22h, 1 + invoke DrawString8x8, 226, 76, OFFSET textDiceOdd, 00D0D8E0h + invoke DrawString8x8, 224, 90, OFFSET textDiceOddNums, 0080B090h + +dice_center_cubes: + call RenderDiceThrow3D + + cmp dice3d_state, 1 + je dice_render_rolling + cmp dice3d_state, 2 + je dice_render_result + jmp dice_render_keys + +dice_render_rolling: + invoke DrawString8x8, 76, 138, OFFSET textDiceRolling, 00FFFF00h + jmp dice_render_keys + +dice_render_result: + invoke DrawBoxBorder, 36, 130, 248, 36, 00072E13h, 00FFD700h, 1 + invoke DrawString8x8, 44, 135, OFFSET textDiceSumHdr, 00FFD700h + invoke FormatNumber, dice3d_val1, OFFSET hudNumBuffer + invoke DrawString8x8, 92, 135, OFFSET hudNumBuffer, 00FFFF00h + invoke DrawString8x8, 110, 135, OFFSET textDicePlus, 00FFD700h + invoke FormatNumber, dice3d_val2, OFFSET hudNumBuffer + invoke DrawString8x8, 126, 135, OFFSET hudNumBuffer, 00FFFF00h + invoke DrawString8x8, 144, 135, OFFSET textDiceEqual, 00FFD700h + invoke FormatNumber, dice3d_sum, OFFSET hudNumBuffer + invoke DrawString8x8, 168, 135, OFFSET hudNumBuffer, 00FFFF00h + + mov eax, dice3d_sum + and eax, 1 + jnz dice_render_odd_res + invoke DrawString8x8, 186, 135, OFFSET textDiceEvenResult, 003CFF3Ch + jmp dice_render_outcome +dice_render_odd_res: + invoke DrawString8x8, 186, 135, OFFSET textDiceOddResult, 003CFF3Ch + +dice_render_outcome: + mov eax, dice3d_win + test eax, eax + jz dice_render_loss_outcome + invoke DrawString8x8, 68, 150, OFFSET textDiceWin, 003CFF3Ch + invoke FormatNumber, dice3d_win, OFFSET hudNumBuffer + invoke DrawString8x8, 156, 150, OFFSET hudNumBuffer, 003CFF3Ch + invoke DrawString8x8, 188, 150, OFFSET textDiceWinMult, 003CFF3Ch + jmp dice_render_keys + +dice_render_loss_outcome: + invoke DrawString8x8, 116, 150, OFFSET textDiceLose, 00FF6464h + +dice_render_keys: + mov kx, 16 + xor eax, eax + cmp dice3d_choice, 1 + sete al + invoke DrawKeycap3D, kx, 192, OFFSET textDiceKey1, eax + add kx, eax + + xor eax, eax + cmp dice3d_choice, 2 + sete al + invoke DrawKeycap3D, kx, 192, OFFSET textDiceKey2, eax + add kx, eax + + invoke DrawKeycap3D, kx, 192, OFFSET textDiceKeySpace, 1 + add kx, eax + + invoke DrawKeycap3D, kx, 192, 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, 002E1E08h + invoke DrawCircle, cxVal, cyVal, 11, 00583A10h + invoke DrawCircle, cxVal, cyVal, 8, 008A581Ah + invoke DrawCircle, cxVal, cyVal, 6, 00D0B000h + invoke DrawCircle, cxVal, cyVal, 4, 00FFE000h + mov eax, cxVal + dec eax + mov edx, cyVal + dec edx + invoke DrawCircle, eax, edx, 2, 00FFFF80h + dec eax + dec edx + 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, 36 +@@: + mov liftY, eax + + ; Drop shadow + cmp isLifted, 0 + jne cup_shadow_lifted + mov eax, x + add eax, 6 + mov edx, y + add edx, 42 + invoke DrawBox, eax, edx, 36, 4, 0010040Ah + jmp cup_ball_check +cup_shadow_lifted: + mov eax, x + add eax, 10 + mov edx, y + add edx, 42 + invoke DrawBox, eax, edx, 28, 2, 001A0612h + +cup_ball_check: + cmp isLifted, 0 + je cup_body_draw + cmp hasBall, 0 + je cup_body_draw + mov eax, x + add eax, 24 + mov edx, y + add edx, 26 + invoke DrawGlowingOrb, eax, edx + +cup_body_draw: + ; Base pedestal + mov eax, x + add eax, 6 + mov edx, liftY + add edx, 36 + invoke DrawBoxBorder, eax, edx, 36, 6, 00301A22h, 00D0B000h, 1 + + ; Stem + mov eax, x + add eax, 18 + mov edx, liftY + add edx, 28 + invoke DrawBox, eax, edx, 12, 8, 00452533h + mov eax, x + add eax, 22 + invoke DrawBox, eax, edx, 4, 8, 006E4055h + + ; Goblet Bowl + mov eax, x + add eax, 8 + mov edx, liftY + add edx, 8 + invoke DrawBoxBorder, eax, edx, 32, 20, 00401E2Dh, 00FFD700h, 1 + + mov eax, x + add eax, 14 + mov edx, liftY + add edx, 10 + invoke DrawBox, eax, edx, 6, 16, 00703550h + mov eax, x + add eax, 17 + invoke DrawBox, eax, edx, 3, 16, 00A05078h + + ; Golden Rim + mov eax, x + add eax, 4 + mov edx, liftY + add edx, 2 + invoke DrawBoxBorder, eax, edx, 40, 7, 00200A15h, 00FFFF00h, 1 + mov eax, x + add eax, 12 + mov edx, liftY + add edx, 4 + invoke DrawBox, eax, edx, 16, 2, 00FFFF00h + + ; Skull face emblem + mov eax, x + add eax, 21 + mov edx, liftY + add edx, 12 + invoke DrawBox, eax, edx, 6, 5, 00FFD700h + mov eax, x + add eax, 22 + mov edx, liftY + add edx, 17 + invoke DrawBox, eax, edx, 4, 3, 00FFD700h + mov eax, x + add eax, 22 + mov edx, liftY + add edx, 14 + invoke DrawPixel, eax, edx, 00200A15h + mov eax, x + add eax, 24 + invoke DrawPixel, eax, edx, 00200A15h + + ; Cup number label + mov eax, x + add eax, 21 + mov edx, liftY + add edx, 24 + mov ecx, cupId + add ecx, '1' + invoke DrawChar8x8, eax, edx, ecx, 00FFFF00h + ret +DrawGothicCup ENDP + +InitSkullsGame PROC + mov skulls3d_state, 0 + mov skulls3d_timer, 0 + mov skulls3d_win, 0 + mov skulls3d_choice, 1 + mov skulls3d_cup0, 0 + mov skulls3d_cup1, 1 + mov skulls3d_cup2, 2 + invoke RandomRange3D, 3 + mov skulls3d_ballPos, eax + ret +InitSkullsGame ENDP + +FinalizeSkullsGuess PROC uses ebx + cmp skulls3d_state,3 + jne skulls_guess_done + mov eax, skulls3d_choice + cmp eax, skulls3d_ballPos + jne skulls_guess_wrong + + ; Correct! 3x payout + mov eax, skulls3d_bet + imul eax, 3 + add bankroll, eax + mov skulls3d_win, eax + mov skulls3d_state, 4 + invoke PlayCasinoSound3D, OFFSET soundRoundWin, 0, 1 + invoke NpcRecordRound3D,9,1 + call SaveProgress3D + ret + +skulls_guess_wrong: + mov skulls3d_win, 0 + mov skulls3d_state, 4 + invoke PlayCasinoSound3D, OFFSET soundLose, 0, 1 + invoke NpcRecordRound3D,9,0 + call SaveProgress3D +skulls_guess_done: + ret +FinalizeSkullsGuess ENDP + +HandleSkullsInput PROC + cmp skulls3d_state, 0 + je skulls_handle_idle + cmp skulls3d_state, 1 + je skulls_handle_show + cmp skulls3d_state, 2 + je skulls_handle_shuffle + cmp skulls3d_state, 3 + je skulls_handle_pick + cmp skulls3d_state, 4 + je skulls_handle_reveal + ret + +skulls_handle_idle: + invoke Pressed3D, 26h ; UP + test eax, eax + jnz skulls_bet_up + invoke Pressed3D, 57h ; 'W' + test eax, eax + jnz skulls_bet_up + invoke Pressed3D, 28h ; DOWN + test eax, eax + jnz skulls_bet_down + invoke Pressed3D, 53h ; 'S' + test eax, eax + jnz skulls_bet_down + invoke Pressed3D, 20h ; SPACE + test eax, eax + jnz skulls_start_game + ret + +skulls_bet_up: + mov eax, skulls3d_bet + add eax, 50 + cmp eax, bankroll + jle @F + mov eax, bankroll +@@: + cmp eax, 5000 + jle @F + mov eax, 5000 +@@: + mov skulls3d_bet, eax + invoke PlayCasinoSound3D, OFFSET soundClick, 0, 1 + ret + +skulls_bet_down: + mov eax, skulls3d_bet + sub eax, 50 + cmp eax, 50 + jge @F + mov eax, 50 +@@: + mov skulls3d_bet, eax + invoke PlayCasinoSound3D, OFFSET soundClick, 0, 1 + ret + +skulls_start_game: + mov eax, skulls3d_bet + cmp eax, bankroll + jle @F + mov eax, bankroll + mov skulls3d_bet, eax + test eax, eax + jz skulls_input_done +@@: + mov eax, skulls3d_bet + sub bankroll, eax + invoke RandomRange3D, 3 + mov skulls3d_ballPos, eax + mov skulls3d_cup0, 0 + mov skulls3d_cup1, 1 + mov skulls3d_cup2, 2 + + ; Pre-generate 3 dynamic swap pairs + 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 + invoke PlayCasinoSound3D, OFFSET soundClick, 0, 1 + ret + +skulls_handle_show: + inc skulls3d_timer + cmp skulls3d_timer, 45 + jl skulls_input_done + ; Transition to Phase 2: Active Shuffle Animation + mov skulls3d_state, 2 + mov skulls3d_timer, 0 + invoke PlayCasinoSound3D, OFFSET soundShuffle, 0, 1 + ret + +skulls_handle_shuffle: + inc skulls3d_timer + cmp skulls3d_timer, 60 + jl skulls_input_done + ; Transition to Phase 3: Pick cup + mov skulls3d_state, 3 + mov skulls3d_timer, 0 + ret + +skulls_handle_pick: + invoke Pressed3D, 31h ; '1' + test eax, eax + jnz skulls_pick_1 + invoke Pressed3D, 32h ; '2' + test eax, eax + jnz skulls_pick_2 + invoke Pressed3D, 33h ; '3' + test eax, eax + jnz skulls_pick_3 + ret + +skulls_pick_1: + mov skulls3d_choice, 0 + call FinalizeSkullsGuess + ret + +skulls_pick_2: + mov skulls3d_choice, 1 + call FinalizeSkullsGuess + ret + +skulls_pick_3: + mov skulls3d_choice, 2 + call FinalizeSkullsGuess + ret + +skulls_handle_reveal: + invoke Pressed3D, 20h + test eax, eax + jz skulls_input_done + mov skulls3d_state, 0 + invoke PlayCasinoSound3D, OFFSET soundClick, 0, 1 +skulls_input_done: + ret +HandleSkullsInput ENDP + +RenderSkullsGame PROC uses ebx esi edi + local kx:DWORD + 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 + + ; Mahogany & Gothic Purple table + invoke DrawBox, 0, 0, 320, 240, 00140906h + invoke DrawBoxBorder, 6, 6, 308, 228, 00300F22h, 00FFD700h, 2 + + ; Header + invoke DrawBoxBorder, 20, 12, 280, 26, 001A0812h, 00FFD700h, 2 + invoke DrawString8x8, 44, 21, OFFSET textSkullsTitle, 00FFFF00h + + ; Status + invoke DrawBoxBorder, 20, 44, 110, 18, 001A0812h, 00452033h, 1 + invoke DrawString8x8, 24, 49, OFFSET textBankPrompt, 003CFF3Ch + invoke FormatNumber, bankroll, OFFSET hudNumBuffer + invoke DrawString8x8, 72, 49, OFFSET hudNumBuffer, 003CFF3Ch + + invoke DrawBoxBorder, 190, 44, 110, 18, 001A0812h, 00452033h, 1 + invoke DrawString8x8, 194, 49, OFFSET textBetPrompt, 00FFD700h + invoke FormatNumber, skulls3d_bet, OFFSET hudNumBuffer + invoke DrawString8x8, 254, 49, OFFSET hudNumBuffer, 00FFD700h + + ; Phase Prompts + cmp skulls3d_state, 0 + jne @F + invoke DrawString8x8, 56, 62, OFFSET textSkullsPhase0, 00FFD700h + jmp skulls_draw_idle_cups +@@: + cmp skulls3d_state, 1 + jne @F + invoke DrawString8x8, 56, 62, OFFSET textSkullsPhase1, 00FFFF00h + jmp skulls_draw_phase1_cups +@@: + cmp skulls3d_state, 2 + jne @F + invoke DrawString8x8, 44, 62, OFFSET textSkullsPhase2, 00FFFF00h + jmp skulls_draw_animated_cups +@@: + cmp skulls3d_state, 3 + jne @F + invoke DrawString8x8, 28, 62, OFFSET textSkullsPhase3, 00FFFF00h + jmp skulls_draw_idle_cups +@@: + ; Phase 4: Reveal outcome + mov eax, skulls3d_win + test eax, eax + jz skulls_reveal_loss_text + invoke DrawString8x8, 40, 62, OFFSET textSkullsWin, 003CFF3Ch + invoke FormatNumber, skulls3d_win, OFFSET hudNumBuffer + invoke DrawString8x8, 136, 62, OFFSET hudNumBuffer, 003CFF3Ch + invoke DrawString8x8, 168, 62, OFFSET textSkullsWinMult, 003CFF3Ch + jmp skulls_draw_reveal_cups + +skulls_reveal_loss_text: + invoke DrawString8x8, 40, 62, OFFSET textSkullsLose, 00FF6464h + jmp skulls_draw_reveal_cups + +skulls_draw_idle_cups: + ; Draw resting cups at static slots: Slot 0 (X=36), Slot 1 (X=136), Slot 2 (X=236) + invoke DrawGothicCup, 36, 114, skulls3d_cup0, 0, 0 + invoke DrawGothicCup, 136, 114, skulls3d_cup1, 0, 0 + invoke DrawGothicCup, 236, 114, skulls3d_cup2, 0, 0 + jmp skulls_render_controls + +skulls_draw_phase1_cups: + ; Draw with golden ball showing under starting cup + mov ebx, 0 + mov edx, 0 + cmp skulls3d_ballPos, 0 + jne @F + mov ebx, 1 + mov edx, 1 +@@: + invoke DrawGothicCup, 36, 114, skulls3d_cup0, ebx, edx + + mov ebx, 0 + mov edx, 0 + cmp skulls3d_ballPos, 1 + jne @F + mov ebx, 1 + mov edx, 1 +@@: + invoke DrawGothicCup, 136, 114, skulls3d_cup1, ebx, edx + + mov ebx, 0 + mov edx, 0 + cmp skulls3d_ballPos, 2 + jne @F + mov ebx, 1 + mov edx, 1 +@@: + invoke DrawGothicCup, 236, 114, skulls3d_cup2, ebx, edx + jmp skulls_render_controls + +skulls_draw_animated_cups: + ; 60 frames = 3 passes of 20 frames + 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 + +pass_0: + dec eax + mov passTick, eax + mov eax, skulls3d_swapPair0 + mov curPair, eax + jmp setup_pass + +pass_1: + sub eax, 21 + mov passTick, eax + mov eax, skulls3d_swapPair1 + mov curPair, eax + +setup_pass: + ; curPair determines swap pair: + ; 0: swap slot 0 (X=36) and slot 1 (X=136) + ; 1: swap slot 1 (X=136) and slot 2 (X=236) + ; 2: swap slot 0 (X=36) and slot 2 (X=236) + cmp curPair, 1 + je pair_1 + cmp curPair, 2 + je pair_2 + mov swapSlotA, 0 + mov swapSlotB, 1 + mov xA, 36 + mov xB, 136 + jmp calc_coords +pair_1: + mov swapSlotA, 1 + mov swapSlotB, 2 + mov xA, 136 + mov xB, 236 + jmp calc_coords +pair_2: + mov swapSlotA, 0 + mov swapSlotB, 2 + mov xA, 36 + mov xB, 236 + +calc_coords: + ; distX = xB - xA + mov eax, xB + sub eax, xA + mov distX, eax + + ; dxVal = (distX * passTick) / 20 + mov eax, distX + imul eax, passTick + xor edx, edx + mov ecx, 20 + div ecx + mov dxVal, eax + + ; curXA = xA + dxVal + mov eax, xA + add eax, dxVal + mov curXA, eax + + ; curXB = xB - dxVal + mov eax, xB + sub eax, dxVal + mov curXB, eax + + ; archY = (passTick * (20 - passTick)) / 10 + mov eax, passTick + mov ecx, 20 + sub ecx, eax + imul eax, ecx + xor edx, edx + mov ecx, 10 + div ecx + mov archY, eax + + ; Cup A hops UP: 114 - archY + mov eax, 114 + sub eax, archY + mov curYA, eax + + ; Cup B hops DOWN: 114 + archY + mov eax, 114 + add eax, archY + mov curYB, eax + + ; Check if pass ended (frame 19): swap ball position and cups + cmp passTick, 19 + jne draw_active_shuffle + + ; Swap ball position if involved + mov eax, skulls3d_ballPos + cmp eax, swapSlotA + jne check_ball_b + mov edx, swapSlotB + mov skulls3d_ballPos, edx + jmp swap_slot_identities +check_ball_b: + cmp eax, swapSlotB + jne swap_slot_identities + mov edx, swapSlotA + mov skulls3d_ballPos, edx + +swap_slot_identities: + cmp curPair, 1 + je swap_ids_1_2 + cmp curPair, 2 + je swap_ids_0_2 + ; swap 0 and 1 + mov eax, skulls3d_cup0 + xchg eax, skulls3d_cup1 + mov skulls3d_cup0, eax + jmp swap_sound_tick +swap_ids_1_2: + mov eax, skulls3d_cup1 + xchg eax, skulls3d_cup2 + mov skulls3d_cup1, eax + jmp swap_sound_tick +swap_ids_0_2: + mov eax, skulls3d_cup0 + xchg eax, skulls3d_cup2 + mov skulls3d_cup0, eax + +swap_sound_tick: + invoke PlayCasinoSound3D, OFFSET soundShuffle, 0, 1 + +draw_active_shuffle: + ; Draw stationary cup + cmp curPair, 1 + je draw_stat_cup0 + cmp curPair, 2 + je draw_stat_cup1 + ; Stationary cup is slot 2 (X=236) + invoke DrawGothicCup, 236, 114, skulls3d_cup2, 0, 0 + jmp draw_moving_cups +draw_stat_cup0: + ; Stationary cup is slot 0 (X=36) + invoke DrawGothicCup, 36, 114, skulls3d_cup0, 0, 0 + jmp draw_moving_cups +draw_stat_cup1: + ; Stationary cup is slot 1 (X=136) + invoke DrawGothicCup, 136, 114, skulls3d_cup1, 0, 0 + +draw_moving_cups: + ; Moving Cup A and Moving Cup B + cmp curPair, 1 + je ids_pair_1 + cmp curPair, 2 + je ids_pair_2 + mov eax, skulls3d_cup0 + mov ebx, skulls3d_cup1 + jmp draw_the_pair +ids_pair_1: + mov eax, skulls3d_cup1 + mov ebx, skulls3d_cup2 + jmp draw_the_pair +ids_pair_2: + mov eax, skulls3d_cup0 + mov ebx, skulls3d_cup2 + +draw_the_pair: + push ebx + invoke DrawGothicCup, curXA, curYA, eax, 0, 0 + pop ebx + invoke DrawGothicCup, curXB, curYB, ebx, 0, 0 + jmp skulls_render_controls + +skulls_draw_reveal_cups: + ; Reveal Phase: lift chosen cup and lift actual ball cup if different + ; Slot 0 + mov ebx, 0 + mov edx, 0 + cmp skulls3d_choice, 0 + je slot0_is_lifted + cmp skulls3d_ballPos, 0 + jne @F +slot0_is_lifted: + mov ebx, 1 + cmp skulls3d_ballPos, 0 + sete dl +@@: + invoke DrawGothicCup, 36, 114, skulls3d_cup0, ebx, edx + + ; Slot 1 + mov ebx, 0 + mov edx, 0 + cmp skulls3d_choice, 1 + je slot1_is_lifted + cmp skulls3d_ballPos, 1 + jne @F +slot1_is_lifted: + mov ebx, 1 + cmp skulls3d_ballPos, 1 + sete dl +@@: + invoke DrawGothicCup, 136, 114, skulls3d_cup1, ebx, edx + + ; Slot 2 + mov ebx, 0 + mov edx, 0 + cmp skulls3d_choice, 2 + je slot2_is_lifted + cmp skulls3d_ballPos, 2 + jne @F +slot2_is_lifted: + mov ebx, 1 + cmp skulls3d_ballPos, 2 + sete dl +@@: + invoke DrawGothicCup, 236, 114, skulls3d_cup2, ebx, edx + +skulls_render_controls: + ; Cup selection slot labels [1], [2], [3] + invoke DrawString8x8, 54, 168, OFFSET textSkullsKey1, 00D0D8E0h + invoke DrawString8x8, 150, 168, OFFSET textSkullsKey2, 00D0D8E0h + invoke DrawString8x8, 250, 168, OFFSET textSkullsKey3, 00D0D8E0h + + ; Keycaps + mov kx, 16 + xor eax, eax + cmp skulls3d_state, 3 + je key1_active + cmp skulls3d_choice, 0 + sete al + jmp draw_key1 +key1_active: + mov eax, 1 +draw_key1: + invoke DrawKeycap3D, kx, 192, OFFSET textSkullsKey1, eax + add kx, eax + + xor eax, eax + cmp skulls3d_state, 3 + je key2_active + cmp skulls3d_choice, 1 + sete al + jmp draw_key2 +key2_active: + mov eax, 1 +draw_key2: + invoke DrawKeycap3D, kx, 192, OFFSET textSkullsKey2, eax + add kx, eax + + xor eax, eax + cmp skulls3d_state, 3 + je key3_active + cmp skulls3d_choice, 2 + sete al + jmp draw_key3 +key3_active: + mov eax, 1 +draw_key3: + invoke DrawKeycap3D, kx, 192, OFFSET textSkullsKey3, eax + add kx, eax + + xor eax, eax + cmp skulls3d_state, 0 + je start_active + cmp skulls3d_state, 4 + je start_active + jmp draw_start_key +start_active: + mov eax, 1 +draw_start_key: + invoke DrawKeycap3D, kx, 192, OFFSET textSkullsKeySpace, eax + add kx, eax + + invoke DrawKeycap3D, kx, 192, OFFSET textKeyEsc, 0 + ret +RenderSkullsGame ENDP + +InitSkillGame PROC + mov skill3d_state, 0 + mov skill3d_timer, 0 + mov skill3d_hits, 0 + mov skill3d_misses, 0 + mov skill3d_needle, 55 + mov skill3d_speed, 4 + mov skill3d_dir, 1 + mov skill3d_last_result, 0 + mov skill3d_win_amount, 0 + + ; Randomize initial zone: 80 + RandomRange(90) -> 80..170 + invoke RandomRange3D, 90 + add eax, 80 + mov skill3d_zone_start, eax + + ; Great zone: start + 20 + RandomRange(12) + invoke RandomRange3D, 12 + add eax, skill3d_zone_start + add eax, 20 + mov skill3d_great_start, eax + ret +InitSkillGame ENDP + +HandleSkillInput PROC uses ebx esi + mov eax, skill3d_state + cmp eax, 0 + je skill_handle_ready + cmp eax, 1 + je skill_handle_active + cmp eax, 2 + je skill_handle_round_wait + cmp eax, 3 + je skill_handle_round_wait + cmp eax, 4 + je skill_handle_end_wait + cmp eax, 5 + je skill_handle_end_wait + ret + +skill_handle_ready: + invoke Pressed3D, 26h ; UP + test eax, eax + jnz skill_bet_up + invoke Pressed3D, 57h ; 'W' + test eax, eax + jnz skill_bet_up + invoke Pressed3D, 28h ; DOWN + test eax, eax + jnz skill_bet_down + invoke Pressed3D, 53h ; 'S' + test eax, eax + jnz skill_bet_down + jmp skill_check_start + +skill_bet_up: + mov eax, skill3d_bet + add eax, 50 + cmp eax, bankroll + jle @F + mov eax, bankroll +@@: + cmp eax, 5000 + jle @F + mov eax, 5000 +@@: + mov skill3d_bet, eax + invoke PlayCasinoSound3D, OFFSET soundClick, 0, 1 + ret + +skill_bet_down: + mov eax, skill3d_bet + sub eax, 50 + cmp eax, 50 + jge @F + mov eax, 50 +@@: + mov skill3d_bet, eax + invoke PlayCasinoSound3D, OFFSET soundClick, 0, 1 + ret + +skill_check_start: + invoke Pressed3D, 20h ; SPACE + test eax, eax + jz skill_input_done + + ; Deduct bet on game start if beginning of run + mov eax, skill3d_hits + or eax, skill3d_misses + jnz @F + mov eax, skill3d_bet + cmp eax, bankroll + jle skill_has_funds + mov eax, bankroll + mov skill3d_bet, eax + test eax, eax + jz skill_input_done +skill_has_funds: + mov eax, skill3d_bet + sub bankroll, eax +@@: + mov skill3d_state, 1 + mov skill3d_needle, 55 + mov skill3d_dir, 1 + invoke PlayCasinoSound3D, OFFSET soundClick, 0, 1 + ret + +skill_handle_active: + ; Move needle smoothly + mov eax, skill3d_needle + mov edx, skill3d_speed + cmp skill3d_dir, 1 + je skill_move_right + sub eax, edx + cmp eax, 52 + jge skill_update_needle + mov eax, 52 + mov skill3d_dir, 1 + jmp skill_update_needle +skill_move_right: + add eax, edx + cmp eax, 268 + jle skill_update_needle + mov eax, 268 + mov skill3d_dir, -1 +skill_update_needle: + mov skill3d_needle, eax + + ; Check SPACE pressed (Reaction Hit Attempt!) + invoke Pressed3D, 20h + test eax, eax + jz skill_input_done + + ; Is needle in Great Sweet Spot? + mov eax, skill3d_needle + mov edx, skill3d_great_start + cmp eax, edx + jl check_success_zone + add edx, skill3d_great_width + cmp eax, edx + jg check_success_zone + + ; GREAT HIT! + mov skill3d_last_result, 2 + add skill3d_hits, 2 + mov skill3d_state, 2 + mov skill3d_timer, 40 + invoke PlayCasinoSound3D, OFFSET soundSkillPerfect, 0, 1 + jmp skill_check_finish_round + +check_success_zone: + mov eax, skill3d_needle + mov edx, skill3d_zone_start + cmp eax, edx + jl skill_was_miss + add edx, skill3d_zone_width + cmp eax, edx + jg skill_was_miss + + ; NORMAL HIT! + mov skill3d_last_result, 1 + inc skill3d_hits + mov skill3d_state, 2 + mov skill3d_timer, 40 + invoke PlayCasinoSound3D, OFFSET soundSkillHit, 0, 1 + jmp skill_check_finish_round + +skill_was_miss: + ; MISS! + mov skill3d_last_result, 0 + inc skill3d_misses + mov skill3d_state, 3 + mov skill3d_timer, 45 + invoke PlayCasinoSound3D, OFFSET soundSkillMiss, 0, 1 + +skill_check_finish_round: + cmp skill3d_hits, 5 + jge skill_game_escaped + cmp skill3d_misses, 3 + jge skill_game_lost + ret + +skill_game_escaped: + mov skill3d_state, 4 + mov skill3d_timer, 0 + ; Payout: 3x total return (+$2x bet profit) + mov eax, skill3d_bet + imul eax, 3 + add bankroll, eax + mov eax, skill3d_bet + shl eax, 1 + mov skill3d_win_amount, eax + invoke NpcRecordRound3D,10,1 + call SaveProgress3D + invoke PlayCasinoSound3D, OFFSET soundRoundWin, 0, 1 + ret + +skill_game_lost: + mov skill3d_state, 5 + mov skill3d_timer, 0 + invoke NpcRecordRound3D,10,0 + call SaveProgress3D + invoke PlayCasinoSound3D, OFFSET soundLose, 0, 1 + ret + +skill_handle_round_wait: + dec skill3d_timer + cmp skill3d_timer, 0 + jg skill_input_done + + ; Next round setup + invoke RandomRange3D, 90 + add eax, 80 + mov skill3d_zone_start, eax + + invoke RandomRange3D, 12 + add eax, skill3d_zone_start + add eax, 20 + mov skill3d_great_start, eax + + mov eax, skill3d_hits + shr eax, 1 + add eax, 4 + mov skill3d_speed, eax + mov skill3d_state, 1 + ret + +skill_handle_end_wait: + invoke Pressed3D, 20h + test eax, eax + jz skill_input_done + call InitSkillGame + ret + +skill_input_done: + ret +HandleSkillInput ENDP + +RenderSkillGame PROC uses ebx esi edi + local kx:DWORD + local tx:DWORD + + ; Industrial Steel bezel + invoke DrawBox, 0, 0, 320, 240, 00121416h + invoke DrawBoxBorder, 6, 6, 308, 228, 001A1D20h, 00FFD700h, 2 + + ; Header + invoke DrawBoxBorder, 20, 12, 280, 26, 00121418h, 00FFD700h, 2 + invoke DrawString8x8, 40, 21, OFFSET textSkillTitle, 00FFFF00h + + ; Status + invoke DrawBoxBorder, 20, 44, 110, 18, 00121418h, 002A3540h, 1 + invoke DrawString8x8, 24, 49, OFFSET textBankPrompt, 003CFF3Ch + invoke FormatNumber, bankroll, OFFSET hudNumBuffer + invoke DrawString8x8, 72, 49, OFFSET hudNumBuffer, 003CFF3Ch + + invoke DrawBoxBorder, 190, 44, 110, 18, 00121418h, 002A3540h, 1 + invoke DrawString8x8, 194, 49, OFFSET textBetPrompt, 00FFD700h + invoke FormatNumber, skill3d_bet, OFFSET hudNumBuffer + invoke DrawString8x8, 254, 49, OFFSET hudNumBuffer, 00FFD700h + + ; Survivor Progress + invoke DrawString8x8, 24, 70, OFFSET textSkillHitsHdr, 003CFF3Ch + invoke FormatNumber, skill3d_hits, OFFSET hudNumBuffer + invoke DrawString8x8, 64, 70, OFFSET hudNumBuffer, 003CFF3Ch + + invoke DrawString8x8, 180, 70, OFFSET textSkillMissHdr, 00FF6464h + invoke FormatNumber, skill3d_misses, OFFSET hudNumBuffer + invoke DrawString8x8, 240, 70, OFFSET hudNumBuffer, 00FF6464h + + ; Dial Frame (Track: X=50..270, Y=102..134) + invoke DrawBoxBorder, 50, 102, 220, 32, 000F1114h, 00404855h, 2 + + ; Calibrated ticks + mov tx, 60 +skill_ticks_loop: + cmp tx, 260 + jge skill_draw_zones + invoke DrawBox, tx, 104, 1, 6, 00303845h + invoke DrawBox, tx, 126, 1, 6, 00303845h + add tx, 12 + jmp skill_ticks_loop + +skill_draw_zones: + ; Normal Success Zone (Green) + invoke DrawBoxBorder, skill3d_zone_start, 106, skill3d_zone_width, 24, 00155020h, 003CFF3Ch, 1 + + ; Great Zone (Gold) + invoke DrawBoxBorder, skill3d_great_start, 106, skill3d_great_width, 24, 00FFD700h, 00FFFF00h, 1 + + ; Pointer / Needle at skill3d_needle + mov eax, skill3d_needle + dec eax + invoke DrawBox, eax, 98, 3, 40, 00FFFFFFh + mov eax, skill3d_needle + sub eax, 2 + invoke DrawBox, eax, 96, 5, 2, 00FF3030h + invoke DrawBox, eax, 138, 5, 2, 00FF3030h + + ; Center prompts / outcome + cmp skill3d_state, 0 + jne @F + invoke DrawString8x8, 52, 150, OFFSET textSkillReadyMsg, 00FFD700h + invoke DrawString8x8, 76, 166, OFFSET textSkillPrompt, 00D0D8E0h + jmp skill_render_keys +@@: + cmp skill3d_state, 1 + jne @F + invoke DrawString8x8, 76, 150, OFFSET textSkillPrompt, 00FFFF00h + jmp skill_render_keys +@@: + cmp skill3d_state, 2 + jne @F + cmp skill3d_last_result, 2 + jne skill_normal_hit_text + invoke DrawString8x8, 36, 150, OFFSET textSkillGreatMsg, 00FFFF00h + jmp skill_render_keys +skill_normal_hit_text: + invoke DrawString8x8, 64, 150, OFFSET textSkillHitMsg, 003CFF3Ch + jmp skill_render_keys +@@: + cmp skill3d_state, 3 + jne @F + invoke DrawString8x8, 88, 150, OFFSET textSkillMissMsg, 00FF6464h + jmp skill_render_keys +@@: + cmp skill3d_state, 4 + jne @F + invoke DrawString8x8, 48, 150, OFFSET textSkillEscape, 003CFF3Ch + invoke FormatNumber, skill3d_win_amount, OFFSET hudNumBuffer + invoke DrawString8x8, 240, 150, OFFSET hudNumBuffer, 003CFF3Ch + invoke DrawString8x8, 64, 166, OFFSET textSkullsAgain, 00FFD700h + jmp skill_render_keys +@@: + invoke DrawString8x8, 44, 150, OFFSET textSkillLost, 00FF6464h + invoke DrawString8x8, 64, 166, OFFSET textSkullsAgain, 00FFD700h + +skill_render_keys: + mov kx, 16 + invoke DrawKeycap3D, kx, 192, OFFSET textSkillKeySpace, 1 + add kx, eax + + invoke DrawKeycap3D, kx, 192, OFFSET textSkillKeyBet, 0 + add kx, eax + + invoke DrawKeycap3D, kx, 192, OFFSET textKeyEsc, 0 + ret +RenderSkillGame 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: + call CheckHallInteractions3D + 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: + invoke PlayCasinoSound3D, 0, 0, 0 + call InitSounds + ; Çàïóñê îðèãèíàëüíîé èãðû! + call pGameProc + call CloseLegacySounds3D + + ; Çàêðûâàåì êîíñîëü + 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 + call TriggerHallInteraction3D + test eax, eax + jnz trigger_done + 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 PlayCasinoSound3D, OFFSET soundClick, 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 + call InitNativeBlackjack3D + mov engineMode, MODE_BLACKJACK + ret + +check_target_poker: + cmp eax, INTERACT_POKER + jne check_target_durak + call InitNativePoker3D + test eax, eax + jz target_unported + mov engineMode, MODE_POKER + ret + +check_target_durak: + cmp eax, INTERACT_DURAK + jne check_target_slots777 + call InitNativeDurak3D + mov engineMode, MODE_DURAK + ret + +check_target_slots777: + cmp eax, INTERACT_SLOTS_777 + jne check_target_slots_clover + call InitNativeSlots3D + test eax,eax + jz target_unported + mov engineMode,MODE_SLOTS + ret + +check_target_slots_clover: + cmp eax, INTERACT_SLOTS_CLOVER + jne check_target_roulette + call InitNativeClover3D + test eax,eax + jz target_unported + mov engineMode,MODE_CLOVER + ret + +check_target_roulette: + cmp eax, INTERACT_ROULETTE + jne check_target_dice + call InitNativeWheel3D + mov engineMode, MODE_ROULETTE + 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 + call InitSkillGame + mov engineMode, MODE_SKILL + ret + +check_target_buckshot: + cmp eax, INTERACT_BUCKSHOT + jne check_target_rr + call InitBuckshot3D + mov engineMode, MODE_BUCKSHOT + ret + +check_target_rr: + cmp eax, INTERACT_RUSSIAN_ROULETTE + jne check_target_online_rr + call InitRussianGame3D + test eax, eax + jz @F + mov engineMode, MODE_RUSSIAN +@@: + ret + +check_target_online_rr: + cmp eax, INTERACT_ONLINE_RR + jne check_target_umamusume + call BeginUnavailable3D + ret + +check_target_umamusume: + cmp eax, INTERACT_UMAMUSUME + jne check_target_hell + call BeginUnavailable3D + ret + +check_target_hell: + cmp eax, INTERACT_HELL_TOWER + jne check_target_shop + call BeginUnavailable3D + ret + +check_target_shop: + cmp eax, INTERACT_SHOP + jne check_target_atm + call BeginMerchant3D + 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 + call BeginUnavailable3D + ret + +check_target_observer: + cmp eax, INTERACT_OBSERVER + jne target_unported + call BeginUnavailable3D + ret + +target_unported: + call BeginUnavailable3D +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 LoadDisplaySettings3D + call Create3DWindow + test eax, eax + jz init_failed + call LoadTextures3D + test eax, eax + jz init_failed + + call InitializeCasinoSprites3D + + ; Initialize raycasting worker thread and sync events + invoke CreateEventA, 0, 0, 0, 0 + mov hRaycastStartEvent, eax + invoke CreateEventA, 0, 0, 0, 0 + mov hRaycastDoneEvent, eax + mov bRaycastQuit, 0 + invoke CreateThread, 0, 65536, OFFSET RaycastWorkerProc, 0, 0, ADDR raycastThreadId + mov hRaycastThread, eax + + call InitHall3D + call BeginStartup3D + call RenderStartup3D + invoke ShowWindow, h3DWnd, SW_SHOW + invoke UpdateWindow, h3DWnd + invoke SetForegroundWindow, h3DWnd + mov eax, 1 + jmp init_return +init_failed: + xor eax, eax +init_return: + pop edi + pop esi + pop ebx + ret +Init3DEngine ENDP + +InitializeCasinoSprites3D PROC +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 + ret +InitializeCasinoSprites3D ENDP + +include src_graphics\audio_code.inc +include src_graphics\dice_animation.inc +include src_graphics\russian_roulette.inc +include src_graphics\startup_code.inc +include src_graphics\card_table_assets.inc +include src_graphics\poker_evaluator.inc +include src_graphics\native_poker.inc +include src_graphics\native_blackjack.inc +include src_graphics\native_durak.inc +include src_graphics\card_tables_render.inc +include src_graphics\durak_render.inc +include src_graphics\card_table_input.inc +include src_graphics\scene_animation.inc +include src_graphics\native_slots.inc +include src_graphics\native_clover.inc +include src_graphics\native_coin.inc +include src_graphics\graphic_profiles.inc +include src_graphics\city_arrival_scene.inc +include src_graphics\arrival_scene.inc +include src_graphics\merchant_scene.inc +include src_graphics\hall_scene.inc +include src_graphics\npc_mind.inc +include src_graphics\npc_life.inc +include src_graphics\npc_contracts.inc +include src_graphics\native_wheel.inc +include src_graphics\billiards.inc +include src_graphics\buckshot.inc +include src_graphics\russian_table.inc +include src_graphics\unavailable.inc + +; --- 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_INTRO + jne @F + call FinishStartup3D + jmp engine_tick +@@: + cmp engineMode, MODE_ARRIVAL + jne @F + call ArrivalEscape3D + jmp engine_tick +@@: + cmp engineMode, MODE_WALK + jne leave_table + xor paused3D, 1 + jmp engine_tick +leave_table: + call CardTableEscape3D + test eax, eax + jnz engine_tick + call TableBusy3D + test eax, eax + jz leave_idle_table + xor paused3D, 1 + call ClearKeys3D + jmp engine_tick +leave_idle_table: + mov paused3D, 0 + mov engineMode, MODE_WALK + call ClearKeys3D + invoke PlayCasinoSound3D, 0, 0, 0 +engine_tick: + cmp paused3D, 0 + jne draw_pause + mov eax, deltaTime3D + add animationClock3D, eax + cmp engineMode, MODE_INTRO + jne check_arrival_mode + call HandleStartupInput3D + cmp engineMode, MODE_INTRO + jne check_arrival_mode + call RenderStartup3D + jmp present_frame +check_arrival_mode: + cmp engineMode, MODE_ARRIVAL + jne check_walk_mode + call HandleArrival3D + cmp engineMode, MODE_WALK + je check_walk_mode + call RenderArrival3D + jmp present_frame +check_walk_mode: + cmp engineMode, MODE_WALK + jne check_slots_mode + call UpdateHall3D + call UpdateCamera3D + call CheckInteractions + call HandlePlayerInput + call UpdateCamera3D + call RenderCeilingAndFloor + call RenderWalls + call PrepareCityDepth3D + call RenderSprites + call RenderHall3D + call RenderHUD + call RenderMinimap + jmp present_frame +check_slots_mode: + cmp engineMode,MODE_CLOVER + jne @F + call HandleNativeClover3D + call RenderNativeClover3D + jmp present_frame +@@: + cmp engineMode,MODE_NPC_DIALOG + jne @F + call HandleNpcDialog3D + call RenderNpcDialog3D + jmp present_frame +@@: + cmp engineMode, MODE_UNAVAILABLE + jne @F + call HandleUnavailable3D + call RenderUnavailable3D + jmp present_frame +@@: + cmp engineMode, MODE_POOL + jne @F + call HandlePool3D + call RenderPool3D + jmp present_frame +@@: + cmp engineMode, MODE_BAR + jne @F + call HandleBar3D + call RenderBar3D + jmp present_frame +@@: + cmp engineMode, MODE_STAIRS + jne @F + call HandleStairs3D + call RenderStairs3D + jmp present_frame +@@: + cmp engineMode, MODE_SLOTS + jne check_bj_mode + call HandleNativeSlots3D + cmp engineMode,MODE_WALK + je check_walk_mode + call RenderNativeSlots3D + jmp present_frame +check_bj_mode: + cmp engineMode, MODE_BLACKJACK + jne check_poker_mode + call HandleNativeBlackjack3D + cmp engineMode, MODE_WALK + je check_walk_mode + call RenderNativeBlackjack3D + jmp present_frame +check_poker_mode: + cmp engineMode, MODE_POKER + jne check_durak_mode + call HandleNativePoker3D + cmp engineMode, MODE_WALK + je check_walk_mode + call RenderNativePoker3D + jmp present_frame +check_durak_mode: + cmp engineMode, MODE_DURAK + jne check_roul_mode + call HandleNativeDurak3D + cmp engineMode, MODE_WALK + je check_walk_mode + call RenderNativeDurak3D + jmp present_frame +check_roul_mode: + cmp engineMode, MODE_ROULETTE + jne check_shop_mode + call HandleNativeWheel3D + call RenderNativeWheel3D + jmp present_frame +check_shop_mode: + cmp engineMode, MODE_SHOP + jne check_atm_mode + call HandleMerchant3D + call RenderMerchant3D + 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 check_skill_mode + call HandleSkullsInput + call RenderSkullsGame + jmp present_frame +check_skill_mode: + cmp engineMode, MODE_SKILL + jne check_buckshot_mode + call HandleSkillInput + call RenderSkillGame + jmp present_frame +check_buckshot_mode: + cmp engineMode, MODE_BUCKSHOT + jne check_russian_mode + call HandleBuckshot3D + call RenderBuckshot3D + jmp present_frame +check_russian_mode: + cmp engineMode, MODE_RUSSIAN + jne present_frame + call HandleRussianInput3D + call RenderRussianGame3D + jmp present_frame +draw_pause: + invoke DrawBoxBorder, 28, 36, 264, 168, 00151C21h, 00D8BC6Ah, 2 + invoke DrawString8x8, 44, 48, OFFSET textPause3D, 00FFFFFFh + cmp displayFill3D, 0 + je @F + invoke DrawString8x8, 44, 72, OFFSET textDisplayFill3D, 00D8BC6Ah + jmp pause_draw_quality +@@: + invoke DrawString8x8, 44, 72, OFFSET textDisplayFit3D, 00D8BC6Ah +pause_draw_quality: + invoke DrawString8x8, 44, 92, OFFSET textLowSpec3D, 00D8BC6Ah + mov eax, settingsLowSpec + cmp eax, 0 + jne @F + mov edx, OFFSET textLowSpecOff3D + jmp pause_draw_quality_value +@@: + cmp eax, 1 + jne @F + mov edx, OFFSET textLowSpecEco3D + jmp pause_draw_quality_value +@@: + mov edx, OFFSET textLowSpecQuiet3D +pause_draw_quality_value: + invoke DrawString8x8, 208, 92, edx, 00FFFFFFh + invoke DrawString8x8, 44, 112, OFFSET textVolumeKeys3D, 00D8BC6Ah + invoke DrawString8x8, 44, 130, OFFSET textSoundLevel3D, 00BBBBBBh + invoke FormatNumber, settingsVolume, OFFSET hudNumBuffer + invoke DrawString8x8, 124, 130, OFFSET hudNumBuffer, 00FFFFFFh + invoke DrawString8x8, 44, 150, OFFSET textFullscreenKey3D, 00A0A0A0h + invoke DrawString8x8, 44, 170, OFFSET textResume3D, 00D8BC6Ah + invoke DrawString8x8, 44, 188, OFFSET textQuit3D, 00BBBBBBh + invoke Pressed3D, 31h + test eax, eax + jz @F + xor displayFill3D, 1 + call SaveDisplaySettings3D +@@: + invoke Pressed3D, 32h + test eax, eax + jz @F + inc settingsLowSpec + cmp settingsLowSpec, 3 + jb pause_low_spec_saved + mov settingsLowSpec, 0 +pause_low_spec_saved: + call SaveProgress3D +@@: + invoke Pressed3D, 0BBh + test eax, eax + jz @F + cmp settingsVolume, 10 + jae @F + inc settingsVolume + call ApplySoundVolume + call SaveProgress3D +@@: + invoke Pressed3D, 0BDh + test eax, eax + jz @F + mov eax, settingsVolume + test eax, eax + jz @F + dec settingsVolume + call ApplySoundVolume + call SaveProgress3D +@@: + invoke Pressed3D, 51h + test eax, eax + jz @F + call SaveProgress3D + jmp engine_shutdown +present_frame: + mov eax, engineMode + cmp eax, lastPersistMode3D + je @F + cmp eax, MODE_WALK + jne @F + call SaveProgress3D +@@: + mov eax, engineMode + mov lastPersistMode3D, eax + call Present3D + mov mouseClick3D, 0 + lea edi, pressedKeys3D + xor eax, eax + mov ecx, 64 + rep stosd + invoke GetTickCount + sub eax, frameStart3D + mov ecx, 16 + cmp settingsLowSpec, 1 + jne @F + mov ecx, 24 +@@: + cmp settingsLowSpec, 2 + jne @F + mov ecx, 33 +@@: + cmp eax, ecx + jae engine_loop + sub ecx, eax + invoke Sleep, ecx + jmp engine_loop +engine_idle: + invoke Sleep, 50 + jmp engine_loop +engine_shutdown: + cmp hRaycastThread, 0 + je @F + mov bRaycastQuit, 1 + invoke SetEvent, hRaycastStartEvent + invoke WaitForSingleObject, hRaycastThread, 1000 + invoke CloseHandle, hRaycastThread + invoke CloseHandle, hRaycastStartEvent + invoke CloseHandle, hRaycastDoneEvent + mov hRaycastThread, 0 + mov hRaycastStartEvent, 0 + mov hRaycastDoneEvent, 0 +@@: + call SaveProgress3D + invoke PlayCasinoSound3D, 0, 0, 0 + call FreeRussianAssets3D + call FreeStartupAssets3D + call FreeCardTableAssets3D + call FreeBuckshotAssets3D + call FreeNativeSlots3D + call FreeNativeClover3D + call FreePyramidAssets3D + call FreeArrivalAssets3D + 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 + +IFDEF CASINO_ACTION_TEST +include tools\tests\casino_actions_test.inc +ENDIF diff --git a/poker.exe b/poker.exe index f017cf7..2f4481c 100644 Binary files a/poker.exe and b/poker.exe differ diff --git a/poker.obj b/poker.obj index ac52956..1a3aa40 100644 Binary files a/poker.obj and b/poker.obj differ