; ============================================================================== ; 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 timeBeginPeriod PROTO :DWORD timeEndPeriod PROTO :DWORD timeGetTime PROTO GetCursorPos PROTO :DWORD SetCursorPos PROTO :DWORD,:DWORD ShowCursor PROTO :DWORD ClientToScreen 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 include src_graphics\native_dice_data.inc include src_graphics\scratch_data.inc include src_graphics\hell_tower_data.inc include src_graphics\charms_data.inc include src_graphics\observer_data.inc include src_graphics\darts_data.inc include src_graphics\jackbox_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 ALIGN 4 mouseLocked3D 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 startInHellTower 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 cmp portalRendering3D,0 je wall_ray_start_ready mov ebx,col mov ecx,portalClipDepth3D[ebx*4] test ecx,ecx jnz @F mov zBuffer[ebx*4],7FFFFFFFh jmp next_col @@: ; Start DDA just inside the destination aperture, never in its rear wall. add ecx,FP_1/100 mov eax,rayDirX imul ecx shrd eax,edx,16 add eax,playerX sar eax,16 mov mapX,eax mov eax,rayDirY imul ecx shrd eax,edx,16 add eax,playerY sar eax,16 mov mapY,eax wall_ray_start_ready: 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,132 jb wall_sample_other_hd cmp edx,135 ja wall_sample_other_hd mov ebx,fortuneMaterialArt3D.pixels test ebx,ebx jz wall_fortune_material_missing sub edx,132 shl edx,18 add ebx,edx jmp wall_room_hd_coordinates wall_fortune_material_missing: mov edx,92 mov eax,edi shr eax,16 and eax,127 jmp wall_sample_standard wall_sample_other_hd: cmp edx,122 jb wall_sample_existing_hd cmp edx,125 ja wall_sample_existing_hd mov ebx,upperMaterialArt3D.pixels test ebx,ebx jz wall_upper_material_missing sub edx,122 shl edx,18 add ebx,edx jmp wall_room_hd_coordinates wall_upper_material_missing: mov edx,102 wall_sample_existing_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 wall_room_hd_coordinates: 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 hud_charms_bottom invoke DrawBoxBorder, 4, 199, 312, 18, 0014191Dh, 00D8BC6Ah, 1 invoke DrawString8x8, 10, 204, interactPromptPtr, 00F5E2B0h invoke DrawCharmsHUD, 8, 18 jmp hud_charms_done hud_charms_bottom: invoke DrawCharmsHUD, 8, 214 hud_charms_done: 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 cmp esi,17 je radar_skip_sprite cmp esi,19 je radar_skip_sprite cmp esi,21 je radar_skip_sprite 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 radar_skip_sprite: 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 call HandleTerminal3D ret HandleATMInput ENDP RenderATMGame PROC call RenderTerminal3D 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 call LoadNativeDiceArt3D mov diceExitQueued3D,0 mov dice3d_state, 0 mov dice3d_timer, 0 mov dice3d_win, 0 ret InitDiceGame ENDP HandleDiceRules3D 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 TriggerCharmLossProtection, dice3d_bet test eax, eax jnz @F invoke PlayCasinoSound3D, OFFSET soundLose, 0, 1 @@: invoke NpcRecordRound3D,8,0 call SaveProgress3D ret dice_handle_result: cmp tournamentMode, 1 jne @F invoke Pressed3D, 20h test eax, eax jnz dice_tourney_report invoke Pressed3D, 0Dh test eax, eax jnz dice_tourney_report ret dice_tourney_report: cmp dice3d_win, 0 je dice_tourney_loss invoke TowerReportRoundOutcome, 1 ret dice_tourney_loss: invoke TowerReportRoundOutcome, 2 ret @@: invoke Pressed3D, 20h test eax, eax jz dice_done mov dice3d_state, 0 invoke PlayCasinoSound3D, OFFSET soundClick, 0, 1 dice_done: ret HandleDiceRules3D ENDP RenderDiceGame PROC call RenderNativeDice3D 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: cmp tournamentMode, 1 jne @F invoke Pressed3D, 20h test eax, eax jnz skulls_tourney_report invoke Pressed3D, 0Dh test eax, eax jnz skulls_tourney_report ret skulls_tourney_report: cmp skulls3d_win, 0 je skulls_tourney_loss invoke TowerReportRoundOutcome, 1 ret skulls_tourney_loss: invoke TowerReportRoundOutcome, 2 ret @@: 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: cmp tournamentMode, 1 jne @F invoke Pressed3D, 20h test eax, eax jnz skill_tourney_report invoke Pressed3D, 0Dh test eax, eax jnz skill_tourney_report ret skill_tourney_report: cmp skill3d_state, 4 jne skill_tourney_loss invoke TowerReportRoundOutcome, 1 ret skill_tourney_loss: invoke TowerReportRoundOutcome, 2 ret @@: 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 ; --- Mouse Lock & Unlock Routines for Free Camera Look --- LockMouse3D PROC LOCAL rcClient[16]:BYTE LOCAL ptCenter:C3D_POINT cmp mouseLocked3D, 1 je lock_done mov mouseLocked3D, 1 invoke ShowCursor, 0 lea eax, rcClient invoke GetClientRect, h3DWnd, eax mov eax, dword ptr rcClient[8] shr eax, 1 mov ptCenter.x, eax mov eax, dword ptr rcClient[12] shr eax, 1 mov ptCenter.y, eax lea eax, ptCenter invoke ClientToScreen, h3DWnd, eax invoke SetCursorPos, ptCenter.x, ptCenter.y lock_done: ret LockMouse3D ENDP UnlockMouse3D PROC cmp mouseLocked3D, 0 je unlock_done mov mouseLocked3D, 0 invoke ShowCursor, 1 unlock_done: ret UnlockMouse3D ENDP UpdateMouseLockState PROC cmp engineMode,MODE_STAIRS je lock_interior_check cmp engineMode, MODE_WALK jne unlock_it lock_interior_check: cmp paused3D, 0 jne unlock_it invoke GetForegroundWindow cmp eax, h3DWnd jne unlock_it invoke IsIconic, h3DWnd test eax, eax jnz unlock_it call LockMouse3D ret unlock_it: call UnlockMouse3D ret UpdateMouseLockState ENDP HandlePlayerInput PROC uses ebx esi edi local speed:DWORD local nextX:DWORD local nextY:DWORD local fwdDir:DWORD local strafeDir:DWORD local deltaMoveX:DWORD local deltaMoveY:DWORD local rcClient[16]:BYTE local ptCenter:C3D_POINT local ptCursor:C3D_POINT ; --- Mouse Look Camera Rotation --- cmp mouseLocked3D, 1 jne skip_mouse_look lea eax, rcClient invoke GetClientRect, h3DWnd, eax mov eax, dword ptr rcClient[8] shr eax, 1 mov ptCenter.x, eax mov eax, dword ptr rcClient[12] shr eax, 1 mov ptCenter.y, eax lea eax, ptCenter invoke ClientToScreen, h3DWnd, eax lea eax, ptCursor invoke GetCursorPos, eax mov eax, ptCursor.x sub eax, ptCenter.x test eax, eax jz mouse_recenter cmp eax, 64 jle @F mov eax, 64 @@: cmp eax, -64 jge @F mov eax, -64 @@: add playerAngle, eax mouse_recenter: invoke SetCursorPos, ptCenter.x, ptCenter.y skip_mouse_look: ; Movement speed with sprint (Shift = 10h) mov eax, deltaTime3D cmp eax,50 jbe @F mov eax,50 @@: imul eax, 200 mov speed, eax cmp keys3D[10h], 0 je @F shl speed, 1 @@: ; --- Keyboard Arrow Turning (VK_LEFT = 25h, VK_RIGHT = 27h) --- mov eax, deltaTime3D shr eax, 2 inc eax cmp keys3D[25h], 0 je @F sub playerAngle, eax @@: cmp keys3D[27h], 0 je @F add playerAngle, eax @@: and playerAngle, 511 call UpdateCamera3D ; --- Forward / Backward Direction (W / Up / S / Down) --- mov fwdDir, 0 cmp keys3D[57h], 0 jne @F cmp keys3D[26h], 0 je check_back_key @@: inc fwdDir check_back_key: cmp keys3D[53h], 0 jne @F cmp keys3D[28h], 0 je check_strafe_keys @@: dec fwdDir check_strafe_keys: ; --- Strafe Direction (A = Left, D = Right) --- mov strafeDir, 0 cmp keys3D[44h], 0 je @F inc strafeDir @@: cmp keys3D[41h], 0 je @F dec strafeDir @@: ; --- Movement Calculation --- mov deltaMoveX, 0 mov deltaMoveY, 0 ; Forward / Backward component mov edi, fwdDir test edi, edi jz calc_strafe_comp imul edi, speed mov eax, playerDirX imul edi shrd eax, edx, 16 add deltaMoveX, eax mov eax, playerDirY imul edi shrd eax, edx, 16 add deltaMoveY, eax calc_strafe_comp: ; Strafe Left / Right component: Right vector is (-playerDirY, playerDirX) mov edi, strafeDir test edi, edi jz check_total_movement imul edi, speed mov eax, playerDirY neg eax imul edi shrd eax, edx, 16 add deltaMoveX, eax mov eax, playerDirX imul edi shrd eax, edx, 16 add deltaMoveY, eax check_total_movement: mov eax, deltaMoveX or eax, deltaMoveY jz input_action mov eax, playerX add eax, deltaMoveX mov nextX, eax mov eax, playerY add eax, deltaMoveY 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: cmp engineMode,MODE_STAIRS je player_input_complete invoke Pressed3D, 45h test eax, eax jz @F call Trigger3DInteraction @@: player_input_complete: ret HandlePlayerInput ENDP CheckInteractions PROC uses ebx esi edi local nearest:DWORD mov nearest, 262144 mov interactTargetId, 0 mov interactPromptPtr, 0 cmp hallLevel3D,0 jne interaction_done xor esi, esi interaction_scan: cmp esi, NUM_SPRITES jge interaction_done cmp esi,3 jb interaction_next cmp esi,17 je interaction_next cmp esi,19 je interaction_next cmp esi,21 je interaction_next 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 ; (Legacy console arcade bezel bridge removed) 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 InitHellTower3D 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 invoke BeginTerminal3D,0 ret check_target_terminal: cmp eax, INTERACT_TERMINAL jne check_target_observer invoke BeginTerminal3D,1 ret check_target_observer: cmp eax, INTERACT_OBSERVER jne target_unported call BeginObserver3D 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 invoke timeBeginPeriod, 1 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\native_dice.inc include src_graphics\scratch.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 include src_graphics\fortune_dialog.inc include src_graphics\hell_tower.inc include src_graphics\charms.inc include src_graphics\observer.inc include src_graphics\darts.inc include src_graphics\jackbox.inc ; --- Main Loop of the 3D Casino Engine --- StartHellTower3D PROC uses ebx esi edi mov startInHellTower, 1 call StartCasino3D ret StartHellTower3D ENDP StartCasino3D PROC uses ebx esi edi call Init3DEngine test eax, eax jz engine_shutdown invoke timeGetTime mov rngSeed3D, eax mov previousTick3D, eax cmp startInHellTower, 1 jne engine_loop mov startInHellTower, 0 call InitHellTower3D 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 timeGetTime 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 @@: cmp obsActive3D,0 jne engine_observer_frame cmp engineMode,MODE_OBSERVER jne engine_observer_skip engine_observer_frame: call UpdateMouseLockState call ObserverFrame3D jmp present_frame engine_observer_skip: 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_STAIRS je pause_interior_walk cmp engineMode, MODE_WALK jne leave_table pause_interior_walk: xor paused3D, 1 jmp engine_tick leave_table: cmp engineMode,MODE_FORTUNE jne @F call StopFortuneWorker3D mov engineMode,MODE_WALK mov paused3D,0 call ClearKeys3D jmp engine_tick @@: cmp engineMode,MODE_SCRATCH jne @F call LeaveScratch3D jmp engine_tick @@: cmp engineMode,MODE_DICE jne @F call DiceEscape3D jmp engine_tick @@: 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 cmp tournamentMode, 1 jne @F call TowerExitToHall jmp engine_tick @@: mov engineMode, MODE_WALK call ClearKeys3D invoke PlayCasinoSound3D, 0, 0, 0 engine_tick: call UpdateMouseLockState 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 HandleJukeboxKeys3D call UpdateInteriorTravel3D call UpdateInteriorEye3D 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_JACKBOX jne check_jackbox_done call HandleJackbox3D cmp engineMode,MODE_WALK je check_walk_mode call RenderJackbox3D jmp present_frame check_jackbox_done: cmp engineMode,MODE_DARTS jne check_darts_done call HandleDarts3D call RenderDarts3D jmp present_frame check_darts_done: cmp engineMode,MODE_FORTUNE jne @F call HandleFortuneDialog3D cmp engineMode,MODE_WALK je check_walk_mode call RenderFortuneDialog3D jmp present_frame @@: cmp engineMode,MODE_CABARET jne @F call HandleCabaret3D call RenderCabaret3D jmp present_frame @@: cmp engineMode,MODE_SCRATCH jne @F call HandleScratch3D cmp engineMode,MODE_WALK je check_walk_mode call RenderScratch3D jmp present_frame @@: cmp engineMode, MODE_HELL_TOWER jne @F call HandleHellTowerInput call RenderHellTower3D jmp present_frame @@: 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 HandleJukeboxKeys3D 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: call UpdateJukeboxAudio3D call RenderTowerInGameBadge call RenderJukeboxVolumeHUD 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 timeGetTime 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: call UnlockMouse3D invoke Sleep, 50 jmp engine_loop engine_shutdown: call StopFortuneWorker3D call SettleScratchOnQuit3D call UnlockMouse3D 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 FreeDarts3D 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 @@: invoke timeEndPeriod, 1 ret StartCasino3D ENDP include src_graphics\platform_code.inc IFDEF CASINO_ACTION_TEST include tools\tests\casino_actions_test.inc ENDIF