diff --git a/build/graphics/poker.exe b/build/graphics/poker.exe index 2f4481c..bdeacf0 100644 Binary files a/build/graphics/poker.exe and b/build/graphics/poker.exe differ diff --git a/casino3d.inc b/casino3d.inc index 72afffe..6b3dab5 100644 --- a/casino3d.inc +++ b/casino3d.inc @@ -1,5614 +1,5384 @@ - -; ============================================================================== -; CASINO 2.5D - MASM32 SOFTWARE RAYCASTER (CP1251) -; Graphical migration; this is not id Software's Doom engine. -; ============================================================================== - -includelib gdi32.lib -includelib winmm.lib - -CreateWindowExA PROTO :DWORD,:DWORD,:DWORD,:DWORD,:DWORD,:DWORD,:DWORD,:DWORD,:DWORD,:DWORD,:DWORD,:DWORD -RegisterClassExA PROTO :DWORD -DefWindowProcA PROTO :DWORD,:DWORD,:DWORD,:DWORD -ShowWindow PROTO :DWORD,:DWORD -UpdateWindow PROTO :DWORD -GetDC PROTO :DWORD -ReleaseDC PROTO :DWORD,:DWORD -StretchDIBits PROTO :DWORD,:DWORD,:DWORD,:DWORD,:DWORD,:DWORD,:DWORD,:DWORD,:DWORD,:DWORD,:DWORD,:DWORD,:DWORD -PeekMessageA PROTO :DWORD,:DWORD,:DWORD,:DWORD,:DWORD -TranslateMessage PROTO :DWORD -DispatchMessageA PROTO :DWORD -PostQuitMessage PROTO :DWORD -DestroyWindow PROTO :DWORD -SetWindowTextA PROTO :DWORD,:DWORD -SetForegroundWindow PROTO :DWORD -GetConsoleWindow PROTO -GetSystemMetrics PROTO :DWORD -CreateFileA PROTO :DWORD,:DWORD,:DWORD,:DWORD,:DWORD,:DWORD,:DWORD -ReadFile PROTO :DWORD,:DWORD,:DWORD,:DWORD,:DWORD -CloseHandle PROTO :DWORD -GetAsyncKeyState PROTO :DWORD -PlaySoundA PROTO :DWORD,:DWORD,:DWORD -GetModuleFileNameA PROTO :DWORD,:DWORD,:DWORD -CopyFileA PROTO :DWORD,:DWORD,:DWORD -lstrcmpiA PROTO :DWORD,:DWORD -GetFileSize PROTO :DWORD,:DWORD -Sleep PROTO :DWORD -CreateThread PROTO :DWORD,:DWORD,:DWORD,:DWORD,:DWORD,:DWORD -CreateEventA PROTO :DWORD,:DWORD,:DWORD,:DWORD -SetEvent PROTO :DWORD -WaitForSingleObject PROTO :DWORD,:DWORD - -C3D_POINT STRUCT - x dd ? - y dd ? -C3D_POINT ENDS - -C3D_MSG STRUCT - hwnd dd ? - message dd ? - wParam dd ? - lParam dd ? - time dd ? - pt C3D_POINT <> -C3D_MSG ENDS - -C3D_WNDCLASSEX STRUCT - cbSize dd ? - style dd ? - lpfnWndProc dd ? - cbClsExtra dd ? - cbWndExtra dd ? - hInstance dd ? - hIcon dd ? - hCursor dd ? - hbrBackground dd ? - lpszMenuName dd ? - lpszClassName dd ? - hIconSm dd ? -C3D_WNDCLASSEX ENDS - -C3D_BITMAPINFOHEADER STRUCT - biSize dd ? - biWidth dd ? - biHeight dd ? - biPlanes dw ? - biBitCount dw ? - biCompression dd ? - biSizeImage dd ? - biXPelsPerMeter dd ? - biYPelsPerMeter dd ? - biClrUsed dd ? - biClrImportant dd ? -C3D_BITMAPINFOHEADER ENDS - -C3D_BITMAPINFO STRUCT - bmiHeader C3D_BITMAPINFOHEADER <> - bmiColors dd ? -C3D_BITMAPINFO ENDS - -SpriteObject STRUCT - posX dd ? - posY dd ? - baseTexId dd ? - frameCount dd ? - curFrame dd ? - animTimer dd ? - animSpeed dd ? - interactId dd ? - promptPtr dd ? - distSq dd ? -SpriteObject ENDS - -SCREEN_W equ 640 -SCREEN_H equ 480 -HALF_W equ 320 -HALF_H equ 240 -SCREEN_SIZE equ (SCREEN_W * SCREEN_H) -WIN_SCALE equ 1 -WINDOW_W equ (SCREEN_W * WIN_SCALE) -WINDOW_H equ (SCREEN_H * WIN_SCALE) - -FP_1 equ 65536 -FP_HALF equ 32768 -CHROMA_KEY equ 00FF00FFh - -MODE_WALK equ 0 -MODE_SLOTS equ 1 -MODE_BLACKJACK equ 2 -MODE_ROULETTE equ 3 -MODE_SHOP equ 4 -MODE_ATM equ 5 -MODE_COIN equ 6 -MODE_DICE equ 7 -MODE_SKULLS equ 8 -MODE_SKILL equ 9 - -WS_OVERLAPPEDWINDOW equ 00CF0000h -SW_SHOW equ 5 -SW_HIDE equ 0 -PM_REMOVE equ 1 -WM_DESTROY equ 0002h -WM_CLOSE equ 0010h -WM_QUIT equ 0012h -CS_HREDRAW equ 2 -CS_VREDRAW equ 1 -DIB_RGB_COLORS equ 0 -SRCCOPY equ 00CC0020h -INVALID_FILE_HANDLE equ -1 - -include casino3d_data.inc -include font8x8.inc -include src_graphics\platform_data.inc -include src_graphics\casino_actions_data.inc -include src_graphics\audio_data.inc -include src_graphics\startup_data.inc -include src_graphics\card_tables_data.inc -include src_graphics\native_durak_data.inc -include src_graphics\scene_animation_data.inc -include src_graphics\arrival_data.inc -include src_graphics\city_arrival_data.inc -include src_graphics\merchant_data.inc -include src_graphics\hall_data.inc -include src_graphics\npc_mind_data.inc -include src_graphics\npc_life_data.inc -include src_graphics\native_wheel_data.inc -include src_graphics\billiards_data.inc -include src_graphics\buckshot_data.inc -include src_graphics\russian_view_data.inc -include src_graphics\unavailable_data.inc -include src_graphics\native_slots_data.inc -include src_graphics\native_clover_data.inc -include src_graphics\native_coin_data.inc - -.data -ALIGN 4 -h3DInst dd 0 -h3DWnd dd 0 -h3DDC dd 0 -hCasinoConsole dd 0 - -ALIGN 4 -hRaycastThread dd 0 -hRaycastStartEvent dd 0 -hRaycastDoneEvent dd 0 -bRaycastQuit dd 0 -raycastThreadId dd 0 - -bmi3D C3D_BITMAPINFO <> -msg3D C3D_MSG <> -wc3D C3D_WNDCLASSEX <> - -sz3DClassName db "Casino3DRetroClass",0 -sz3DWindowTitle db 192,241,241,229,236,225,235,229,240,32,202,224,231,232,237,238,32,45,32,50,46,53,68,0 -szTexturesRelPath db "assets\textures\casino3d-hd.bin",0 -szTexturesFullPath db 260 dup(0) - - -playerX dd (16 * FP_1 + FP_HALF) -playerY dd (16 * FP_1 + FP_HALF) -playerAngle dd 384 -playerDirX dd 0 -playerDirY dd -FP_1 -playerPlaneX dd (FP_1 * 66 / 100) -playerPlaneY dd 0 - -engineMode dd 0 -interactTargetId dd 0 -interactPromptPtr dd 0 -dancerLuckBuff dd 0 -flashTimer dd 0 -flashMessage db 128 dup(0) - -promptDancer db "[E] КАБАРЕ - ЧАЕВЫЕ $100",0 -promptBlackjack db "[E] БЛЭКДЖЕК (21)",0 -promptPoker db 91,69,93,32,207,206,202,197,208,32,40,210,197,213,192,209,209,202,200,201,32,213,206,203,196,197,204,41,0 -promptDurak db "[E] КАРТЫ: ПОДКИДНОЙ ДУРАК",0 -promptCasinoRoulette db "[E] ЕВРОПЕЙСКАЯ РУЛЕТКА",0 -promptClassicSlot db "[E] КЛАССИЧЕСКИЕ СЛОТЫ 777",0 -promptCloverSlot db "[E] СЛОТЫ CLOVERPIT (5x3)",0 -promptDice db 91,69,93,32,200,195,208,192,32,194,32,202,206,209,210,200,0 -promptSkulls db "[E] НАПЁРСТКИ (ЧЕРЕПА)",0 -promptCoin db "[E] МОНЕТКА (ОРЁЛ/РЕШКА)",0 -promptSkillCheck db "[E] ТРЕНИРОВКА РЕАКЦИИ",0 -promptBuckshot db 91,69,93,32,193,192,202,216,206,210,32,208,211,203,197,210,202,192,0 -promptRussianRoulette db "[E] РУССКАЯ РУЛЕТКА (VIP)",0 -promptOnlineRR db "[E] СЕТЕВАЯ РУЛЕТКА (NET)",0 -promptUmamusume db "[E] СКАЧКИ УМАМУСУМЭ",0 -promptHellTower db "[E] БАШНЯ АДА (10 ЭТАЖЕЙ)",0 -promptShop db "[E] БУТИК И ТАЛИСМАНЫ",0 -promptATM db "[E] БАНКОМАТ И БАЛАНС",0 -promptPlayerTerminal db "[E] ТЕРМИНАЛ: СТАТЫ И АЧИВКИ",0 -promptObserver db "[E] РЕЖИМ НАБЛЮДАТЕЛЯ (ИИ)",0 - -szTitleBlackjack db 202,192,199,200,202,32,51,68,32,45,32,193,203,221,202,196,198,197,202,32,40,50,49,41,0 -szTitlePoker db 202,192,199,200,202,32,51,68,32,45,32,207,206,202,197,208,32,40,210,197,213,192,209,209,202,200,201,32,213,206,203,196 - db 197,204,41,0 -szTitleDurak db 202,192,199,200,202,32,51,68,32,45,32,207,197,208,197,194,206,196,205,206,201,32,196,211,208,192,202,0 -szTitleCasinoRoulette db 202,192,199,200,202,32,51,68,32,45,32,197,194,208,206,207,197,201,209,202,192,223,32,208,211,203,197,210,202,192,0 -szTitleClassicSlot db 202,192,199,200,202,32,51,68,32,45,32,192,194,210,206,204,192,210,32,55,55,55,0 -szTitleCloverSlot db 202,192,199,200,202,32,51,68,32,45,32,202,203,197,194,197,208,205,192,223,32,223,204,192,32,40,53,120,51,41,0 -szTitleDice db 202,192,199,200,202,32,51,68,32,45,32,200,195,208,192,32,194,32,202,206,209,210,200,0 -szTitleSkulls db 202,192,199,200,202,32,51,68,32,45,32,205,192,207,168,208,209,210,202,200,0 -szTitleCoin db 202,192,199,200,202,32,51,68,32,45,32,204,206,205,197,210,202,192,32,40,206,208,168,203,47,208,197,216,202,192,41,0 -szTitleSkillCheck db 202,192,199,200,202,32,51,68,32,45,32,207,208,206,194,197,208,202,192,32,205,192,194,219,202,192,0 -szTitleBuckshot db 202,192,199,200,202,32,51,68,32,45,32,193,192,202,216,206,210,32,208,211,203,197,210,202,192,0 -szTitleRussianRoulette db 202,192,199,200,202,32,51,68,32,45,32,208,211,209,209,202,192,223,32,208,211,203,197,210,202,192,0 -szTitleOnlineRR db 202,192,199,200,202,32,51,68,32,45,32,209,197,210,197,194,192,223,32,208,211,209,209,202,192,223,32,208,211,203,197,210 - db 202,192,0 -szTitleUmamusume db 202,192,199,200,202,32,51,68,32,45,32,195,206,205,202,200,32,211,204,192,204,211,209,211,204,197,0 -szTitleHellTower db 202,192,199,200,202,32,51,68,32,45,32,192,196,209,202,192,223,32,193,192,216,205,223,0 -szTitleShop db 202,192,199,200,202,32,51,68,32,45,32,202,192,208,210,219,32,200,32,210,192,203,200,209,204,192,205,219,0 -szTitleATM db 202,192,199,200,202,32,51,68,32,45,32,193,192,205,202,206,204,192,210,0 -szTitleTerminal db 202,192,199,200,202,32,51,68,32,45,32,203,206,202,192,203,220,205,219,197,32,207,208,206,212,200,203,200,0 -szTitleObserver db 202,192,199,200,202,32,51,68,32,45,32,205,192,193,203,222,196,192,210,197,203,220,32,40,200,200,41,0 -textCabinetFooter db "[ ВЫХОД: ВВЕДИТЕ 0 / ВЫБЕРИТЕ 'N' ДЛЯ ВОЗВРАТА В ЗАЛ ]",0 - -msgDancerTipped db "Вы бросили $100 танцовщице! УДАЧА АКТИВИРОВАНА!",0 -msgNeedMoney db "Недостаточно денег в кошельке!",0 -statusHUDFormat db "БАНКРОЛЛ: $",0 -targetHUDFormat db " ЦЕЛЬ: $",0 -luckHUDFormat db " УДАЧА: +",0 -controlsHUD db "WASD/Стрелки: Ходьба | E: Действие | ESC: Меню",0 - -NUM_SPRITES equ 22 - -INTERACT_NONE equ 0 -INTERACT_BLACKJACK equ 1 -INTERACT_POKER equ 2 -INTERACT_SLOTS_777 equ 3 -INTERACT_ROULETTE equ 4 -INTERACT_SKULLS equ 5 -INTERACT_SHOP equ 6 -INTERACT_ATM equ 7 -INTERACT_DANCER equ 8 -INTERACT_HELL_TOWER equ 9 -INTERACT_DURAK equ 10 -INTERACT_BUCKSHOT equ 11 -INTERACT_COIN equ 12 -INTERACT_DICE equ 13 -INTERACT_SLOTS_CLOVER equ 14 -INTERACT_UMAMUSUME equ 15 -INTERACT_OBSERVER equ 16 -INTERACT_TERMINAL equ 17 -INTERACT_ONLINE_RR equ 18 -INTERACT_RUSSIAN_ROULETTE equ 19 -INTERACT_SKILL_CHECK equ 20 -ALIGN 4 -casinoSprites SpriteObject NUM_SPRITES dup(<>) -sortedSprites dd NUM_SPRITES dup(0) - -rowDistTable dd 120 dup(0) -rngSeed3D dd 12345678h - -slotBet dd 50 -slotReel1 dd 0 -slotReel2 dd 1 -slotReel3 dd 2 -slotSpinState dd 0 -slotSpinTimer dd 0 -slotWinAmount dd 0 -slotWinMsg db 64 dup(0) - -bjState dd 0 -bjBet dd 100 -bjPlayerCards dd 10 dup(0) -bjPlayerCardCount dd 0 -bjPlayerScore dd 0 -bjDealerCards dd 10 dup(0) -bjDealerCardCount dd 0 -bjDealerScore dd 0 -bjDealerHideHole dd 1 -bjOutcomeMsg db 64 dup(0) - -roulState dd 0 -roulBetType dd 1 -roulBetAmount dd 100 -roulWheelAngle dd 0 -roulBallAngle dd 0 -roulSpinTimer dd 0 -roulWinningNum dd 0 -roulPayout dd 0 -roulOutcomeMsg db 64 dup(0) - -coinRxAnimTable db 26, 22, 16, 6, 16, 22, 26, 22, 16, 6 - -; --- Native 2.5D Coin Flip --- -coin3d_bet dd 50 -coin3d_choice dd 1 ; 1 = Орёл, 2 = Решка -coin3d_state dd 0 ; 0 = Idle, 1 = Flipping, 2 = Result -coin3d_timer dd 0 -coin3d_result dd 1 ; 1 = Орёл, 2 = Решка -coin3d_streak dd 0 -coin3d_win dd 0 - -textCoinTitle db "* * * З О Л О Т А Я М О Н Е Т А * * *",0 -textCoinHeads db "ОРЁЛ",0 -textCoinTails db "РЕШКА",0 -textCoinSide1 db "[1] ОРЁЛ",0 -textCoinSide2 db "[2] РЕШКА",0 -textCoinFlipping db "МОНЕТА В ПОЛЁТЕ...",0 -textCoinWin db "ПОБЕДА: +$",0 -textCoinLose db "НЕ УГАДАЛИ!",0 -textCoinStreakFmt db "СЕРИЯ ПОБЕД: x",0 -textCoinSelected db "ВЫБРАНО",0 -textCoinKey1 db "[1] ОРЁЛ",0 -textCoinKey2 db "[2] РЕШКА",0 -textCoinKeySpace db "[SPACE]",0 - -; --- Native 2.5D Dice Game --- -dice3d_bet dd 50 -dice3d_choice dd 1 ; 1 = Чёт, 2 = Нечет -dice3d_state dd 0 ; 0 = Idle, 1 = Rolling, 2 = Result -dice3d_timer dd 0 -dice3d_val1 dd 4 -dice3d_val2 dd 6 -dice3d_sum dd 10 -dice3d_win dd 0 - -textDiceTitle db 200,195,208,192,32,194,32,202,206,209,210,200,0 -textDiceEven db "[1] ЧЁТ",0 -textDiceOdd db "[2] НЕЧЕТ",0 -textDiceEvenNums db "2 4 6 ...",0 -textDiceOddNums db "3 5 7 ...",0 -textDiceSumHdr db "СУММА: ",0 -textDicePlus db " + ",0 -textDiceEqual db " = ",0 -textDiceEvenResult db " (ЧЁТ)",0 -textDiceOddResult db " (НЕЧЕТ)",0 -textDiceRolling db "КОСТИ ЛЕТЯТ ПО СУКНУ...",0 -textDiceWin db "ВЫИГРЫШ: +$",0 -textDiceWinMult db "! (x2)",0 -textDiceLose db "ПРОИГРЫШ!",0 -textDiceKey1 db "[1] ЧЁТ",0 -textDiceKey2 db "[2] НЕЧЕТ",0 -textDiceKeySpace db "[SPACE]",0 - -; --- Native 2.5D Skulls Game --- -skulls3d_bet dd 50 -skulls3d_state dd 0 ; 0 = Idle, 1 = Show ball, 2 = Shuffle, 3 = Pick, 4 = Reveal -skulls3d_timer dd 0 -skulls3d_ballPos dd 1 ; 0, 1, 2 -skulls3d_choice dd 1 ; 0, 1, 2 -skulls3d_win dd 0 -skulls3d_swapPair0 dd 0 -skulls3d_swapPair1 dd 1 -skulls3d_swapPair2 dd 2 -skulls3d_cup0 dd 0 -skulls3d_cup1 dd 1 -skulls3d_cup2 dd 2 - -textSkullsTitle db "* * * Н А П Ё Р С Т К И * * *",0 -textSkullsPhase0 db "ДЕЛАЙ СТАВКУ И ЖМИ [ПРОБЕЛ]",0 -textSkullsPhase1 db "СМОТРИ, ГДЕ ЗОЛОТОЙ ШАР...",0 -textSkullsPhase2 db "КРУЧУ, ВЕРЧУ, ЗАПУТАТЬ ХОЧУ...",0 -textSkullsPhase3 db "ГДЕ ШАР? ВЫБИРАЙ: [1], [2] ИЛИ [3]!",0 -textSkullsWin db "ВЫИГРЫШ: +$",0 -textSkullsWinMult db "! (x3) ВЫ УГАДАЛИ!",0 -textSkullsLose db "МИМО! ШАР БЫЛ В ДРУГОМ МЕСТЕ!",0 -textSkullsAgain db "[ПРОБЕЛ] - СЫГРАТЬ ЕЩЁ РАЗ",0 -textSkullsKey1 db "[1]",0 -textSkullsKey2 db "[2]",0 -textSkullsKey3 db "[3]",0 -textSkullsKeySpace db "[SPACE] СТАРТ",0 - -; --- Native 2.5D Skill Check (Dead by Daylight Survivor Check) --- -skill3d_bet dd 50 -skill3d_state dd 0 ; 0=Ready, 1=Active, 2=Hit Result, 3=Miss Result, 4=Escaped, 5=Defeated -skill3d_timer dd 0 -skill3d_needle dd 55 ; Needle X (52..268) -skill3d_speed dd 4 -skill3d_dir dd 1 ; 1=Right, -1=Left -skill3d_zone_start dd 140 -skill3d_zone_width dd 48 -skill3d_great_start dd 176 -skill3d_great_width dd 12 -skill3d_hits dd 0 -skill3d_misses dd 0 -skill3d_last_result dd 0 -skill3d_win_amount dd 0 - -textSkillTitle db 61,61,61,32,207,208,206,194,197,208,202,192,32,205,192,194,219,202,192,32,61,61,61,0 -textSkillHitsHdr db "ХИТ: ",0 -textSkillMissHdr db "ПРОМАХ: ",0 -textSkillReadyMsg db "НАЖМИТЕ [ПРОБЕЛ] ДЛЯ СТАРТА",0 -textSkillPrompt db "НАЖМИТЕ [ПРОБЕЛ] В ЗОНЕ!",0 -textSkillHitMsg db "ХИТ! ТОЧНОЕ ПОПАДАНИЕ!",0 -textSkillGreatMsg db 206,210,203,200,215,205,206,33,32,43,193,206,205,211,209,33,0 -textSkillMissMsg db "ПРОМАХ! ТРЕВОГА!",0 -textSkillEscape db "ПОБЕГ УСПЕШЕН! ВЫИГРЫШ: +$",0 -textSkillLost db "ВЫ ПОЙМАНЫ! ПРОИГРЫШ СТАВКИ!",0 -textSkillKeySpace db "[SPACE] РЕАКЦИЯ",0 -textSkillKeyBet db "[ВВЕРХ/ВНИЗ]",0 - -; --- Shared UI Strings --- -textKeyEsc db "[ESC]",0 -textBankPrompt db "БАНК: $",0 -textBetPrompt db "СТАВКА: $",0 -textBetHint db " [W/S]",0 - -shopMsg db 128 dup(0) -atmMsg db 128 dup(0) - -strWin db "ПОБЕДА! +$",0 -strLose db "ПРОИГРЫШ",0 -strJackpot db "ДЖЕКПОТ! +$",0 -strPush db 205,200,215,220,223,0 -strDealerBust db "ДИЛЕР ПЕРЕБРАЛ! ПОБЕДА! +$",0 -strPlayerBust db "ПЕРЕБОР (>21)! ПРОИГРЫШ",0 - -sym7 db " 777 ",0 -symBar db " BAR ",0 -symBell db 32,199,194,206,205,0 -symCherry db 194,200,216,205,223,0 -symClover db 202,203,197,194,197,208,0 -symGem db 192,203,204,192,199,0 -symCrown db 202,206,208,206,205,192,0 - -cardRankStr db "A ",0,"2 ",0,"3 ",0,"4 ",0,"5 ",0,"6 ",0,"7 ",0,"8 ",0,"9 ",0,"10",0,"J ",0,"Q ",0,"K ",0 - -.data? -ALIGN 4 -screenBuffer dd SCREEN_SIZE dup(?) -ALIGN 4 -zBuffer dd SCREEN_W dup(?) -ALIGN 4 -texturesBuffer dd (104 * 128 * 128) dup(?) - -hudNumBuffer db 32 dup(?) - -.code - -; --- 3D Window Procedure --- -Casino3DWndProc PROC hwnd:DWORD, uMsg:DWORD, wParam:DWORD, lParam:DWORD - invoke WindowEvents3D, hwnd, uMsg, wParam, lParam - ret -Casino3DWndProc ENDP - -; --- Random Generator --- -RandomRange3D PROC maxVal:DWORD - mov eax, rngSeed3D - imul eax, 1103515245 - add eax, 12345 - mov rngSeed3D, eax - shr eax, 16 - and eax, 7FFFh - xor edx, edx - div maxVal - mov eax, edx - ret -RandomRange3D ENDP - -; --- Copy String --- -CopyString3D PROC src:DWORD, dst:DWORD - push esi - push edi - mov esi, src - mov edi, dst -@@: - mov al, [esi] - mov [edi], al - test al, al - jz @F - inc esi - inc edi - jmp @B -@@: - pop edi - pop esi - ret -CopyString3D ENDP - -; --- Format Number to Decimal String --- -FormatNumber PROC num:DWORD, buf:DWORD - push ebx - push esi - push edi - mov eax, num - mov edi, buf - test eax, eax - jns fn_pos - mov BYTE PTR [edi], '-' - inc edi - neg eax -fn_pos: - mov ebx, 10 - push 0 -fn_div: - xor edx, edx - div ebx - add dl, '0' - push edx - test eax, eax - jnz fn_div -fn_pop: - pop eax - test al, al - jz fn_done - mov [edi], al - inc edi - jmp fn_pop -fn_done: - mov BYTE PTR [edi], 0 - pop edi - pop esi - pop ebx - ret -FormatNumber ENDP - -; --- Fast 2D Drawing Primitives --- -DrawBox PROTO :DWORD,:DWORD,:DWORD,:DWORD,:DWORD - -DrawPixel PROC x:DWORD, y:DWORD, color:DWORD - invoke DrawBox, x, y, 1, 1, color - ret -DrawPixel ENDP - -DrawBox PROC x:DWORD, y:DWORD, w:DWORD, h:DWORD, color:DWORD - shl x, 1 - shl y, 1 - shl w, 1 - shl h, 1 - push ebx - push esi - push edi - mov edi, y -box_row_loop: - mov eax, y - add eax, h - cmp edi, eax - jge box_done - cmp edi, 0 - jl next_box_row - cmp edi, SCREEN_H - jge box_done - - mov esi, x -box_col_loop: - mov eax, x - add eax, w - cmp esi, eax - jge next_box_row - cmp esi, 0 - jl next_box_col - cmp esi, SCREEN_W - jge next_box_row - - mov ecx, edi - imul ecx, SCREEN_W - add ecx, esi - mov edx, color - mov [screenBuffer + ecx*4], edx - -next_box_col: - inc esi - jmp box_col_loop - -next_box_row: - inc edi - jmp box_row_loop - -box_done: - pop edi - pop esi - pop ebx - ret -DrawBox ENDP - -DrawBoxBorder PROC uses ebx x:DWORD, y:DWORD, w:DWORD, h:DWORD, fillColor:DWORD, borderColor:DWORD, bWidth:DWORD - invoke DrawBox, x, y, w, h, borderColor - mov eax, x - add eax, bWidth - mov edx, y - add edx, bWidth - mov ecx, w - sub ecx, bWidth - sub ecx, bWidth - mov ebx, h - sub ebx, bWidth - sub ebx, bWidth - invoke DrawBox, eax, edx, ecx, ebx, fillColor - ret -DrawBoxBorder ENDP - -DrawCircle PROC cxVal:DWORD, cyVal:DWORD, radius:DWORD, color:DWORD - push ebx - push esi - push edi - mov eax, radius - neg eax - mov edi, eax -circ_y: - cmp edi, radius - jg circ_done - mov eax, radius - neg eax - mov esi, eax -circ_x: - cmp esi, radius - jg next_circ_y - - mov eax, esi - imul eax, eax - mov ebx, edi - imul ebx, ebx - add eax, ebx - mov edx, radius - imul edx, edx - cmp eax, edx - jg next_circ_x - - mov eax, cxVal - add eax, esi - mov ecx, cyVal - add ecx, edi - invoke DrawPixel, eax, ecx, color - -next_circ_x: - inc esi - jmp circ_x -next_circ_y: - inc edi - jmp circ_y -circ_done: - pop edi - pop esi - pop ebx - ret -DrawCircle ENDP - -DrawChar8x8 PROC uses ebx esi edi x:DWORD, y:DWORD, chVal:DWORD, color:DWORD - local column:DWORD - mov eax, chVal - and eax, 255 - lea esi, [font8x8 + eax*8] - xor edi, edi -glyph_row: - movzx ebx, BYTE PTR [esi+edi] - mov column, 0 -glyph_col: - test ebx, 80h - jz glyph_next - mov eax, x - add eax, column - mov edx, y - add edx, edi - invoke DrawPixel, eax, edx, color -glyph_next: - shl ebx, 1 - inc column - cmp column, 8 - jl glyph_col - inc edi - cmp edi, 8 - jl glyph_row - ret -DrawChar8x8 ENDP - -DrawString8x8 PROC x:DWORD, y:DWORD, strPtr:DWORD, color:DWORD - push ebx - push esi - mov esi, strPtr - mov ebx, x -str_loop: - movzx eax, BYTE PTR [esi] - test al, al - jz str_done - invoke DrawChar8x8, ebx, y, eax, color - add ebx, 8 - inc esi - jmp str_loop -str_done: - pop esi - pop ebx - ret -DrawString8x8 ENDP - -; --- True 3D Perspective Floor & Ceiling Rendering --- - -; --- DDA Raycasting Walls --- -RenderWallsRange PROC colStart:DWORD, colLimit:DWORD - local col:DWORD - local originalStart:DWORD - local camX:DWORD - local rayDirX:DWORD - local rayDirY:DWORD - local mapX:DWORD - local mapY:DWORD - local deltaDistX:DWORD - local deltaDistY:DWORD - local stepX:DWORD - local stepY:DWORD - local sideDistX:DWORD - local sideDistY:DWORD - local side:DWORD - local perpWallDist:DWORD - local lineH:DWORD - local drawStart:DWORD - local drawEnd:DWORD - local wallHit:DWORD - local texX:DWORD - local texXHD:DWORD - local pixelMaterial:DWORD - local texId:DWORD - local shade:DWORD - - push ebx - push esi - push edi - - mov eax, playerAngle - and eax, 511 - mov ebx, [tableCos + eax*4] - mov playerDirX, ebx - mov ebx, [tableSin + eax*4] - mov playerDirY, ebx - - mov eax, ebx - imul eax, -66 - cdq - mov ecx, 100 - idiv ecx - mov playerPlaneX, eax - - mov eax, playerDirX - imul eax, 66 - cdq - idiv ecx - mov playerPlaneY, eax - - mov eax, colStart - mov col, eax -col_loop: - mov eax, colLimit - cmp col, eax - jge walls_done - - mov eax, col - shl eax, 1 - sub eax, SCREEN_W - imul eax, FP_1 - cdq - mov ecx, SCREEN_W - idiv ecx - mov camX, eax - - mov eax, playerPlaneX - imul camX - shrd eax, edx, 16 - add eax, playerDirX - mov rayDirX, eax - - mov eax, playerPlaneY - imul camX - shrd eax, edx, 16 - add eax, playerDirY - mov rayDirY, eax - - mov eax, playerX - sar eax, 16 - mov mapX, eax - mov eax, playerY - sar eax, 16 - mov mapY, eax - - mov eax, rayDirX - test eax, eax - jnz calc_delta_x - mov deltaDistX, 7FFFFFFFh - jmp calc_delta_y -calc_delta_x: - test eax, eax - jns @F - neg eax -@@: - mov ebx, eax - cmp ebx, 4 - jbe delta_x_clamp - xor eax, eax - mov edx, 1 - div ebx - mov deltaDistX, eax - jmp calc_delta_y -delta_x_clamp: - mov deltaDistX, 7FFFFFFFh - -calc_delta_y: - mov eax, rayDirY - test eax, eax - jnz calc_delta_y_ok - mov deltaDistY, 7FFFFFFFh - jmp check_step -calc_delta_y_ok: - test eax, eax - jns @F - neg eax -@@: - mov ebx, eax - cmp ebx, 4 - jbe delta_y_clamp - xor eax, eax - mov edx, 1 - div ebx - mov deltaDistY, eax - jmp check_step -delta_y_clamp: - mov deltaDistY, 7FFFFFFFh - -check_step: - cmp rayDirX, 0 - jge step_x_pos - mov stepX, -1 - mov eax, playerX - mov edx, mapX - shl edx, 16 - sub eax, edx - imul deltaDistX - shrd eax, edx, 16 - mov sideDistX, eax - jmp check_step_y -step_x_pos: - mov stepX, 1 - mov eax, mapX - inc eax - shl eax, 16 - sub eax, playerX - imul deltaDistX - shrd eax, edx, 16 - mov sideDistX, eax - -check_step_y: - cmp rayDirY, 0 - jge step_y_pos - mov stepY, -1 - mov eax, playerY - mov edx, mapY - shl edx, 16 - sub eax, edx - imul deltaDistY - shrd eax, edx, 16 - mov sideDistY, eax - jmp dda_start -step_y_pos: - mov stepY, 1 - mov eax, mapY - inc eax - shl eax, 16 - sub eax, playerY - imul deltaDistY - shrd eax, edx, 16 - mov sideDistY, eax - -dda_start: - xor ecx, ecx -dda_step_loop: - inc ecx - cmp ecx, 64 - jge wall_map_boundary - - mov eax, sideDistX - cmp eax, sideDistY - jge step_in_y - - mov eax, deltaDistX - add sideDistX, eax - mov eax, stepX - add mapX, eax - mov side, 0 - jmp check_tile - -step_in_y: - mov eax, deltaDistY - add sideDistY, eax - mov eax, stepY - add mapY, eax - mov side, 1 - -check_tile: - cmp mapX, 0 - jl wall_map_boundary - cmp mapX, MAP_WIDTH - jge wall_map_boundary - cmp mapY, 0 - jl wall_map_boundary - cmp mapY, MAP_HEIGHT - jge wall_map_boundary - - mov eax, mapY - shl eax, 5 - add eax, mapX - mov edx, worldMap3D - movzx eax, BYTE PTR [edx + eax] - test eax, eax - jnz hit_wall - jmp dda_step_loop - -wall_map_boundary: - cmp outdoorRender3D, 0 - je hit_wall - mov eax, col - mov zBuffer[eax*4], 7FFFFFFFh - jmp next_col - -hit_wall: - cmp side, 0 - jne perp_y - mov eax, sideDistX - sub eax, deltaDistX - mov perpWallDist, eax - jmp perp_done -perp_y: - mov eax, sideDistY - sub eax, deltaDistY - mov perpWallDist, eax - -perp_done: - cmp perpWallDist, 2048 - jge @F - mov perpWallDist, 2048 -@@: - mov eax, col - mov edx, perpWallDist - mov [zBuffer + eax*4], edx - - ; Unit projection is shared by indoor room height and outdoor storeys. - mov eax, SCREEN_H - imul eax, FP_1 - cdq - idiv perpWallDist - mov lineH, eax - - mov eax, lineH - imul viewEye3D - shrd eax, edx, 16 - add eax, viewHorizon3D - mov drawEnd, eax - mov ebx, lineH - mov eax, viewCeiling3D - cmp outdoorRender3D, 0 - je @F - mov eax, CITY_STOREY_HEIGHT -@@: - imul ebx - shrd eax, edx, 16 - mov ebx, eax - mov lineH, ebx - mov eax, drawEnd - sub eax, ebx - mov drawStart, eax - cmp outdoorRender3D, 0 - je wall_store_original_start - ; Floor height is independent of storey height. - mov eax, drawEnd - sub eax, lineH - mov drawStart, eax - mov eax, mapY - shl eax, 5 - add eax, mapX - mov edx, worldMap3D - movzx eax, BYTE PTR [edx+eax] -wall_exterior_tall: - ; Roof projection and texture sampling use the same storey count. - mov eax, lineH - imul eax, CITY_BUILDING_STOREYS-1 - sub drawStart, eax - mov eax, lineH - imul eax, CITY_BUILDING_STOREYS - mov lineH, eax -wall_store_original_start: - mov eax, drawStart - mov originalStart, eax - - cmp side, 0 - jne hit_side_y - mov eax, perpWallDist - imul rayDirY - shrd eax, edx, 16 - add eax, playerY - mov wallHit, eax - jmp calc_tex_x -hit_side_y: - mov eax, perpWallDist - imul rayDirX - shrd eax, edx, 16 - add eax, playerX - mov wallHit, eax - -calc_tex_x: - ; MASK WITH 0FFFFh to prevent texture scrambling! - mov eax, wallHit - and eax, 0FFFFh - mov texXHD, eax - shr eax, 9 - and eax, 127 - mov texX, eax - - cmp side, 0 - jne @F - cmp rayDirX, 0 - jle @F - mov eax, 127 - sub eax, texX - mov texX, eax - xor texXHD, 0FFFFh -@@: - cmp side, 1 - jne select_tex - cmp rayDirY, 0 - jge select_tex - mov eax, 127 - sub eax, texX - mov texX, eax - xor texXHD, 0FFFFh - -select_tex: - mov eax, mapY - shl eax, 5 - add eax, mapX - mov edx, worldMap3D - movzx eax, BYTE PTR [edx + eax] - mov texId, eax - cmp texId, 0 - jne @F - mov texId, 1 -@@: - - mov eax, perpWallDist - shr eax, 13 - mov edx, 256 - sub edx, eax - cmp edx, 75 - jge @F - mov edx, 75 -@@: - cmp side, 1 - jne @F - imul edx, 3 - shr edx, 2 -@@: - mov shade, edx - - cmp drawStart, 0 - jge @F - mov drawStart, 0 -@@: - cmp drawEnd, SCREEN_H - jl @F - mov drawEnd, SCREEN_H - 1 -@@: - - mov eax, lineH - cmp eax, 1 - jge @F - mov eax, 1 - mov lineH, eax -@@: - - mov eax, 128 * FP_1 - cdq - idiv lineH - mov esi, eax ; stepY - - mov eax, drawStart - sub eax, originalStart - imul eax, esi - mov edi, eax ; texPos - - mov ecx, drawStart -draw_stripe_loop: - cmp ecx, drawEnd - jg next_col - - mov eax, edi - shr eax, 16 - and eax, 127 - mov edx, texId - cmp outdoorRender3D, 0 - je wall_sample_material - imul eax, CITY_BUILDING_STOREYS - cmp eax, 128*(CITY_BUILDING_STOREYS-1) - jae wall_lower_storey - push eax - shr eax, 7 - add eax, mapX - add eax, mapY - xor edx, edx - mov ebx, 3 - div ebx - add edx, 65 - pop eax - and eax, 127 - jmp wall_sample_material -wall_lower_storey: - sub eax, 128*(CITY_BUILDING_STOREYS-1) -wall_sample_material: - mov pixelMaterial, edx - cmp outdoorRender3D, 0 - je wall_sample_indoor_hd - cmp hallCityDetail3D.pixels, 0 - je wall_sample_standard - cmp edx, 57 - jb wall_sample_standard - cmp edx, 72 - ja wall_sample_standard - cmp perpWallDist, 6*FP_1 - ja wall_sample_standard - ; Preserve subtexel detail near facades; retain the 128px mip at distance. - push edx - mov eax, edi - shr eax, 15 - imul eax, CITY_BUILDING_STOREYS - and eax, 255 - shl eax, 8 - mov ebx, texXHD - shr ebx, 8 - add eax, ebx - pop edx - sub edx, 57 - shl edx, 16 - add eax, edx - mov ebx, hallCityDetail3D.pixels - mov eax, [ebx+eax*4] - jmp wall_shade_pixel -wall_sample_indoor_hd: - cmp edx, 80 - jb wall_sample_standard - cmp edx, 103 - ja wall_sample_standard - mov ebx, hallRoomHD3D.pixels - cmp edx, 92 - jb wall_sample_room_hd - mov ebx, hallArchitectureHD3D.pixels - sub edx, 12 -wall_sample_room_hd: - test ebx, ebx - jz wall_sample_standard_restore - sub edx, 80 - shl edx, 18 - add ebx, edx - mov eax, edi - shr eax, 15 - and eax, 255 - shl eax, 8 - mov edx, texXHD - shr edx, 8 - add eax, edx - mov eax, [ebx+eax*4] - jmp wall_shade_pixel -wall_sample_standard_restore: - mov edx, texId - mov eax, edi - shr eax, 16 - and eax, 127 -wall_sample_standard: - shl eax, 7 - add eax, texX - - shl edx, 14 - add eax, edx - mov eax, [texturesBuffer + eax*4] - - ; Shade wall pixel -wall_shade_pixel: - mov ebx, shade - cmp outdoorRender3D, 0 - je wall_ambient_shade - push eax - push ecx - invoke IsCityEmissive3D, eax, pixelMaterial - pop ecx - test eax, eax - pop eax - jz wall_ambient_shade - mov ebx, 256 -wall_ambient_shade: - cmp hallLevel3D, 0 - je @F - imul ebx, 7 - shr ebx, 3 -@@: - movzx edx, al - imul edx, ebx - shr edx, 8 - push edx - - movzx edx, ah - imul edx, ebx - shr edx, 8 - shl edx, 8 - - shr eax, 16 - movzx eax, al - imul eax, ebx - shr eax, 8 - shl eax, 16 - or eax, edx - pop edx - or eax, edx - - mov edx, ecx - imul edx, SCREEN_W - add edx, col - mov [screenBuffer + edx*4], eax - - add edi, esi - inc ecx - jmp draw_stripe_loop - -next_col: - inc col - jmp col_loop - -walls_done: - pop edi - pop esi - pop ebx - ret -RenderWallsRange ENDP - -; --- Raycasting Background Worker Thread --- -RaycastWorkerProc PROC uses ebx esi edi lpParam:DWORD -worker_loop: - invoke WaitForSingleObject, hRaycastStartEvent, 0FFFFFFFFh - cmp bRaycastQuit, 1 - je worker_exit - invoke RenderWallsRange, 320, 640 - invoke SetEvent, hRaycastDoneEvent - jmp worker_loop -worker_exit: - xor eax, eax - ret -RaycastWorkerProc ENDP - -; --- Multi-Threaded DDA Raycasting Walls Dispatcher --- -RenderWalls PROC - push ebx - push esi - push edi - - mov eax, playerAngle - and eax, 511 - mov ebx, [tableCos + eax*4] - mov playerDirX, ebx - mov ebx, [tableSin + eax*4] - mov playerDirY, ebx - - mov eax, ebx - imul eax, -66 - cdq - mov ecx, 100 - idiv ecx - mov playerPlaneX, eax - - mov eax, playerDirX - imul eax, 66 - cdq - idiv ecx - mov playerPlaneY, eax - - cmp hRaycastStartEvent, 0 - je single_thread_fallback - - ; Signal background worker to render columns [320..640) - invoke SetEvent, hRaycastStartEvent - - ; Main thread processes columns [0..320) in parallel - invoke RenderWallsRange, 0, 320 - - ; Synchronize with worker completion - invoke WaitForSingleObject, hRaycastDoneEvent, 0FFFFFFFFh - jmp walls_finished - -single_thread_fallback: - invoke RenderWallsRange, 0, SCREEN_W - -walls_finished: - pop edi - pop esi - pop ebx - ret -RenderWalls ENDP - -; --- Render 3D Billboard Sprites --- - -; --- HUD & Minimap Radar --- -RenderHUD PROC uses ebx esi edi - invoke DrawBox, 0, 0, 320, 16, 0014191Dh - invoke DrawString8x8, 8, 4, OFFSET textBank3D, 00D8BC6Ah - invoke FormatNumber, bankroll, OFFSET hudNumBuffer - invoke DrawString8x8, 64, 4, OFFSET hudNumBuffer, 00FFFFFFh - invoke DrawString8x8, 176, 4, OFFSET textWindowKeys3D, 00A8B6BBh - invoke DrawBox, 0, 226, 320, 14, 0014191Dh - invoke DrawString8x8, 12, 230, OFFSET textWalkKeys3D, 00A8B6BBh - invoke DrawBox, 159, 118, 2, 5, 00E7DFC8h - invoke DrawBox, 157, 120, 6, 1, 00E7DFC8h - cmp interactPromptPtr, 0 - je @F - invoke DrawBoxBorder, 4, 199, 312, 18, 0014191Dh, 00D8BC6Ah, 1 - invoke DrawString8x8, 10, 204, interactPromptPtr, 00F5E2B0h -@@: - cmp flashTimer, 0 - je hud_finished - dec flashTimer - invoke DrawBox, 4, 22, 312, 16, 0014191Dh - invoke DrawString8x8, 10, 26, OFFSET flashMessage, 00FFFFFFh -hud_finished: - ret -RenderHUD ENDP - -RenderMinimap PROC uses ebx esi edi - local radarX:DWORD - local radarY:DWORD - local radarSize:DWORD - - mov radarX, 320 - 48 - mov radarY, 20 - mov radarSize, 44 - - invoke DrawBoxBorder, radarX, radarY, radarSize, radarSize, 00101510h, 00FFD700h, 1 - - ; Draw Sprites on radar - cmp hallLevel3D, 0 - jne draw_player_radar - xor esi, esi -radar_spr_loop: - cmp esi, NUM_SPRITES - jge draw_player_radar - mov eax, esi - imul eax, SIZEOF SpriteObject - mov eax, [casinoSprites + eax].posX - sar eax, 16 - imul eax, radarSize - shr eax, 5 - add eax, radarX - mov ebx, eax - - mov eax, esi - imul eax, SIZEOF SpriteObject - mov eax, [casinoSprites + eax].posY - sar eax, 16 - imul eax, radarSize - shr eax, 5 - add eax, radarY - - invoke DrawPixel, ebx, eax, 00FFAA00h - inc esi - jmp radar_spr_loop - -draw_player_radar: - mov eax, playerX - sar eax, 16 - imul eax, radarSize - shr eax, 5 - add eax, radarX - mov ebx, eax - - mov eax, playerY - sar eax, 16 - imul eax, radarSize - shr eax, 5 - add eax, radarY - - invoke DrawCircle, ebx, eax, 2, 00FF2020h - ret -RenderMinimap ENDP - -; ============================================================================== -; IN-ENGINE 2.5D MINI-GAME: SLOTS 777 -; ============================================================================== -HandleSlotsInput PROC - cmp slotSpinState, 1 - je slots_input_done - - invoke Pressed3D, 20h ; SPACE -> Spin - test ah, 80h - jz check_bet_adjust - mov eax, bankroll - cmp eax, slotBet - jl @F - sub eax, slotBet - mov bankroll, eax - mov slotSpinState, 1 - mov slotSpinTimer, 0 - mov slotWinAmount, 0 - invoke PlayCasinoSound3D, OFFSET soundSlotSpin, 0, 1 - jmp slots_input_done -@@: - invoke CopyString3D, OFFSET msgNeedMoney, OFFSET flashMessage - mov flashTimer, 60 - -check_bet_adjust: - invoke Pressed3D, 26h ; UP / W - test ah, 80h - jnz inc_bet - invoke Pressed3D, 57h - test ah, 80h - jz check_bet_down -inc_bet: - cmp slotBet, 500 - jge slots_input_done - cmp slotBet, 100 - jge @F - cmp slotBet, 50 - jge set_100 - mov slotBet, 50 - jmp slots_input_done -set_100: - mov slotBet, 100 - jmp slots_input_done -@@: - mov slotBet, 500 - jmp slots_input_done - -check_bet_down: - invoke Pressed3D, 28h ; DOWN / S - test ah, 80h - jnz dec_bet - invoke Pressed3D, 53h - test ah, 80h - jz slots_input_done -dec_bet: - cmp slotBet, 50 - jle set_10 - cmp slotBet, 100 - jle set_50 - mov slotBet, 100 - jmp slots_input_done -set_50: - mov slotBet, 50 - jmp slots_input_done -set_10: - mov slotBet, 10 - -slots_input_done: - ret -HandleSlotsInput ENDP - -RenderSlotsGame PROC uses ebx esi edi - ; Cabinet Background (Dark Cherry Wood & Gold) - invoke DrawBox, 0, 0, SCREEN_W, SCREEN_H, 00150A10h - invoke DrawBoxBorder, 10, 10, 300, 220, 00251015h, 00FFD700h, 3 - - ; Illuminated Top Marquee - invoke DrawBoxBorder, 25, 20, 270, 32, 000A0505h, 00FFFF00h, 2 - invoke DrawString8x8, 55, 32, OFFSET textSlots3D, 00FFD700h - - ; Spinning Animation Logic - cmp slotSpinState, 1 - jne draw_reels - inc slotSpinTimer - - cmp slotSpinTimer, 22 - jge @F - invoke RandomRange3D, 7 - mov slotReel1, eax -@@: - cmp slotSpinTimer, 36 - jge @F - invoke RandomRange3D, 7 - mov slotReel2, eax -@@: - cmp slotSpinTimer, 50 - jge @F - invoke RandomRange3D, 7 - mov slotReel3, eax -@@: - cmp slotSpinTimer, 50 - jl draw_reels - - ; Spin finished! Check outcome! - mov slotSpinState, 0 - mov eax, slotReel1 - cmp eax, slotReel2 - jne check_pairs - cmp eax, slotReel3 - jne check_pairs - - ; 3 Matching! - cmp eax, 0 ; 777! - jne @F - mov eax, slotBet - imul eax, 25 - mov slotWinAmount, eax - add bankroll, eax - invoke PlayCasinoSound3D, OFFSET soundJackpot, 0, 1 - jmp draw_reels -@@: - cmp eax, 6 ; CROWN! - jne @F - mov eax, slotBet - imul eax, 50 - mov slotWinAmount, eax - add bankroll, eax - invoke PlayCasinoSound3D, OFFSET soundJackpot, 0, 1 - jmp draw_reels -@@: - mov eax, slotBet - imul eax, 10 - mov slotWinAmount, eax - add bankroll, eax - invoke PlayCasinoSound3D, OFFSET soundRoundWin, 0, 1 - jmp draw_reels - -check_pairs: - mov eax, slotReel1 - cmp eax, slotReel2 - je pair_win - mov eax, slotReel2 - cmp eax, slotReel3 - je pair_win - mov eax, slotReel1 - cmp eax, slotReel3 - je pair_win - jmp draw_reels -pair_win: - mov eax, slotBet - imul eax, 2 - mov slotWinAmount, eax - add bankroll, eax - invoke PlayCasinoSound3D, OFFSET soundRoundWin, 0, 1 - -draw_reels: - ; Reels Window - invoke DrawBoxBorder, 30, 62, 260, 95, 000F0F12h, 0000A5FFh, 2 - - ; Reel 1 (45..105) - invoke DrawBoxBorder, 45, 68, 65, 82, 00F0F0F5h, 00505050h, 2 - mov eax, slotReel1 - call DrawReelSymbolAt1 - - ; Reel 2 (128..188) - invoke DrawBoxBorder, 128, 68, 65, 82, 00F0F0F5h, 00505050h, 2 - mov eax, slotReel2 - call DrawReelSymbolAt2 - - ; Reel 3 (210..270) - invoke DrawBoxBorder, 210, 68, 65, 82, 00F0F0F5h, 00505050h, 2 - mov eax, slotReel3 - call DrawReelSymbolAt3 - - ; Bottom Control Panel - invoke DrawBoxBorder, 20, 165, 280, 58, 00151515h, 00FFD700h, 1 - - invoke DrawString8x8, 28, 172, OFFSET textBank3D, 00FFD700h - invoke FormatNumber, bankroll, OFFSET hudNumBuffer - invoke DrawString8x8, 110, 172, OFFSET hudNumBuffer, 00FFFF00h - - invoke DrawString8x8, 175, 172, OFFSET textBet3D, 00FFD700h - invoke FormatNumber, slotBet, OFFSET hudNumBuffer - invoke DrawString8x8, 240, 172, OFFSET hudNumBuffer, 0050FF50h - - cmp slotWinAmount, 0 - jle draw_slot_ctrls - invoke DrawString8x8, 28, 187, OFFSET strWin, 00FFFF00h - invoke FormatNumber, slotWinAmount, OFFSET hudNumBuffer - invoke DrawString8x8, 110, 187, OFFSET hudNumBuffer, 00FFFF00h - -draw_slot_ctrls: - invoke DrawString8x8, 28, 204, OFFSET textSlotsKeys3D, 00A0A0A0h - ret -RenderSlotsGame ENDP - -DrawReelSymbolAt1 PROC - cmp eax, 0 - jne @F - invoke DrawString8x8, 52, 105, OFFSET sym7, 00FF2020h - ret -@@: - cmp eax, 1 - jne @F - invoke DrawString8x8, 52, 105, OFFSET symBar, 00FFAA00h - ret -@@: - cmp eax, 2 - jne @F - invoke DrawString8x8, 52, 105, OFFSET symBell, 00FFD700h - ret -@@: - cmp eax, 3 - jne @F - invoke DrawString8x8, 48, 105, OFFSET symCherry, 000000D0h - ret -@@: - cmp eax, 4 - jne @F - invoke DrawString8x8, 48, 105, OFFSET symClover, 0000A000h - ret -@@: - cmp eax, 5 - jne @F - invoke DrawString8x8, 52, 105, OFFSET symGem, 00FFFF00h - ret -@@: - invoke DrawString8x8, 52, 105, OFFSET symCrown, 00FFD700h - ret -DrawReelSymbolAt1 ENDP - -DrawReelSymbolAt2 PROC - cmp eax, 0 - jne @F - invoke DrawString8x8, 135, 105, OFFSET sym7, 00FF2020h - ret -@@: - cmp eax, 1 - jne @F - invoke DrawString8x8, 135, 105, OFFSET symBar, 00FFAA00h - ret -@@: - cmp eax, 2 - jne @F - invoke DrawString8x8, 135, 105, OFFSET symBell, 00FFD700h - ret -@@: - cmp eax, 3 - jne @F - invoke DrawString8x8, 131, 105, OFFSET symCherry, 000000D0h - ret -@@: - cmp eax, 4 - jne @F - invoke DrawString8x8, 131, 105, OFFSET symClover, 0000A000h - ret -@@: - cmp eax, 5 - jne @F - invoke DrawString8x8, 135, 105, OFFSET symGem, 00FFFF00h - ret -@@: - invoke DrawString8x8, 135, 105, OFFSET symCrown, 00FFD700h - ret -DrawReelSymbolAt2 ENDP - -DrawReelSymbolAt3 PROC - cmp eax, 0 - jne @F - invoke DrawString8x8, 218, 105, OFFSET sym7, 00FF2020h - ret -@@: - cmp eax, 1 - jne @F - invoke DrawString8x8, 218, 105, OFFSET symBar, 00FFAA00h - ret -@@: - cmp eax, 2 - jne @F - invoke DrawString8x8, 218, 105, OFFSET symBell, 00FFD700h - ret -@@: - cmp eax, 3 - jne @F - invoke DrawString8x8, 214, 105, OFFSET symCherry, 000000D0h - ret -@@: - cmp eax, 4 - jne @F - invoke DrawString8x8, 214, 105, OFFSET symClover, 0000A000h - ret -@@: - cmp eax, 5 - jne @F - invoke DrawString8x8, 218, 105, OFFSET symGem, 00FFFF00h - ret -@@: - invoke DrawString8x8, 218, 105, OFFSET symCrown, 00FFD700h - ret -DrawReelSymbolAt3 ENDP - -; ============================================================================== -; IN-ENGINE 2.5D MINI-GAME: BLACKJACK (21) -; ============================================================================== -HandleBlackjackInput PROC uses ebx - cmp bjState, 0 ; Need Deal - jne check_bj_player_turn - invoke Pressed3D, 20h ; SPACE -> Deal - test ah, 80h - jz check_bj_bet_change - mov eax, bankroll - cmp eax, bjBet - jl bj_need_cash - sub eax, bjBet - mov bankroll, eax - - ; Deal 2 cards to player, 2 cards to dealer - mov bjPlayerCardCount, 0 - mov bjDealerCardCount, 0 - mov bjDealerHideHole, 1 - - ; Player Card 1 - invoke RandomRange3D, 13 - inc eax - mov ebx, bjPlayerCardCount - mov [bjPlayerCards + ebx*4], eax - inc bjPlayerCardCount - - ; Dealer Card 1 - invoke RandomRange3D, 13 - inc eax - mov ebx, bjDealerCardCount - mov [bjDealerCards + ebx*4], eax - inc bjDealerCardCount - - ; Player Card 2 - invoke RandomRange3D, 13 - inc eax - mov ebx, bjPlayerCardCount - mov [bjPlayerCards + ebx*4], eax - inc bjPlayerCardCount - - ; Dealer Card 2 (Hole card) - invoke RandomRange3D, 13 - inc eax - mov ebx, bjDealerCardCount - mov [bjDealerCards + ebx*4], eax - inc bjDealerCardCount - - invoke PlayCasinoSound3D, OFFSET soundCards, 0, 1 - - ; Calc Player Score - call CalcPlayerBJScore - cmp bjPlayerScore, 21 - jne set_bj_turn - ; Instant Blackjack! - mov bjDealerHideHole, 0 - mov eax, bjBet - imul eax, 5 - shr eax, 1 - add bankroll, eax - invoke CopyString3D, OFFSET strWin, OFFSET bjOutcomeMsg - invoke PlayCasinoSound3D, OFFSET soundRoundWin, 0, 1 - mov bjState, 2 - ret -set_bj_turn: - mov bjState, 1 - mov BYTE PTR [bjOutcomeMsg], 0 - ret - -bj_need_cash: - invoke CopyString3D, OFFSET msgNeedMoney, OFFSET flashMessage - mov flashTimer, 60 - ret - -check_bj_player_turn: - cmp bjState, 1 - jne check_bj_round_over - - invoke Pressed3D, 48h ; 'H' -> Hit - test ah, 80h - jz check_bj_stand - invoke RandomRange3D, 13 - inc eax - mov ebx, bjPlayerCardCount - cmp ebx, 8 - jge @F - mov [bjPlayerCards + ebx*4], eax - inc bjPlayerCardCount -@@: - invoke PlayCasinoSound3D, OFFSET soundCards, 0, 1 - call CalcPlayerBJScore - cmp bjPlayerScore, 21 - jle bj_input_done - ; Bust! - invoke CopyString3D, OFFSET strPlayerBust, OFFSET bjOutcomeMsg - mov bjDealerHideHole, 0 - mov bjState, 2 - ret - -check_bj_stand: - invoke Pressed3D, 53h ; 'S' -> Stand - test ah, 80h - jz bj_input_done - - ; Dealer Turn - mov bjDealerHideHole, 0 -dealer_loop: - call CalcDealerBJScore - cmp bjDealerScore, 17 - jge dealer_finished - invoke RandomRange3D, 13 - inc eax - mov ebx, bjDealerCardCount - cmp ebx, 8 - jge dealer_finished - mov [bjDealerCards + ebx*4], eax - inc bjDealerCardCount - jmp dealer_loop - -dealer_finished: - cmp bjDealerScore, 21 - jle compare_scores - ; Dealer Bust! - mov eax, bjBet - shl eax, 1 - add bankroll, eax - invoke CopyString3D, OFFSET strDealerBust, OFFSET bjOutcomeMsg - invoke PlayCasinoSound3D, OFFSET soundRoundWin, 0, 1 - mov bjState, 2 - ret - -compare_scores: - mov eax, bjPlayerScore - cmp eax, bjDealerScore - jle check_dealer_won - ; Player Won! - mov eax, bjBet - shl eax, 1 - add bankroll, eax - invoke CopyString3D, OFFSET strWin, OFFSET bjOutcomeMsg - invoke PlayCasinoSound3D, OFFSET soundRoundWin, 0, 1 - mov bjState, 2 - ret -check_dealer_won: - cmp eax, bjDealerScore - jl dealer_wins - ; Push (Tie) - mov eax, bjBet - add bankroll, eax - invoke CopyString3D, OFFSET strPush, OFFSET bjOutcomeMsg - mov bjState, 2 - ret -dealer_wins: - invoke CopyString3D, OFFSET strLose, OFFSET bjOutcomeMsg - mov bjState, 2 - ret - -check_bj_round_over: - invoke Pressed3D, 20h ; SPACE -> Next Hand - test ah, 80h - jz bj_input_done - mov bjState, 0 - ret - -check_bj_bet_change: - invoke Pressed3D, 26h ; UP - test ah, 80h - jz @F - cmp bjBet, 500 - jge bj_input_done - add bjBet, 50 - ret -@@: - invoke Pressed3D, 28h ; DOWN - test ah, 80h - jz bj_input_done - cmp bjBet, 50 - jle bj_input_done - sub bjBet, 50 - -bj_input_done: - ret -HandleBlackjackInput ENDP - -CalcPlayerBJScore PROC uses ebx esi - xor eax, eax - xor ebx, ebx - xor esi, esi -calc_p_loop: - cmp esi, bjPlayerCardCount - jge calc_p_done - mov edx, [bjPlayerCards + esi*4] - cmp edx, 10 - jle @F - mov edx, 10 -@@: - cmp edx, 1 - jne add_p_val - inc ebx ; count Aces - add eax, 11 - jmp next_p_card -add_p_val: - add eax, edx -next_p_card: - inc esi - jmp calc_p_loop -calc_p_done: - ; Soft Ace reduction -reduce_p_ace: - cmp eax, 21 - jle store_p_score - test ebx, ebx - jz store_p_score - sub eax, 10 - dec ebx - jmp reduce_p_ace -store_p_score: - mov bjPlayerScore, eax - ret -CalcPlayerBJScore ENDP - -CalcDealerBJScore PROC uses ebx esi - xor eax, eax - xor ebx, ebx - xor esi, esi -calc_d_loop: - cmp esi, bjDealerCardCount - jge calc_d_done - mov edx, [bjDealerCards + esi*4] - cmp edx, 10 - jle @F - mov edx, 10 -@@: - cmp edx, 1 - jne add_d_val - inc ebx - add eax, 11 - jmp next_d_card -add_d_val: - add eax, edx -next_d_card: - inc esi - jmp calc_d_loop -calc_d_done: -reduce_d_ace: - cmp eax, 21 - jle store_d_score - test ebx, ebx - jz store_d_score - sub eax, 10 - dec ebx - jmp reduce_d_ace -store_d_score: - mov bjDealerScore, eax - ret -CalcDealerBJScore ENDP - -RenderBlackjackGame PROC uses ebx esi edi - ; Emerald Felt Table Background - invoke DrawBox, 0, 0, SCREEN_W, SCREEN_H, 000A3015h - invoke DrawBoxBorder, 10, 10, 300, 220, 000D4018h, 00FFD700h, 3 - - ; Dealer Area Top - invoke DrawString8x8, 25, 20, OFFSET textBJ3D, 00FFD700h - invoke DrawString8x8, 25, 35, OFFSET textDealer3D, 00FFFFFFh - invoke FormatNumber, bjDealerScore, OFFSET hudNumBuffer - invoke DrawString8x8, 120, 35, OFFSET hudNumBuffer, 00FFFF00h - - ; Dealer Cards - xor esi, esi -draw_dealer_cards: - cmp esi, bjDealerCardCount - jge draw_player_bj_area - mov eax, esi - imul eax, 45 - add eax, 25 - mov ebx, eax - - cmp esi, 1 - jne draw_dealer_face - cmp bjDealerHideHole, 1 - jne draw_dealer_face - ; Face Down Card - mov eax, selectedBack3D - mov eax, cardBackColors3D[eax*4] - invoke DrawBoxBorder, ebx, 48, 38, 52, eax, 00FFFFFFh, 2 - jmp next_dealer_card_draw - -draw_dealer_face: - invoke DrawBoxBorder, ebx, 48, 38, 52, 00F0F0F5h, 00000000h, 2 - mov eax, [bjDealerCards + esi*4] - dec eax - imul eax, 3 - lea edx, [cardRankStr + eax] - mov eax, ebx - add eax, 8 - invoke DrawString8x8, eax, 68, edx, 00000000h - -next_dealer_card_draw: - inc esi - jmp draw_dealer_cards - -draw_player_bj_area: - ; Player Area Bottom - invoke DrawString8x8, 25, 110, OFFSET textPlayer3D, 00FFFFFFh - invoke FormatNumber, bjPlayerScore, OFFSET hudNumBuffer - invoke DrawString8x8, 120, 110, OFFSET hudNumBuffer, 0050FF50h - - ; Player Cards - xor esi, esi -draw_player_cards: - cmp esi, bjPlayerCardCount - jge draw_bj_footer - mov eax, esi - imul eax, 45 - add eax, 25 - mov ebx, eax - - invoke DrawBoxBorder, ebx, 124, 38, 52, 00F0F0F5h, 00000000h, 2 - mov eax, [bjPlayerCards + esi*4] - dec eax - imul eax, 3 - lea edx, [cardRankStr + eax] - mov eax, ebx - add eax, 8 - invoke DrawString8x8, eax, 144, edx, 00000000h - - inc esi - jmp draw_player_cards - -draw_bj_footer: - ; Footer Status & Controls - invoke DrawBoxBorder, 20, 182, 280, 42, 00102010h, 00FFD700h, 1 - cmp BYTE PTR [bjOutcomeMsg], 0 - je draw_bj_controls - invoke DrawString8x8, 28, 188, OFFSET bjOutcomeMsg, 00FFFF00h - invoke DrawString8x8, 28, 204, OFFSET textNext3D, 00A0A0A0h - ret - -draw_bj_controls: - invoke DrawString8x8, 28, 188, OFFSET textBJKeys3D, 00FFFFFFh - invoke DrawString8x8, 28, 204, OFFSET textDeal3D, 00A0A0A0h - ret -RenderBlackjackGame ENDP - -; ============================================================================== -; IN-ENGINE 2.5D MINI-GAME: ROULETTE -; ============================================================================== -HandleRouletteInput PROC uses ebx - cmp roulState, 1 - je roul_input_done - - invoke Pressed3D, 31h ; '1' -> RED - test ah, 80h - jz @F - mov roulBetType, 1 -@@: - invoke Pressed3D, 32h ; '2' -> BLACK - test ah, 80h - jz @F - mov roulBetType, 2 -@@: - invoke Pressed3D, 33h ; '3' -> ZERO (0) - test ah, 80h - jz @F - mov roulBetType, 3 -@@: - invoke Pressed3D, 34h ; '4' -> EVEN - test ah, 80h - jz @F - mov roulBetType, 4 -@@: - invoke Pressed3D, 35h ; '5' -> ODD - test ah, 80h - jz check_roul_spin - mov roulBetType, 5 - -check_roul_spin: - invoke Pressed3D, 20h ; SPACE -> Spin - test ah, 80h - jz roul_input_done - mov eax, bankroll - cmp eax, roulBetAmount - jl roul_no_cash - sub eax, roulBetAmount - mov bankroll, eax - mov roulState, 1 - mov roulSpinTimer, 50 - mov roulPayout, 0 - invoke PlayCasinoSound3D, OFFSET soundRoulette, 0, 1 - ret - -roul_no_cash: - invoke CopyString3D, OFFSET msgNeedMoney, OFFSET flashMessage - mov flashTimer, 60 - -roul_input_done: - ret -HandleRouletteInput ENDP - -RenderRouletteGame PROC uses ebx esi edi - ; Table felt background - invoke DrawBox, 0, 0, SCREEN_W, SCREEN_H, 00151525h - invoke DrawBoxBorder, 10, 10, 300, 220, 00201525h, 00FFD700h, 3 - - ; 2.5D Rotating Wheel on Left - invoke DrawCircle, 85, 110, 65, 00102550h - invoke DrawCircle, 85, 110, 60, 00FFD700h - invoke DrawCircle, 85, 110, 52, 00101010h - invoke DrawCircle, 85, 110, 22, 00FFD700h ; Center brass turret - - ; Spinning Wheel / Ball Logic - cmp roulState, 1 - jne draw_roul_ball - dec roulSpinTimer - add roulWheelAngle, 8 - sub roulBallAngle, 14 - cmp roulSpinTimer, 0 - jg draw_roul_ball - - ; Wheel stopped! Determine result! - mov roulState, 2 - invoke RandomRange3D, 37 - mov roulWinningNum, eax - - ; Check bet - cmp roulBetType, 1 ; RED - jne check_ro_black - call IsNumberRed - test eax, eax - jz ro_lost - mov eax, roulBetAmount - shl eax, 1 - mov roulPayout, eax - add bankroll, eax - invoke CopyString3D, OFFSET strWin, OFFSET roulOutcomeMsg - invoke PlayCasinoSound3D, OFFSET soundRoundWin, 0, 1 - jmp draw_roul_ball - -check_ro_black: - cmp roulBetType, 2 ; BLACK - jne check_ro_zero - cmp roulWinningNum, 0 - je ro_lost - call IsNumberRed - test eax, eax - jnz ro_lost - mov eax, roulBetAmount - shl eax, 1 - mov roulPayout, eax - add bankroll, eax - invoke CopyString3D, OFFSET strWin, OFFSET roulOutcomeMsg - invoke PlayCasinoSound3D, OFFSET soundRoundWin, 0, 1 - jmp draw_roul_ball - -check_ro_zero: - cmp roulBetType, 3 ; ZERO - jne check_ro_even - cmp roulWinningNum, 0 - jne ro_lost - mov eax, roulBetAmount - imul eax, 36 - mov roulPayout, eax - add bankroll, eax - invoke CopyString3D, OFFSET strJackpot, OFFSET roulOutcomeMsg - invoke PlayCasinoSound3D, OFFSET soundJackpot, 0, 1 - jmp draw_roul_ball - -check_ro_even: - cmp roulBetType, 4 ; EVEN - jne check_ro_odd - mov eax, roulWinningNum - test eax, eax - jz ro_lost - test al, 1 - jnz ro_lost - mov eax, roulBetAmount - shl eax, 1 - mov roulPayout, eax - add bankroll, eax - invoke CopyString3D, OFFSET strWin, OFFSET roulOutcomeMsg - invoke PlayCasinoSound3D, OFFSET soundRoundWin, 0, 1 - jmp draw_roul_ball - -check_ro_odd: - mov eax, roulWinningNum - test eax, eax - jz ro_lost - test al, 1 - jz ro_lost - mov eax, roulBetAmount - shl eax, 1 - mov roulPayout, eax - add bankroll, eax - invoke CopyString3D, OFFSET strWin, OFFSET roulOutcomeMsg - invoke PlayCasinoSound3D, OFFSET soundRoundWin, 0, 1 - jmp draw_roul_ball - -ro_lost: - invoke CopyString3D, OFFSET strLose, OFFSET roulOutcomeMsg - -draw_roul_ball: - ; Draw White Ball on Rim - mov eax, roulBallAngle - and eax, 511 - mov ebx, [tableCos + eax*4] - imul ebx, 42 - sar ebx, 16 - add ebx, 85 - - mov eax, roulBallAngle - and eax, 511 - mov edx, [tableSin + eax*4] - imul edx, 42 - sar edx, 16 - add edx, 110 - invoke DrawCircle, ebx, edx, 3, 00FFFFFFh - - ; Right Betting Board - invoke DrawBoxBorder, 175, 25, 125, 28, 001010C0h, 00FFFFFFh, 2 ; [1] RED - invoke DrawString8x8, 190, 35, OFFSET textRed3D, 00FFFFFFh - - invoke DrawBoxBorder, 175, 60, 125, 28, 00151515h, 00FFFFFFh, 2 ; [2] BLACK - invoke DrawString8x8, 190, 70, OFFSET textBlack3D, 00FFFFFFh - - invoke DrawBoxBorder, 175, 95, 125, 28, 00106010h, 00FFFFFFh, 2 ; [3] ZERO - invoke DrawString8x8, 190, 105, OFFSET textZero3D, 00FFFFFFh - - invoke DrawBoxBorder, 175, 130, 60, 26, 00302020h, 00FFFFFFh, 1 ; [4] EVEN - invoke DrawString8x8, 185, 139, OFFSET textEven3D, 00FFFFFFh - - invoke DrawBoxBorder, 240, 130, 60, 26, 00302020h, 00FFFFFFh, 1 ; [5] ODD - invoke DrawString8x8, 250, 139, OFFSET textOdd3D, 00FFFFFFh - - ; Highlight Active Bet - cmp roulBetType, 1 - jne @F - invoke DrawBoxBorder, 173, 23, 129, 32, 0, 00FFFF00h, 2 -@@: - cmp roulBetType, 2 - jne @F - invoke DrawBoxBorder, 173, 58, 129, 32, 0, 00FFFF00h, 2 -@@: - cmp roulBetType, 3 - jne @F - invoke DrawBoxBorder, 173, 93, 129, 32, 0, 00FFFF00h, 2 -@@: - cmp roulBetType, 4 - jne @F - invoke DrawBoxBorder, 173, 128, 64, 30, 0, 00FFFF00h, 2 -@@: - cmp roulBetType, 5 - jne draw_ro_footer - invoke DrawBoxBorder, 238, 128, 64, 30, 0, 00FFFF00h, 2 - -draw_ro_footer: - invoke DrawBoxBorder, 20, 180, 280, 42, 00101015h, 00FFD700h, 1 - - cmp roulState, 2 - jne @F - invoke DrawString8x8, 28, 186, OFFSET textResult3D, 00FFD700h - invoke FormatNumber, roulWinningNum, OFFSET hudNumBuffer - invoke DrawString8x8, 85, 186, OFFSET hudNumBuffer, 00FFFF00h - invoke DrawString8x8, 130, 186, OFFSET roulOutcomeMsg, 0050FF50h -@@: - invoke DrawString8x8, 28, 202, OFFSET textSpin3D, 00A0A0A0h - ret -RenderRouletteGame ENDP - -IsNumberRed PROC - mov eax, roulWinningNum - cmp eax, 1 - je red_yes - cmp eax, 3 - je red_yes - cmp eax, 5 - je red_yes - cmp eax, 7 - je red_yes - cmp eax, 9 - je red_yes - cmp eax, 12 - je red_yes - cmp eax, 14 - je red_yes - cmp eax, 16 - je red_yes - cmp eax, 18 - je red_yes - cmp eax, 19 - je red_yes - cmp eax, 21 - je red_yes - cmp eax, 23 - je red_yes - cmp eax, 25 - je red_yes - cmp eax, 27 - je red_yes - cmp eax, 30 - je red_yes - cmp eax, 32 - je red_yes - cmp eax, 34 - je red_yes - cmp eax, 36 - je red_yes - xor eax, eax - ret -red_yes: - mov eax, 1 - ret -IsNumberRed ENDP - -; ============================================================================== -; IN-ENGINE 2.5D MINI-GAME: BAR & SHOP -; ============================================================================== -HandleShopInput PROC uses ebx esi - xor esi, esi -shop_choice: - inc esi - lea eax, [esi+30h] - invoke Pressed3D, eax - test eax, eax - jnz shop_chosen - cmp esi, 3 - jb shop_choice - ret -shop_chosen: - bt ownedBacks3D, esi - jc shop_equip - mov ebx, 1500 - cmp esi, 1 - jne @F - mov ebx, 1000 -@@: - cmp bankroll, ebx - jb shop_no_money - sub bankroll, ebx - bts ownedBacks3D, esi -shop_equip: - mov selectedBack3D, esi - invoke CopyString3D, OFFSET textBought3D, OFFSET shopMsg - call SaveProgress3D - ret -shop_no_money: - invoke CopyString3D, OFFSET textNoCash3D, OFFSET shopMsg - ret -HandleShopInput ENDP - -RenderShopGame PROC - invoke DrawBox, 0, 0, SCREEN_W, SCREEN_H, 00150A0Ah - invoke DrawBoxBorder, 10, 10, 300, 220, 00251515h, 00FFD700h, 3 - invoke DrawString8x8, 25, 20, OFFSET textShop3D, 00FFD700h - - invoke DrawBoxBorder, 20, 40, 280, 32, 001A1010h, 00FFFFFFh, 1 - invoke DrawString8x8, 28, 46, OFFSET textItem1_3D, 00FFFF00h - invoke DrawString8x8, 28, 58, OFFSET textShopHint3D, 00A0A0A0h - - invoke DrawBoxBorder, 20, 80, 280, 32, 001A1010h, 00FFFFFFh, 1 - invoke DrawString8x8, 28, 86, OFFSET textItem2_3D, 00FFFF00h - invoke DrawString8x8, 28, 98, OFFSET textShopHint3D, 00A0A0A0h - - invoke DrawBoxBorder, 20, 120, 280, 32, 001A1010h, 00FFFFFFh, 1 - invoke DrawString8x8, 28, 126, OFFSET textItem3_3D, 00FFFF00h - invoke DrawString8x8, 28, 138, OFFSET textShopHint3D, 00A0A0A0h - - invoke DrawBoxBorder, 20, 165, 280, 55, 00100A0Ah, 00FFD700h, 1 - invoke DrawString8x8, 28, 172, OFFSET textBank3D, 00FFD700h - invoke FormatNumber, bankroll, OFFSET hudNumBuffer - invoke DrawString8x8, 110, 172, OFFSET hudNumBuffer, 00FFFF00h - - cmp BYTE PTR [shopMsg], 0 - je @F - invoke DrawString8x8, 28, 188, OFFSET shopMsg, 0050FF50h -@@: - invoke DrawString8x8, 28, 204, OFFSET textBack3D, 00A0A0A0h - ret -RenderShopGame ENDP - -; ============================================================================== -; IN-ENGINE 2.5D MINI-GAME: ATM TERMINAL -; ============================================================================== -HandleATMInput PROC - ret -HandleATMInput ENDP - -RenderATMGame PROC - invoke DrawBox, 0, 0, 320, 240, 00172120h - invoke DrawString8x8, 24, 30, OFFSET textATM3D, 00D8BC6Ah - invoke DrawString8x8, 24, 70, OFFSET textBank3D, 00FFFFFFh - invoke FormatNumber, bankroll, OFFSET hudNumBuffer - invoke DrawString8x8, 96, 70, OFFSET hudNumBuffer, 0089DAB2h - invoke DrawString8x8, 24, 115, OFFSET textATMNote3D, 00B7C8C1h - invoke DrawString8x8, 24, 140, OFFSET textATMNote2_3D, 00B7C8C1h - invoke DrawString8x8, 24, 208, OFFSET textBack3D, 00D8BC6Ah - ret -RenderATMGame ENDP - -; ============================================================================== -; ============================================================================== -; ============================================================================== -; SHARED RICH UI PROCEDURES -; ============================================================================== -DrawKeycap3D PROC uses ebx esi edi, x:DWORD, y:DWORD, strPtr:DWORD, isActive:DWORD - local keyW:DWORD - mov esi, strPtr - xor ecx, ecx -keycap_len: - mov al, [esi+ecx] - test al, al - jz keycap_len_done - inc ecx - jmp keycap_len -keycap_len_done: - shl ecx, 3 - add ecx, 8 - mov keyW, ecx - - ; Drop shadow - mov eax, y - add eax, 2 - invoke DrawBox, x, eax, keyW, 13, 0008080Ch - - ; Border and Fill - cmp isActive, 0 - je keycap_inactive - mov eax, 00FFFF00h ; Bright Yellow active border - mov edx, 001B4B22h ; Casino Green active fill - mov ebx, 00FFFF00h ; Bright Yellow active text - jmp keycap_draw_box -keycap_inactive: - mov eax, 00606870h ; Slate inactive border - mov edx, 001A1C22h ; Charcoal inactive fill - mov ebx, 00D0D8E0h ; Silver inactive text - -keycap_draw_box: - push ebx - invoke DrawBoxBorder, x, y, keyW, 13, edx, eax, 1 - pop ebx - - ; Text label - mov eax, x - add eax, 4 - mov edx, y - add edx, 3 - invoke DrawString8x8, eax, edx, strPtr, ebx - - mov eax, keyW - add eax, 4 - ret -DrawKeycap3D ENDP - -DrawChipStack PROC uses ebx esi edi, x:DWORD, y:DWORD, chipCount:DWORD - mov edi, chipCount - xor esi, esi -chip_loop: - cmp esi, edi - jge chip_done - mov eax, esi - shl eax, 2 - mov edx, y - sub edx, eax - - ; Shadow - mov eax, x - add eax, 2 - mov ecx, edx - add ecx, 5 - invoke DrawBox, eax, ecx, 20, 2, 00061004h - - ; Red Clay Chip body with white rim - invoke DrawBoxBorder, x, edx, 24, 6, 00B81515h, 00FFFFFFh, 1 - - ; White stripe inlays - mov eax, x - add eax, 4 - mov ecx, edx - add ecx, 1 - invoke DrawBox, eax, ecx, 3, 4, 00FFFFFFh - - mov eax, x - add eax, 17 - mov ecx, edx - add ecx, 1 - invoke DrawBox, eax, ecx, 3, 4, 00FFFFFFh - - inc esi - jmp chip_loop -chip_done: - ret -DrawChipStack ENDP - -DrawDetailedCoin PROC uses ebx esi edi, cxVal:DWORD, cyVal:DWORD, rxVal:DWORD, ryVal:DWORD, outerColor:DWORD, innerColor:DWORD, reliefType:DWORD - local rxSq:DWORD - local rySq:DWORD - local rxRySq:DWORD - local threshSq:DWORD - local curDy:DWORD - local curDx:DWORD - local curX:DWORD - local curY:DWORD - - mov eax, rxVal - cmp eax, 0 - jle coin_draw_done - mov eax, ryVal - cmp eax, 0 - jle coin_draw_done - - mov eax, rxVal - imul eax, rxVal - mov rxSq, eax - - mov eax, ryVal - imul eax, ryVal - mov rySq, eax - - imul eax, rxSq - mov rxRySq, eax - - ; 3/4 threshold for rim bevel - mov ecx, 3 - imul eax, ecx - shr eax, 2 - mov threshSq, eax - - ; Scan rows - mov eax, ryVal - neg eax - mov curDy, eax -coin_row_loop: - mov eax, curDy - cmp eax, ryVal - jg coin_relief_check - - mov edx, cyVal - add edx, curDy - mov curY, edx - - ; Scan columns - mov eax, rxVal - neg eax - mov curDx, eax -coin_col_loop: - mov eax, curDx - cmp eax, rxVal - jg coin_col_next_row - - mov ecx, cxVal - add ecx, curDx - mov curX, ecx - - ; val = dx*dx*rySq + dy*dy*rxSq - mov eax, curDx - imul eax, curDx - imul eax, rySq - mov ebx, eax - - mov eax, curDy - imul eax, curDy - imul eax, rxSq - add eax, ebx - - cmp eax, rxRySq - ja coin_pixel_outside - - cmp eax, threshSq - jb coin_draw_inner - invoke DrawPixel, curX, curY, outerColor - jmp coin_pixel_outside -coin_draw_inner: - invoke DrawPixel, curX, curY, innerColor - -coin_pixel_outside: - inc curDx - jmp coin_col_loop - -coin_col_next_row: - inc curDy - jmp coin_row_loop - -coin_relief_check: - cmp rxVal, 14 - jl coin_draw_done - - cmp reliefType, 1 - je coin_draw_eagle - cmp reliefType, 2 - je coin_draw_numeral - jmp coin_draw_done - -coin_draw_eagle: - ; Imperial Eagle relief (Dark Gold 009A7A00h / Bright 00FFD700h) - mov eax, cxVal - sub eax, 3 - mov edx, cyVal - sub edx, 14 - invoke DrawBox, eax, edx, 7, 2, 009A7A00h - - mov eax, cxVal - sub eax, 4 - mov edx, cyVal - sub edx, 12 - invoke DrawBox, eax, edx, 9, 2, 009A7A00h - - mov eax, cxVal - sub eax, 2 - mov edx, cyVal - sub edx, 9 - invoke DrawBox, eax, edx, 5, 12, 009A7A00h - - mov eax, cxVal - sub eax, 1 - mov edx, cyVal - sub edx, 8 - invoke DrawBox, eax, edx, 3, 10, 00FFD700h - - mov eax, cxVal - sub eax, 10 - mov edx, cyVal - sub edx, 8 - invoke DrawBox, eax, edx, 7, 3, 009A7A00h - - mov eax, cxVal - sub eax, 13 - mov edx, cyVal - sub edx, 5 - invoke DrawBox, eax, edx, 10, 3, 009A7A00h - - mov eax, cxVal - sub eax, 11 - mov edx, cyVal - sub edx, 2 - invoke DrawBox, eax, edx, 7, 3, 009A7A00h - - mov eax, cxVal - add eax, 4 - mov edx, cyVal - sub edx, 8 - invoke DrawBox, eax, edx, 7, 3, 009A7A00h - - mov eax, cxVal - add eax, 4 - mov edx, cyVal - sub edx, 5 - invoke DrawBox, eax, edx, 10, 3, 009A7A00h - - mov eax, cxVal - add eax, 5 - mov edx, cyVal - sub edx, 2 - invoke DrawBox, eax, edx, 7, 3, 009A7A00h - - mov eax, cxVal - sub eax, 4 - mov edx, cyVal - add edx, 4 - invoke DrawBox, eax, edx, 9, 3, 009A7A00h - - mov eax, cxVal - sub eax, 3 - mov edx, cyVal - add edx, 7 - invoke DrawBox, eax, edx, 7, 3, 009A7A00h - jmp coin_draw_done - -coin_draw_numeral: - ; Roman numeral 'I' & laurel - mov eax, cxVal - sub eax, 5 - mov edx, cyVal - sub edx, 10 - invoke DrawBox, eax, edx, 11, 3, 009A7A00h - - mov eax, cxVal - sub eax, 2 - mov edx, cyVal - sub edx, 7 - invoke DrawBox, eax, edx, 5, 14, 009A7A00h - - mov eax, cxVal - sub eax, 1 - mov edx, cyVal - sub edx, 6 - invoke DrawBox, eax, edx, 3, 12, 00FFD700h - - mov eax, cxVal - sub eax, 6 - mov edx, cyVal - add edx, 7 - invoke DrawBox, eax, edx, 13, 3, 009A7A00h - - ; Laurel dots - mov eax, cxVal - sub eax, 12 - mov edx, cyVal - sub edx, 8 - invoke DrawBox, eax, edx, 2, 2, 009A7A00h - - mov eax, cxVal - add eax, 11 - mov edx, cyVal - sub edx, 8 - invoke DrawBox, eax, edx, 2, 2, 009A7A00h - - mov eax, cxVal - sub eax, 12 - mov edx, cyVal - invoke DrawBox, eax, edx, 2, 2, 009A7A00h - - mov eax, cxVal - add eax, 11 - mov edx, cyVal - invoke DrawBox, eax, edx, 2, 2, 009A7A00h - - mov eax, cxVal - sub eax, 12 - mov edx, cyVal - add edx, 8 - invoke DrawBox, eax, edx, 2, 2, 009A7A00h - - mov eax, cxVal - add eax, 11 - mov edx, cyVal - add edx, 8 - invoke DrawBox, eax, edx, 2, 2, 009A7A00h - -coin_draw_done: - ret -DrawDetailedCoin ENDP - -; ============================================================================== -; IN-ENGINE 2.5D MINI-GAME: COIN FLIP -; ============================================================================== -InitCoinGame PROC - call InitNativeCoin3D - ret -InitCoinGame ENDP - -HandleCoinInput PROC - call HandleNativeCoin3D - ret -; Retained legacy frame-count prototype, excluded from the executable. -IF 0 - cmp coin3d_state, 0 - je coin_handle_idle - cmp coin3d_state, 1 - je coin_handle_flipping - cmp coin3d_state, 2 - je coin_handle_result - ret - -coin_handle_idle: - invoke Pressed3D, 26h ; UP - test eax, eax - jnz coin_bet_up - invoke Pressed3D, 57h ; 'W' - test eax, eax - jnz coin_bet_up - invoke Pressed3D, 28h ; DOWN - test eax, eax - jnz coin_bet_down - invoke Pressed3D, 53h ; 'S' - test eax, eax - jnz coin_bet_down - invoke Pressed3D, 31h ; '1' - test eax, eax - jnz coin_pick_1 - invoke Pressed3D, 32h ; '2' - test eax, eax - jnz coin_pick_2 - invoke Pressed3D, 20h ; SPACE - test eax, eax - jnz coin_start_flip - ret - -coin_bet_up: - mov eax, coin3d_bet - add eax, 50 - cmp eax, bankroll - jle @F - mov eax, bankroll -@@: - cmp eax, 5000 - jle @F - mov eax, 5000 -@@: - mov coin3d_bet, eax - invoke PlayCasinoSound3D, OFFSET soundClick, 0, 1 - ret - -coin_bet_down: - mov eax, coin3d_bet - sub eax, 50 - cmp eax, 50 - jge @F - mov eax, 50 -@@: - mov coin3d_bet, eax - invoke PlayCasinoSound3D, OFFSET soundClick, 0, 1 - ret - -coin_pick_1: - mov coin3d_choice, 1 - invoke PlayCasinoSound3D, OFFSET soundClick, 0, 1 - ret - -coin_pick_2: - mov coin3d_choice, 2 - invoke PlayCasinoSound3D, OFFSET soundClick, 0, 1 - ret - -coin_start_flip: - mov eax, coin3d_bet - cmp eax, bankroll - jle @F - mov eax, bankroll - mov coin3d_bet, eax - test eax, eax - jz coin_done -@@: - mov eax, coin3d_bet - sub bankroll, eax - mov coin3d_state, 1 - mov coin3d_timer, 40 - invoke PlayCasinoSound3D, OFFSET soundCoin, 0, 1 - ret - -coin_handle_flipping: - dec coin3d_timer - cmp coin3d_timer, 0 - jg coin_done - invoke RandomRange3D, 2 - inc eax - mov coin3d_result, eax - mov edx, coin3d_choice - cmp eax, edx - jne coin_flip_lost - - ; Won! - inc coin3d_streak - mov eax, coin3d_bet - shl eax, 1 - add bankroll, eax - mov coin3d_win, eax - mov coin3d_state, 2 - invoke PlayCasinoSound3D, OFFSET soundCoinDing, 0, 1 - ret - -coin_flip_lost: - mov coin3d_streak, 0 - mov coin3d_win, 0 - mov coin3d_state, 2 - invoke PlayCasinoSound3D, OFFSET soundLose, 0, 1 - ret - -coin_handle_result: - invoke Pressed3D, 20h - test eax, eax - jz coin_done - mov coin3d_state, 0 - invoke PlayCasinoSound3D, OFFSET soundClick, 0, 1 -coin_done: - ret -ENDIF -HandleCoinInput ENDP - -RenderCoinGame PROC uses ebx esi edi - local cyVal:DWORD - local rxVal:DWORD - local kx:DWORD - - call RenderNativeCoin3D - ret -IF 0 - ; Background & Cabinet border - invoke DrawBox, 0, 0, 320, 240, 00140906h - invoke DrawBoxBorder, 6, 6, 308, 228, 0022150Fh, 00482E1Bh, 3 - - ; Header - invoke DrawBoxBorder, 20, 12, 280, 26, 001C100Ah, 00FFD700h, 2 - invoke DrawString8x8, 44, 21, OFFSET textCoinTitle, 00FFFF00h - - ; Corner rivets - invoke DrawBox, 12, 12, 3, 3, 00FFD700h - invoke DrawBox, 306, 12, 3, 3, 00FFD700h - invoke DrawBox, 12, 226, 3, 3, 00FFD700h - invoke DrawBox, 306, 226, 3, 3, 00FFD700h - - ; Status meters - invoke DrawBoxBorder, 20, 44, 110, 18, 000E1A0Ah, 00224B1Ah, 1 - invoke DrawString8x8, 24, 49, OFFSET textBankPrompt, 003CFF3Ch - invoke FormatNumber, bankroll, OFFSET hudNumBuffer - invoke DrawString8x8, 72, 49, OFFSET hudNumBuffer, 003CFF3Ch - - invoke DrawBoxBorder, 190, 44, 110, 18, 001A100Ah, 003A2814h, 1 - invoke DrawString8x8, 194, 49, OFFSET textBetPrompt, 00FFD700h - invoke FormatNumber, coin3d_bet, OFFSET hudNumBuffer - invoke DrawString8x8, 254, 49, OFFSET hudNumBuffer, 00FFD700h - - ; Left: Heads - cmp coin3d_choice, 1 - jne coin_left_inactive - invoke DrawBoxBorder, 20, 72, 76, 68, 00101828h, 00FFFF00h, 2 - invoke DrawString8x8, 30, 78, OFFSET textCoinSide1, 00FFFF00h - invoke DrawDetailedCoin, 58, 106, 14, 14, 00D0A000h, 00FFD700h, 1 - invoke DrawString8x8, 24, 126, OFFSET textCoinSelected, 003CFF3Ch - jmp coin_right_side -coin_left_inactive: - invoke DrawBoxBorder, 20, 72, 76, 68, 000A101Ch, 00404855h, 1 - invoke DrawString8x8, 30, 78, OFFSET textCoinSide1, 00D0D8E0h - invoke DrawDetailedCoin, 58, 106, 14, 14, 009A7A00h, 00D0A000h, 1 - -coin_right_side: - ; Right: Tails - cmp coin3d_choice, 2 - jne coin_right_inactive - invoke DrawBoxBorder, 224, 72, 76, 68, 00101828h, 00FFFF00h, 2 - invoke DrawString8x8, 234, 78, OFFSET textCoinSide2, 00FFFF00h - invoke DrawDetailedCoin, 262, 106, 14, 14, 00D0A000h, 00FFD700h, 2 - invoke DrawString8x8, 228, 126, OFFSET textCoinSelected, 003CFF3Ch - jmp coin_center_area -coin_right_inactive: - invoke DrawBoxBorder, 224, 72, 76, 68, 000A101Ch, 00404855h, 1 - invoke DrawString8x8, 234, 78, OFFSET textCoinSide2, 00D0D8E0h - invoke DrawDetailedCoin, 262, 106, 14, 14, 009A7A00h, 00D0A000h, 2 - -coin_center_area: - ; Center spotlight - invoke DrawCircle, 160, 110, 48, 00121620h - invoke DrawCircle, 160, 110, 44, 00FFD700h - invoke DrawCircle, 160, 110, 42, 000E141Eh - - cmp coin3d_state, 1 - je coin_render_flipping - cmp coin3d_state, 2 - je coin_render_result - - ; Idle coin - invoke DrawDetailedCoin, 160, 110, 26, 26, 00D0A000h, 00FFD700h, coin3d_choice - jmp coin_render_keys - -coin_render_flipping: - mov eax, coin3d_timer - and eax, 7 - movzx eax, byte ptr [coinRxAnimTable + eax] - mov rxVal, eax - invoke DrawDetailedCoin, 160, 110, rxVal, 26, 00D0A000h, 00FFD700h, 0 - invoke DrawString8x8, 88, 160, OFFSET textCoinFlipping, 00FFFF00h - jmp coin_render_keys - -coin_render_result: - invoke DrawDetailedCoin, 160, 110, 26, 26, 00D0A000h, 00FFD700h, coin3d_result - mov eax, coin3d_result - cmp eax, coin3d_choice - jne coin_render_loss_msg - - ; Win banner - invoke DrawBoxBorder, 44, 154, 232, 22, 000E141Eh, 003CFF3Ch, 1 - invoke DrawString8x8, 64, 161, OFFSET textCoinWin, 003CFF3Ch - invoke FormatNumber, coin3d_win, OFFSET hudNumBuffer - invoke DrawString8x8, 152, 161, OFFSET hudNumBuffer, 003CFF3Ch - jmp coin_render_keys - -coin_render_loss_msg: - invoke DrawBoxBorder, 44, 154, 232, 22, 000E141Eh, 00C81414h, 1 - invoke DrawString8x8, 114, 161, OFFSET textCoinLose, 00FF6464h - -coin_render_keys: - mov kx, 16 - xor eax, eax - cmp coin3d_choice, 1 - sete al - invoke DrawKeycap3D, kx, 192, OFFSET textCoinKey1, eax - add kx, eax - - xor eax, eax - cmp coin3d_choice, 2 - sete al - invoke DrawKeycap3D, kx, 192, OFFSET textCoinKey2, eax - add kx, eax - - invoke DrawKeycap3D, kx, 192, OFFSET textCoinKeySpace, 1 - add kx, eax - - invoke DrawKeycap3D, kx, 192, OFFSET textKeyEsc, 0 - ret -ENDIF -RenderCoinGame ENDP - -; ============================================================================== -; IN-ENGINE 2.5D MINI-GAME: CRAPS / DICE -; ============================================================================== -DrawCrapsDie PROC uses ebx esi edi, x:DWORD, y:DWORD, sizeVal:DWORD, valNum:DWORD - ; Drop shadow - mov eax, x - add eax, 3 - mov edx, y - add edx, sizeVal - invoke DrawBox, eax, edx, sizeVal, 3, 00081403h - - mov eax, x - add eax, sizeVal - mov edx, y - add edx, 3 - invoke DrawBox, eax, edx, 3, sizeVal, 00081403h - - ; Ivory body & bevel - invoke DrawBoxBorder, x, y, sizeVal, sizeVal, 00FAF4F0h, 00403535h, 1 - mov eax, x - inc eax - mov edx, y - inc edx - mov ecx, sizeVal - sub ecx, 2 - invoke DrawBox, eax, edx, ecx, 1, 00FFFFFFh - invoke DrawBox, eax, edx, 1, ecx, 00FFFFFFh - - ; Ruby pips (00C81515h) - mov eax, valNum - test al, 1 - jz @F - ; Center pip - mov eax, x - add eax, 18 - mov edx, y - add edx, 18 - invoke DrawCircle, eax, edx, 3, 00C81515h - dec eax - dec edx - invoke DrawPixel, eax, edx, 00FFFFFFh -@@: - cmp valNum, 2 - jl die_pips_done - mov eax, x - add eax, 9 - mov edx, y - add edx, 9 - invoke DrawCircle, eax, edx, 3, 00C81515h - mov eax, x - add eax, 27 - mov edx, y - add edx, 27 - invoke DrawCircle, eax, edx, 3, 00C81515h - - cmp valNum, 4 - jl die_pips_done - mov eax, x - add eax, 27 - mov edx, y - add edx, 9 - invoke DrawCircle, eax, edx, 3, 00C81515h - mov eax, x - add eax, 9 - mov edx, y - add edx, 27 - invoke DrawCircle, eax, edx, 3, 00C81515h - - cmp valNum, 6 - jl die_pips_done - mov eax, x - add eax, 9 - mov edx, y - add edx, 18 - invoke DrawCircle, eax, edx, 3, 00C81515h - mov eax, x - add eax, 27 - mov edx, y - add edx, 18 - invoke DrawCircle, eax, edx, 3, 00C81515h - -die_pips_done: - ret -DrawCrapsDie ENDP - -InitDiceGame PROC - mov dice3d_state, 0 - mov dice3d_timer, 0 - mov dice3d_win, 0 - ret -InitDiceGame ENDP - -HandleDiceInput PROC - cmp dice3d_state, 0 - je dice_handle_idle - cmp dice3d_state, 1 - je dice_handle_rolling - cmp dice3d_state, 2 - je dice_handle_result - ret - -dice_handle_idle: - invoke Pressed3D, 26h ; UP - test eax, eax - jnz dice_bet_up - invoke Pressed3D, 57h ; 'W' - test eax, eax - jnz dice_bet_up - invoke Pressed3D, 28h ; DOWN - test eax, eax - jnz dice_bet_down - invoke Pressed3D, 53h ; 'S' - test eax, eax - jnz dice_bet_down - invoke Pressed3D, 31h ; '1' - test eax, eax - jnz dice_pick_1 - invoke Pressed3D, 32h ; '2' - test eax, eax - jnz dice_pick_2 - invoke Pressed3D, 20h ; SPACE - test eax, eax - jnz dice_start_roll - ret - -dice_bet_up: - mov eax, dice3d_bet - add eax, 50 - cmp eax, bankroll - jle @F - mov eax, bankroll -@@: - cmp eax, 5000 - jle @F - mov eax, 5000 -@@: - mov dice3d_bet, eax - invoke PlayCasinoSound3D, OFFSET soundClick, 0, 1 - ret - -dice_bet_down: - mov eax, dice3d_bet - sub eax, 50 - cmp eax, 50 - jge @F - mov eax, 50 -@@: - mov dice3d_bet, eax - invoke PlayCasinoSound3D, OFFSET soundClick, 0, 1 - ret - -dice_pick_1: - mov dice3d_choice, 1 - invoke PlayCasinoSound3D, OFFSET soundClick, 0, 1 - ret - -dice_pick_2: - mov dice3d_choice, 2 - invoke PlayCasinoSound3D, OFFSET soundClick, 0, 1 - ret - -dice_start_roll: - mov eax, dice3d_bet - cmp eax, bankroll - jle @F - mov eax, bankroll - mov dice3d_bet, eax - test eax, eax - jz dice_done -@@: - mov eax, dice3d_bet - test eax, eax - jle dice_done - sub bankroll, eax - mov dice3d_state, 1 - mov dice3d_timer, 0 - invoke RandomRange3D, 6 - inc eax - mov dice3d_val1, eax - invoke RandomRange3D, 6 - inc eax - mov dice3d_val2, eax - invoke PlayCasinoSound3D, OFFSET soundDiceRoll, 0, 1 - call SaveProgress3D - ret - -dice_handle_rolling: - mov eax, deltaTime3D - add dice3d_timer, eax - cmp dice3d_timer, 1600 - jb dice_done - mov dice3d_timer, 1600 - mov eax, dice3d_val2 - mov edx, dice3d_val1 - add edx, eax - mov dice3d_sum, edx - - ; Parity check - mov eax, edx - and eax, 1 - jnz dice_sum_is_odd - ; Even - mov eax, 1 - jmp dice_check_win -dice_sum_is_odd: - mov eax, 2 - -dice_check_win: - cmp eax, dice3d_choice - jne dice_roll_lost - - ; Won! - mov eax, dice3d_bet - shl eax, 1 - add bankroll, eax - mov dice3d_win, eax - mov dice3d_state, 2 - invoke PlayCasinoSound3D, OFFSET soundRoundWin, 0, 1 - invoke NpcRecordRound3D,8,1 - call SaveProgress3D - ret - -dice_roll_lost: - mov dice3d_win, 0 - mov dice3d_state, 2 - invoke PlayCasinoSound3D, OFFSET soundLose, 0, 1 - invoke NpcRecordRound3D,8,0 - call SaveProgress3D - ret - -dice_handle_result: - invoke Pressed3D, 20h - test eax, eax - jz dice_done - mov dice3d_state, 0 - invoke PlayCasinoSound3D, OFFSET soundClick, 0, 1 -dice_done: - ret -HandleDiceInput ENDP - -RenderDiceGame PROC uses ebx esi edi - local kx:DWORD - - ; Mahogany frame & Deep Felt Green table - invoke DrawBox, 0, 0, 320, 240, 00140906h - invoke DrawBoxBorder, 6, 6, 308, 228, 000A3816h, 00FFD700h, 2 - - ; Header - invoke DrawBoxBorder, 20, 12, 280, 26, 00072E13h, 00FFD700h, 2 - invoke DrawString8x8, 116, 21, OFFSET textDiceTitle, 00FFFF00h - - ; Status - invoke DrawBoxBorder, 20, 44, 110, 18, 00072E13h, 001B4B22h, 1 - invoke DrawString8x8, 24, 49, OFFSET textBankPrompt, 003CFF3Ch - invoke FormatNumber, bankroll, OFFSET hudNumBuffer - invoke DrawString8x8, 72, 49, OFFSET hudNumBuffer, 003CFF3Ch - - invoke DrawBoxBorder, 190, 44, 110, 18, 00072E13h, 001B4B22h, 1 - invoke DrawString8x8, 194, 49, OFFSET textBetPrompt, 00FFD700h - invoke FormatNumber, dice3d_bet, OFFSET hudNumBuffer - invoke DrawString8x8, 258, 49, OFFSET hudNumBuffer, 00FFD700h - - ; [1] ЧЁТ - cmp dice3d_choice, 1 - jne dice_even_inactive - invoke DrawBoxBorder, 16, 70, 88, 48, 00072E13h, 00FFFF00h, 2 - invoke DrawString8x8, 30, 76, OFFSET textDiceEven, 00FFFF00h - invoke DrawString8x8, 22, 90, OFFSET textDiceEvenNums, 00FFD700h - invoke DrawString8x8, 26, 104, OFFSET textCoinSelected, 003CFF3Ch - jmp dice_odd_side -dice_even_inactive: - invoke DrawBoxBorder, 16, 70, 88, 48, 00072E13h, 001B4B22h, 1 - invoke DrawString8x8, 30, 76, OFFSET textDiceEven, 00D0D8E0h - invoke DrawString8x8, 22, 90, OFFSET textDiceEvenNums, 0080B090h - -dice_odd_side: - ; [2] НЕЧЕТ - cmp dice3d_choice, 2 - jne dice_odd_inactive - invoke DrawBoxBorder, 216, 70, 88, 48, 00072E13h, 00FFFF00h, 2 - invoke DrawString8x8, 226, 76, OFFSET textDiceOdd, 00FFFF00h - invoke DrawString8x8, 224, 90, OFFSET textDiceOddNums, 00FFD700h - invoke DrawString8x8, 226, 104, OFFSET textCoinSelected, 003CFF3Ch - jmp dice_center_cubes -dice_odd_inactive: - invoke DrawBoxBorder, 216, 70, 88, 48, 00072E13h, 001B4B22h, 1 - invoke DrawString8x8, 226, 76, OFFSET textDiceOdd, 00D0D8E0h - invoke DrawString8x8, 224, 90, OFFSET textDiceOddNums, 0080B090h - -dice_center_cubes: - call RenderDiceThrow3D - - cmp dice3d_state, 1 - je dice_render_rolling - cmp dice3d_state, 2 - je dice_render_result - jmp dice_render_keys - -dice_render_rolling: - invoke DrawString8x8, 76, 138, OFFSET textDiceRolling, 00FFFF00h - jmp dice_render_keys - -dice_render_result: - invoke DrawBoxBorder, 36, 130, 248, 36, 00072E13h, 00FFD700h, 1 - invoke DrawString8x8, 44, 135, OFFSET textDiceSumHdr, 00FFD700h - invoke FormatNumber, dice3d_val1, OFFSET hudNumBuffer - invoke DrawString8x8, 92, 135, OFFSET hudNumBuffer, 00FFFF00h - invoke DrawString8x8, 110, 135, OFFSET textDicePlus, 00FFD700h - invoke FormatNumber, dice3d_val2, OFFSET hudNumBuffer - invoke DrawString8x8, 126, 135, OFFSET hudNumBuffer, 00FFFF00h - invoke DrawString8x8, 144, 135, OFFSET textDiceEqual, 00FFD700h - invoke FormatNumber, dice3d_sum, OFFSET hudNumBuffer - invoke DrawString8x8, 168, 135, OFFSET hudNumBuffer, 00FFFF00h - - mov eax, dice3d_sum - and eax, 1 - jnz dice_render_odd_res - invoke DrawString8x8, 186, 135, OFFSET textDiceEvenResult, 003CFF3Ch - jmp dice_render_outcome -dice_render_odd_res: - invoke DrawString8x8, 186, 135, OFFSET textDiceOddResult, 003CFF3Ch - -dice_render_outcome: - mov eax, dice3d_win - test eax, eax - jz dice_render_loss_outcome - invoke DrawString8x8, 68, 150, OFFSET textDiceWin, 003CFF3Ch - invoke FormatNumber, dice3d_win, OFFSET hudNumBuffer - invoke DrawString8x8, 156, 150, OFFSET hudNumBuffer, 003CFF3Ch - invoke DrawString8x8, 188, 150, OFFSET textDiceWinMult, 003CFF3Ch - jmp dice_render_keys - -dice_render_loss_outcome: - invoke DrawString8x8, 116, 150, OFFSET textDiceLose, 00FF6464h - -dice_render_keys: - mov kx, 16 - xor eax, eax - cmp dice3d_choice, 1 - sete al - invoke DrawKeycap3D, kx, 192, OFFSET textDiceKey1, eax - add kx, eax - - xor eax, eax - cmp dice3d_choice, 2 - sete al - invoke DrawKeycap3D, kx, 192, OFFSET textDiceKey2, eax - add kx, eax - - invoke DrawKeycap3D, kx, 192, OFFSET textDiceKeySpace, 1 - add kx, eax - - invoke DrawKeycap3D, kx, 192, OFFSET textKeyEsc, 0 - ret -RenderDiceGame ENDP - -; ============================================================================== -; IN-ENGINE 2.5D MINI-GAME: SKULLS & CUPS (НАПЁРСТКИ) -; ============================================================================== -DrawGlowingOrb PROC uses ebx esi edi, cxVal:DWORD, cyVal:DWORD - invoke DrawCircle, cxVal, cyVal, 14, 002E1E08h - invoke DrawCircle, cxVal, cyVal, 11, 00583A10h - invoke DrawCircle, cxVal, cyVal, 8, 008A581Ah - invoke DrawCircle, cxVal, cyVal, 6, 00D0B000h - invoke DrawCircle, cxVal, cyVal, 4, 00FFE000h - mov eax, cxVal - dec eax - mov edx, cyVal - dec edx - invoke DrawCircle, eax, edx, 2, 00FFFF80h - dec eax - dec edx - invoke DrawPixel, eax, edx, 00FFFFFFh - ret -DrawGlowingOrb ENDP - -DrawGothicCup PROC uses ebx esi edi, x:DWORD, y:DWORD, cupId:DWORD, isLifted:DWORD, hasBall:DWORD - local liftY:DWORD - - mov eax, y - cmp isLifted, 0 - je @F - sub eax, 36 -@@: - mov liftY, eax - - ; Drop shadow - cmp isLifted, 0 - jne cup_shadow_lifted - mov eax, x - add eax, 6 - mov edx, y - add edx, 42 - invoke DrawBox, eax, edx, 36, 4, 0010040Ah - jmp cup_ball_check -cup_shadow_lifted: - mov eax, x - add eax, 10 - mov edx, y - add edx, 42 - invoke DrawBox, eax, edx, 28, 2, 001A0612h - -cup_ball_check: - cmp isLifted, 0 - je cup_body_draw - cmp hasBall, 0 - je cup_body_draw - mov eax, x - add eax, 24 - mov edx, y - add edx, 26 - invoke DrawGlowingOrb, eax, edx - -cup_body_draw: - ; Base pedestal - mov eax, x - add eax, 6 - mov edx, liftY - add edx, 36 - invoke DrawBoxBorder, eax, edx, 36, 6, 00301A22h, 00D0B000h, 1 - - ; Stem - mov eax, x - add eax, 18 - mov edx, liftY - add edx, 28 - invoke DrawBox, eax, edx, 12, 8, 00452533h - mov eax, x - add eax, 22 - invoke DrawBox, eax, edx, 4, 8, 006E4055h - - ; Goblet Bowl - mov eax, x - add eax, 8 - mov edx, liftY - add edx, 8 - invoke DrawBoxBorder, eax, edx, 32, 20, 00401E2Dh, 00FFD700h, 1 - - mov eax, x - add eax, 14 - mov edx, liftY - add edx, 10 - invoke DrawBox, eax, edx, 6, 16, 00703550h - mov eax, x - add eax, 17 - invoke DrawBox, eax, edx, 3, 16, 00A05078h - - ; Golden Rim - mov eax, x - add eax, 4 - mov edx, liftY - add edx, 2 - invoke DrawBoxBorder, eax, edx, 40, 7, 00200A15h, 00FFFF00h, 1 - mov eax, x - add eax, 12 - mov edx, liftY - add edx, 4 - invoke DrawBox, eax, edx, 16, 2, 00FFFF00h - - ; Skull face emblem - mov eax, x - add eax, 21 - mov edx, liftY - add edx, 12 - invoke DrawBox, eax, edx, 6, 5, 00FFD700h - mov eax, x - add eax, 22 - mov edx, liftY - add edx, 17 - invoke DrawBox, eax, edx, 4, 3, 00FFD700h - mov eax, x - add eax, 22 - mov edx, liftY - add edx, 14 - invoke DrawPixel, eax, edx, 00200A15h - mov eax, x - add eax, 24 - invoke DrawPixel, eax, edx, 00200A15h - - ; Cup number label - mov eax, x - add eax, 21 - mov edx, liftY - add edx, 24 - mov ecx, cupId - add ecx, '1' - invoke DrawChar8x8, eax, edx, ecx, 00FFFF00h - ret -DrawGothicCup ENDP - -InitSkullsGame PROC - mov skulls3d_state, 0 - mov skulls3d_timer, 0 - mov skulls3d_win, 0 - mov skulls3d_choice, 1 - mov skulls3d_cup0, 0 - mov skulls3d_cup1, 1 - mov skulls3d_cup2, 2 - invoke RandomRange3D, 3 - mov skulls3d_ballPos, eax - ret -InitSkullsGame ENDP - -FinalizeSkullsGuess PROC uses ebx - cmp skulls3d_state,3 - jne skulls_guess_done - mov eax, skulls3d_choice - cmp eax, skulls3d_ballPos - jne skulls_guess_wrong - - ; Correct! 3x payout - mov eax, skulls3d_bet - imul eax, 3 - add bankroll, eax - mov skulls3d_win, eax - mov skulls3d_state, 4 - invoke PlayCasinoSound3D, OFFSET soundRoundWin, 0, 1 - invoke NpcRecordRound3D,9,1 - call SaveProgress3D - ret - -skulls_guess_wrong: - mov skulls3d_win, 0 - mov skulls3d_state, 4 - invoke PlayCasinoSound3D, OFFSET soundLose, 0, 1 - invoke NpcRecordRound3D,9,0 - call SaveProgress3D -skulls_guess_done: - ret -FinalizeSkullsGuess ENDP - -HandleSkullsInput PROC - cmp skulls3d_state, 0 - je skulls_handle_idle - cmp skulls3d_state, 1 - je skulls_handle_show - cmp skulls3d_state, 2 - je skulls_handle_shuffle - cmp skulls3d_state, 3 - je skulls_handle_pick - cmp skulls3d_state, 4 - je skulls_handle_reveal - ret - -skulls_handle_idle: - invoke Pressed3D, 26h ; UP - test eax, eax - jnz skulls_bet_up - invoke Pressed3D, 57h ; 'W' - test eax, eax - jnz skulls_bet_up - invoke Pressed3D, 28h ; DOWN - test eax, eax - jnz skulls_bet_down - invoke Pressed3D, 53h ; 'S' - test eax, eax - jnz skulls_bet_down - invoke Pressed3D, 20h ; SPACE - test eax, eax - jnz skulls_start_game - ret - -skulls_bet_up: - mov eax, skulls3d_bet - add eax, 50 - cmp eax, bankroll - jle @F - mov eax, bankroll -@@: - cmp eax, 5000 - jle @F - mov eax, 5000 -@@: - mov skulls3d_bet, eax - invoke PlayCasinoSound3D, OFFSET soundClick, 0, 1 - ret - -skulls_bet_down: - mov eax, skulls3d_bet - sub eax, 50 - cmp eax, 50 - jge @F - mov eax, 50 -@@: - mov skulls3d_bet, eax - invoke PlayCasinoSound3D, OFFSET soundClick, 0, 1 - ret - -skulls_start_game: - mov eax, skulls3d_bet - cmp eax, bankroll - jle @F - mov eax, bankroll - mov skulls3d_bet, eax - test eax, eax - jz skulls_input_done -@@: - mov eax, skulls3d_bet - sub bankroll, eax - invoke RandomRange3D, 3 - mov skulls3d_ballPos, eax - mov skulls3d_cup0, 0 - mov skulls3d_cup1, 1 - mov skulls3d_cup2, 2 - - ; Pre-generate 3 dynamic swap pairs - invoke RandomRange3D, 3 - mov skulls3d_swapPair0, eax - invoke RandomRange3D, 3 - mov skulls3d_swapPair1, eax - invoke RandomRange3D, 3 - mov skulls3d_swapPair2, eax - - mov skulls3d_state, 1 - mov skulls3d_timer, 0 - invoke PlayCasinoSound3D, OFFSET soundClick, 0, 1 - ret - -skulls_handle_show: - inc skulls3d_timer - cmp skulls3d_timer, 45 - jl skulls_input_done - ; Transition to Phase 2: Active Shuffle Animation - mov skulls3d_state, 2 - mov skulls3d_timer, 0 - invoke PlayCasinoSound3D, OFFSET soundShuffle, 0, 1 - ret - -skulls_handle_shuffle: - inc skulls3d_timer - cmp skulls3d_timer, 60 - jl skulls_input_done - ; Transition to Phase 3: Pick cup - mov skulls3d_state, 3 - mov skulls3d_timer, 0 - ret - -skulls_handle_pick: - invoke Pressed3D, 31h ; '1' - test eax, eax - jnz skulls_pick_1 - invoke Pressed3D, 32h ; '2' - test eax, eax - jnz skulls_pick_2 - invoke Pressed3D, 33h ; '3' - test eax, eax - jnz skulls_pick_3 - ret - -skulls_pick_1: - mov skulls3d_choice, 0 - call FinalizeSkullsGuess - ret - -skulls_pick_2: - mov skulls3d_choice, 1 - call FinalizeSkullsGuess - ret - -skulls_pick_3: - mov skulls3d_choice, 2 - call FinalizeSkullsGuess - ret - -skulls_handle_reveal: - invoke Pressed3D, 20h - test eax, eax - jz skulls_input_done - mov skulls3d_state, 0 - invoke PlayCasinoSound3D, OFFSET soundClick, 0, 1 -skulls_input_done: - ret -HandleSkullsInput ENDP - -RenderSkullsGame PROC uses ebx esi edi - local kx:DWORD - local passTick:DWORD, curPair:DWORD, swapSlotA:DWORD, swapSlotB:DWORD - local xA:DWORD, xB:DWORD, curXA:DWORD, curXB:DWORD, curYA:DWORD, curYB:DWORD - local distX:DWORD, dxVal:DWORD, archY:DWORD - - ; Mahogany & Gothic Purple table - invoke DrawBox, 0, 0, 320, 240, 00140906h - invoke DrawBoxBorder, 6, 6, 308, 228, 00300F22h, 00FFD700h, 2 - - ; Header - invoke DrawBoxBorder, 20, 12, 280, 26, 001A0812h, 00FFD700h, 2 - invoke DrawString8x8, 44, 21, OFFSET textSkullsTitle, 00FFFF00h - - ; Status - invoke DrawBoxBorder, 20, 44, 110, 18, 001A0812h, 00452033h, 1 - invoke DrawString8x8, 24, 49, OFFSET textBankPrompt, 003CFF3Ch - invoke FormatNumber, bankroll, OFFSET hudNumBuffer - invoke DrawString8x8, 72, 49, OFFSET hudNumBuffer, 003CFF3Ch - - invoke DrawBoxBorder, 190, 44, 110, 18, 001A0812h, 00452033h, 1 - invoke DrawString8x8, 194, 49, OFFSET textBetPrompt, 00FFD700h - invoke FormatNumber, skulls3d_bet, OFFSET hudNumBuffer - invoke DrawString8x8, 254, 49, OFFSET hudNumBuffer, 00FFD700h - - ; Phase Prompts - cmp skulls3d_state, 0 - jne @F - invoke DrawString8x8, 56, 62, OFFSET textSkullsPhase0, 00FFD700h - jmp skulls_draw_idle_cups -@@: - cmp skulls3d_state, 1 - jne @F - invoke DrawString8x8, 56, 62, OFFSET textSkullsPhase1, 00FFFF00h - jmp skulls_draw_phase1_cups -@@: - cmp skulls3d_state, 2 - jne @F - invoke DrawString8x8, 44, 62, OFFSET textSkullsPhase2, 00FFFF00h - jmp skulls_draw_animated_cups -@@: - cmp skulls3d_state, 3 - jne @F - invoke DrawString8x8, 28, 62, OFFSET textSkullsPhase3, 00FFFF00h - jmp skulls_draw_idle_cups -@@: - ; Phase 4: Reveal outcome - mov eax, skulls3d_win - test eax, eax - jz skulls_reveal_loss_text - invoke DrawString8x8, 40, 62, OFFSET textSkullsWin, 003CFF3Ch - invoke FormatNumber, skulls3d_win, OFFSET hudNumBuffer - invoke DrawString8x8, 136, 62, OFFSET hudNumBuffer, 003CFF3Ch - invoke DrawString8x8, 168, 62, OFFSET textSkullsWinMult, 003CFF3Ch - jmp skulls_draw_reveal_cups - -skulls_reveal_loss_text: - invoke DrawString8x8, 40, 62, OFFSET textSkullsLose, 00FF6464h - jmp skulls_draw_reveal_cups - -skulls_draw_idle_cups: - ; Draw resting cups at static slots: Slot 0 (X=36), Slot 1 (X=136), Slot 2 (X=236) - invoke DrawGothicCup, 36, 114, skulls3d_cup0, 0, 0 - invoke DrawGothicCup, 136, 114, skulls3d_cup1, 0, 0 - invoke DrawGothicCup, 236, 114, skulls3d_cup2, 0, 0 - jmp skulls_render_controls - -skulls_draw_phase1_cups: - ; Draw with golden ball showing under starting cup - mov ebx, 0 - mov edx, 0 - cmp skulls3d_ballPos, 0 - jne @F - mov ebx, 1 - mov edx, 1 -@@: - invoke DrawGothicCup, 36, 114, skulls3d_cup0, ebx, edx - - mov ebx, 0 - mov edx, 0 - cmp skulls3d_ballPos, 1 - jne @F - mov ebx, 1 - mov edx, 1 -@@: - invoke DrawGothicCup, 136, 114, skulls3d_cup1, ebx, edx - - mov ebx, 0 - mov edx, 0 - cmp skulls3d_ballPos, 2 - jne @F - mov ebx, 1 - mov edx, 1 -@@: - invoke DrawGothicCup, 236, 114, skulls3d_cup2, ebx, edx - jmp skulls_render_controls - -skulls_draw_animated_cups: - ; 60 frames = 3 passes of 20 frames - mov eax, skulls3d_timer - cmp eax, 20 - jbe pass_0 - cmp eax, 40 - jbe pass_1 - sub eax, 41 - mov passTick, eax - mov eax, skulls3d_swapPair2 - mov curPair, eax - jmp setup_pass - -pass_0: - dec eax - mov passTick, eax - mov eax, skulls3d_swapPair0 - mov curPair, eax - jmp setup_pass - -pass_1: - sub eax, 21 - mov passTick, eax - mov eax, skulls3d_swapPair1 - mov curPair, eax - -setup_pass: - ; curPair determines swap pair: - ; 0: swap slot 0 (X=36) and slot 1 (X=136) - ; 1: swap slot 1 (X=136) and slot 2 (X=236) - ; 2: swap slot 0 (X=36) and slot 2 (X=236) - cmp curPair, 1 - je pair_1 - cmp curPair, 2 - je pair_2 - mov swapSlotA, 0 - mov swapSlotB, 1 - mov xA, 36 - mov xB, 136 - jmp calc_coords -pair_1: - mov swapSlotA, 1 - mov swapSlotB, 2 - mov xA, 136 - mov xB, 236 - jmp calc_coords -pair_2: - mov swapSlotA, 0 - mov swapSlotB, 2 - mov xA, 36 - mov xB, 236 - -calc_coords: - ; distX = xB - xA - mov eax, xB - sub eax, xA - mov distX, eax - - ; dxVal = (distX * passTick) / 20 - mov eax, distX - imul eax, passTick - xor edx, edx - mov ecx, 20 - div ecx - mov dxVal, eax - - ; curXA = xA + dxVal - mov eax, xA - add eax, dxVal - mov curXA, eax - - ; curXB = xB - dxVal - mov eax, xB - sub eax, dxVal - mov curXB, eax - - ; archY = (passTick * (20 - passTick)) / 10 - mov eax, passTick - mov ecx, 20 - sub ecx, eax - imul eax, ecx - xor edx, edx - mov ecx, 10 - div ecx - mov archY, eax - - ; Cup A hops UP: 114 - archY - mov eax, 114 - sub eax, archY - mov curYA, eax - - ; Cup B hops DOWN: 114 + archY - mov eax, 114 - add eax, archY - mov curYB, eax - - ; Check if pass ended (frame 19): swap ball position and cups - cmp passTick, 19 - jne draw_active_shuffle - - ; Swap ball position if involved - mov eax, skulls3d_ballPos - cmp eax, swapSlotA - jne check_ball_b - mov edx, swapSlotB - mov skulls3d_ballPos, edx - jmp swap_slot_identities -check_ball_b: - cmp eax, swapSlotB - jne swap_slot_identities - mov edx, swapSlotA - mov skulls3d_ballPos, edx - -swap_slot_identities: - cmp curPair, 1 - je swap_ids_1_2 - cmp curPair, 2 - je swap_ids_0_2 - ; swap 0 and 1 - mov eax, skulls3d_cup0 - xchg eax, skulls3d_cup1 - mov skulls3d_cup0, eax - jmp swap_sound_tick -swap_ids_1_2: - mov eax, skulls3d_cup1 - xchg eax, skulls3d_cup2 - mov skulls3d_cup1, eax - jmp swap_sound_tick -swap_ids_0_2: - mov eax, skulls3d_cup0 - xchg eax, skulls3d_cup2 - mov skulls3d_cup0, eax - -swap_sound_tick: - invoke PlayCasinoSound3D, OFFSET soundShuffle, 0, 1 - -draw_active_shuffle: - ; Draw stationary cup - cmp curPair, 1 - je draw_stat_cup0 - cmp curPair, 2 - je draw_stat_cup1 - ; Stationary cup is slot 2 (X=236) - invoke DrawGothicCup, 236, 114, skulls3d_cup2, 0, 0 - jmp draw_moving_cups -draw_stat_cup0: - ; Stationary cup is slot 0 (X=36) - invoke DrawGothicCup, 36, 114, skulls3d_cup0, 0, 0 - jmp draw_moving_cups -draw_stat_cup1: - ; Stationary cup is slot 1 (X=136) - invoke DrawGothicCup, 136, 114, skulls3d_cup1, 0, 0 - -draw_moving_cups: - ; Moving Cup A and Moving Cup B - cmp curPair, 1 - je ids_pair_1 - cmp curPair, 2 - je ids_pair_2 - mov eax, skulls3d_cup0 - mov ebx, skulls3d_cup1 - jmp draw_the_pair -ids_pair_1: - mov eax, skulls3d_cup1 - mov ebx, skulls3d_cup2 - jmp draw_the_pair -ids_pair_2: - mov eax, skulls3d_cup0 - mov ebx, skulls3d_cup2 - -draw_the_pair: - push ebx - invoke DrawGothicCup, curXA, curYA, eax, 0, 0 - pop ebx - invoke DrawGothicCup, curXB, curYB, ebx, 0, 0 - jmp skulls_render_controls - -skulls_draw_reveal_cups: - ; Reveal Phase: lift chosen cup and lift actual ball cup if different - ; Slot 0 - mov ebx, 0 - mov edx, 0 - cmp skulls3d_choice, 0 - je slot0_is_lifted - cmp skulls3d_ballPos, 0 - jne @F -slot0_is_lifted: - mov ebx, 1 - cmp skulls3d_ballPos, 0 - sete dl -@@: - invoke DrawGothicCup, 36, 114, skulls3d_cup0, ebx, edx - - ; Slot 1 - mov ebx, 0 - mov edx, 0 - cmp skulls3d_choice, 1 - je slot1_is_lifted - cmp skulls3d_ballPos, 1 - jne @F -slot1_is_lifted: - mov ebx, 1 - cmp skulls3d_ballPos, 1 - sete dl -@@: - invoke DrawGothicCup, 136, 114, skulls3d_cup1, ebx, edx - - ; Slot 2 - mov ebx, 0 - mov edx, 0 - cmp skulls3d_choice, 2 - je slot2_is_lifted - cmp skulls3d_ballPos, 2 - jne @F -slot2_is_lifted: - mov ebx, 1 - cmp skulls3d_ballPos, 2 - sete dl -@@: - invoke DrawGothicCup, 236, 114, skulls3d_cup2, ebx, edx - -skulls_render_controls: - ; Cup selection slot labels [1], [2], [3] - invoke DrawString8x8, 54, 168, OFFSET textSkullsKey1, 00D0D8E0h - invoke DrawString8x8, 150, 168, OFFSET textSkullsKey2, 00D0D8E0h - invoke DrawString8x8, 250, 168, OFFSET textSkullsKey3, 00D0D8E0h - - ; Keycaps - mov kx, 16 - xor eax, eax - cmp skulls3d_state, 3 - je key1_active - cmp skulls3d_choice, 0 - sete al - jmp draw_key1 -key1_active: - mov eax, 1 -draw_key1: - invoke DrawKeycap3D, kx, 192, OFFSET textSkullsKey1, eax - add kx, eax - - xor eax, eax - cmp skulls3d_state, 3 - je key2_active - cmp skulls3d_choice, 1 - sete al - jmp draw_key2 -key2_active: - mov eax, 1 -draw_key2: - invoke DrawKeycap3D, kx, 192, OFFSET textSkullsKey2, eax - add kx, eax - - xor eax, eax - cmp skulls3d_state, 3 - je key3_active - cmp skulls3d_choice, 2 - sete al - jmp draw_key3 -key3_active: - mov eax, 1 -draw_key3: - invoke DrawKeycap3D, kx, 192, OFFSET textSkullsKey3, eax - add kx, eax - - xor eax, eax - cmp skulls3d_state, 0 - je start_active - cmp skulls3d_state, 4 - je start_active - jmp draw_start_key -start_active: - mov eax, 1 -draw_start_key: - invoke DrawKeycap3D, kx, 192, OFFSET textSkullsKeySpace, eax - add kx, eax - - invoke DrawKeycap3D, kx, 192, OFFSET textKeyEsc, 0 - ret -RenderSkullsGame ENDP - -InitSkillGame PROC - mov skill3d_state, 0 - mov skill3d_timer, 0 - mov skill3d_hits, 0 - mov skill3d_misses, 0 - mov skill3d_needle, 55 - mov skill3d_speed, 4 - mov skill3d_dir, 1 - mov skill3d_last_result, 0 - mov skill3d_win_amount, 0 - - ; Randomize initial zone: 80 + RandomRange(90) -> 80..170 - invoke RandomRange3D, 90 - add eax, 80 - mov skill3d_zone_start, eax - - ; Great zone: start + 20 + RandomRange(12) - invoke RandomRange3D, 12 - add eax, skill3d_zone_start - add eax, 20 - mov skill3d_great_start, eax - ret -InitSkillGame ENDP - -HandleSkillInput PROC uses ebx esi - mov eax, skill3d_state - cmp eax, 0 - je skill_handle_ready - cmp eax, 1 - je skill_handle_active - cmp eax, 2 - je skill_handle_round_wait - cmp eax, 3 - je skill_handle_round_wait - cmp eax, 4 - je skill_handle_end_wait - cmp eax, 5 - je skill_handle_end_wait - ret - -skill_handle_ready: - invoke Pressed3D, 26h ; UP - test eax, eax - jnz skill_bet_up - invoke Pressed3D, 57h ; 'W' - test eax, eax - jnz skill_bet_up - invoke Pressed3D, 28h ; DOWN - test eax, eax - jnz skill_bet_down - invoke Pressed3D, 53h ; 'S' - test eax, eax - jnz skill_bet_down - jmp skill_check_start - -skill_bet_up: - mov eax, skill3d_bet - add eax, 50 - cmp eax, bankroll - jle @F - mov eax, bankroll -@@: - cmp eax, 5000 - jle @F - mov eax, 5000 -@@: - mov skill3d_bet, eax - invoke PlayCasinoSound3D, OFFSET soundClick, 0, 1 - ret - -skill_bet_down: - mov eax, skill3d_bet - sub eax, 50 - cmp eax, 50 - jge @F - mov eax, 50 -@@: - mov skill3d_bet, eax - invoke PlayCasinoSound3D, OFFSET soundClick, 0, 1 - ret - -skill_check_start: - invoke Pressed3D, 20h ; SPACE - test eax, eax - jz skill_input_done - - ; Deduct bet on game start if beginning of run - mov eax, skill3d_hits - or eax, skill3d_misses - jnz @F - mov eax, skill3d_bet - cmp eax, bankroll - jle skill_has_funds - mov eax, bankroll - mov skill3d_bet, eax - test eax, eax - jz skill_input_done -skill_has_funds: - mov eax, skill3d_bet - sub bankroll, eax -@@: - mov skill3d_state, 1 - mov skill3d_needle, 55 - mov skill3d_dir, 1 - invoke PlayCasinoSound3D, OFFSET soundClick, 0, 1 - ret - -skill_handle_active: - ; Move needle smoothly - mov eax, skill3d_needle - mov edx, skill3d_speed - cmp skill3d_dir, 1 - je skill_move_right - sub eax, edx - cmp eax, 52 - jge skill_update_needle - mov eax, 52 - mov skill3d_dir, 1 - jmp skill_update_needle -skill_move_right: - add eax, edx - cmp eax, 268 - jle skill_update_needle - mov eax, 268 - mov skill3d_dir, -1 -skill_update_needle: - mov skill3d_needle, eax - - ; Check SPACE pressed (Reaction Hit Attempt!) - invoke Pressed3D, 20h - test eax, eax - jz skill_input_done - - ; Is needle in Great Sweet Spot? - mov eax, skill3d_needle - mov edx, skill3d_great_start - cmp eax, edx - jl check_success_zone - add edx, skill3d_great_width - cmp eax, edx - jg check_success_zone - - ; GREAT HIT! - mov skill3d_last_result, 2 - add skill3d_hits, 2 - mov skill3d_state, 2 - mov skill3d_timer, 40 - invoke PlayCasinoSound3D, OFFSET soundSkillPerfect, 0, 1 - jmp skill_check_finish_round - -check_success_zone: - mov eax, skill3d_needle - mov edx, skill3d_zone_start - cmp eax, edx - jl skill_was_miss - add edx, skill3d_zone_width - cmp eax, edx - jg skill_was_miss - - ; NORMAL HIT! - mov skill3d_last_result, 1 - inc skill3d_hits - mov skill3d_state, 2 - mov skill3d_timer, 40 - invoke PlayCasinoSound3D, OFFSET soundSkillHit, 0, 1 - jmp skill_check_finish_round - -skill_was_miss: - ; MISS! - mov skill3d_last_result, 0 - inc skill3d_misses - mov skill3d_state, 3 - mov skill3d_timer, 45 - invoke PlayCasinoSound3D, OFFSET soundSkillMiss, 0, 1 - -skill_check_finish_round: - cmp skill3d_hits, 5 - jge skill_game_escaped - cmp skill3d_misses, 3 - jge skill_game_lost - ret - -skill_game_escaped: - mov skill3d_state, 4 - mov skill3d_timer, 0 - ; Payout: 3x total return (+$2x bet profit) - mov eax, skill3d_bet - imul eax, 3 - add bankroll, eax - mov eax, skill3d_bet - shl eax, 1 - mov skill3d_win_amount, eax - invoke NpcRecordRound3D,10,1 - call SaveProgress3D - invoke PlayCasinoSound3D, OFFSET soundRoundWin, 0, 1 - ret - -skill_game_lost: - mov skill3d_state, 5 - mov skill3d_timer, 0 - invoke NpcRecordRound3D,10,0 - call SaveProgress3D - invoke PlayCasinoSound3D, OFFSET soundLose, 0, 1 - ret - -skill_handle_round_wait: - dec skill3d_timer - cmp skill3d_timer, 0 - jg skill_input_done - - ; Next round setup - invoke RandomRange3D, 90 - add eax, 80 - mov skill3d_zone_start, eax - - invoke RandomRange3D, 12 - add eax, skill3d_zone_start - add eax, 20 - mov skill3d_great_start, eax - - mov eax, skill3d_hits - shr eax, 1 - add eax, 4 - mov skill3d_speed, eax - mov skill3d_state, 1 - ret - -skill_handle_end_wait: - invoke Pressed3D, 20h - test eax, eax - jz skill_input_done - call InitSkillGame - ret - -skill_input_done: - ret -HandleSkillInput ENDP - -RenderSkillGame PROC uses ebx esi edi - local kx:DWORD - local tx:DWORD - - ; Industrial Steel bezel - invoke DrawBox, 0, 0, 320, 240, 00121416h - invoke DrawBoxBorder, 6, 6, 308, 228, 001A1D20h, 00FFD700h, 2 - - ; Header - invoke DrawBoxBorder, 20, 12, 280, 26, 00121418h, 00FFD700h, 2 - invoke DrawString8x8, 40, 21, OFFSET textSkillTitle, 00FFFF00h - - ; Status - invoke DrawBoxBorder, 20, 44, 110, 18, 00121418h, 002A3540h, 1 - invoke DrawString8x8, 24, 49, OFFSET textBankPrompt, 003CFF3Ch - invoke FormatNumber, bankroll, OFFSET hudNumBuffer - invoke DrawString8x8, 72, 49, OFFSET hudNumBuffer, 003CFF3Ch - - invoke DrawBoxBorder, 190, 44, 110, 18, 00121418h, 002A3540h, 1 - invoke DrawString8x8, 194, 49, OFFSET textBetPrompt, 00FFD700h - invoke FormatNumber, skill3d_bet, OFFSET hudNumBuffer - invoke DrawString8x8, 254, 49, OFFSET hudNumBuffer, 00FFD700h - - ; Survivor Progress - invoke DrawString8x8, 24, 70, OFFSET textSkillHitsHdr, 003CFF3Ch - invoke FormatNumber, skill3d_hits, OFFSET hudNumBuffer - invoke DrawString8x8, 64, 70, OFFSET hudNumBuffer, 003CFF3Ch - - invoke DrawString8x8, 180, 70, OFFSET textSkillMissHdr, 00FF6464h - invoke FormatNumber, skill3d_misses, OFFSET hudNumBuffer - invoke DrawString8x8, 240, 70, OFFSET hudNumBuffer, 00FF6464h - - ; Dial Frame (Track: X=50..270, Y=102..134) - invoke DrawBoxBorder, 50, 102, 220, 32, 000F1114h, 00404855h, 2 - - ; Calibrated ticks - mov tx, 60 -skill_ticks_loop: - cmp tx, 260 - jge skill_draw_zones - invoke DrawBox, tx, 104, 1, 6, 00303845h - invoke DrawBox, tx, 126, 1, 6, 00303845h - add tx, 12 - jmp skill_ticks_loop - -skill_draw_zones: - ; Normal Success Zone (Green) - invoke DrawBoxBorder, skill3d_zone_start, 106, skill3d_zone_width, 24, 00155020h, 003CFF3Ch, 1 - - ; Great Zone (Gold) - invoke DrawBoxBorder, skill3d_great_start, 106, skill3d_great_width, 24, 00FFD700h, 00FFFF00h, 1 - - ; Pointer / Needle at skill3d_needle - mov eax, skill3d_needle - dec eax - invoke DrawBox, eax, 98, 3, 40, 00FFFFFFh - mov eax, skill3d_needle - sub eax, 2 - invoke DrawBox, eax, 96, 5, 2, 00FF3030h - invoke DrawBox, eax, 138, 5, 2, 00FF3030h - - ; Center prompts / outcome - cmp skill3d_state, 0 - jne @F - invoke DrawString8x8, 52, 150, OFFSET textSkillReadyMsg, 00FFD700h - invoke DrawString8x8, 76, 166, OFFSET textSkillPrompt, 00D0D8E0h - jmp skill_render_keys -@@: - cmp skill3d_state, 1 - jne @F - invoke DrawString8x8, 76, 150, OFFSET textSkillPrompt, 00FFFF00h - jmp skill_render_keys -@@: - cmp skill3d_state, 2 - jne @F - cmp skill3d_last_result, 2 - jne skill_normal_hit_text - invoke DrawString8x8, 36, 150, OFFSET textSkillGreatMsg, 00FFFF00h - jmp skill_render_keys -skill_normal_hit_text: - invoke DrawString8x8, 64, 150, OFFSET textSkillHitMsg, 003CFF3Ch - jmp skill_render_keys -@@: - cmp skill3d_state, 3 - jne @F - invoke DrawString8x8, 88, 150, OFFSET textSkillMissMsg, 00FF6464h - jmp skill_render_keys -@@: - cmp skill3d_state, 4 - jne @F - invoke DrawString8x8, 48, 150, OFFSET textSkillEscape, 003CFF3Ch - invoke FormatNumber, skill3d_win_amount, OFFSET hudNumBuffer - invoke DrawString8x8, 240, 150, OFFSET hudNumBuffer, 003CFF3Ch - invoke DrawString8x8, 64, 166, OFFSET textSkullsAgain, 00FFD700h - jmp skill_render_keys -@@: - invoke DrawString8x8, 44, 150, OFFSET textSkillLost, 00FF6464h - invoke DrawString8x8, 64, 166, OFFSET textSkullsAgain, 00FFD700h - -skill_render_keys: - mov kx, 16 - invoke DrawKeycap3D, kx, 192, OFFSET textSkillKeySpace, 1 - add kx, eax - - invoke DrawKeycap3D, kx, 192, OFFSET textSkillKeyBet, 0 - add kx, eax - - invoke DrawKeycap3D, kx, 192, OFFSET textKeyEsc, 0 - ret -RenderSkillGame ENDP - -HandlePlayerInput PROC uses ebx esi edi - local speed:DWORD - local nextX:DWORD - local nextY:DWORD - mov eax, deltaTime3D - imul eax, 200 - mov speed, eax - cmp keys3D[10h], 0 - je @F - shl speed, 1 -@@: - mov eax, deltaTime3D - shr eax, 2 - inc eax - cmp keys3D[41h], 0 - jne input_turn_left - cmp keys3D[25h], 0 - je input_right -input_turn_left: - sub playerAngle, eax -input_right: - cmp keys3D[44h], 0 - jne input_turn_right - cmp keys3D[27h], 0 - je input_forward -input_turn_right: - add playerAngle, eax -input_forward: - and playerAngle, 511 - call UpdateCamera3D - xor edi, edi - cmp keys3D[57h], 0 - jne input_go_forward - cmp keys3D[26h], 0 - je input_back -input_go_forward: - inc edi -input_back: - cmp keys3D[53h], 0 - jne input_go_back - cmp keys3D[28h], 0 - je input_move -input_go_back: - dec edi -input_move: - test edi, edi - jz input_action - imul edi, speed - mov eax, playerDirX - imul edi - shrd eax, edx, 16 - add eax, playerX - mov nextX, eax - mov eax, playerDirY - imul edi - shrd eax, edx, 16 - add eax, playerY - mov nextY, eax - invoke CanWalk3D, nextX, playerY - test eax, eax - jz @F - mov eax, nextX - mov playerX, eax -@@: - invoke CanWalk3D, playerX, nextY - test eax, eax - jz input_action - mov eax, nextY - mov playerY, eax -input_action: - invoke Pressed3D, 45h - test eax, eax - jz @F - call Trigger3DInteraction -@@: - ret -HandlePlayerInput ENDP - -CheckInteractions PROC uses ebx esi edi - local nearest:DWORD - mov nearest, 262144 - mov interactTargetId, 0 - mov interactPromptPtr, 0 - xor esi, esi -interaction_scan: - cmp esi, NUM_SPRITES - jge interaction_done - imul edi, esi, SIZEOF SpriteObject - cmp [casinoSprites+edi].interactId, 0 - je interaction_next - mov eax, [casinoSprites+edi].posX - sub eax, playerX - sar eax, 8 - mov ebx, eax - imul eax, eax - mov ecx, eax - mov eax, [casinoSprites+edi].posY - sub eax, playerY - sar eax, 8 - mov edx, eax - imul eax, eax - add ecx, eax - cmp ecx, nearest - jae interaction_next - ; Only target objects in front of the camera. - mov eax, playerDirX - sar eax, 8 - imul eax, ebx - mov ebx, playerDirY - sar ebx, 8 - imul ebx, edx - add eax, ebx - cmp eax, 18000 - jl interaction_next - mov nearest, ecx - mov eax, [casinoSprites+edi].interactId - mov interactTargetId, eax - mov eax, [casinoSprites+edi].promptPtr - mov interactPromptPtr, eax -interaction_next: - inc esi - jmp interaction_scan -interaction_done: - call CheckHallInteractions3D - ret -CheckInteractions ENDP - -; --- RenderCabinetBezel: Отрисовка аркадного безеля терминала на 3D экране --- -RenderCabinetBezel PROC uses ebx esi edi, pTitle:DWORD - ; Затемняем 3D-зал в буфере кадра (делим яркость пополам) - mov ecx, SCREEN_SIZE - xor esi, esi -dim_bezel_loop: - mov eax, [screenBuffer + esi*4] - shr eax, 1 - and eax, 007F7F7Fh - mov [screenBuffer + esi*4], eax - inc esi - loop dim_bezel_loop - - ; Внешняя золотая рамка терминала - invoke DrawBoxBorder, 10, 14, 300, 212, 000C0E14h, 00D8BC6Ah, 2 - - ; Шапка терминала с названием игры - invoke DrawBox, 12, 16, 296, 16, 00221A10h - invoke DrawString8x8, 20, 20, pTitle, 00F5E2B0h - - ; Подвальная плашка с подсказкой по выходу - invoke DrawBox, 12, 210, 296, 14, 00141416h - invoke DrawString8x8, 20, 213, OFFSET textCabinetFooter, 00AAAAAAh - - ; Выводим кадр безеля в окно - call Present3D - ret -RenderCabinetBezel ENDP - -; --- LaunchClassicGame: Встраивание игры в UI терминала казино --- -LaunchClassicGame PROC uses ebx esi edi, pGameProc:DWORD, gameId:DWORD, pTitle:DWORD - LOCAL rcClient[16]:BYTE - LOCAL ptScreen[8]:BYTE - LOCAL fontInfo[84]:BYTE - LOCAL conWnd:DWORD - LOCAL conW:DWORD, conH:DWORD, conX:DWORD, conY:DWORD - LOCAL viewW:DWORD, viewH:DWORD - LOCAL offsetX:DWORD, offsetY:DWORD - - mov eax, gameId - mov currentGameId, eax - - ; 1. Рисуем золотой безель терминала на 3D экране - cmp pTitle, 0 - je @F - invoke RenderCabinetBezel, pTitle -@@: - - ; 2. Выделяем консоль - invoke AllocConsole - test eax, eax - jz launch_ret - - invoke GetStdHandle, STD_OUTPUT_HANDLE - mov hOut, eax - invoke GetStdHandle, STD_INPUT_HANDLE - mov hIn, eax - - invoke SetConsoleCP, 1251 - invoke SetConsoleOutputCP, 1251 - - cmp pTitle, 0 - je @F - invoke SetConsoleTitleA, pTitle -@@: - call EnableAnsi - call ConfigureConsoleSize - - ; 3. Настраиваем шрифт Consolas Bold 16pt - lea edi, fontInfo - xor eax, eax - mov ecx, 21 - rep stosd - mov dword ptr fontInfo[0], 84 ; cbSize - mov word ptr fontInfo[8], 0 ; dwFontSize.X - mov word ptr fontInfo[10], 16 ; dwFontSize.Y - mov dword ptr fontInfo[16], 700 ; FontWeight = FW_BOLD - mov word ptr fontInfo[20], 'C' - mov word ptr fontInfo[22], 'o' - mov word ptr fontInfo[24], 'n' - mov word ptr fontInfo[26], 's' - mov word ptr fontInfo[28], 'o' - mov word ptr fontInfo[30], 'l' - mov word ptr fontInfo[32], 'a' - mov word ptr fontInfo[34], 's' - mov word ptr fontInfo[36], 0 - lea eax, fontInfo - invoke SetCurrentConsoleFontEx, hOut, 0, eax - - ; 4. Получаем дескриптор окна консоли - invoke GetConsoleWindow - mov conWnd, eax - test eax, eax - jz run_game_body - - ; 5. Снимаем системную рамку Windows и заголовок с кнопками закрытия/сворачивания - invoke GetWindowLongA, conWnd, -16 ; GWL_STYLE - and eax, NOT (00C00000h or 00040000h or 00080000h or 00010000h or 00020000h) - or eax, 80000000h ; WS_POPUP - invoke SetWindowLongA, conWnd, -16, eax - - ; Связываем как дочернее/принадлежащее окно к окну игры - cmp h3DWnd, 0 - je show_con_fallback - invoke SetWindowLongA, conWnd, -8, h3DWnd ; GWL_HWNDPARENT - - ; 6. Вычисляем точные координаты для посадки экрана внутрь безеля - lea eax, rcClient - invoke GetClientRect, h3DWnd, eax - mov esi, dword ptr rcClient[8] ; ширина клиентской области - mov edi, dword ptr rcClient[12] ; высота клиентской области - test esi, esi - jz show_con_fallback - test edi, edi - jz show_con_fallback - - ; Расчет вьюпорта 4:3 точно как в Present3D - mov viewW, esi - mov eax, esi - imul eax, 3 - shr eax, 2 - cmp eax, edi - jle calc_view_h - mov eax, edi - imul eax, 4 - xor edx, edx - mov ecx, 3 - div ecx - mov viewW, eax - mov eax, edi -calc_view_h: - mov viewH, eax - - mov ebx, esi - sub ebx, viewW - shr ebx, 1 - mov offsetX, ebx - - mov ebx, edi - sub ebx, viewH - shr ebx, 1 - mov offsetY, ebx - - ; Экранные координаты левого верхнего угла клиентской области - mov dword ptr ptScreen[0], 0 - mov dword ptr ptScreen[4], 0 - lea eax, ptScreen - invoke ClientToScreen, h3DWnd, eax - - ; conW = viewW * 280 / 320 (внутреннее окно безеля) - mov eax, viewW - imul eax, 280 - xor edx, edx - mov ecx, 320 - div ecx - mov conW, eax - - ; conH = viewH * 168 / 240 - mov eax, viewH - imul eax, 168 - xor edx, edx - mov ecx, 240 - div ecx - mov conH, eax - - ; conX = ptScreen.x + offsetX + (viewW * 20 / 320) - mov eax, viewW - imul eax, 20 - xor edx, edx - mov ecx, 320 - div ecx - add eax, offsetX - add eax, dword ptr ptScreen[0] - mov conX, eax - - ; conY = ptScreen.y + offsetY + (viewH * 38 / 240) - mov eax, viewH - imul eax, 38 - xor edx, edx - mov ecx, 240 - div ecx - add eax, offsetY - add eax, dword ptr ptScreen[4] - mov conY, eax - - ; Позиционируем безрамочный экран точно внутрь золотой рамки безеля - invoke SetWindowPos, conWnd, 0, conX, conY, conW, conH, 20h or 40h ; SWP_FRAMECHANGED | SWP_SHOWWINDOW - jmp set_con_focus - -show_con_fallback: - invoke ShowWindow, conWnd, 5 ; SW_SHOW -set_con_focus: - invoke SetForegroundWindow, conWnd - invoke SetFocus, conWnd - -run_game_body: - invoke PlayCasinoSound3D, 0, 0, 0 - call InitSounds - ; Запуск оригинальной игры! - call pGameProc - call CloseLegacySounds3D - - ; Закрываем консоль - invoke FreeConsole - mov hOut, 0 - mov hIn, 0 - - ; Возвращаем фокус в окно 3D игры - cmp h3DWnd, 0 - je cleanup_game_input - invoke SetForegroundWindow, h3DWnd - invoke SetFocus, h3DWnd - -cleanup_game_input: - mov ecx, 256 - xor eax, eax - lea edi, keys3D - rep stosb - mov ecx, 256 - lea edi, pressedKeys3D - rep stosb - - invoke GetTickCount - mov previousTick3D, eax - mov frameStart3D, eax - mov deltaTime3D, 0 - - call SaveProgress3D - -launch_ret: - ret -LaunchClassicGame ENDP - -Trigger3DInteraction PROC - call TriggerHallInteraction3D - test eax, eax - jnz trigger_done - mov eax, interactTargetId - test eax, eax - jz trigger_done - - cmp eax, INTERACT_DANCER - jne check_target_bj - cmp bankroll, 100 - jl dancer_no_cash - sub bankroll, 100 - inc dancerLuckBuff - invoke CopyString3D, OFFSET textTips3D, OFFSET flashMessage - mov flashTimer, 100 - invoke PlayCasinoSound3D, OFFSET soundClick, 0, 1 - ret -dancer_no_cash: - invoke CopyString3D, OFFSET msgNeedMoney, OFFSET flashMessage - mov flashTimer, 60 - ret - -check_target_bj: - cmp eax, INTERACT_BLACKJACK - jne check_target_poker - call InitNativeBlackjack3D - mov engineMode, MODE_BLACKJACK - ret - -check_target_poker: - cmp eax, INTERACT_POKER - jne check_target_durak - call InitNativePoker3D - test eax, eax - jz target_unported - mov engineMode, MODE_POKER - ret - -check_target_durak: - cmp eax, INTERACT_DURAK - jne check_target_slots777 - call InitNativeDurak3D - mov engineMode, MODE_DURAK - ret - -check_target_slots777: - cmp eax, INTERACT_SLOTS_777 - jne check_target_slots_clover - call InitNativeSlots3D - test eax,eax - jz target_unported - mov engineMode,MODE_SLOTS - ret - -check_target_slots_clover: - cmp eax, INTERACT_SLOTS_CLOVER - jne check_target_roulette - call InitNativeClover3D - test eax,eax - jz target_unported - mov engineMode,MODE_CLOVER - ret - -check_target_roulette: - cmp eax, INTERACT_ROULETTE - jne check_target_dice - call InitNativeWheel3D - mov engineMode, MODE_ROULETTE - ret - -check_target_dice: - cmp eax, INTERACT_DICE - jne check_target_skulls - call InitDiceGame - mov engineMode, MODE_DICE - ret - -check_target_skulls: - cmp eax, INTERACT_SKULLS - jne check_target_coin - call InitSkullsGame - mov engineMode, MODE_SKULLS - ret - -check_target_coin: - cmp eax, INTERACT_COIN - jne check_target_skill - call InitCoinGame - mov engineMode, MODE_COIN - ret - -check_target_skill: - cmp eax, INTERACT_SKILL_CHECK - jne check_target_buckshot - call InitSkillGame - mov engineMode, MODE_SKILL - ret - -check_target_buckshot: - cmp eax, INTERACT_BUCKSHOT - jne check_target_rr - call InitBuckshot3D - mov engineMode, MODE_BUCKSHOT - ret - -check_target_rr: - cmp eax, INTERACT_RUSSIAN_ROULETTE - jne check_target_online_rr - call InitRussianGame3D - test eax, eax - jz @F - mov engineMode, MODE_RUSSIAN -@@: - ret - -check_target_online_rr: - cmp eax, INTERACT_ONLINE_RR - jne check_target_umamusume - call BeginUnavailable3D - ret - -check_target_umamusume: - cmp eax, INTERACT_UMAMUSUME - jne check_target_hell - call BeginUnavailable3D - ret - -check_target_hell: - cmp eax, INTERACT_HELL_TOWER - jne check_target_shop - call BeginUnavailable3D - ret - -check_target_shop: - cmp eax, INTERACT_SHOP - jne check_target_atm - call BeginMerchant3D - ret - -check_target_atm: - cmp eax, INTERACT_ATM - jne check_target_terminal - mov engineMode, MODE_ATM - ret - -check_target_terminal: - cmp eax, INTERACT_TERMINAL - jne check_target_observer - call BeginUnavailable3D - ret - -check_target_observer: - cmp eax, INTERACT_OBSERVER - jne target_unported - call BeginUnavailable3D - ret - -target_unported: - call BeginUnavailable3D -trigger_done: - ret -Trigger3DInteraction ENDP - -; --- Engine Initialization --- -Init3DEngine PROC - local screenCX:DWORD - local screenCY:DWORD - local posX:DWORD - local posY:DWORD - local bytesRead:DWORD - - push ebx - push esi - push edi - - call LoadDisplaySettings3D - call Create3DWindow - test eax, eax - jz init_failed - call LoadTextures3D - test eax, eax - jz init_failed - - call InitializeCasinoSprites3D - - ; Initialize raycasting worker thread and sync events - invoke CreateEventA, 0, 0, 0, 0 - mov hRaycastStartEvent, eax - invoke CreateEventA, 0, 0, 0, 0 - mov hRaycastDoneEvent, eax - mov bRaycastQuit, 0 - invoke CreateThread, 0, 65536, OFFSET RaycastWorkerProc, 0, 0, ADDR raycastThreadId - mov hRaycastThread, eax - - call InitHall3D - call BeginStartup3D - call RenderStartup3D - invoke ShowWindow, h3DWnd, SW_SHOW - invoke UpdateWindow, h3DWnd - invoke SetForegroundWindow, h3DWnd - mov eax, 1 - jmp init_return -init_failed: - xor eax, eax -init_return: - pop edi - pop esi - pop ebx - ret -Init3DEngine ENDP - -InitializeCasinoSprites3D PROC -init_sprites_table: - ; Sprite 0: VIP Dancer 1 (Stage Left) - mov casinoSprites[0*SIZEOF SpriteObject].posX, (13 * FP_1 + FP_HALF) - mov casinoSprites[0*SIZEOF SpriteObject].posY, (4 * FP_1) - mov casinoSprites[0*SIZEOF SpriteObject].baseTexId, 10 - mov casinoSprites[0*SIZEOF SpriteObject].frameCount, 12 - mov casinoSprites[0*SIZEOF SpriteObject].curFrame, 0 - mov casinoSprites[0*SIZEOF SpriteObject].animTimer, 0 - mov casinoSprites[0*SIZEOF SpriteObject].animSpeed, 5 - mov casinoSprites[0*SIZEOF SpriteObject].interactId, INTERACT_DANCER - mov casinoSprites[0*SIZEOF SpriteObject].promptPtr, OFFSET promptDancer - - ; Sprite 1: VIP Dancer 2 (Center Stage Star) - mov casinoSprites[1*SIZEOF SpriteObject].posX, (16 * FP_1 + FP_HALF) - mov casinoSprites[1*SIZEOF SpriteObject].posY, (3 * FP_1 + FP_HALF) - mov casinoSprites[1*SIZEOF SpriteObject].baseTexId, 10 - mov casinoSprites[1*SIZEOF SpriteObject].frameCount, 12 - mov casinoSprites[1*SIZEOF SpriteObject].curFrame, 2 - mov casinoSprites[1*SIZEOF SpriteObject].animTimer, 0 - mov casinoSprites[1*SIZEOF SpriteObject].animSpeed, 5 - mov casinoSprites[1*SIZEOF SpriteObject].interactId, INTERACT_DANCER - mov casinoSprites[1*SIZEOF SpriteObject].promptPtr, OFFSET promptDancer - - ; Sprite 2: VIP Dancer 3 (Stage Right) - mov casinoSprites[2*SIZEOF SpriteObject].posX, (19 * FP_1 + FP_HALF) - mov casinoSprites[2*SIZEOF SpriteObject].posY, (4 * FP_1) - mov casinoSprites[2*SIZEOF SpriteObject].baseTexId, 10 - mov casinoSprites[2*SIZEOF SpriteObject].frameCount, 12 - mov casinoSprites[2*SIZEOF SpriteObject].curFrame, 1 - mov casinoSprites[2*SIZEOF SpriteObject].animTimer, 0 - mov casinoSprites[2*SIZEOF SpriteObject].animSpeed, 5 - mov casinoSprites[2*SIZEOF SpriteObject].interactId, INTERACT_DANCER - mov casinoSprites[2*SIZEOF SpriteObject].promptPtr, OFFSET promptDancer - - ; Sprite 3: VIP Blackjack (Front Center Left) - mov casinoSprites[3*SIZEOF SpriteObject].posX, (12 * FP_1 + FP_HALF) - mov casinoSprites[3*SIZEOF SpriteObject].posY, (8 * FP_1) - mov casinoSprites[3*SIZEOF SpriteObject].baseTexId, 30 - mov casinoSprites[3*SIZEOF SpriteObject].frameCount, 1 - mov casinoSprites[3*SIZEOF SpriteObject].curFrame, 0 - mov casinoSprites[3*SIZEOF SpriteObject].animTimer, 0 - mov casinoSprites[3*SIZEOF SpriteObject].animSpeed, 1 - mov casinoSprites[3*SIZEOF SpriteObject].interactId, INTERACT_BLACKJACK - mov casinoSprites[3*SIZEOF SpriteObject].promptPtr, OFFSET promptBlackjack - - ; Sprite 4: European Roulette Table (Front Center) - mov casinoSprites[4*SIZEOF SpriteObject].posX, (16 * FP_1 + FP_HALF) - mov casinoSprites[4*SIZEOF SpriteObject].posY, (10 * FP_1) - mov casinoSprites[4*SIZEOF SpriteObject].baseTexId, 31 - mov casinoSprites[4*SIZEOF SpriteObject].frameCount, 1 - mov casinoSprites[4*SIZEOF SpriteObject].curFrame, 0 - mov casinoSprites[4*SIZEOF SpriteObject].animTimer, 0 - mov casinoSprites[4*SIZEOF SpriteObject].animSpeed, 1 - mov casinoSprites[4*SIZEOF SpriteObject].interactId, INTERACT_ROULETTE - mov casinoSprites[4*SIZEOF SpriteObject].promptPtr, OFFSET promptCasinoRoulette - - ; Sprite 5: Texas Hold'em Poker Table (Front Center Right) - mov casinoSprites[5*SIZEOF SpriteObject].posX, (20 * FP_1 + FP_HALF) - mov casinoSprites[5*SIZEOF SpriteObject].posY, (8 * FP_1) - mov casinoSprites[5*SIZEOF SpriteObject].baseTexId, 30 - mov casinoSprites[5*SIZEOF SpriteObject].frameCount, 1 - mov casinoSprites[5*SIZEOF SpriteObject].curFrame, 0 - mov casinoSprites[5*SIZEOF SpriteObject].animTimer, 0 - mov casinoSprites[5*SIZEOF SpriteObject].animSpeed, 1 - mov casinoSprites[5*SIZEOF SpriteObject].interactId, INTERACT_POKER - mov casinoSprites[5*SIZEOF SpriteObject].promptPtr, OFFSET promptPoker - - ; Sprite 6: Podkidnoy Durak Card Table - mov casinoSprites[6*SIZEOF SpriteObject].posX, (24 * FP_1 + FP_HALF) - mov casinoSprites[6*SIZEOF SpriteObject].posY, (8 * FP_1) - mov casinoSprites[6*SIZEOF SpriteObject].baseTexId, 30 - mov casinoSprites[6*SIZEOF SpriteObject].frameCount, 1 - mov casinoSprites[6*SIZEOF SpriteObject].curFrame, 0 - mov casinoSprites[6*SIZEOF SpriteObject].animTimer, 0 - mov casinoSprites[6*SIZEOF SpriteObject].animSpeed, 1 - mov casinoSprites[6*SIZEOF SpriteObject].interactId, INTERACT_DURAK - mov casinoSprites[6*SIZEOF SpriteObject].promptPtr, OFFSET promptDurak - - ; Sprite 7: Classic Slots 777 (West Arcade 1) - mov casinoSprites[7*SIZEOF SpriteObject].posX, (6 * FP_1) - mov casinoSprites[7*SIZEOF SpriteObject].posY, (8 * FP_1) - mov casinoSprites[7*SIZEOF SpriteObject].baseTexId, 24 - mov casinoSprites[7*SIZEOF SpriteObject].frameCount, 3 - mov casinoSprites[7*SIZEOF SpriteObject].curFrame, 0 - mov casinoSprites[7*SIZEOF SpriteObject].animTimer, 0 - mov casinoSprites[7*SIZEOF SpriteObject].animSpeed, 8 - mov casinoSprites[7*SIZEOF SpriteObject].interactId, INTERACT_SLOTS_777 - mov casinoSprites[7*SIZEOF SpriteObject].promptPtr, OFFSET promptClassicSlot - - ; Sprite 8: CloverPit Slots 5x3 (West Arcade 2) - mov casinoSprites[8*SIZEOF SpriteObject].posX, (6 * FP_1) - mov casinoSprites[8*SIZEOF SpriteObject].posY, (11 * FP_1) - mov casinoSprites[8*SIZEOF SpriteObject].baseTexId, 24 - mov casinoSprites[8*SIZEOF SpriteObject].frameCount, 3 - mov casinoSprites[8*SIZEOF SpriteObject].curFrame, 1 - mov casinoSprites[8*SIZEOF SpriteObject].animTimer, 0 - mov casinoSprites[8*SIZEOF SpriteObject].animSpeed, 8 - mov casinoSprites[8*SIZEOF SpriteObject].interactId, INTERACT_SLOTS_CLOVER - mov casinoSprites[8*SIZEOF SpriteObject].promptPtr, OFFSET promptCloverSlot - - ; Sprite 9: Craps & Dice Table (West Arcade 3) - mov casinoSprites[9*SIZEOF SpriteObject].posX, (6 * FP_1) - mov casinoSprites[9*SIZEOF SpriteObject].posY, (14 * FP_1) - mov casinoSprites[9*SIZEOF SpriteObject].baseTexId, 30 - mov casinoSprites[9*SIZEOF SpriteObject].frameCount, 1 - mov casinoSprites[9*SIZEOF SpriteObject].curFrame, 0 - mov casinoSprites[9*SIZEOF SpriteObject].animTimer, 0 - mov casinoSprites[9*SIZEOF SpriteObject].animSpeed, 1 - mov casinoSprites[9*SIZEOF SpriteObject].interactId, INTERACT_DICE - mov casinoSprites[9*SIZEOF SpriteObject].promptPtr, OFFSET promptDice - - ; Sprite 10: Skulls & Cups Table - mov casinoSprites[10*SIZEOF SpriteObject].posX, (10 * FP_1) - mov casinoSprites[10*SIZEOF SpriteObject].posY, (15 * FP_1) - mov casinoSprites[10*SIZEOF SpriteObject].baseTexId, 30 - mov casinoSprites[10*SIZEOF SpriteObject].frameCount, 1 - mov casinoSprites[10*SIZEOF SpriteObject].curFrame, 0 - mov casinoSprites[10*SIZEOF SpriteObject].animTimer, 0 - mov casinoSprites[10*SIZEOF SpriteObject].animSpeed, 1 - mov casinoSprites[10*SIZEOF SpriteObject].interactId, INTERACT_SKULLS - mov casinoSprites[10*SIZEOF SpriteObject].promptPtr, OFFSET promptSkulls - - ; Sprite 11: Coin Toss Stand - mov casinoSprites[11*SIZEOF SpriteObject].posX, (14 * FP_1) - mov casinoSprites[11*SIZEOF SpriteObject].posY, (15 * FP_1) - mov casinoSprites[11*SIZEOF SpriteObject].baseTexId, 30 - mov casinoSprites[11*SIZEOF SpriteObject].frameCount, 1 - mov casinoSprites[11*SIZEOF SpriteObject].curFrame, 0 - mov casinoSprites[11*SIZEOF SpriteObject].animTimer, 0 - mov casinoSprites[11*SIZEOF SpriteObject].animSpeed, 1 - mov casinoSprites[11*SIZEOF SpriteObject].interactId, INTERACT_COIN - mov casinoSprites[11*SIZEOF SpriteObject].promptPtr, OFFSET promptCoin - - ; Sprite 12: Skill Check Stand - mov casinoSprites[12*SIZEOF SpriteObject].posX, (18 * FP_1) - mov casinoSprites[12*SIZEOF SpriteObject].posY, (15 * FP_1) - mov casinoSprites[12*SIZEOF SpriteObject].baseTexId, 30 - mov casinoSprites[12*SIZEOF SpriteObject].frameCount, 1 - mov casinoSprites[12*SIZEOF SpriteObject].curFrame, 0 - mov casinoSprites[12*SIZEOF SpriteObject].animTimer, 0 - mov casinoSprites[12*SIZEOF SpriteObject].animSpeed, 1 - mov casinoSprites[12*SIZEOF SpriteObject].interactId, INTERACT_SKILL_CHECK - mov casinoSprites[12*SIZEOF SpriteObject].promptPtr, OFFSET promptSkillCheck - - ; Sprite 13: Umamusume Derby Lounge - mov casinoSprites[13*SIZEOF SpriteObject].posX, (22 * FP_1) - mov casinoSprites[13*SIZEOF SpriteObject].posY, (15 * FP_1) - mov casinoSprites[13*SIZEOF SpriteObject].baseTexId, 30 - mov casinoSprites[13*SIZEOF SpriteObject].frameCount, 1 - mov casinoSprites[13*SIZEOF SpriteObject].curFrame, 0 - mov casinoSprites[13*SIZEOF SpriteObject].animTimer, 0 - mov casinoSprites[13*SIZEOF SpriteObject].animSpeed, 1 - mov casinoSprites[13*SIZEOF SpriteObject].interactId, INTERACT_UMAMUSUME - mov casinoSprites[13*SIZEOF SpriteObject].promptPtr, OFFSET promptUmamusume - - ; Sprite 14: Boutique & Shop (East Wing) - mov casinoSprites[14*SIZEOF SpriteObject].posX, (26 * FP_1) - mov casinoSprites[14*SIZEOF SpriteObject].posY, (12 * FP_1) - mov casinoSprites[14*SIZEOF SpriteObject].baseTexId, 32 - mov casinoSprites[14*SIZEOF SpriteObject].frameCount, 1 - mov casinoSprites[14*SIZEOF SpriteObject].curFrame, 0 - mov casinoSprites[14*SIZEOF SpriteObject].animTimer, 0 - mov casinoSprites[14*SIZEOF SpriteObject].animSpeed, 1 - mov casinoSprites[14*SIZEOF SpriteObject].interactId, INTERACT_SHOP - mov casinoSprites[14*SIZEOF SpriteObject].promptPtr, OFFSET promptShop - - ; Sprite 15: Cashier & ATM (East Wing) - mov casinoSprites[15*SIZEOF SpriteObject].posX, (26 * FP_1) - mov casinoSprites[15*SIZEOF SpriteObject].posY, (16 * FP_1) - mov casinoSprites[15*SIZEOF SpriteObject].baseTexId, 33 - mov casinoSprites[15*SIZEOF SpriteObject].frameCount, 1 - mov casinoSprites[15*SIZEOF SpriteObject].curFrame, 0 - mov casinoSprites[15*SIZEOF SpriteObject].animTimer, 0 - mov casinoSprites[15*SIZEOF SpriteObject].animSpeed, 1 - mov casinoSprites[15*SIZEOF SpriteObject].interactId, INTERACT_ATM - mov casinoSprites[15*SIZEOF SpriteObject].promptPtr, OFFSET promptATM - - ; Sprite 16: Player Terminal (East Wing) - mov casinoSprites[16*SIZEOF SpriteObject].posX, (26 * FP_1) - mov casinoSprites[16*SIZEOF SpriteObject].posY, (20 * FP_1) - mov casinoSprites[16*SIZEOF SpriteObject].baseTexId, 33 - mov casinoSprites[16*SIZEOF SpriteObject].frameCount, 1 - mov casinoSprites[16*SIZEOF SpriteObject].curFrame, 0 - mov casinoSprites[16*SIZEOF SpriteObject].animTimer, 0 - mov casinoSprites[16*SIZEOF SpriteObject].animSpeed, 1 - mov casinoSprites[16*SIZEOF SpriteObject].interactId, INTERACT_TERMINAL - mov casinoSprites[16*SIZEOF SpriteObject].promptPtr, OFFSET promptPlayerTerminal - - ; Sprite 17: Buckshot Roulette (South-West) - mov casinoSprites[17*SIZEOF SpriteObject].posX, (12 * FP_1) - mov casinoSprites[17*SIZEOF SpriteObject].posY, (22 * FP_1) - mov casinoSprites[17*SIZEOF SpriteObject].baseTexId, 30 - mov casinoSprites[17*SIZEOF SpriteObject].frameCount, 1 - mov casinoSprites[17*SIZEOF SpriteObject].curFrame, 0 - mov casinoSprites[17*SIZEOF SpriteObject].animTimer, 0 - mov casinoSprites[17*SIZEOF SpriteObject].animSpeed, 1 - mov casinoSprites[17*SIZEOF SpriteObject].interactId, INTERACT_BUCKSHOT - mov casinoSprites[17*SIZEOF SpriteObject].promptPtr, OFFSET promptBuckshot - - ; Sprite 18: Observer Lounge (South-East) - mov casinoSprites[18*SIZEOF SpriteObject].posX, (20 * FP_1) - mov casinoSprites[18*SIZEOF SpriteObject].posY, (22 * FP_1) - mov casinoSprites[18*SIZEOF SpriteObject].baseTexId, 30 - mov casinoSprites[18*SIZEOF SpriteObject].frameCount, 1 - mov casinoSprites[18*SIZEOF SpriteObject].curFrame, 0 - mov casinoSprites[18*SIZEOF SpriteObject].animTimer, 0 - mov casinoSprites[18*SIZEOF SpriteObject].animSpeed, 1 - mov casinoSprites[18*SIZEOF SpriteObject].interactId, INTERACT_OBSERVER - mov casinoSprites[18*SIZEOF SpriteObject].promptPtr, OFFSET promptObserver - - ; Sprite 19: Russian Roulette (Backroom Entrance) - mov casinoSprites[19*SIZEOF SpriteObject].posX, (16 * FP_1) - mov casinoSprites[19*SIZEOF SpriteObject].posY, (25 * FP_1) - mov casinoSprites[19*SIZEOF SpriteObject].baseTexId, 34 - mov casinoSprites[19*SIZEOF SpriteObject].frameCount, 1 - mov casinoSprites[19*SIZEOF SpriteObject].curFrame, 0 - mov casinoSprites[19*SIZEOF SpriteObject].animTimer, 0 - mov casinoSprites[19*SIZEOF SpriteObject].animSpeed, 1 - mov casinoSprites[19*SIZEOF SpriteObject].interactId, INTERACT_RUSSIAN_ROULETTE - mov casinoSprites[19*SIZEOF SpriteObject].promptPtr, OFFSET promptRussianRoulette - - ; Sprite 20: Online Russian Roulette (Backroom Secret Terminal) - mov casinoSprites[20*SIZEOF SpriteObject].posX, (18 * FP_1) - mov casinoSprites[20*SIZEOF SpriteObject].posY, (25 * FP_1) - mov casinoSprites[20*SIZEOF SpriteObject].baseTexId, 34 - mov casinoSprites[20*SIZEOF SpriteObject].frameCount, 1 - mov casinoSprites[20*SIZEOF SpriteObject].curFrame, 0 - mov casinoSprites[20*SIZEOF SpriteObject].animTimer, 0 - mov casinoSprites[20*SIZEOF SpriteObject].animSpeed, 1 - mov casinoSprites[20*SIZEOF SpriteObject].interactId, INTERACT_ONLINE_RR - mov casinoSprites[20*SIZEOF SpriteObject].promptPtr, OFFSET promptOnlineRR - - ; Sprite 21: Hell Tower Portal (South Wing Deep End) - mov casinoSprites[21*SIZEOF SpriteObject].posX, (16 * FP_1 + FP_HALF) - mov casinoSprites[21*SIZEOF SpriteObject].posY, (29 * FP_1) - mov casinoSprites[21*SIZEOF SpriteObject].baseTexId, 4 - mov casinoSprites[21*SIZEOF SpriteObject].frameCount, 1 - mov casinoSprites[21*SIZEOF SpriteObject].curFrame, 0 - mov casinoSprites[21*SIZEOF SpriteObject].animTimer, 0 - mov casinoSprites[21*SIZEOF SpriteObject].animSpeed, 1 - mov casinoSprites[21*SIZEOF SpriteObject].interactId, INTERACT_HELL_TOWER - mov casinoSprites[21*SIZEOF SpriteObject].promptPtr, OFFSET promptHellTower - ret -InitializeCasinoSprites3D ENDP - -include src_graphics\audio_code.inc -include src_graphics\dice_animation.inc -include src_graphics\russian_roulette.inc -include src_graphics\startup_code.inc -include src_graphics\card_table_assets.inc -include src_graphics\poker_evaluator.inc -include src_graphics\native_poker.inc -include src_graphics\native_blackjack.inc -include src_graphics\native_durak.inc -include src_graphics\card_tables_render.inc -include src_graphics\durak_render.inc -include src_graphics\card_table_input.inc -include src_graphics\scene_animation.inc -include src_graphics\native_slots.inc -include src_graphics\native_clover.inc -include src_graphics\native_coin.inc -include src_graphics\graphic_profiles.inc -include src_graphics\city_arrival_scene.inc -include src_graphics\arrival_scene.inc -include src_graphics\merchant_scene.inc -include src_graphics\hall_scene.inc -include src_graphics\npc_mind.inc -include src_graphics\npc_life.inc -include src_graphics\npc_contracts.inc -include src_graphics\native_wheel.inc -include src_graphics\billiards.inc -include src_graphics\buckshot.inc -include src_graphics\russian_table.inc -include src_graphics\unavailable.inc - -; --- Main Loop of the 3D Casino Engine --- -StartCasino3D PROC uses ebx esi edi - call Init3DEngine - test eax, eax - jz engine_shutdown - invoke GetTickCount - mov rngSeed3D, eax - mov previousTick3D, eax -engine_loop: - invoke PeekMessageA, OFFSET msg3D, 0, 0, 0, PM_REMOVE - test eax, eax - jz dispatch_frame - cmp msg3D.message, WM_QUIT - je engine_shutdown - invoke TranslateMessage, OFFSET msg3D - invoke DispatchMessageA, OFFSET msg3D - jmp engine_loop - -dispatch_frame: - invoke GetTickCount - mov frameStart3D, eax - sub eax, previousTick3D - cmp eax, 50 - jbe @F - mov eax, 50 -@@: - mov deltaTime3D, eax - mov eax, frameStart3D - mov previousTick3D, eax - invoke GetForegroundWindow - cmp eax, h3DWnd - jne engine_idle - invoke IsIconic, h3DWnd - test eax, eax - jnz engine_idle - invoke Pressed3D, 7Ah - test eax, eax - jz @F - call ToggleFullscreen3D -@@: - invoke Pressed3D, 1Bh - test eax, eax - jz engine_tick - cmp engineMode, MODE_INTRO - jne @F - call FinishStartup3D - jmp engine_tick -@@: - cmp engineMode, MODE_ARRIVAL - jne @F - call ArrivalEscape3D - jmp engine_tick -@@: - cmp engineMode, MODE_WALK - jne leave_table - xor paused3D, 1 - jmp engine_tick -leave_table: - call CardTableEscape3D - test eax, eax - jnz engine_tick - call TableBusy3D - test eax, eax - jz leave_idle_table - xor paused3D, 1 - call ClearKeys3D - jmp engine_tick -leave_idle_table: - mov paused3D, 0 - mov engineMode, MODE_WALK - call ClearKeys3D - invoke PlayCasinoSound3D, 0, 0, 0 -engine_tick: - cmp paused3D, 0 - jne draw_pause - mov eax, deltaTime3D - add animationClock3D, eax - cmp engineMode, MODE_INTRO - jne check_arrival_mode - call HandleStartupInput3D - cmp engineMode, MODE_INTRO - jne check_arrival_mode - call RenderStartup3D - jmp present_frame -check_arrival_mode: - cmp engineMode, MODE_ARRIVAL - jne check_walk_mode - call HandleArrival3D - cmp engineMode, MODE_WALK - je check_walk_mode - call RenderArrival3D - jmp present_frame -check_walk_mode: - cmp engineMode, MODE_WALK - jne check_slots_mode - call UpdateHall3D - call UpdateCamera3D - call CheckInteractions - call HandlePlayerInput - call UpdateCamera3D - call RenderCeilingAndFloor - call RenderWalls - call PrepareCityDepth3D - call RenderSprites - call RenderHall3D - call RenderHUD - call RenderMinimap - jmp present_frame -check_slots_mode: - cmp engineMode,MODE_CLOVER - jne @F - call HandleNativeClover3D - call RenderNativeClover3D - jmp present_frame -@@: - cmp engineMode,MODE_NPC_DIALOG - jne @F - call HandleNpcDialog3D - call RenderNpcDialog3D - jmp present_frame -@@: - cmp engineMode, MODE_UNAVAILABLE - jne @F - call HandleUnavailable3D - call RenderUnavailable3D - jmp present_frame -@@: - cmp engineMode, MODE_POOL - jne @F - call HandlePool3D - call RenderPool3D - jmp present_frame -@@: - cmp engineMode, MODE_BAR - jne @F - call HandleBar3D - call RenderBar3D - jmp present_frame -@@: - cmp engineMode, MODE_STAIRS - jne @F - call HandleStairs3D - call RenderStairs3D - jmp present_frame -@@: - cmp engineMode, MODE_SLOTS - jne check_bj_mode - call HandleNativeSlots3D - cmp engineMode,MODE_WALK - je check_walk_mode - call RenderNativeSlots3D - jmp present_frame -check_bj_mode: - cmp engineMode, MODE_BLACKJACK - jne check_poker_mode - call HandleNativeBlackjack3D - cmp engineMode, MODE_WALK - je check_walk_mode - call RenderNativeBlackjack3D - jmp present_frame -check_poker_mode: - cmp engineMode, MODE_POKER - jne check_durak_mode - call HandleNativePoker3D - cmp engineMode, MODE_WALK - je check_walk_mode - call RenderNativePoker3D - jmp present_frame -check_durak_mode: - cmp engineMode, MODE_DURAK - jne check_roul_mode - call HandleNativeDurak3D - cmp engineMode, MODE_WALK - je check_walk_mode - call RenderNativeDurak3D - jmp present_frame -check_roul_mode: - cmp engineMode, MODE_ROULETTE - jne check_shop_mode - call HandleNativeWheel3D - call RenderNativeWheel3D - jmp present_frame -check_shop_mode: - cmp engineMode, MODE_SHOP - jne check_atm_mode - call HandleMerchant3D - call RenderMerchant3D - jmp present_frame -check_atm_mode: - cmp engineMode, MODE_ATM - jne check_coin_mode - call HandleATMInput - call RenderATMGame - jmp present_frame -check_coin_mode: - cmp engineMode, MODE_COIN - jne check_dice_mode - call HandleCoinInput - call RenderCoinGame - jmp present_frame -check_dice_mode: - cmp engineMode, MODE_DICE - jne check_skulls_mode - call HandleDiceInput - call RenderDiceGame - jmp present_frame -check_skulls_mode: - cmp engineMode, MODE_SKULLS - jne check_skill_mode - call HandleSkullsInput - call RenderSkullsGame - jmp present_frame -check_skill_mode: - cmp engineMode, MODE_SKILL - jne check_buckshot_mode - call HandleSkillInput - call RenderSkillGame - jmp present_frame -check_buckshot_mode: - cmp engineMode, MODE_BUCKSHOT - jne check_russian_mode - call HandleBuckshot3D - call RenderBuckshot3D - jmp present_frame -check_russian_mode: - cmp engineMode, MODE_RUSSIAN - jne present_frame - call HandleRussianInput3D - call RenderRussianGame3D - jmp present_frame -draw_pause: - invoke DrawBoxBorder, 28, 36, 264, 168, 00151C21h, 00D8BC6Ah, 2 - invoke DrawString8x8, 44, 48, OFFSET textPause3D, 00FFFFFFh - cmp displayFill3D, 0 - je @F - invoke DrawString8x8, 44, 72, OFFSET textDisplayFill3D, 00D8BC6Ah - jmp pause_draw_quality -@@: - invoke DrawString8x8, 44, 72, OFFSET textDisplayFit3D, 00D8BC6Ah -pause_draw_quality: - invoke DrawString8x8, 44, 92, OFFSET textLowSpec3D, 00D8BC6Ah - mov eax, settingsLowSpec - cmp eax, 0 - jne @F - mov edx, OFFSET textLowSpecOff3D - jmp pause_draw_quality_value -@@: - cmp eax, 1 - jne @F - mov edx, OFFSET textLowSpecEco3D - jmp pause_draw_quality_value -@@: - mov edx, OFFSET textLowSpecQuiet3D -pause_draw_quality_value: - invoke DrawString8x8, 208, 92, edx, 00FFFFFFh - invoke DrawString8x8, 44, 112, OFFSET textVolumeKeys3D, 00D8BC6Ah - invoke DrawString8x8, 44, 130, OFFSET textSoundLevel3D, 00BBBBBBh - invoke FormatNumber, settingsVolume, OFFSET hudNumBuffer - invoke DrawString8x8, 124, 130, OFFSET hudNumBuffer, 00FFFFFFh - invoke DrawString8x8, 44, 150, OFFSET textFullscreenKey3D, 00A0A0A0h - invoke DrawString8x8, 44, 170, OFFSET textResume3D, 00D8BC6Ah - invoke DrawString8x8, 44, 188, OFFSET textQuit3D, 00BBBBBBh - invoke Pressed3D, 31h - test eax, eax - jz @F - xor displayFill3D, 1 - call SaveDisplaySettings3D -@@: - invoke Pressed3D, 32h - test eax, eax - jz @F - inc settingsLowSpec - cmp settingsLowSpec, 3 - jb pause_low_spec_saved - mov settingsLowSpec, 0 -pause_low_spec_saved: - call SaveProgress3D -@@: - invoke Pressed3D, 0BBh - test eax, eax - jz @F - cmp settingsVolume, 10 - jae @F - inc settingsVolume - call ApplySoundVolume - call SaveProgress3D -@@: - invoke Pressed3D, 0BDh - test eax, eax - jz @F - mov eax, settingsVolume - test eax, eax - jz @F - dec settingsVolume - call ApplySoundVolume - call SaveProgress3D -@@: - invoke Pressed3D, 51h - test eax, eax - jz @F - call SaveProgress3D - jmp engine_shutdown -present_frame: - mov eax, engineMode - cmp eax, lastPersistMode3D - je @F - cmp eax, MODE_WALK - jne @F - call SaveProgress3D -@@: - mov eax, engineMode - mov lastPersistMode3D, eax - call Present3D - mov mouseClick3D, 0 - lea edi, pressedKeys3D - xor eax, eax - mov ecx, 64 - rep stosd - invoke GetTickCount - sub eax, frameStart3D - mov ecx, 16 - cmp settingsLowSpec, 1 - jne @F - mov ecx, 24 -@@: - cmp settingsLowSpec, 2 - jne @F - mov ecx, 33 -@@: - cmp eax, ecx - jae engine_loop - sub ecx, eax - invoke Sleep, ecx - jmp engine_loop -engine_idle: - invoke Sleep, 50 - jmp engine_loop -engine_shutdown: - cmp hRaycastThread, 0 - je @F - mov bRaycastQuit, 1 - invoke SetEvent, hRaycastStartEvent - invoke WaitForSingleObject, hRaycastThread, 1000 - invoke CloseHandle, hRaycastThread - invoke CloseHandle, hRaycastStartEvent - invoke CloseHandle, hRaycastDoneEvent - mov hRaycastThread, 0 - mov hRaycastStartEvent, 0 - mov hRaycastDoneEvent, 0 -@@: - call SaveProgress3D - invoke PlayCasinoSound3D, 0, 0, 0 - call FreeRussianAssets3D - call FreeStartupAssets3D - call FreeCardTableAssets3D - call FreeBuckshotAssets3D - call FreeNativeSlots3D - call FreeNativeClover3D - call FreePyramidAssets3D - call FreeArrivalAssets3D - cmp h3DDC, 0 - je @F - invoke ReleaseDC, h3DWnd, h3DDC - mov h3DDC, 0 -@@: - cmp h3DWnd, 0 - je @F - invoke DestroyWindow, h3DWnd - mov h3DWnd, 0 -@@: - ret -StartCasino3D ENDP - -include src_graphics\platform_code.inc - -IFDEF CASINO_ACTION_TEST -include tools\tests\casino_actions_test.inc -ENDIF + +; ============================================================================== +; CASINO 2.5D - MASM32 SOFTWARE RAYCASTER (CP1251) +; Graphical migration; this is not id Software's Doom engine. +; ============================================================================== + +includelib gdi32.lib +includelib winmm.lib + +CreateWindowExA PROTO :DWORD,:DWORD,:DWORD,:DWORD,:DWORD,:DWORD,:DWORD,:DWORD,:DWORD,:DWORD,:DWORD,:DWORD +RegisterClassExA PROTO :DWORD +DefWindowProcA PROTO :DWORD,:DWORD,:DWORD,:DWORD +ShowWindow PROTO :DWORD,:DWORD +UpdateWindow PROTO :DWORD +GetDC PROTO :DWORD +ReleaseDC PROTO :DWORD,:DWORD +StretchDIBits PROTO :DWORD,:DWORD,:DWORD,:DWORD,:DWORD,:DWORD,:DWORD,:DWORD,:DWORD,:DWORD,:DWORD,:DWORD,:DWORD +PeekMessageA PROTO :DWORD,:DWORD,:DWORD,:DWORD,:DWORD +TranslateMessage PROTO :DWORD +DispatchMessageA PROTO :DWORD +PostQuitMessage PROTO :DWORD +DestroyWindow PROTO :DWORD +SetWindowTextA PROTO :DWORD,:DWORD +SetForegroundWindow PROTO :DWORD +GetConsoleWindow PROTO +GetSystemMetrics PROTO :DWORD +CreateFileA PROTO :DWORD,:DWORD,:DWORD,:DWORD,:DWORD,:DWORD,:DWORD +ReadFile PROTO :DWORD,:DWORD,:DWORD,:DWORD,:DWORD +CloseHandle PROTO :DWORD +GetAsyncKeyState PROTO :DWORD +PlaySoundA PROTO :DWORD,:DWORD,:DWORD +GetModuleFileNameA PROTO :DWORD,:DWORD,:DWORD +CopyFileA PROTO :DWORD,:DWORD,:DWORD +lstrcmpiA PROTO :DWORD,:DWORD +GetFileSize PROTO :DWORD,:DWORD +Sleep PROTO :DWORD +CreateThread PROTO :DWORD,:DWORD,:DWORD,:DWORD,:DWORD,:DWORD +CreateEventA PROTO :DWORD,:DWORD,:DWORD,:DWORD +SetEvent PROTO :DWORD +WaitForSingleObject PROTO :DWORD,:DWORD + +C3D_POINT STRUCT + x dd ? + y dd ? +C3D_POINT ENDS + +C3D_MSG STRUCT + hwnd dd ? + message dd ? + wParam dd ? + lParam dd ? + time dd ? + pt C3D_POINT <> +C3D_MSG ENDS + +C3D_WNDCLASSEX STRUCT + cbSize dd ? + style dd ? + lpfnWndProc dd ? + cbClsExtra dd ? + cbWndExtra dd ? + hInstance dd ? + hIcon dd ? + hCursor dd ? + hbrBackground dd ? + lpszMenuName dd ? + lpszClassName dd ? + hIconSm dd ? +C3D_WNDCLASSEX ENDS + +C3D_BITMAPINFOHEADER STRUCT + biSize dd ? + biWidth dd ? + biHeight dd ? + biPlanes dw ? + biBitCount dw ? + biCompression dd ? + biSizeImage dd ? + biXPelsPerMeter dd ? + biYPelsPerMeter dd ? + biClrUsed dd ? + biClrImportant dd ? +C3D_BITMAPINFOHEADER ENDS + +C3D_BITMAPINFO STRUCT + bmiHeader C3D_BITMAPINFOHEADER <> + bmiColors dd ? +C3D_BITMAPINFO ENDS + +SpriteObject STRUCT + posX dd ? + posY dd ? + baseTexId dd ? + frameCount dd ? + curFrame dd ? + animTimer dd ? + animSpeed dd ? + interactId dd ? + promptPtr dd ? + distSq dd ? +SpriteObject ENDS + +SCREEN_W equ 640 +SCREEN_H equ 480 +HALF_W equ 320 +HALF_H equ 240 +SCREEN_SIZE equ (SCREEN_W * SCREEN_H) +WIN_SCALE equ 1 +WINDOW_W equ (SCREEN_W * WIN_SCALE) +WINDOW_H equ (SCREEN_H * WIN_SCALE) + +FP_1 equ 65536 +FP_HALF equ 32768 +CHROMA_KEY equ 00FF00FFh + +MODE_WALK equ 0 +MODE_SLOTS equ 1 +MODE_BLACKJACK equ 2 +MODE_ROULETTE equ 3 +MODE_SHOP equ 4 +MODE_ATM equ 5 +MODE_COIN equ 6 +MODE_DICE equ 7 +MODE_SKULLS equ 8 +MODE_SKILL equ 9 + +WS_OVERLAPPEDWINDOW equ 00CF0000h +SW_SHOW equ 5 +SW_HIDE equ 0 +PM_REMOVE equ 1 +WM_DESTROY equ 0002h +WM_CLOSE equ 0010h +WM_QUIT equ 0012h +CS_HREDRAW equ 2 +CS_VREDRAW equ 1 +DIB_RGB_COLORS equ 0 +SRCCOPY equ 00CC0020h +INVALID_FILE_HANDLE equ -1 + +include casino3d_data.inc +include font8x8.inc +include src_graphics\platform_data.inc +include src_graphics\casino_actions_data.inc +include src_graphics\audio_data.inc +include src_graphics\startup_data.inc +include src_graphics\card_tables_data.inc +include src_graphics\native_durak_data.inc +include src_graphics\scene_animation_data.inc +include src_graphics\arrival_data.inc +include src_graphics\city_arrival_data.inc +include src_graphics\merchant_data.inc +include src_graphics\hall_data.inc +include src_graphics\npc_mind_data.inc +include src_graphics\npc_life_data.inc +include src_graphics\native_wheel_data.inc +include src_graphics\billiards_data.inc +include src_graphics\buckshot_data.inc +include src_graphics\russian_view_data.inc +include src_graphics\unavailable_data.inc +include src_graphics\native_slots_data.inc +include src_graphics\native_clover_data.inc +include src_graphics\native_coin_data.inc + +.data +ALIGN 4 +h3DInst dd 0 +h3DWnd dd 0 +h3DDC dd 0 +hCasinoConsole dd 0 + +ALIGN 4 +hRaycastThread dd 0 +hRaycastStartEvent dd 0 +hRaycastDoneEvent dd 0 +bRaycastQuit dd 0 +raycastThreadId dd 0 + +bmi3D C3D_BITMAPINFO <> +msg3D C3D_MSG <> +wc3D C3D_WNDCLASSEX <> + +sz3DClassName db "Casino3DRetroClass",0 +sz3DWindowTitle db 192,241,241,229,236,225,235,229,240,32,202,224,231,232,237,238,32,45,32,50,46,53,68,0 +szTexturesRelPath db "assets\textures\casino3d-hd.bin",0 +szTexturesFullPath db 260 dup(0) + + +playerX dd (16 * FP_1 + FP_HALF) +playerY dd (16 * FP_1 + FP_HALF) +playerAngle dd 384 +playerDirX dd 0 +playerDirY dd -FP_1 +playerPlaneX dd (FP_1 * 66 / 100) +playerPlaneY dd 0 + +engineMode dd 0 +interactTargetId dd 0 +interactPromptPtr dd 0 +dancerLuckBuff dd 0 +flashTimer dd 0 +flashMessage db 128 dup(0) + +promptDancer db "[E] КАБАРЕ - ЧАЕВЫЕ $100",0 +promptBlackjack db "[E] БЛЭКДЖЕК (21)",0 +promptPoker db 91,69,93,32,207,206,202,197,208,32,40,210,197,213,192,209,209,202,200,201,32,213,206,203,196,197,204,41,0 +promptDurak db "[E] КАРТЫ: ПОДКИДНОЙ ДУРАК",0 +promptCasinoRoulette db "[E] ЕВРОПЕЙСКАЯ РУЛЕТКА",0 +promptClassicSlot db "[E] КЛАССИЧЕСКИЕ СЛОТЫ 777",0 +promptCloverSlot db "[E] СЛОТЫ CLOVERPIT (5x3)",0 +promptDice db 91,69,93,32,200,195,208,192,32,194,32,202,206,209,210,200,0 +promptSkulls db "[E] НАПЁРСТКИ (ЧЕРЕПА)",0 +promptCoin db "[E] МОНЕТКА (ОРЁЛ/РЕШКА)",0 +promptSkillCheck db "[E] ТРЕНИРОВКА РЕАКЦИИ",0 +promptBuckshot db 91,69,93,32,193,192,202,216,206,210,32,208,211,203,197,210,202,192,0 +promptRussianRoulette db "[E] РУССКАЯ РУЛЕТКА (VIP)",0 +promptOnlineRR db "[E] СЕТЕВАЯ РУЛЕТКА (NET)",0 +promptUmamusume db "[E] СКАЧКИ УМАМУСУМЭ",0 +promptHellTower db "[E] БАШНЯ АДА (10 ЭТАЖЕЙ)",0 +promptShop db "[E] БУТИК И ТАЛИСМАНЫ",0 +promptATM db "[E] БАНКОМАТ И БАЛАНС",0 +promptPlayerTerminal db "[E] ТЕРМИНАЛ: СТАТЫ И АЧИВКИ",0 +promptObserver db "[E] РЕЖИМ НАБЛЮДАТЕЛЯ (ИИ)",0 + +szTitleBlackjack db 202,192,199,200,202,32,51,68,32,45,32,193,203,221,202,196,198,197,202,32,40,50,49,41,0 +szTitlePoker db 202,192,199,200,202,32,51,68,32,45,32,207,206,202,197,208,32,40,210,197,213,192,209,209,202,200,201,32,213,206,203,196 + db 197,204,41,0 +szTitleDurak db 202,192,199,200,202,32,51,68,32,45,32,207,197,208,197,194,206,196,205,206,201,32,196,211,208,192,202,0 +szTitleCasinoRoulette db 202,192,199,200,202,32,51,68,32,45,32,197,194,208,206,207,197,201,209,202,192,223,32,208,211,203,197,210,202,192,0 +szTitleClassicSlot db 202,192,199,200,202,32,51,68,32,45,32,192,194,210,206,204,192,210,32,55,55,55,0 +szTitleCloverSlot db 202,192,199,200,202,32,51,68,32,45,32,202,203,197,194,197,208,205,192,223,32,223,204,192,32,40,53,120,51,41,0 +szTitleDice db 202,192,199,200,202,32,51,68,32,45,32,200,195,208,192,32,194,32,202,206,209,210,200,0 +szTitleSkulls db 202,192,199,200,202,32,51,68,32,45,32,205,192,207,168,208,209,210,202,200,0 +szTitleCoin db 202,192,199,200,202,32,51,68,32,45,32,204,206,205,197,210,202,192,32,40,206,208,168,203,47,208,197,216,202,192,41,0 +szTitleSkillCheck db 202,192,199,200,202,32,51,68,32,45,32,207,208,206,194,197,208,202,192,32,205,192,194,219,202,192,0 +szTitleBuckshot db 202,192,199,200,202,32,51,68,32,45,32,193,192,202,216,206,210,32,208,211,203,197,210,202,192,0 +szTitleRussianRoulette db 202,192,199,200,202,32,51,68,32,45,32,208,211,209,209,202,192,223,32,208,211,203,197,210,202,192,0 +szTitleOnlineRR db 202,192,199,200,202,32,51,68,32,45,32,209,197,210,197,194,192,223,32,208,211,209,209,202,192,223,32,208,211,203,197,210 + db 202,192,0 +szTitleUmamusume db 202,192,199,200,202,32,51,68,32,45,32,195,206,205,202,200,32,211,204,192,204,211,209,211,204,197,0 +szTitleHellTower db 202,192,199,200,202,32,51,68,32,45,32,192,196,209,202,192,223,32,193,192,216,205,223,0 +szTitleShop db 202,192,199,200,202,32,51,68,32,45,32,202,192,208,210,219,32,200,32,210,192,203,200,209,204,192,205,219,0 +szTitleATM db 202,192,199,200,202,32,51,68,32,45,32,193,192,205,202,206,204,192,210,0 +szTitleTerminal db 202,192,199,200,202,32,51,68,32,45,32,203,206,202,192,203,220,205,219,197,32,207,208,206,212,200,203,200,0 +szTitleObserver db 202,192,199,200,202,32,51,68,32,45,32,205,192,193,203,222,196,192,210,197,203,220,32,40,200,200,41,0 +textCabinetFooter db "[ ВЫХОД: ВВЕДИТЕ 0 / ВЫБЕРИТЕ 'N' ДЛЯ ВОЗВРАТА В ЗАЛ ]",0 + +msgDancerTipped db "Вы бросили $100 танцовщице! УДАЧА АКТИВИРОВАНА!",0 +msgNeedMoney db "Недостаточно денег в кошельке!",0 +statusHUDFormat db "БАНКРОЛЛ: $",0 +targetHUDFormat db " ЦЕЛЬ: $",0 +luckHUDFormat db " УДАЧА: +",0 +controlsHUD db "WASD/Стрелки: Ходьба | E: Действие | ESC: Меню",0 + +NUM_SPRITES equ 22 + +INTERACT_NONE equ 0 +INTERACT_BLACKJACK equ 1 +INTERACT_POKER equ 2 +INTERACT_SLOTS_777 equ 3 +INTERACT_ROULETTE equ 4 +INTERACT_SKULLS equ 5 +INTERACT_SHOP equ 6 +INTERACT_ATM equ 7 +INTERACT_DANCER equ 8 +INTERACT_HELL_TOWER equ 9 +INTERACT_DURAK equ 10 +INTERACT_BUCKSHOT equ 11 +INTERACT_COIN equ 12 +INTERACT_DICE equ 13 +INTERACT_SLOTS_CLOVER equ 14 +INTERACT_UMAMUSUME equ 15 +INTERACT_OBSERVER equ 16 +INTERACT_TERMINAL equ 17 +INTERACT_ONLINE_RR equ 18 +INTERACT_RUSSIAN_ROULETTE equ 19 +INTERACT_SKILL_CHECK equ 20 +ALIGN 4 +casinoSprites SpriteObject NUM_SPRITES dup(<>) +sortedSprites dd NUM_SPRITES dup(0) + +rowDistTable dd 120 dup(0) +rngSeed3D dd 12345678h + +slotBet dd 50 +slotReel1 dd 0 +slotReel2 dd 1 +slotReel3 dd 2 +slotSpinState dd 0 +slotSpinTimer dd 0 +slotWinAmount dd 0 +slotWinMsg db 64 dup(0) + +bjState dd 0 +bjBet dd 100 +bjPlayerCards dd 10 dup(0) +bjPlayerCardCount dd 0 +bjPlayerScore dd 0 +bjDealerCards dd 10 dup(0) +bjDealerCardCount dd 0 +bjDealerScore dd 0 +bjDealerHideHole dd 1 +bjOutcomeMsg db 64 dup(0) + +roulState dd 0 +roulBetType dd 1 +roulBetAmount dd 100 +roulWheelAngle dd 0 +roulBallAngle dd 0 +roulSpinTimer dd 0 +roulWinningNum dd 0 +roulPayout dd 0 +roulOutcomeMsg db 64 dup(0) + +coinRxAnimTable db 26, 22, 16, 6, 16, 22, 26, 22, 16, 6 + +; --- Native 2.5D Coin Flip --- +coin3d_bet dd 50 +coin3d_choice dd 1 ; 1 = Орёл, 2 = Решка +coin3d_state dd 0 ; 0 = Idle, 1 = Flipping, 2 = Result +coin3d_timer dd 0 +coin3d_result dd 1 ; 1 = Орёл, 2 = Решка +coin3d_streak dd 0 +coin3d_win dd 0 + +textCoinTitle db "* * * З О Л О Т А Я М О Н Е Т А * * *",0 +textCoinHeads db "ОРЁЛ",0 +textCoinTails db "РЕШКА",0 +textCoinSide1 db "[1] ОРЁЛ",0 +textCoinSide2 db "[2] РЕШКА",0 +textCoinFlipping db "МОНЕТА В ПОЛЁТЕ...",0 +textCoinWin db "ПОБЕДА: +$",0 +textCoinLose db "НЕ УГАДАЛИ!",0 +textCoinStreakFmt db "СЕРИЯ ПОБЕД: x",0 +textCoinSelected db "ВЫБРАНО",0 +textCoinKey1 db "[1] ОРЁЛ",0 +textCoinKey2 db "[2] РЕШКА",0 +textCoinKeySpace db "[SPACE]",0 + +; --- Native 2.5D Dice Game --- +dice3d_bet dd 50 +dice3d_choice dd 1 ; 1 = Чёт, 2 = Нечет +dice3d_state dd 0 ; 0 = Idle, 1 = Rolling, 2 = Result +dice3d_timer dd 0 +dice3d_val1 dd 4 +dice3d_val2 dd 6 +dice3d_sum dd 10 +dice3d_win dd 0 + +textDiceTitle db 200,195,208,192,32,194,32,202,206,209,210,200,0 +textDiceEven db "[1] ЧЁТ",0 +textDiceOdd db "[2] НЕЧЕТ",0 +textDiceEvenNums db "2 4 6 ...",0 +textDiceOddNums db "3 5 7 ...",0 +textDiceSumHdr db "СУММА: ",0 +textDicePlus db " + ",0 +textDiceEqual db " = ",0 +textDiceEvenResult db " (ЧЁТ)",0 +textDiceOddResult db " (НЕЧЕТ)",0 +textDiceRolling db "КОСТИ ЛЕТЯТ ПО СУКНУ...",0 +textDiceWin db "ВЫИГРЫШ: +$",0 +textDiceWinMult db "! (x2)",0 +textDiceLose db "ПРОИГРЫШ!",0 +textDiceKey1 db "[1] ЧЁТ",0 +textDiceKey2 db "[2] НЕЧЕТ",0 +textDiceKeySpace db "[SPACE]",0 + +; --- Native 2.5D Skulls Game --- +skulls3d_bet dd 50 +skulls3d_state dd 0 ; 0 = Idle, 1 = Show ball, 2 = Shuffle, 3 = Pick, 4 = Reveal +skulls3d_timer dd 0 +skulls3d_ballPos dd 1 ; 0, 1, 2 +skulls3d_choice dd 1 ; 0, 1, 2 +skulls3d_win dd 0 +skulls3d_swapPair0 dd 0 +skulls3d_swapPair1 dd 1 +skulls3d_swapPair2 dd 2 +skulls3d_cup0 dd 0 +skulls3d_cup1 dd 1 +skulls3d_cup2 dd 2 + +textSkullsTitle db "* * * Н А П Ё Р С Т К И * * *",0 +textSkullsPhase0 db "ДЕЛАЙ СТАВКУ И ЖМИ [ПРОБЕЛ]",0 +textSkullsPhase1 db "СМОТРИ, ГДЕ ЗОЛОТОЙ ШАР...",0 +textSkullsPhase2 db "КРУЧУ, ВЕРЧУ, ЗАПУТАТЬ ХОЧУ...",0 +textSkullsPhase3 db "ГДЕ ШАР? ВЫБИРАЙ: [1], [2] ИЛИ [3]!",0 +textSkullsWin db "ВЫИГРЫШ: +$",0 +textSkullsWinMult db "! (x3) ВЫ УГАДАЛИ!",0 +textSkullsLose db "МИМО! ШАР БЫЛ В ДРУГОМ МЕСТЕ!",0 +textSkullsAgain db "[ПРОБЕЛ] - СЫГРАТЬ ЕЩЁ РАЗ",0 +textSkullsKey1 db "[1]",0 +textSkullsKey2 db "[2]",0 +textSkullsKey3 db "[3]",0 +textSkullsKeySpace db "[SPACE] СТАРТ",0 + +; --- Native 2.5D Skill Check (Dead by Daylight Survivor Check) --- +skill3d_bet dd 50 +skill3d_state dd 0 ; 0=Ready, 1=Active, 2=Hit Result, 3=Miss Result, 4=Escaped, 5=Defeated +skill3d_timer dd 0 +skill3d_needle dd 55 ; Needle X (52..268) +skill3d_speed dd 4 +skill3d_dir dd 1 ; 1=Right, -1=Left +skill3d_zone_start dd 140 +skill3d_zone_width dd 48 +skill3d_great_start dd 176 +skill3d_great_width dd 12 +skill3d_hits dd 0 +skill3d_misses dd 0 +skill3d_last_result dd 0 +skill3d_win_amount dd 0 + +textSkillTitle db 61,61,61,32,207,208,206,194,197,208,202,192,32,205,192,194,219,202,192,32,61,61,61,0 +textSkillHitsHdr db "ХИТ: ",0 +textSkillMissHdr db "ПРОМАХ: ",0 +textSkillReadyMsg db "НАЖМИТЕ [ПРОБЕЛ] ДЛЯ СТАРТА",0 +textSkillPrompt db "НАЖМИТЕ [ПРОБЕЛ] В ЗОНЕ!",0 +textSkillHitMsg db "ХИТ! ТОЧНОЕ ПОПАДАНИЕ!",0 +textSkillGreatMsg db 206,210,203,200,215,205,206,33,32,43,193,206,205,211,209,33,0 +textSkillMissMsg db "ПРОМАХ! ТРЕВОГА!",0 +textSkillEscape db "ПОБЕГ УСПЕШЕН! ВЫИГРЫШ: +$",0 +textSkillLost db "ВЫ ПОЙМАНЫ! ПРОИГРЫШ СТАВКИ!",0 +textSkillKeySpace db "[SPACE] РЕАКЦИЯ",0 +textSkillKeyBet db "[ВВЕРХ/ВНИЗ]",0 + +; --- Shared UI Strings --- +textKeyEsc db "[ESC]",0 +textBankPrompt db "БАНК: $",0 +textBetPrompt db "СТАВКА: $",0 +textBetHint db " [W/S]",0 + +shopMsg db 128 dup(0) +atmMsg db 128 dup(0) + +strWin db "ПОБЕДА! +$",0 +strLose db "ПРОИГРЫШ",0 +strJackpot db "ДЖЕКПОТ! +$",0 +strPush db 205,200,215,220,223,0 +strDealerBust db "ДИЛЕР ПЕРЕБРАЛ! ПОБЕДА! +$",0 +strPlayerBust db "ПЕРЕБОР (>21)! ПРОИГРЫШ",0 + +sym7 db " 777 ",0 +symBar db " BAR ",0 +symBell db 32,199,194,206,205,0 +symCherry db 194,200,216,205,223,0 +symClover db 202,203,197,194,197,208,0 +symGem db 192,203,204,192,199,0 +symCrown db 202,206,208,206,205,192,0 + +cardRankStr db "A ",0,"2 ",0,"3 ",0,"4 ",0,"5 ",0,"6 ",0,"7 ",0,"8 ",0,"9 ",0,"10",0,"J ",0,"Q ",0,"K ",0 + +.data? +ALIGN 4 +screenBuffer dd SCREEN_SIZE dup(?) +ALIGN 4 +zBuffer dd SCREEN_W dup(?) +ALIGN 4 +texturesBuffer dd (104 * 128 * 128) dup(?) + +hudNumBuffer db 32 dup(?) + +.code + +; --- 3D Window Procedure --- +Casino3DWndProc PROC hwnd:DWORD, uMsg:DWORD, wParam:DWORD, lParam:DWORD + invoke WindowEvents3D, hwnd, uMsg, wParam, lParam + ret +Casino3DWndProc ENDP + +; --- Random Generator --- +RandomRange3D PROC maxVal:DWORD + mov eax, rngSeed3D + imul eax, 1103515245 + add eax, 12345 + mov rngSeed3D, eax + shr eax, 16 + and eax, 7FFFh + xor edx, edx + div maxVal + mov eax, edx + ret +RandomRange3D ENDP + +; --- Copy String --- +CopyString3D PROC src:DWORD, dst:DWORD + push esi + push edi + mov esi, src + mov edi, dst +@@: + mov al, [esi] + mov [edi], al + test al, al + jz @F + inc esi + inc edi + jmp @B +@@: + pop edi + pop esi + ret +CopyString3D ENDP + +; --- Format Number to Decimal String --- +FormatNumber PROC num:DWORD, buf:DWORD + push ebx + push esi + push edi + mov eax, num + mov edi, buf + test eax, eax + jns fn_pos + mov BYTE PTR [edi], '-' + inc edi + neg eax +fn_pos: + mov ebx, 10 + push 0 +fn_div: + xor edx, edx + div ebx + add dl, '0' + push edx + test eax, eax + jnz fn_div +fn_pop: + pop eax + test al, al + jz fn_done + mov [edi], al + inc edi + jmp fn_pop +fn_done: + mov BYTE PTR [edi], 0 + pop edi + pop esi + pop ebx + ret +FormatNumber ENDP + +; --- Fast 2D Drawing Primitives --- +DrawBox PROTO :DWORD,:DWORD,:DWORD,:DWORD,:DWORD + +DrawPixel PROC x:DWORD, y:DWORD, color:DWORD + invoke DrawBox, x, y, 1, 1, color + ret +DrawPixel ENDP + +DrawBox PROC x:DWORD, y:DWORD, w:DWORD, h:DWORD, color:DWORD + shl x, 1 + shl y, 1 + shl w, 1 + shl h, 1 + push ebx + push esi + push edi + mov edi, y +box_row_loop: + mov eax, y + add eax, h + cmp edi, eax + jge box_done + cmp edi, 0 + jl next_box_row + cmp edi, SCREEN_H + jge box_done + + mov esi, x +box_col_loop: + mov eax, x + add eax, w + cmp esi, eax + jge next_box_row + cmp esi, 0 + jl next_box_col + cmp esi, SCREEN_W + jge next_box_row + + mov ecx, edi + imul ecx, SCREEN_W + add ecx, esi + mov edx, color + mov [screenBuffer + ecx*4], edx + +next_box_col: + inc esi + jmp box_col_loop + +next_box_row: + inc edi + jmp box_row_loop + +box_done: + pop edi + pop esi + pop ebx + ret +DrawBox ENDP + +DrawBoxBorder PROC uses ebx x:DWORD, y:DWORD, w:DWORD, h:DWORD, fillColor:DWORD, borderColor:DWORD, bWidth:DWORD + invoke DrawBox, x, y, w, h, borderColor + mov eax, x + add eax, bWidth + mov edx, y + add edx, bWidth + mov ecx, w + sub ecx, bWidth + sub ecx, bWidth + mov ebx, h + sub ebx, bWidth + sub ebx, bWidth + invoke DrawBox, eax, edx, ecx, ebx, fillColor + ret +DrawBoxBorder ENDP + +DrawCircle PROC cxVal:DWORD, cyVal:DWORD, radius:DWORD, color:DWORD + push ebx + push esi + push edi + mov eax, radius + neg eax + mov edi, eax +circ_y: + cmp edi, radius + jg circ_done + mov eax, radius + neg eax + mov esi, eax +circ_x: + cmp esi, radius + jg next_circ_y + + mov eax, esi + imul eax, eax + mov ebx, edi + imul ebx, ebx + add eax, ebx + mov edx, radius + imul edx, edx + cmp eax, edx + jg next_circ_x + + mov eax, cxVal + add eax, esi + mov ecx, cyVal + add ecx, edi + invoke DrawPixel, eax, ecx, color + +next_circ_x: + inc esi + jmp circ_x +next_circ_y: + inc edi + jmp circ_y +circ_done: + pop edi + pop esi + pop ebx + ret +DrawCircle ENDP + +DrawChar8x8 PROC uses ebx esi edi x:DWORD, y:DWORD, chVal:DWORD, color:DWORD + local column:DWORD + mov eax, chVal + and eax, 255 + lea esi, [font8x8 + eax*8] + xor edi, edi +glyph_row: + movzx ebx, BYTE PTR [esi+edi] + mov column, 0 +glyph_col: + test ebx, 80h + jz glyph_next + mov eax, x + add eax, column + mov edx, y + add edx, edi + invoke DrawPixel, eax, edx, color +glyph_next: + shl ebx, 1 + inc column + cmp column, 8 + jl glyph_col + inc edi + cmp edi, 8 + jl glyph_row + ret +DrawChar8x8 ENDP + +DrawString8x8 PROC x:DWORD, y:DWORD, strPtr:DWORD, color:DWORD + push ebx + push esi + mov esi, strPtr + mov ebx, x +str_loop: + movzx eax, BYTE PTR [esi] + test al, al + jz str_done + invoke DrawChar8x8, ebx, y, eax, color + add ebx, 8 + inc esi + jmp str_loop +str_done: + pop esi + pop ebx + ret +DrawString8x8 ENDP + +; --- True 3D Perspective Floor & Ceiling Rendering --- + +; --- DDA Raycasting Walls --- +RenderWallsRange PROC colStart:DWORD, colLimit:DWORD + local col:DWORD + local originalStart:DWORD + local camX:DWORD + local rayDirX:DWORD + local rayDirY:DWORD + local mapX:DWORD + local mapY:DWORD + local deltaDistX:DWORD + local deltaDistY:DWORD + local stepX:DWORD + local stepY:DWORD + local sideDistX:DWORD + local sideDistY:DWORD + local side:DWORD + local perpWallDist:DWORD + local lineH:DWORD + local drawStart:DWORD + local drawEnd:DWORD + local wallHit:DWORD + local texX:DWORD + local texXHD:DWORD + local pixelMaterial:DWORD + local texId:DWORD + local shade:DWORD + + push ebx + push esi + push edi + + mov eax, playerAngle + and eax, 511 + mov ebx, [tableCos + eax*4] + mov playerDirX, ebx + mov ebx, [tableSin + eax*4] + mov playerDirY, ebx + + mov eax, ebx + imul eax, -66 + cdq + mov ecx, 100 + idiv ecx + mov playerPlaneX, eax + + mov eax, playerDirX + imul eax, 66 + cdq + idiv ecx + mov playerPlaneY, eax + + mov eax, colStart + mov col, eax +col_loop: + mov eax, colLimit + cmp col, eax + jge walls_done + + mov eax, col + shl eax, 1 + sub eax, SCREEN_W + imul eax, FP_1 + cdq + mov ecx, SCREEN_W + idiv ecx + mov camX, eax + + mov eax, playerPlaneX + imul camX + shrd eax, edx, 16 + add eax, playerDirX + mov rayDirX, eax + + mov eax, playerPlaneY + imul camX + shrd eax, edx, 16 + add eax, playerDirY + mov rayDirY, eax + + mov eax, playerX + sar eax, 16 + mov mapX, eax + mov eax, playerY + sar eax, 16 + mov mapY, eax + + mov eax, rayDirX + test eax, eax + jnz calc_delta_x + mov deltaDistX, 7FFFFFFFh + jmp calc_delta_y +calc_delta_x: + test eax, eax + jns @F + neg eax +@@: + mov ebx, eax + cmp ebx, 4 + jbe delta_x_clamp + xor eax, eax + mov edx, 1 + div ebx + mov deltaDistX, eax + jmp calc_delta_y +delta_x_clamp: + mov deltaDistX, 7FFFFFFFh + +calc_delta_y: + mov eax, rayDirY + test eax, eax + jnz calc_delta_y_ok + mov deltaDistY, 7FFFFFFFh + jmp check_step +calc_delta_y_ok: + test eax, eax + jns @F + neg eax +@@: + mov ebx, eax + cmp ebx, 4 + jbe delta_y_clamp + xor eax, eax + mov edx, 1 + div ebx + mov deltaDistY, eax + jmp check_step +delta_y_clamp: + mov deltaDistY, 7FFFFFFFh + +check_step: + cmp rayDirX, 0 + jge step_x_pos + mov stepX, -1 + mov eax, playerX + mov edx, mapX + shl edx, 16 + sub eax, edx + imul deltaDistX + shrd eax, edx, 16 + mov sideDistX, eax + jmp check_step_y +step_x_pos: + mov stepX, 1 + mov eax, mapX + inc eax + shl eax, 16 + sub eax, playerX + imul deltaDistX + shrd eax, edx, 16 + mov sideDistX, eax + +check_step_y: + cmp rayDirY, 0 + jge step_y_pos + mov stepY, -1 + mov eax, playerY + mov edx, mapY + shl edx, 16 + sub eax, edx + imul deltaDistY + shrd eax, edx, 16 + mov sideDistY, eax + jmp dda_start +step_y_pos: + mov stepY, 1 + mov eax, mapY + inc eax + shl eax, 16 + sub eax, playerY + imul deltaDistY + shrd eax, edx, 16 + mov sideDistY, eax + +dda_start: + xor ecx, ecx +dda_step_loop: + inc ecx + cmp ecx, 64 + jge wall_map_boundary + + mov eax, sideDistX + cmp eax, sideDistY + jge step_in_y + + mov eax, deltaDistX + add sideDistX, eax + mov eax, stepX + add mapX, eax + mov side, 0 + jmp check_tile + +step_in_y: + mov eax, deltaDistY + add sideDistY, eax + mov eax, stepY + add mapY, eax + mov side, 1 + +check_tile: + cmp mapX, 0 + jl wall_map_boundary + cmp mapX, MAP_WIDTH + jge wall_map_boundary + cmp mapY, 0 + jl wall_map_boundary + cmp mapY, MAP_HEIGHT + jge wall_map_boundary + + mov eax, mapY + shl eax, 5 + add eax, mapX + mov edx, worldMap3D + movzx eax, BYTE PTR [edx + eax] + test eax, eax + jnz hit_wall + jmp dda_step_loop + +wall_map_boundary: + cmp outdoorRender3D, 0 + je hit_wall + mov eax, col + mov zBuffer[eax*4], 7FFFFFFFh + jmp next_col + +hit_wall: + cmp side, 0 + jne perp_y + mov eax, sideDistX + sub eax, deltaDistX + mov perpWallDist, eax + jmp perp_done +perp_y: + mov eax, sideDistY + sub eax, deltaDistY + mov perpWallDist, eax + +perp_done: + cmp perpWallDist, 2048 + jge @F + mov perpWallDist, 2048 +@@: + mov eax, col + mov edx, perpWallDist + mov [zBuffer + eax*4], edx + + ; Unit projection is shared by indoor room height and outdoor storeys. + mov eax, SCREEN_H + imul eax, FP_1 + cdq + idiv perpWallDist + mov lineH, eax + + mov eax, lineH + imul viewEye3D + shrd eax, edx, 16 + add eax, viewHorizon3D + mov drawEnd, eax + mov ebx, lineH + mov eax, viewCeiling3D + cmp outdoorRender3D, 0 + je @F + mov eax, CITY_STOREY_HEIGHT +@@: + imul ebx + shrd eax, edx, 16 + mov ebx, eax + mov lineH, ebx + mov eax, drawEnd + sub eax, ebx + mov drawStart, eax + cmp outdoorRender3D, 0 + je wall_store_original_start + ; Floor height is independent of storey height. + mov eax, drawEnd + sub eax, lineH + mov drawStart, eax + mov eax, mapY + shl eax, 5 + add eax, mapX + mov edx, worldMap3D + movzx eax, BYTE PTR [edx+eax] +wall_exterior_tall: + ; Roof projection and texture sampling use the same storey count. + mov eax, lineH + imul eax, CITY_BUILDING_STOREYS-1 + sub drawStart, eax + mov eax, lineH + imul eax, CITY_BUILDING_STOREYS + mov lineH, eax +wall_store_original_start: + mov eax, drawStart + mov originalStart, eax + + cmp side, 0 + jne hit_side_y + mov eax, perpWallDist + imul rayDirY + shrd eax, edx, 16 + add eax, playerY + mov wallHit, eax + jmp calc_tex_x +hit_side_y: + mov eax, perpWallDist + imul rayDirX + shrd eax, edx, 16 + add eax, playerX + mov wallHit, eax + +calc_tex_x: + ; MASK WITH 0FFFFh to prevent texture scrambling! + mov eax, wallHit + and eax, 0FFFFh + mov texXHD, eax + shr eax, 9 + and eax, 127 + mov texX, eax + + cmp side, 0 + jne @F + cmp rayDirX, 0 + jle @F + mov eax, 127 + sub eax, texX + mov texX, eax + xor texXHD, 0FFFFh +@@: + cmp side, 1 + jne select_tex + cmp rayDirY, 0 + jge select_tex + mov eax, 127 + sub eax, texX + mov texX, eax + xor texXHD, 0FFFFh + +select_tex: + mov eax, mapY + shl eax, 5 + add eax, mapX + mov edx, worldMap3D + movzx eax, BYTE PTR [edx + eax] + mov texId, eax + cmp texId, 0 + jne @F + mov texId, 1 +@@: + + mov eax, perpWallDist + shr eax, 13 + mov edx, 256 + sub edx, eax + cmp edx, 75 + jge @F + mov edx, 75 +@@: + cmp side, 1 + jne @F + imul edx, 3 + shr edx, 2 +@@: + mov shade, edx + + cmp drawStart, 0 + jge @F + mov drawStart, 0 +@@: + cmp drawEnd, SCREEN_H + jl @F + mov drawEnd, SCREEN_H - 1 +@@: + + mov eax, lineH + cmp eax, 1 + jge @F + mov eax, 1 + mov lineH, eax +@@: + + mov eax, 128 * FP_1 + cdq + idiv lineH + mov esi, eax ; stepY + + mov eax, drawStart + sub eax, originalStart + imul eax, esi + mov edi, eax ; texPos + + mov ecx, drawStart +draw_stripe_loop: + cmp ecx, drawEnd + jg next_col + + mov eax, edi + shr eax, 16 + and eax, 127 + mov edx, texId + cmp outdoorRender3D, 0 + je wall_sample_material + imul eax, CITY_BUILDING_STOREYS + cmp eax, 128*(CITY_BUILDING_STOREYS-1) + jae wall_lower_storey + push eax + shr eax, 7 + add eax, mapX + add eax, mapY + xor edx, edx + mov ebx, 3 + div ebx + add edx, 65 + pop eax + and eax, 127 + jmp wall_sample_material +wall_lower_storey: + sub eax, 128*(CITY_BUILDING_STOREYS-1) +wall_sample_material: + mov pixelMaterial, edx + cmp outdoorRender3D, 0 + je wall_sample_indoor_hd + cmp hallCityDetail3D.pixels, 0 + je wall_sample_standard + cmp edx, 57 + jb wall_sample_standard + cmp edx, 72 + ja wall_sample_standard + cmp perpWallDist, 6*FP_1 + ja wall_sample_standard + ; Preserve subtexel detail near facades; retain the 128px mip at distance. + push edx + mov eax, edi + shr eax, 15 + imul eax, CITY_BUILDING_STOREYS + and eax, 255 + shl eax, 8 + mov ebx, texXHD + shr ebx, 8 + add eax, ebx + pop edx + sub edx, 57 + shl edx, 16 + add eax, edx + mov ebx, hallCityDetail3D.pixels + mov eax, [ebx+eax*4] + jmp wall_shade_pixel +wall_sample_indoor_hd: + cmp edx, 80 + jb wall_sample_standard + cmp edx, 103 + ja wall_sample_standard + mov ebx, hallRoomHD3D.pixels + cmp edx, 92 + jb wall_sample_room_hd + mov ebx, hallArchitectureHD3D.pixels + sub edx, 12 +wall_sample_room_hd: + test ebx, ebx + jz wall_sample_standard_restore + sub edx, 80 + shl edx, 18 + add ebx, edx + mov eax, edi + shr eax, 15 + and eax, 255 + shl eax, 8 + mov edx, texXHD + shr edx, 8 + add eax, edx + mov eax, [ebx+eax*4] + jmp wall_shade_pixel +wall_sample_standard_restore: + mov edx, texId + mov eax, edi + shr eax, 16 + and eax, 127 +wall_sample_standard: + shl eax, 7 + add eax, texX + + shl edx, 14 + add eax, edx + mov eax, [texturesBuffer + eax*4] + + ; Shade wall pixel +wall_shade_pixel: + mov ebx, shade + cmp outdoorRender3D, 0 + je wall_ambient_shade + push eax + push ecx + invoke IsCityEmissive3D, eax, pixelMaterial + pop ecx + test eax, eax + pop eax + jz wall_ambient_shade + mov ebx, 256 +wall_ambient_shade: + cmp hallLevel3D, 0 + je @F + imul ebx, 7 + shr ebx, 3 +@@: + movzx edx, al + imul edx, ebx + shr edx, 8 + push edx + + movzx edx, ah + imul edx, ebx + shr edx, 8 + shl edx, 8 + + shr eax, 16 + movzx eax, al + imul eax, ebx + shr eax, 8 + shl eax, 16 + or eax, edx + pop edx + or eax, edx + + mov edx, ecx + imul edx, SCREEN_W + add edx, col + mov [screenBuffer + edx*4], eax + + add edi, esi + inc ecx + jmp draw_stripe_loop + +next_col: + inc col + jmp col_loop + +walls_done: + pop edi + pop esi + pop ebx + ret +RenderWallsRange ENDP + +; --- Raycasting Background Worker Thread --- +RaycastWorkerProc PROC uses ebx esi edi lpParam:DWORD +worker_loop: + invoke WaitForSingleObject, hRaycastStartEvent, 0FFFFFFFFh + cmp bRaycastQuit, 1 + je worker_exit + invoke RenderWallsRange, 320, 640 + invoke SetEvent, hRaycastDoneEvent + jmp worker_loop +worker_exit: + xor eax, eax + ret +RaycastWorkerProc ENDP + +; --- Multi-Threaded DDA Raycasting Walls Dispatcher --- +RenderWalls PROC + push ebx + push esi + push edi + + mov eax, playerAngle + and eax, 511 + mov ebx, [tableCos + eax*4] + mov playerDirX, ebx + mov ebx, [tableSin + eax*4] + mov playerDirY, ebx + + mov eax, ebx + imul eax, -66 + cdq + mov ecx, 100 + idiv ecx + mov playerPlaneX, eax + + mov eax, playerDirX + imul eax, 66 + cdq + idiv ecx + mov playerPlaneY, eax + + cmp hRaycastStartEvent, 0 + je single_thread_fallback + + ; Signal background worker to render columns [320..640) + invoke SetEvent, hRaycastStartEvent + + ; Main thread processes columns [0..320) in parallel + invoke RenderWallsRange, 0, 320 + + ; Synchronize with worker completion + invoke WaitForSingleObject, hRaycastDoneEvent, 0FFFFFFFFh + jmp walls_finished + +single_thread_fallback: + invoke RenderWallsRange, 0, SCREEN_W + +walls_finished: + pop edi + pop esi + pop ebx + ret +RenderWalls ENDP + +; --- Render 3D Billboard Sprites --- + +; --- HUD & Minimap Radar --- +RenderHUD PROC uses ebx esi edi + invoke DrawBox, 0, 0, 320, 16, 0014191Dh + invoke DrawString8x8, 8, 4, OFFSET textBank3D, 00D8BC6Ah + invoke FormatNumber, bankroll, OFFSET hudNumBuffer + invoke DrawString8x8, 64, 4, OFFSET hudNumBuffer, 00FFFFFFh + invoke DrawString8x8, 176, 4, OFFSET textWindowKeys3D, 00A8B6BBh + invoke DrawBox, 0, 226, 320, 14, 0014191Dh + invoke DrawString8x8, 12, 230, OFFSET textWalkKeys3D, 00A8B6BBh + invoke DrawBox, 159, 118, 2, 5, 00E7DFC8h + invoke DrawBox, 157, 120, 6, 1, 00E7DFC8h + cmp interactPromptPtr, 0 + je @F + invoke DrawBoxBorder, 4, 199, 312, 18, 0014191Dh, 00D8BC6Ah, 1 + invoke DrawString8x8, 10, 204, interactPromptPtr, 00F5E2B0h +@@: + cmp flashTimer, 0 + je hud_finished + dec flashTimer + invoke DrawBox, 4, 22, 312, 16, 0014191Dh + invoke DrawString8x8, 10, 26, OFFSET flashMessage, 00FFFFFFh +hud_finished: + ret +RenderHUD ENDP + +RenderMinimap PROC uses ebx esi edi + local radarX:DWORD + local radarY:DWORD + local radarSize:DWORD + + mov radarX, 320 - 48 + mov radarY, 20 + mov radarSize, 44 + + invoke DrawBoxBorder, radarX, radarY, radarSize, radarSize, 00101510h, 00FFD700h, 1 + + ; Draw Sprites on radar + cmp hallLevel3D, 0 + jne draw_player_radar + xor esi, esi +radar_spr_loop: + cmp esi, NUM_SPRITES + jge draw_player_radar + mov eax, esi + imul eax, SIZEOF SpriteObject + mov eax, [casinoSprites + eax].posX + sar eax, 16 + imul eax, radarSize + shr eax, 5 + add eax, radarX + mov ebx, eax + + mov eax, esi + imul eax, SIZEOF SpriteObject + mov eax, [casinoSprites + eax].posY + sar eax, 16 + imul eax, radarSize + shr eax, 5 + add eax, radarY + + invoke DrawPixel, ebx, eax, 00FFAA00h + inc esi + jmp radar_spr_loop + +draw_player_radar: + mov eax, playerX + sar eax, 16 + imul eax, radarSize + shr eax, 5 + add eax, radarX + mov ebx, eax + + mov eax, playerY + sar eax, 16 + imul eax, radarSize + shr eax, 5 + add eax, radarY + + invoke DrawCircle, ebx, eax, 2, 00FF2020h + ret +RenderMinimap ENDP + +; ============================================================================== +; IN-ENGINE 2.5D MINI-GAME: SLOTS 777 +; ============================================================================== +HandleSlotsInput PROC + cmp slotSpinState, 1 + je slots_input_done + + invoke Pressed3D, 20h ; SPACE -> Spin + test ah, 80h + jz check_bet_adjust + mov eax, bankroll + cmp eax, slotBet + jl @F + sub eax, slotBet + mov bankroll, eax + mov slotSpinState, 1 + mov slotSpinTimer, 0 + mov slotWinAmount, 0 + invoke PlayCasinoSound3D, OFFSET soundSlotSpin, 0, 1 + jmp slots_input_done +@@: + invoke CopyString3D, OFFSET msgNeedMoney, OFFSET flashMessage + mov flashTimer, 60 + +check_bet_adjust: + invoke Pressed3D, 26h ; UP / W + test ah, 80h + jnz inc_bet + invoke Pressed3D, 57h + test ah, 80h + jz check_bet_down +inc_bet: + cmp slotBet, 500 + jge slots_input_done + cmp slotBet, 100 + jge @F + cmp slotBet, 50 + jge set_100 + mov slotBet, 50 + jmp slots_input_done +set_100: + mov slotBet, 100 + jmp slots_input_done +@@: + mov slotBet, 500 + jmp slots_input_done + +check_bet_down: + invoke Pressed3D, 28h ; DOWN / S + test ah, 80h + jnz dec_bet + invoke Pressed3D, 53h + test ah, 80h + jz slots_input_done +dec_bet: + cmp slotBet, 50 + jle set_10 + cmp slotBet, 100 + jle set_50 + mov slotBet, 100 + jmp slots_input_done +set_50: + mov slotBet, 50 + jmp slots_input_done +set_10: + mov slotBet, 10 + +slots_input_done: + ret +HandleSlotsInput ENDP + +RenderSlotsGame PROC uses ebx esi edi + ; Cabinet Background (Dark Cherry Wood & Gold) + invoke DrawBox, 0, 0, SCREEN_W, SCREEN_H, 00150A10h + invoke DrawBoxBorder, 10, 10, 300, 220, 00251015h, 00FFD700h, 3 + + ; Illuminated Top Marquee + invoke DrawBoxBorder, 25, 20, 270, 32, 000A0505h, 00FFFF00h, 2 + invoke DrawString8x8, 55, 32, OFFSET textSlots3D, 00FFD700h + + ; Spinning Animation Logic + cmp slotSpinState, 1 + jne draw_reels + inc slotSpinTimer + + cmp slotSpinTimer, 22 + jge @F + invoke RandomRange3D, 7 + mov slotReel1, eax +@@: + cmp slotSpinTimer, 36 + jge @F + invoke RandomRange3D, 7 + mov slotReel2, eax +@@: + cmp slotSpinTimer, 50 + jge @F + invoke RandomRange3D, 7 + mov slotReel3, eax +@@: + cmp slotSpinTimer, 50 + jl draw_reels + + ; Spin finished! Check outcome! + mov slotSpinState, 0 + mov eax, slotReel1 + cmp eax, slotReel2 + jne check_pairs + cmp eax, slotReel3 + jne check_pairs + + ; 3 Matching! + cmp eax, 0 ; 777! + jne @F + mov eax, slotBet + imul eax, 25 + mov slotWinAmount, eax + add bankroll, eax + invoke PlayCasinoSound3D, OFFSET soundJackpot, 0, 1 + jmp draw_reels +@@: + cmp eax, 6 ; CROWN! + jne @F + mov eax, slotBet + imul eax, 50 + mov slotWinAmount, eax + add bankroll, eax + invoke PlayCasinoSound3D, OFFSET soundJackpot, 0, 1 + jmp draw_reels +@@: + mov eax, slotBet + imul eax, 10 + mov slotWinAmount, eax + add bankroll, eax + invoke PlayCasinoSound3D, OFFSET soundRoundWin, 0, 1 + jmp draw_reels + +check_pairs: + mov eax, slotReel1 + cmp eax, slotReel2 + je pair_win + mov eax, slotReel2 + cmp eax, slotReel3 + je pair_win + mov eax, slotReel1 + cmp eax, slotReel3 + je pair_win + jmp draw_reels +pair_win: + mov eax, slotBet + imul eax, 2 + mov slotWinAmount, eax + add bankroll, eax + invoke PlayCasinoSound3D, OFFSET soundRoundWin, 0, 1 + +draw_reels: + ; Reels Window + invoke DrawBoxBorder, 30, 62, 260, 95, 000F0F12h, 0000A5FFh, 2 + + ; Reel 1 (45..105) + invoke DrawBoxBorder, 45, 68, 65, 82, 00F0F0F5h, 00505050h, 2 + mov eax, slotReel1 + call DrawReelSymbolAt1 + + ; Reel 2 (128..188) + invoke DrawBoxBorder, 128, 68, 65, 82, 00F0F0F5h, 00505050h, 2 + mov eax, slotReel2 + call DrawReelSymbolAt2 + + ; Reel 3 (210..270) + invoke DrawBoxBorder, 210, 68, 65, 82, 00F0F0F5h, 00505050h, 2 + mov eax, slotReel3 + call DrawReelSymbolAt3 + + ; Bottom Control Panel + invoke DrawBoxBorder, 20, 165, 280, 58, 00151515h, 00FFD700h, 1 + + invoke DrawString8x8, 28, 172, OFFSET textBank3D, 00FFD700h + invoke FormatNumber, bankroll, OFFSET hudNumBuffer + invoke DrawString8x8, 110, 172, OFFSET hudNumBuffer, 00FFFF00h + + invoke DrawString8x8, 175, 172, OFFSET textBet3D, 00FFD700h + invoke FormatNumber, slotBet, OFFSET hudNumBuffer + invoke DrawString8x8, 240, 172, OFFSET hudNumBuffer, 0050FF50h + + cmp slotWinAmount, 0 + jle draw_slot_ctrls + invoke DrawString8x8, 28, 187, OFFSET strWin, 00FFFF00h + invoke FormatNumber, slotWinAmount, OFFSET hudNumBuffer + invoke DrawString8x8, 110, 187, OFFSET hudNumBuffer, 00FFFF00h + +draw_slot_ctrls: + invoke DrawString8x8, 28, 204, OFFSET textSlotsKeys3D, 00A0A0A0h + ret +RenderSlotsGame ENDP + +DrawReelSymbolAt1 PROC + cmp eax, 0 + jne @F + invoke DrawString8x8, 52, 105, OFFSET sym7, 00FF2020h + ret +@@: + cmp eax, 1 + jne @F + invoke DrawString8x8, 52, 105, OFFSET symBar, 00FFAA00h + ret +@@: + cmp eax, 2 + jne @F + invoke DrawString8x8, 52, 105, OFFSET symBell, 00FFD700h + ret +@@: + cmp eax, 3 + jne @F + invoke DrawString8x8, 48, 105, OFFSET symCherry, 000000D0h + ret +@@: + cmp eax, 4 + jne @F + invoke DrawString8x8, 48, 105, OFFSET symClover, 0000A000h + ret +@@: + cmp eax, 5 + jne @F + invoke DrawString8x8, 52, 105, OFFSET symGem, 00FFFF00h + ret +@@: + invoke DrawString8x8, 52, 105, OFFSET symCrown, 00FFD700h + ret +DrawReelSymbolAt1 ENDP + +DrawReelSymbolAt2 PROC + cmp eax, 0 + jne @F + invoke DrawString8x8, 135, 105, OFFSET sym7, 00FF2020h + ret +@@: + cmp eax, 1 + jne @F + invoke DrawString8x8, 135, 105, OFFSET symBar, 00FFAA00h + ret +@@: + cmp eax, 2 + jne @F + invoke DrawString8x8, 135, 105, OFFSET symBell, 00FFD700h + ret +@@: + cmp eax, 3 + jne @F + invoke DrawString8x8, 131, 105, OFFSET symCherry, 000000D0h + ret +@@: + cmp eax, 4 + jne @F + invoke DrawString8x8, 131, 105, OFFSET symClover, 0000A000h + ret +@@: + cmp eax, 5 + jne @F + invoke DrawString8x8, 135, 105, OFFSET symGem, 00FFFF00h + ret +@@: + invoke DrawString8x8, 135, 105, OFFSET symCrown, 00FFD700h + ret +DrawReelSymbolAt2 ENDP + +DrawReelSymbolAt3 PROC + cmp eax, 0 + jne @F + invoke DrawString8x8, 218, 105, OFFSET sym7, 00FF2020h + ret +@@: + cmp eax, 1 + jne @F + invoke DrawString8x8, 218, 105, OFFSET symBar, 00FFAA00h + ret +@@: + cmp eax, 2 + jne @F + invoke DrawString8x8, 218, 105, OFFSET symBell, 00FFD700h + ret +@@: + cmp eax, 3 + jne @F + invoke DrawString8x8, 214, 105, OFFSET symCherry, 000000D0h + ret +@@: + cmp eax, 4 + jne @F + invoke DrawString8x8, 214, 105, OFFSET symClover, 0000A000h + ret +@@: + cmp eax, 5 + jne @F + invoke DrawString8x8, 218, 105, OFFSET symGem, 00FFFF00h + ret +@@: + invoke DrawString8x8, 218, 105, OFFSET symCrown, 00FFD700h + ret +DrawReelSymbolAt3 ENDP + +; ============================================================================== +; IN-ENGINE 2.5D MINI-GAME: BLACKJACK (21) +; ============================================================================== +HandleBlackjackInput PROC uses ebx + cmp bjState, 0 ; Need Deal + jne check_bj_player_turn + invoke Pressed3D, 20h ; SPACE -> Deal + test ah, 80h + jz check_bj_bet_change + mov eax, bankroll + cmp eax, bjBet + jl bj_need_cash + sub eax, bjBet + mov bankroll, eax + + ; Deal 2 cards to player, 2 cards to dealer + mov bjPlayerCardCount, 0 + mov bjDealerCardCount, 0 + mov bjDealerHideHole, 1 + + ; Player Card 1 + invoke RandomRange3D, 13 + inc eax + mov ebx, bjPlayerCardCount + mov [bjPlayerCards + ebx*4], eax + inc bjPlayerCardCount + + ; Dealer Card 1 + invoke RandomRange3D, 13 + inc eax + mov ebx, bjDealerCardCount + mov [bjDealerCards + ebx*4], eax + inc bjDealerCardCount + + ; Player Card 2 + invoke RandomRange3D, 13 + inc eax + mov ebx, bjPlayerCardCount + mov [bjPlayerCards + ebx*4], eax + inc bjPlayerCardCount + + ; Dealer Card 2 (Hole card) + invoke RandomRange3D, 13 + inc eax + mov ebx, bjDealerCardCount + mov [bjDealerCards + ebx*4], eax + inc bjDealerCardCount + + invoke PlayCasinoSound3D, OFFSET soundCards, 0, 1 + + ; Calc Player Score + call CalcPlayerBJScore + cmp bjPlayerScore, 21 + jne set_bj_turn + ; Instant Blackjack! + mov bjDealerHideHole, 0 + mov eax, bjBet + imul eax, 5 + shr eax, 1 + add bankroll, eax + invoke CopyString3D, OFFSET strWin, OFFSET bjOutcomeMsg + invoke PlayCasinoSound3D, OFFSET soundRoundWin, 0, 1 + mov bjState, 2 + ret +set_bj_turn: + mov bjState, 1 + mov BYTE PTR [bjOutcomeMsg], 0 + ret + +bj_need_cash: + invoke CopyString3D, OFFSET msgNeedMoney, OFFSET flashMessage + mov flashTimer, 60 + ret + +check_bj_player_turn: + cmp bjState, 1 + jne check_bj_round_over + + invoke Pressed3D, 48h ; 'H' -> Hit + test ah, 80h + jz check_bj_stand + invoke RandomRange3D, 13 + inc eax + mov ebx, bjPlayerCardCount + cmp ebx, 8 + jge @F + mov [bjPlayerCards + ebx*4], eax + inc bjPlayerCardCount +@@: + invoke PlayCasinoSound3D, OFFSET soundCards, 0, 1 + call CalcPlayerBJScore + cmp bjPlayerScore, 21 + jle bj_input_done + ; Bust! + invoke CopyString3D, OFFSET strPlayerBust, OFFSET bjOutcomeMsg + mov bjDealerHideHole, 0 + mov bjState, 2 + ret + +check_bj_stand: + invoke Pressed3D, 53h ; 'S' -> Stand + test ah, 80h + jz bj_input_done + + ; Dealer Turn + mov bjDealerHideHole, 0 +dealer_loop: + call CalcDealerBJScore + cmp bjDealerScore, 17 + jge dealer_finished + invoke RandomRange3D, 13 + inc eax + mov ebx, bjDealerCardCount + cmp ebx, 8 + jge dealer_finished + mov [bjDealerCards + ebx*4], eax + inc bjDealerCardCount + jmp dealer_loop + +dealer_finished: + cmp bjDealerScore, 21 + jle compare_scores + ; Dealer Bust! + mov eax, bjBet + shl eax, 1 + add bankroll, eax + invoke CopyString3D, OFFSET strDealerBust, OFFSET bjOutcomeMsg + invoke PlayCasinoSound3D, OFFSET soundRoundWin, 0, 1 + mov bjState, 2 + ret + +compare_scores: + mov eax, bjPlayerScore + cmp eax, bjDealerScore + jle check_dealer_won + ; Player Won! + mov eax, bjBet + shl eax, 1 + add bankroll, eax + invoke CopyString3D, OFFSET strWin, OFFSET bjOutcomeMsg + invoke PlayCasinoSound3D, OFFSET soundRoundWin, 0, 1 + mov bjState, 2 + ret +check_dealer_won: + cmp eax, bjDealerScore + jl dealer_wins + ; Push (Tie) + mov eax, bjBet + add bankroll, eax + invoke CopyString3D, OFFSET strPush, OFFSET bjOutcomeMsg + mov bjState, 2 + ret +dealer_wins: + invoke CopyString3D, OFFSET strLose, OFFSET bjOutcomeMsg + mov bjState, 2 + ret + +check_bj_round_over: + invoke Pressed3D, 20h ; SPACE -> Next Hand + test ah, 80h + jz bj_input_done + mov bjState, 0 + ret + +check_bj_bet_change: + invoke Pressed3D, 26h ; UP + test ah, 80h + jz @F + cmp bjBet, 500 + jge bj_input_done + add bjBet, 50 + ret +@@: + invoke Pressed3D, 28h ; DOWN + test ah, 80h + jz bj_input_done + cmp bjBet, 50 + jle bj_input_done + sub bjBet, 50 + +bj_input_done: + ret +HandleBlackjackInput ENDP + +CalcPlayerBJScore PROC uses ebx esi + xor eax, eax + xor ebx, ebx + xor esi, esi +calc_p_loop: + cmp esi, bjPlayerCardCount + jge calc_p_done + mov edx, [bjPlayerCards + esi*4] + cmp edx, 10 + jle @F + mov edx, 10 +@@: + cmp edx, 1 + jne add_p_val + inc ebx ; count Aces + add eax, 11 + jmp next_p_card +add_p_val: + add eax, edx +next_p_card: + inc esi + jmp calc_p_loop +calc_p_done: + ; Soft Ace reduction +reduce_p_ace: + cmp eax, 21 + jle store_p_score + test ebx, ebx + jz store_p_score + sub eax, 10 + dec ebx + jmp reduce_p_ace +store_p_score: + mov bjPlayerScore, eax + ret +CalcPlayerBJScore ENDP + +CalcDealerBJScore PROC uses ebx esi + xor eax, eax + xor ebx, ebx + xor esi, esi +calc_d_loop: + cmp esi, bjDealerCardCount + jge calc_d_done + mov edx, [bjDealerCards + esi*4] + cmp edx, 10 + jle @F + mov edx, 10 +@@: + cmp edx, 1 + jne add_d_val + inc ebx + add eax, 11 + jmp next_d_card +add_d_val: + add eax, edx +next_d_card: + inc esi + jmp calc_d_loop +calc_d_done: +reduce_d_ace: + cmp eax, 21 + jle store_d_score + test ebx, ebx + jz store_d_score + sub eax, 10 + dec ebx + jmp reduce_d_ace +store_d_score: + mov bjDealerScore, eax + ret +CalcDealerBJScore ENDP + +RenderBlackjackGame PROC uses ebx esi edi + ; Emerald Felt Table Background + invoke DrawBox, 0, 0, SCREEN_W, SCREEN_H, 000A3015h + invoke DrawBoxBorder, 10, 10, 300, 220, 000D4018h, 00FFD700h, 3 + + ; Dealer Area Top + invoke DrawString8x8, 25, 20, OFFSET textBJ3D, 00FFD700h + invoke DrawString8x8, 25, 35, OFFSET textDealer3D, 00FFFFFFh + invoke FormatNumber, bjDealerScore, OFFSET hudNumBuffer + invoke DrawString8x8, 120, 35, OFFSET hudNumBuffer, 00FFFF00h + + ; Dealer Cards + xor esi, esi +draw_dealer_cards: + cmp esi, bjDealerCardCount + jge draw_player_bj_area + mov eax, esi + imul eax, 45 + add eax, 25 + mov ebx, eax + + cmp esi, 1 + jne draw_dealer_face + cmp bjDealerHideHole, 1 + jne draw_dealer_face + ; Face Down Card + mov eax, selectedBack3D + mov eax, cardBackColors3D[eax*4] + invoke DrawBoxBorder, ebx, 48, 38, 52, eax, 00FFFFFFh, 2 + jmp next_dealer_card_draw + +draw_dealer_face: + invoke DrawBoxBorder, ebx, 48, 38, 52, 00F0F0F5h, 00000000h, 2 + mov eax, [bjDealerCards + esi*4] + dec eax + imul eax, 3 + lea edx, [cardRankStr + eax] + mov eax, ebx + add eax, 8 + invoke DrawString8x8, eax, 68, edx, 00000000h + +next_dealer_card_draw: + inc esi + jmp draw_dealer_cards + +draw_player_bj_area: + ; Player Area Bottom + invoke DrawString8x8, 25, 110, OFFSET textPlayer3D, 00FFFFFFh + invoke FormatNumber, bjPlayerScore, OFFSET hudNumBuffer + invoke DrawString8x8, 120, 110, OFFSET hudNumBuffer, 0050FF50h + + ; Player Cards + xor esi, esi +draw_player_cards: + cmp esi, bjPlayerCardCount + jge draw_bj_footer + mov eax, esi + imul eax, 45 + add eax, 25 + mov ebx, eax + + invoke DrawBoxBorder, ebx, 124, 38, 52, 00F0F0F5h, 00000000h, 2 + mov eax, [bjPlayerCards + esi*4] + dec eax + imul eax, 3 + lea edx, [cardRankStr + eax] + mov eax, ebx + add eax, 8 + invoke DrawString8x8, eax, 144, edx, 00000000h + + inc esi + jmp draw_player_cards + +draw_bj_footer: + ; Footer Status & Controls + invoke DrawBoxBorder, 20, 182, 280, 42, 00102010h, 00FFD700h, 1 + cmp BYTE PTR [bjOutcomeMsg], 0 + je draw_bj_controls + invoke DrawString8x8, 28, 188, OFFSET bjOutcomeMsg, 00FFFF00h + invoke DrawString8x8, 28, 204, OFFSET textNext3D, 00A0A0A0h + ret + +draw_bj_controls: + invoke DrawString8x8, 28, 188, OFFSET textBJKeys3D, 00FFFFFFh + invoke DrawString8x8, 28, 204, OFFSET textDeal3D, 00A0A0A0h + ret +RenderBlackjackGame ENDP + +; ============================================================================== +; IN-ENGINE 2.5D MINI-GAME: ROULETTE +; ============================================================================== +HandleRouletteInput PROC uses ebx + cmp roulState, 1 + je roul_input_done + + invoke Pressed3D, 31h ; '1' -> RED + test ah, 80h + jz @F + mov roulBetType, 1 +@@: + invoke Pressed3D, 32h ; '2' -> BLACK + test ah, 80h + jz @F + mov roulBetType, 2 +@@: + invoke Pressed3D, 33h ; '3' -> ZERO (0) + test ah, 80h + jz @F + mov roulBetType, 3 +@@: + invoke Pressed3D, 34h ; '4' -> EVEN + test ah, 80h + jz @F + mov roulBetType, 4 +@@: + invoke Pressed3D, 35h ; '5' -> ODD + test ah, 80h + jz check_roul_spin + mov roulBetType, 5 + +check_roul_spin: + invoke Pressed3D, 20h ; SPACE -> Spin + test ah, 80h + jz roul_input_done + mov eax, bankroll + cmp eax, roulBetAmount + jl roul_no_cash + sub eax, roulBetAmount + mov bankroll, eax + mov roulState, 1 + mov roulSpinTimer, 50 + mov roulPayout, 0 + invoke PlayCasinoSound3D, OFFSET soundRoulette, 0, 1 + ret + +roul_no_cash: + invoke CopyString3D, OFFSET msgNeedMoney, OFFSET flashMessage + mov flashTimer, 60 + +roul_input_done: + ret +HandleRouletteInput ENDP + +RenderRouletteGame PROC uses ebx esi edi + ; Table felt background + invoke DrawBox, 0, 0, SCREEN_W, SCREEN_H, 00151525h + invoke DrawBoxBorder, 10, 10, 300, 220, 00201525h, 00FFD700h, 3 + + ; 2.5D Rotating Wheel on Left + invoke DrawCircle, 85, 110, 65, 00102550h + invoke DrawCircle, 85, 110, 60, 00FFD700h + invoke DrawCircle, 85, 110, 52, 00101010h + invoke DrawCircle, 85, 110, 22, 00FFD700h ; Center brass turret + + ; Spinning Wheel / Ball Logic + cmp roulState, 1 + jne draw_roul_ball + dec roulSpinTimer + add roulWheelAngle, 8 + sub roulBallAngle, 14 + cmp roulSpinTimer, 0 + jg draw_roul_ball + + ; Wheel stopped! Determine result! + mov roulState, 2 + invoke RandomRange3D, 37 + mov roulWinningNum, eax + + ; Check bet + cmp roulBetType, 1 ; RED + jne check_ro_black + call IsNumberRed + test eax, eax + jz ro_lost + mov eax, roulBetAmount + shl eax, 1 + mov roulPayout, eax + add bankroll, eax + invoke CopyString3D, OFFSET strWin, OFFSET roulOutcomeMsg + invoke PlayCasinoSound3D, OFFSET soundRoundWin, 0, 1 + jmp draw_roul_ball + +check_ro_black: + cmp roulBetType, 2 ; BLACK + jne check_ro_zero + cmp roulWinningNum, 0 + je ro_lost + call IsNumberRed + test eax, eax + jnz ro_lost + mov eax, roulBetAmount + shl eax, 1 + mov roulPayout, eax + add bankroll, eax + invoke CopyString3D, OFFSET strWin, OFFSET roulOutcomeMsg + invoke PlayCasinoSound3D, OFFSET soundRoundWin, 0, 1 + jmp draw_roul_ball + +check_ro_zero: + cmp roulBetType, 3 ; ZERO + jne check_ro_even + cmp roulWinningNum, 0 + jne ro_lost + mov eax, roulBetAmount + imul eax, 36 + mov roulPayout, eax + add bankroll, eax + invoke CopyString3D, OFFSET strJackpot, OFFSET roulOutcomeMsg + invoke PlayCasinoSound3D, OFFSET soundJackpot, 0, 1 + jmp draw_roul_ball + +check_ro_even: + cmp roulBetType, 4 ; EVEN + jne check_ro_odd + mov eax, roulWinningNum + test eax, eax + jz ro_lost + test al, 1 + jnz ro_lost + mov eax, roulBetAmount + shl eax, 1 + mov roulPayout, eax + add bankroll, eax + invoke CopyString3D, OFFSET strWin, OFFSET roulOutcomeMsg + invoke PlayCasinoSound3D, OFFSET soundRoundWin, 0, 1 + jmp draw_roul_ball + +check_ro_odd: + mov eax, roulWinningNum + test eax, eax + jz ro_lost + test al, 1 + jz ro_lost + mov eax, roulBetAmount + shl eax, 1 + mov roulPayout, eax + add bankroll, eax + invoke CopyString3D, OFFSET strWin, OFFSET roulOutcomeMsg + invoke PlayCasinoSound3D, OFFSET soundRoundWin, 0, 1 + jmp draw_roul_ball + +ro_lost: + invoke CopyString3D, OFFSET strLose, OFFSET roulOutcomeMsg + +draw_roul_ball: + ; Draw White Ball on Rim + mov eax, roulBallAngle + and eax, 511 + mov ebx, [tableCos + eax*4] + imul ebx, 42 + sar ebx, 16 + add ebx, 85 + + mov eax, roulBallAngle + and eax, 511 + mov edx, [tableSin + eax*4] + imul edx, 42 + sar edx, 16 + add edx, 110 + invoke DrawCircle, ebx, edx, 3, 00FFFFFFh + + ; Right Betting Board + invoke DrawBoxBorder, 175, 25, 125, 28, 001010C0h, 00FFFFFFh, 2 ; [1] RED + invoke DrawString8x8, 190, 35, OFFSET textRed3D, 00FFFFFFh + + invoke DrawBoxBorder, 175, 60, 125, 28, 00151515h, 00FFFFFFh, 2 ; [2] BLACK + invoke DrawString8x8, 190, 70, OFFSET textBlack3D, 00FFFFFFh + + invoke DrawBoxBorder, 175, 95, 125, 28, 00106010h, 00FFFFFFh, 2 ; [3] ZERO + invoke DrawString8x8, 190, 105, OFFSET textZero3D, 00FFFFFFh + + invoke DrawBoxBorder, 175, 130, 60, 26, 00302020h, 00FFFFFFh, 1 ; [4] EVEN + invoke DrawString8x8, 185, 139, OFFSET textEven3D, 00FFFFFFh + + invoke DrawBoxBorder, 240, 130, 60, 26, 00302020h, 00FFFFFFh, 1 ; [5] ODD + invoke DrawString8x8, 250, 139, OFFSET textOdd3D, 00FFFFFFh + + ; Highlight Active Bet + cmp roulBetType, 1 + jne @F + invoke DrawBoxBorder, 173, 23, 129, 32, 0, 00FFFF00h, 2 +@@: + cmp roulBetType, 2 + jne @F + invoke DrawBoxBorder, 173, 58, 129, 32, 0, 00FFFF00h, 2 +@@: + cmp roulBetType, 3 + jne @F + invoke DrawBoxBorder, 173, 93, 129, 32, 0, 00FFFF00h, 2 +@@: + cmp roulBetType, 4 + jne @F + invoke DrawBoxBorder, 173, 128, 64, 30, 0, 00FFFF00h, 2 +@@: + cmp roulBetType, 5 + jne draw_ro_footer + invoke DrawBoxBorder, 238, 128, 64, 30, 0, 00FFFF00h, 2 + +draw_ro_footer: + invoke DrawBoxBorder, 20, 180, 280, 42, 00101015h, 00FFD700h, 1 + + cmp roulState, 2 + jne @F + invoke DrawString8x8, 28, 186, OFFSET textResult3D, 00FFD700h + invoke FormatNumber, roulWinningNum, OFFSET hudNumBuffer + invoke DrawString8x8, 85, 186, OFFSET hudNumBuffer, 00FFFF00h + invoke DrawString8x8, 130, 186, OFFSET roulOutcomeMsg, 0050FF50h +@@: + invoke DrawString8x8, 28, 202, OFFSET textSpin3D, 00A0A0A0h + ret +RenderRouletteGame ENDP + +IsNumberRed PROC + mov eax, roulWinningNum + cmp eax, 1 + je red_yes + cmp eax, 3 + je red_yes + cmp eax, 5 + je red_yes + cmp eax, 7 + je red_yes + cmp eax, 9 + je red_yes + cmp eax, 12 + je red_yes + cmp eax, 14 + je red_yes + cmp eax, 16 + je red_yes + cmp eax, 18 + je red_yes + cmp eax, 19 + je red_yes + cmp eax, 21 + je red_yes + cmp eax, 23 + je red_yes + cmp eax, 25 + je red_yes + cmp eax, 27 + je red_yes + cmp eax, 30 + je red_yes + cmp eax, 32 + je red_yes + cmp eax, 34 + je red_yes + cmp eax, 36 + je red_yes + xor eax, eax + ret +red_yes: + mov eax, 1 + ret +IsNumberRed ENDP + +; ============================================================================== +; IN-ENGINE 2.5D MINI-GAME: BAR & SHOP +; ============================================================================== +HandleShopInput PROC uses ebx esi + xor esi, esi +shop_choice: + inc esi + lea eax, [esi+30h] + invoke Pressed3D, eax + test eax, eax + jnz shop_chosen + cmp esi, 3 + jb shop_choice + ret +shop_chosen: + bt ownedBacks3D, esi + jc shop_equip + mov ebx, 1500 + cmp esi, 1 + jne @F + mov ebx, 1000 +@@: + cmp bankroll, ebx + jb shop_no_money + sub bankroll, ebx + bts ownedBacks3D, esi +shop_equip: + mov selectedBack3D, esi + invoke CopyString3D, OFFSET textBought3D, OFFSET shopMsg + call SaveProgress3D + ret +shop_no_money: + invoke CopyString3D, OFFSET textNoCash3D, OFFSET shopMsg + ret +HandleShopInput ENDP + +RenderShopGame PROC + invoke DrawBox, 0, 0, SCREEN_W, SCREEN_H, 00150A0Ah + invoke DrawBoxBorder, 10, 10, 300, 220, 00251515h, 00FFD700h, 3 + invoke DrawString8x8, 25, 20, OFFSET textShop3D, 00FFD700h + + invoke DrawBoxBorder, 20, 40, 280, 32, 001A1010h, 00FFFFFFh, 1 + invoke DrawString8x8, 28, 46, OFFSET textItem1_3D, 00FFFF00h + invoke DrawString8x8, 28, 58, OFFSET textShopHint3D, 00A0A0A0h + + invoke DrawBoxBorder, 20, 80, 280, 32, 001A1010h, 00FFFFFFh, 1 + invoke DrawString8x8, 28, 86, OFFSET textItem2_3D, 00FFFF00h + invoke DrawString8x8, 28, 98, OFFSET textShopHint3D, 00A0A0A0h + + invoke DrawBoxBorder, 20, 120, 280, 32, 001A1010h, 00FFFFFFh, 1 + invoke DrawString8x8, 28, 126, OFFSET textItem3_3D, 00FFFF00h + invoke DrawString8x8, 28, 138, OFFSET textShopHint3D, 00A0A0A0h + + invoke DrawBoxBorder, 20, 165, 280, 55, 00100A0Ah, 00FFD700h, 1 + invoke DrawString8x8, 28, 172, OFFSET textBank3D, 00FFD700h + invoke FormatNumber, bankroll, OFFSET hudNumBuffer + invoke DrawString8x8, 110, 172, OFFSET hudNumBuffer, 00FFFF00h + + cmp BYTE PTR [shopMsg], 0 + je @F + invoke DrawString8x8, 28, 188, OFFSET shopMsg, 0050FF50h +@@: + invoke DrawString8x8, 28, 204, OFFSET textBack3D, 00A0A0A0h + ret +RenderShopGame ENDP + +; ============================================================================== +; IN-ENGINE 2.5D MINI-GAME: ATM TERMINAL +; ============================================================================== +HandleATMInput PROC + ret +HandleATMInput ENDP + +RenderATMGame PROC + invoke DrawBox, 0, 0, 320, 240, 00172120h + invoke DrawString8x8, 24, 30, OFFSET textATM3D, 00D8BC6Ah + invoke DrawString8x8, 24, 70, OFFSET textBank3D, 00FFFFFFh + invoke FormatNumber, bankroll, OFFSET hudNumBuffer + invoke DrawString8x8, 96, 70, OFFSET hudNumBuffer, 0089DAB2h + invoke DrawString8x8, 24, 115, OFFSET textATMNote3D, 00B7C8C1h + invoke DrawString8x8, 24, 140, OFFSET textATMNote2_3D, 00B7C8C1h + invoke DrawString8x8, 24, 208, OFFSET textBack3D, 00D8BC6Ah + ret +RenderATMGame ENDP + +; ============================================================================== +; ============================================================================== +; ============================================================================== +; SHARED RICH UI PROCEDURES +; ============================================================================== +DrawKeycap3D PROC uses ebx esi edi, x:DWORD, y:DWORD, strPtr:DWORD, isActive:DWORD + local keyW:DWORD + mov esi, strPtr + xor ecx, ecx +keycap_len: + mov al, [esi+ecx] + test al, al + jz keycap_len_done + inc ecx + jmp keycap_len +keycap_len_done: + shl ecx, 3 + add ecx, 8 + mov keyW, ecx + + ; Drop shadow + mov eax, y + add eax, 2 + invoke DrawBox, x, eax, keyW, 13, 0008080Ch + + ; Border and Fill + cmp isActive, 0 + je keycap_inactive + mov eax, 00FFFF00h ; Bright Yellow active border + mov edx, 001B4B22h ; Casino Green active fill + mov ebx, 00FFFF00h ; Bright Yellow active text + jmp keycap_draw_box +keycap_inactive: + mov eax, 00606870h ; Slate inactive border + mov edx, 001A1C22h ; Charcoal inactive fill + mov ebx, 00D0D8E0h ; Silver inactive text + +keycap_draw_box: + push ebx + invoke DrawBoxBorder, x, y, keyW, 13, edx, eax, 1 + pop ebx + + ; Text label + mov eax, x + add eax, 4 + mov edx, y + add edx, 3 + invoke DrawString8x8, eax, edx, strPtr, ebx + + mov eax, keyW + add eax, 4 + ret +DrawKeycap3D ENDP + +DrawChipStack PROC uses ebx esi edi, x:DWORD, y:DWORD, chipCount:DWORD + mov edi, chipCount + xor esi, esi +chip_loop: + cmp esi, edi + jge chip_done + mov eax, esi + shl eax, 2 + mov edx, y + sub edx, eax + + ; Shadow + mov eax, x + add eax, 2 + mov ecx, edx + add ecx, 5 + invoke DrawBox, eax, ecx, 20, 2, 00061004h + + ; Red Clay Chip body with white rim + invoke DrawBoxBorder, x, edx, 24, 6, 00B81515h, 00FFFFFFh, 1 + + ; White stripe inlays + mov eax, x + add eax, 4 + mov ecx, edx + add ecx, 1 + invoke DrawBox, eax, ecx, 3, 4, 00FFFFFFh + + mov eax, x + add eax, 17 + mov ecx, edx + add ecx, 1 + invoke DrawBox, eax, ecx, 3, 4, 00FFFFFFh + + inc esi + jmp chip_loop +chip_done: + ret +DrawChipStack ENDP + +DrawDetailedCoin PROC uses ebx esi edi, cxVal:DWORD, cyVal:DWORD, rxVal:DWORD, ryVal:DWORD, outerColor:DWORD, innerColor:DWORD, reliefType:DWORD + local rxSq:DWORD + local rySq:DWORD + local rxRySq:DWORD + local threshSq:DWORD + local curDy:DWORD + local curDx:DWORD + local curX:DWORD + local curY:DWORD + + mov eax, rxVal + cmp eax, 0 + jle coin_draw_done + mov eax, ryVal + cmp eax, 0 + jle coin_draw_done + + mov eax, rxVal + imul eax, rxVal + mov rxSq, eax + + mov eax, ryVal + imul eax, ryVal + mov rySq, eax + + imul eax, rxSq + mov rxRySq, eax + + ; 3/4 threshold for rim bevel + mov ecx, 3 + imul eax, ecx + shr eax, 2 + mov threshSq, eax + + ; Scan rows + mov eax, ryVal + neg eax + mov curDy, eax +coin_row_loop: + mov eax, curDy + cmp eax, ryVal + jg coin_relief_check + + mov edx, cyVal + add edx, curDy + mov curY, edx + + ; Scan columns + mov eax, rxVal + neg eax + mov curDx, eax +coin_col_loop: + mov eax, curDx + cmp eax, rxVal + jg coin_col_next_row + + mov ecx, cxVal + add ecx, curDx + mov curX, ecx + + ; val = dx*dx*rySq + dy*dy*rxSq + mov eax, curDx + imul eax, curDx + imul eax, rySq + mov ebx, eax + + mov eax, curDy + imul eax, curDy + imul eax, rxSq + add eax, ebx + + cmp eax, rxRySq + ja coin_pixel_outside + + cmp eax, threshSq + jb coin_draw_inner + invoke DrawPixel, curX, curY, outerColor + jmp coin_pixel_outside +coin_draw_inner: + invoke DrawPixel, curX, curY, innerColor + +coin_pixel_outside: + inc curDx + jmp coin_col_loop + +coin_col_next_row: + inc curDy + jmp coin_row_loop + +coin_relief_check: + cmp rxVal, 14 + jl coin_draw_done + + cmp reliefType, 1 + je coin_draw_eagle + cmp reliefType, 2 + je coin_draw_numeral + jmp coin_draw_done + +coin_draw_eagle: + ; Imperial Eagle relief (Dark Gold 009A7A00h / Bright 00FFD700h) + mov eax, cxVal + sub eax, 3 + mov edx, cyVal + sub edx, 14 + invoke DrawBox, eax, edx, 7, 2, 009A7A00h + + mov eax, cxVal + sub eax, 4 + mov edx, cyVal + sub edx, 12 + invoke DrawBox, eax, edx, 9, 2, 009A7A00h + + mov eax, cxVal + sub eax, 2 + mov edx, cyVal + sub edx, 9 + invoke DrawBox, eax, edx, 5, 12, 009A7A00h + + mov eax, cxVal + sub eax, 1 + mov edx, cyVal + sub edx, 8 + invoke DrawBox, eax, edx, 3, 10, 00FFD700h + + mov eax, cxVal + sub eax, 10 + mov edx, cyVal + sub edx, 8 + invoke DrawBox, eax, edx, 7, 3, 009A7A00h + + mov eax, cxVal + sub eax, 13 + mov edx, cyVal + sub edx, 5 + invoke DrawBox, eax, edx, 10, 3, 009A7A00h + + mov eax, cxVal + sub eax, 11 + mov edx, cyVal + sub edx, 2 + invoke DrawBox, eax, edx, 7, 3, 009A7A00h + + mov eax, cxVal + add eax, 4 + mov edx, cyVal + sub edx, 8 + invoke DrawBox, eax, edx, 7, 3, 009A7A00h + + mov eax, cxVal + add eax, 4 + mov edx, cyVal + sub edx, 5 + invoke DrawBox, eax, edx, 10, 3, 009A7A00h + + mov eax, cxVal + add eax, 5 + mov edx, cyVal + sub edx, 2 + invoke DrawBox, eax, edx, 7, 3, 009A7A00h + + mov eax, cxVal + sub eax, 4 + mov edx, cyVal + add edx, 4 + invoke DrawBox, eax, edx, 9, 3, 009A7A00h + + mov eax, cxVal + sub eax, 3 + mov edx, cyVal + add edx, 7 + invoke DrawBox, eax, edx, 7, 3, 009A7A00h + jmp coin_draw_done + +coin_draw_numeral: + ; Roman numeral 'I' & laurel + mov eax, cxVal + sub eax, 5 + mov edx, cyVal + sub edx, 10 + invoke DrawBox, eax, edx, 11, 3, 009A7A00h + + mov eax, cxVal + sub eax, 2 + mov edx, cyVal + sub edx, 7 + invoke DrawBox, eax, edx, 5, 14, 009A7A00h + + mov eax, cxVal + sub eax, 1 + mov edx, cyVal + sub edx, 6 + invoke DrawBox, eax, edx, 3, 12, 00FFD700h + + mov eax, cxVal + sub eax, 6 + mov edx, cyVal + add edx, 7 + invoke DrawBox, eax, edx, 13, 3, 009A7A00h + + ; Laurel dots + mov eax, cxVal + sub eax, 12 + mov edx, cyVal + sub edx, 8 + invoke DrawBox, eax, edx, 2, 2, 009A7A00h + + mov eax, cxVal + add eax, 11 + mov edx, cyVal + sub edx, 8 + invoke DrawBox, eax, edx, 2, 2, 009A7A00h + + mov eax, cxVal + sub eax, 12 + mov edx, cyVal + invoke DrawBox, eax, edx, 2, 2, 009A7A00h + + mov eax, cxVal + add eax, 11 + mov edx, cyVal + invoke DrawBox, eax, edx, 2, 2, 009A7A00h + + mov eax, cxVal + sub eax, 12 + mov edx, cyVal + add edx, 8 + invoke DrawBox, eax, edx, 2, 2, 009A7A00h + + mov eax, cxVal + add eax, 11 + mov edx, cyVal + add edx, 8 + invoke DrawBox, eax, edx, 2, 2, 009A7A00h + +coin_draw_done: + ret +DrawDetailedCoin ENDP + +; ============================================================================== +; IN-ENGINE 2.5D MINI-GAME: COIN FLIP +; ============================================================================== +InitCoinGame PROC + call InitNativeCoin3D + ret +InitCoinGame ENDP + +HandleCoinInput PROC + call HandleNativeCoin3D + ret +; Retained legacy frame-count prototype, excluded from the executable. +IF 0 + cmp coin3d_state, 0 + je coin_handle_idle + cmp coin3d_state, 1 + je coin_handle_flipping + cmp coin3d_state, 2 + je coin_handle_result + ret + +coin_handle_idle: + invoke Pressed3D, 26h ; UP + test eax, eax + jnz coin_bet_up + invoke Pressed3D, 57h ; 'W' + test eax, eax + jnz coin_bet_up + invoke Pressed3D, 28h ; DOWN + test eax, eax + jnz coin_bet_down + invoke Pressed3D, 53h ; 'S' + test eax, eax + jnz coin_bet_down + invoke Pressed3D, 31h ; '1' + test eax, eax + jnz coin_pick_1 + invoke Pressed3D, 32h ; '2' + test eax, eax + jnz coin_pick_2 + invoke Pressed3D, 20h ; SPACE + test eax, eax + jnz coin_start_flip + ret + +coin_bet_up: + mov eax, coin3d_bet + add eax, 50 + cmp eax, bankroll + jle @F + mov eax, bankroll +@@: + cmp eax, 5000 + jle @F + mov eax, 5000 +@@: + mov coin3d_bet, eax + invoke PlayCasinoSound3D, OFFSET soundClick, 0, 1 + ret + +coin_bet_down: + mov eax, coin3d_bet + sub eax, 50 + cmp eax, 50 + jge @F + mov eax, 50 +@@: + mov coin3d_bet, eax + invoke PlayCasinoSound3D, OFFSET soundClick, 0, 1 + ret + +coin_pick_1: + mov coin3d_choice, 1 + invoke PlayCasinoSound3D, OFFSET soundClick, 0, 1 + ret + +coin_pick_2: + mov coin3d_choice, 2 + invoke PlayCasinoSound3D, OFFSET soundClick, 0, 1 + ret + +coin_start_flip: + mov eax, coin3d_bet + cmp eax, bankroll + jle @F + mov eax, bankroll + mov coin3d_bet, eax + test eax, eax + jz coin_done +@@: + mov eax, coin3d_bet + sub bankroll, eax + mov coin3d_state, 1 + mov coin3d_timer, 40 + invoke PlayCasinoSound3D, OFFSET soundCoin, 0, 1 + ret + +coin_handle_flipping: + dec coin3d_timer + cmp coin3d_timer, 0 + jg coin_done + invoke RandomRange3D, 2 + inc eax + mov coin3d_result, eax + mov edx, coin3d_choice + cmp eax, edx + jne coin_flip_lost + + ; Won! + inc coin3d_streak + mov eax, coin3d_bet + shl eax, 1 + add bankroll, eax + mov coin3d_win, eax + mov coin3d_state, 2 + invoke PlayCasinoSound3D, OFFSET soundCoinDing, 0, 1 + ret + +coin_flip_lost: + mov coin3d_streak, 0 + mov coin3d_win, 0 + mov coin3d_state, 2 + invoke PlayCasinoSound3D, OFFSET soundLose, 0, 1 + ret + +coin_handle_result: + invoke Pressed3D, 20h + test eax, eax + jz coin_done + mov coin3d_state, 0 + invoke PlayCasinoSound3D, OFFSET soundClick, 0, 1 +coin_done: + ret +ENDIF +HandleCoinInput ENDP + +RenderCoinGame PROC uses ebx esi edi + local cyVal:DWORD + local rxVal:DWORD + local kx:DWORD + + call RenderNativeCoin3D + ret +IF 0 + ; Background & Cabinet border + invoke DrawBox, 0, 0, 320, 240, 00140906h + invoke DrawBoxBorder, 6, 6, 308, 228, 0022150Fh, 00482E1Bh, 3 + + ; Header + invoke DrawBoxBorder, 20, 12, 280, 26, 001C100Ah, 00FFD700h, 2 + invoke DrawString8x8, 44, 21, OFFSET textCoinTitle, 00FFFF00h + + ; Corner rivets + invoke DrawBox, 12, 12, 3, 3, 00FFD700h + invoke DrawBox, 306, 12, 3, 3, 00FFD700h + invoke DrawBox, 12, 226, 3, 3, 00FFD700h + invoke DrawBox, 306, 226, 3, 3, 00FFD700h + + ; Status meters + invoke DrawBoxBorder, 20, 44, 110, 18, 000E1A0Ah, 00224B1Ah, 1 + invoke DrawString8x8, 24, 49, OFFSET textBankPrompt, 003CFF3Ch + invoke FormatNumber, bankroll, OFFSET hudNumBuffer + invoke DrawString8x8, 72, 49, OFFSET hudNumBuffer, 003CFF3Ch + + invoke DrawBoxBorder, 190, 44, 110, 18, 001A100Ah, 003A2814h, 1 + invoke DrawString8x8, 194, 49, OFFSET textBetPrompt, 00FFD700h + invoke FormatNumber, coin3d_bet, OFFSET hudNumBuffer + invoke DrawString8x8, 254, 49, OFFSET hudNumBuffer, 00FFD700h + + ; Left: Heads + cmp coin3d_choice, 1 + jne coin_left_inactive + invoke DrawBoxBorder, 20, 72, 76, 68, 00101828h, 00FFFF00h, 2 + invoke DrawString8x8, 30, 78, OFFSET textCoinSide1, 00FFFF00h + invoke DrawDetailedCoin, 58, 106, 14, 14, 00D0A000h, 00FFD700h, 1 + invoke DrawString8x8, 24, 126, OFFSET textCoinSelected, 003CFF3Ch + jmp coin_right_side +coin_left_inactive: + invoke DrawBoxBorder, 20, 72, 76, 68, 000A101Ch, 00404855h, 1 + invoke DrawString8x8, 30, 78, OFFSET textCoinSide1, 00D0D8E0h + invoke DrawDetailedCoin, 58, 106, 14, 14, 009A7A00h, 00D0A000h, 1 + +coin_right_side: + ; Right: Tails + cmp coin3d_choice, 2 + jne coin_right_inactive + invoke DrawBoxBorder, 224, 72, 76, 68, 00101828h, 00FFFF00h, 2 + invoke DrawString8x8, 234, 78, OFFSET textCoinSide2, 00FFFF00h + invoke DrawDetailedCoin, 262, 106, 14, 14, 00D0A000h, 00FFD700h, 2 + invoke DrawString8x8, 228, 126, OFFSET textCoinSelected, 003CFF3Ch + jmp coin_center_area +coin_right_inactive: + invoke DrawBoxBorder, 224, 72, 76, 68, 000A101Ch, 00404855h, 1 + invoke DrawString8x8, 234, 78, OFFSET textCoinSide2, 00D0D8E0h + invoke DrawDetailedCoin, 262, 106, 14, 14, 009A7A00h, 00D0A000h, 2 + +coin_center_area: + ; Center spotlight + invoke DrawCircle, 160, 110, 48, 00121620h + invoke DrawCircle, 160, 110, 44, 00FFD700h + invoke DrawCircle, 160, 110, 42, 000E141Eh + + cmp coin3d_state, 1 + je coin_render_flipping + cmp coin3d_state, 2 + je coin_render_result + + ; Idle coin + invoke DrawDetailedCoin, 160, 110, 26, 26, 00D0A000h, 00FFD700h, coin3d_choice + jmp coin_render_keys + +coin_render_flipping: + mov eax, coin3d_timer + and eax, 7 + movzx eax, byte ptr [coinRxAnimTable + eax] + mov rxVal, eax + invoke DrawDetailedCoin, 160, 110, rxVal, 26, 00D0A000h, 00FFD700h, 0 + invoke DrawString8x8, 88, 160, OFFSET textCoinFlipping, 00FFFF00h + jmp coin_render_keys + +coin_render_result: + invoke DrawDetailedCoin, 160, 110, 26, 26, 00D0A000h, 00FFD700h, coin3d_result + mov eax, coin3d_result + cmp eax, coin3d_choice + jne coin_render_loss_msg + + ; Win banner + invoke DrawBoxBorder, 44, 154, 232, 22, 000E141Eh, 003CFF3Ch, 1 + invoke DrawString8x8, 64, 161, OFFSET textCoinWin, 003CFF3Ch + invoke FormatNumber, coin3d_win, OFFSET hudNumBuffer + invoke DrawString8x8, 152, 161, OFFSET hudNumBuffer, 003CFF3Ch + jmp coin_render_keys + +coin_render_loss_msg: + invoke DrawBoxBorder, 44, 154, 232, 22, 000E141Eh, 00C81414h, 1 + invoke DrawString8x8, 114, 161, OFFSET textCoinLose, 00FF6464h + +coin_render_keys: + mov kx, 16 + xor eax, eax + cmp coin3d_choice, 1 + sete al + invoke DrawKeycap3D, kx, 192, OFFSET textCoinKey1, eax + add kx, eax + + xor eax, eax + cmp coin3d_choice, 2 + sete al + invoke DrawKeycap3D, kx, 192, OFFSET textCoinKey2, eax + add kx, eax + + invoke DrawKeycap3D, kx, 192, OFFSET textCoinKeySpace, 1 + add kx, eax + + invoke DrawKeycap3D, kx, 192, OFFSET textKeyEsc, 0 + ret +ENDIF +RenderCoinGame ENDP + +; ============================================================================== +; IN-ENGINE 2.5D MINI-GAME: CRAPS / DICE +; ============================================================================== +DrawCrapsDie PROC uses ebx esi edi, x:DWORD, y:DWORD, sizeVal:DWORD, valNum:DWORD + ; Drop shadow + mov eax, x + add eax, 3 + mov edx, y + add edx, sizeVal + invoke DrawBox, eax, edx, sizeVal, 3, 00081403h + + mov eax, x + add eax, sizeVal + mov edx, y + add edx, 3 + invoke DrawBox, eax, edx, 3, sizeVal, 00081403h + + ; Ivory body & bevel + invoke DrawBoxBorder, x, y, sizeVal, sizeVal, 00FAF4F0h, 00403535h, 1 + mov eax, x + inc eax + mov edx, y + inc edx + mov ecx, sizeVal + sub ecx, 2 + invoke DrawBox, eax, edx, ecx, 1, 00FFFFFFh + invoke DrawBox, eax, edx, 1, ecx, 00FFFFFFh + + ; Ruby pips (00C81515h) + mov eax, valNum + test al, 1 + jz @F + ; Center pip + mov eax, x + add eax, 18 + mov edx, y + add edx, 18 + invoke DrawCircle, eax, edx, 3, 00C81515h + dec eax + dec edx + invoke DrawPixel, eax, edx, 00FFFFFFh +@@: + cmp valNum, 2 + jl die_pips_done + mov eax, x + add eax, 9 + mov edx, y + add edx, 9 + invoke DrawCircle, eax, edx, 3, 00C81515h + mov eax, x + add eax, 27 + mov edx, y + add edx, 27 + invoke DrawCircle, eax, edx, 3, 00C81515h + + cmp valNum, 4 + jl die_pips_done + mov eax, x + add eax, 27 + mov edx, y + add edx, 9 + invoke DrawCircle, eax, edx, 3, 00C81515h + mov eax, x + add eax, 9 + mov edx, y + add edx, 27 + invoke DrawCircle, eax, edx, 3, 00C81515h + + cmp valNum, 6 + jl die_pips_done + mov eax, x + add eax, 9 + mov edx, y + add edx, 18 + invoke DrawCircle, eax, edx, 3, 00C81515h + mov eax, x + add eax, 27 + mov edx, y + add edx, 18 + invoke DrawCircle, eax, edx, 3, 00C81515h + +die_pips_done: + ret +DrawCrapsDie ENDP + +InitDiceGame PROC + mov dice3d_state, 0 + mov dice3d_timer, 0 + mov dice3d_win, 0 + ret +InitDiceGame ENDP + +HandleDiceInput PROC + cmp dice3d_state, 0 + je dice_handle_idle + cmp dice3d_state, 1 + je dice_handle_rolling + cmp dice3d_state, 2 + je dice_handle_result + ret + +dice_handle_idle: + invoke Pressed3D, 26h ; UP + test eax, eax + jnz dice_bet_up + invoke Pressed3D, 57h ; 'W' + test eax, eax + jnz dice_bet_up + invoke Pressed3D, 28h ; DOWN + test eax, eax + jnz dice_bet_down + invoke Pressed3D, 53h ; 'S' + test eax, eax + jnz dice_bet_down + invoke Pressed3D, 31h ; '1' + test eax, eax + jnz dice_pick_1 + invoke Pressed3D, 32h ; '2' + test eax, eax + jnz dice_pick_2 + invoke Pressed3D, 20h ; SPACE + test eax, eax + jnz dice_start_roll + ret + +dice_bet_up: + mov eax, dice3d_bet + add eax, 50 + cmp eax, bankroll + jle @F + mov eax, bankroll +@@: + cmp eax, 5000 + jle @F + mov eax, 5000 +@@: + mov dice3d_bet, eax + invoke PlayCasinoSound3D, OFFSET soundClick, 0, 1 + ret + +dice_bet_down: + mov eax, dice3d_bet + sub eax, 50 + cmp eax, 50 + jge @F + mov eax, 50 +@@: + mov dice3d_bet, eax + invoke PlayCasinoSound3D, OFFSET soundClick, 0, 1 + ret + +dice_pick_1: + mov dice3d_choice, 1 + invoke PlayCasinoSound3D, OFFSET soundClick, 0, 1 + ret + +dice_pick_2: + mov dice3d_choice, 2 + invoke PlayCasinoSound3D, OFFSET soundClick, 0, 1 + ret + +dice_start_roll: + mov eax, dice3d_bet + cmp eax, bankroll + jle @F + mov eax, bankroll + mov dice3d_bet, eax + test eax, eax + jz dice_done +@@: + mov eax, dice3d_bet + test eax, eax + jle dice_done + sub bankroll, eax + mov dice3d_state, 1 + mov dice3d_timer, 0 + invoke RandomRange3D, 6 + inc eax + mov dice3d_val1, eax + invoke RandomRange3D, 6 + inc eax + mov dice3d_val2, eax + invoke PlayCasinoSound3D, OFFSET soundDiceRoll, 0, 1 + call SaveProgress3D + ret + +dice_handle_rolling: + mov eax, deltaTime3D + add dice3d_timer, eax + cmp dice3d_timer, 1600 + jb dice_done + mov dice3d_timer, 1600 + mov eax, dice3d_val2 + mov edx, dice3d_val1 + add edx, eax + mov dice3d_sum, edx + + ; Parity check + mov eax, edx + and eax, 1 + jnz dice_sum_is_odd + ; Even + mov eax, 1 + jmp dice_check_win +dice_sum_is_odd: + mov eax, 2 + +dice_check_win: + cmp eax, dice3d_choice + jne dice_roll_lost + + ; Won! + mov eax, dice3d_bet + shl eax, 1 + add bankroll, eax + mov dice3d_win, eax + mov dice3d_state, 2 + invoke PlayCasinoSound3D, OFFSET soundRoundWin, 0, 1 + invoke NpcRecordRound3D,8,1 + call SaveProgress3D + ret + +dice_roll_lost: + mov dice3d_win, 0 + mov dice3d_state, 2 + invoke PlayCasinoSound3D, OFFSET soundLose, 0, 1 + invoke NpcRecordRound3D,8,0 + call SaveProgress3D + ret + +dice_handle_result: + invoke Pressed3D, 20h + test eax, eax + jz dice_done + mov dice3d_state, 0 + invoke PlayCasinoSound3D, OFFSET soundClick, 0, 1 +dice_done: + ret +HandleDiceInput ENDP + +RenderDiceGame PROC uses ebx esi edi + local kx:DWORD + + ; Mahogany frame & Deep Felt Green table + invoke DrawBox, 0, 0, 320, 240, 00140906h + invoke DrawBoxBorder, 6, 6, 308, 228, 000A3816h, 00FFD700h, 2 + + ; Header + invoke DrawBoxBorder, 20, 12, 280, 26, 00072E13h, 00FFD700h, 2 + invoke DrawString8x8, 116, 21, OFFSET textDiceTitle, 00FFFF00h + + ; Status + invoke DrawBoxBorder, 20, 44, 110, 18, 00072E13h, 001B4B22h, 1 + invoke DrawString8x8, 24, 49, OFFSET textBankPrompt, 003CFF3Ch + invoke FormatNumber, bankroll, OFFSET hudNumBuffer + invoke DrawString8x8, 72, 49, OFFSET hudNumBuffer, 003CFF3Ch + + invoke DrawBoxBorder, 190, 44, 110, 18, 00072E13h, 001B4B22h, 1 + invoke DrawString8x8, 194, 49, OFFSET textBetPrompt, 00FFD700h + invoke FormatNumber, dice3d_bet, OFFSET hudNumBuffer + invoke DrawString8x8, 258, 49, OFFSET hudNumBuffer, 00FFD700h + + ; [1] ЧЁТ + cmp dice3d_choice, 1 + jne dice_even_inactive + invoke DrawBoxBorder, 16, 70, 88, 48, 00072E13h, 00FFFF00h, 2 + invoke DrawString8x8, 30, 76, OFFSET textDiceEven, 00FFFF00h + invoke DrawString8x8, 22, 90, OFFSET textDiceEvenNums, 00FFD700h + invoke DrawString8x8, 26, 104, OFFSET textCoinSelected, 003CFF3Ch + jmp dice_odd_side +dice_even_inactive: + invoke DrawBoxBorder, 16, 70, 88, 48, 00072E13h, 001B4B22h, 1 + invoke DrawString8x8, 30, 76, OFFSET textDiceEven, 00D0D8E0h + invoke DrawString8x8, 22, 90, OFFSET textDiceEvenNums, 0080B090h + +dice_odd_side: + ; [2] НЕЧЕТ + cmp dice3d_choice, 2 + jne dice_odd_inactive + invoke DrawBoxBorder, 216, 70, 88, 48, 00072E13h, 00FFFF00h, 2 + invoke DrawString8x8, 226, 76, OFFSET textDiceOdd, 00FFFF00h + invoke DrawString8x8, 224, 90, OFFSET textDiceOddNums, 00FFD700h + invoke DrawString8x8, 226, 104, OFFSET textCoinSelected, 003CFF3Ch + jmp dice_center_cubes +dice_odd_inactive: + invoke DrawBoxBorder, 216, 70, 88, 48, 00072E13h, 001B4B22h, 1 + invoke DrawString8x8, 226, 76, OFFSET textDiceOdd, 00D0D8E0h + invoke DrawString8x8, 224, 90, OFFSET textDiceOddNums, 0080B090h + +dice_center_cubes: + call RenderDiceThrow3D + + cmp dice3d_state, 1 + je dice_render_rolling + cmp dice3d_state, 2 + je dice_render_result + jmp dice_render_keys + +dice_render_rolling: + invoke DrawString8x8, 76, 138, OFFSET textDiceRolling, 00FFFF00h + jmp dice_render_keys + +dice_render_result: + invoke DrawBoxBorder, 36, 130, 248, 36, 00072E13h, 00FFD700h, 1 + invoke DrawString8x8, 44, 135, OFFSET textDiceSumHdr, 00FFD700h + invoke FormatNumber, dice3d_val1, OFFSET hudNumBuffer + invoke DrawString8x8, 92, 135, OFFSET hudNumBuffer, 00FFFF00h + invoke DrawString8x8, 110, 135, OFFSET textDicePlus, 00FFD700h + invoke FormatNumber, dice3d_val2, OFFSET hudNumBuffer + invoke DrawString8x8, 126, 135, OFFSET hudNumBuffer, 00FFFF00h + invoke DrawString8x8, 144, 135, OFFSET textDiceEqual, 00FFD700h + invoke FormatNumber, dice3d_sum, OFFSET hudNumBuffer + invoke DrawString8x8, 168, 135, OFFSET hudNumBuffer, 00FFFF00h + + mov eax, dice3d_sum + and eax, 1 + jnz dice_render_odd_res + invoke DrawString8x8, 186, 135, OFFSET textDiceEvenResult, 003CFF3Ch + jmp dice_render_outcome +dice_render_odd_res: + invoke DrawString8x8, 186, 135, OFFSET textDiceOddResult, 003CFF3Ch + +dice_render_outcome: + mov eax, dice3d_win + test eax, eax + jz dice_render_loss_outcome + invoke DrawString8x8, 68, 150, OFFSET textDiceWin, 003CFF3Ch + invoke FormatNumber, dice3d_win, OFFSET hudNumBuffer + invoke DrawString8x8, 156, 150, OFFSET hudNumBuffer, 003CFF3Ch + invoke DrawString8x8, 188, 150, OFFSET textDiceWinMult, 003CFF3Ch + jmp dice_render_keys + +dice_render_loss_outcome: + invoke DrawString8x8, 116, 150, OFFSET textDiceLose, 00FF6464h + +dice_render_keys: + mov kx, 16 + xor eax, eax + cmp dice3d_choice, 1 + sete al + invoke DrawKeycap3D, kx, 192, OFFSET textDiceKey1, eax + add kx, eax + + xor eax, eax + cmp dice3d_choice, 2 + sete al + invoke DrawKeycap3D, kx, 192, OFFSET textDiceKey2, eax + add kx, eax + + invoke DrawKeycap3D, kx, 192, OFFSET textDiceKeySpace, 1 + add kx, eax + + invoke DrawKeycap3D, kx, 192, OFFSET textKeyEsc, 0 + ret +RenderDiceGame ENDP + +; ============================================================================== +; IN-ENGINE 2.5D MINI-GAME: SKULLS & CUPS (НАПЁРСТКИ) +; ============================================================================== +DrawGlowingOrb PROC uses ebx esi edi, cxVal:DWORD, cyVal:DWORD + invoke DrawCircle, cxVal, cyVal, 14, 002E1E08h + invoke DrawCircle, cxVal, cyVal, 11, 00583A10h + invoke DrawCircle, cxVal, cyVal, 8, 008A581Ah + invoke DrawCircle, cxVal, cyVal, 6, 00D0B000h + invoke DrawCircle, cxVal, cyVal, 4, 00FFE000h + mov eax, cxVal + dec eax + mov edx, cyVal + dec edx + invoke DrawCircle, eax, edx, 2, 00FFFF80h + dec eax + dec edx + invoke DrawPixel, eax, edx, 00FFFFFFh + ret +DrawGlowingOrb ENDP + +DrawGothicCup PROC uses ebx esi edi, x:DWORD, y:DWORD, cupId:DWORD, isLifted:DWORD, hasBall:DWORD + local liftY:DWORD + + mov eax, y + cmp isLifted, 0 + je @F + sub eax, 36 +@@: + mov liftY, eax + + ; Drop shadow + cmp isLifted, 0 + jne cup_shadow_lifted + mov eax, x + add eax, 6 + mov edx, y + add edx, 42 + invoke DrawBox, eax, edx, 36, 4, 0010040Ah + jmp cup_ball_check +cup_shadow_lifted: + mov eax, x + add eax, 10 + mov edx, y + add edx, 42 + invoke DrawBox, eax, edx, 28, 2, 001A0612h + +cup_ball_check: + cmp isLifted, 0 + je cup_body_draw + cmp hasBall, 0 + je cup_body_draw + mov eax, x + add eax, 24 + mov edx, y + add edx, 26 + invoke DrawGlowingOrb, eax, edx + +cup_body_draw: + ; Base pedestal + mov eax, x + add eax, 6 + mov edx, liftY + add edx, 36 + invoke DrawBoxBorder, eax, edx, 36, 6, 00301A22h, 00D0B000h, 1 + + ; Stem + mov eax, x + add eax, 18 + mov edx, liftY + add edx, 28 + invoke DrawBox, eax, edx, 12, 8, 00452533h + mov eax, x + add eax, 22 + invoke DrawBox, eax, edx, 4, 8, 006E4055h + + ; Goblet Bowl + mov eax, x + add eax, 8 + mov edx, liftY + add edx, 8 + invoke DrawBoxBorder, eax, edx, 32, 20, 00401E2Dh, 00FFD700h, 1 + + mov eax, x + add eax, 14 + mov edx, liftY + add edx, 10 + invoke DrawBox, eax, edx, 6, 16, 00703550h + mov eax, x + add eax, 17 + invoke DrawBox, eax, edx, 3, 16, 00A05078h + + ; Golden Rim + mov eax, x + add eax, 4 + mov edx, liftY + add edx, 2 + invoke DrawBoxBorder, eax, edx, 40, 7, 00200A15h, 00FFFF00h, 1 + mov eax, x + add eax, 12 + mov edx, liftY + add edx, 4 + invoke DrawBox, eax, edx, 16, 2, 00FFFF00h + + ; Skull face emblem + mov eax, x + add eax, 21 + mov edx, liftY + add edx, 12 + invoke DrawBox, eax, edx, 6, 5, 00FFD700h + mov eax, x + add eax, 22 + mov edx, liftY + add edx, 17 + invoke DrawBox, eax, edx, 4, 3, 00FFD700h + mov eax, x + add eax, 22 + mov edx, liftY + add edx, 14 + invoke DrawPixel, eax, edx, 00200A15h + mov eax, x + add eax, 24 + invoke DrawPixel, eax, edx, 00200A15h + + ; Cup number label + mov eax, x + add eax, 21 + mov edx, liftY + add edx, 24 + mov ecx, cupId + add ecx, '1' + invoke DrawChar8x8, eax, edx, ecx, 00FFFF00h + ret +DrawGothicCup ENDP + +InitSkullsGame PROC + mov skulls3d_state, 0 + mov skulls3d_timer, 0 + mov skulls3d_win, 0 + mov skulls3d_choice, 1 + mov skulls3d_cup0, 0 + mov skulls3d_cup1, 1 + mov skulls3d_cup2, 2 + invoke RandomRange3D, 3 + mov skulls3d_ballPos, eax + ret +InitSkullsGame ENDP + +FinalizeSkullsGuess PROC uses ebx + cmp skulls3d_state,3 + jne skulls_guess_done + mov eax, skulls3d_choice + cmp eax, skulls3d_ballPos + jne skulls_guess_wrong + + ; Correct! 3x payout + mov eax, skulls3d_bet + imul eax, 3 + add bankroll, eax + mov skulls3d_win, eax + mov skulls3d_state, 4 + invoke PlayCasinoSound3D, OFFSET soundRoundWin, 0, 1 + invoke NpcRecordRound3D,9,1 + call SaveProgress3D + ret + +skulls_guess_wrong: + mov skulls3d_win, 0 + mov skulls3d_state, 4 + invoke PlayCasinoSound3D, OFFSET soundLose, 0, 1 + invoke NpcRecordRound3D,9,0 + call SaveProgress3D +skulls_guess_done: + ret +FinalizeSkullsGuess ENDP + +HandleSkullsInput PROC + cmp skulls3d_state, 0 + je skulls_handle_idle + cmp skulls3d_state, 1 + je skulls_handle_show + cmp skulls3d_state, 2 + je skulls_handle_shuffle + cmp skulls3d_state, 3 + je skulls_handle_pick + cmp skulls3d_state, 4 + je skulls_handle_reveal + ret + +skulls_handle_idle: + invoke Pressed3D, 26h ; UP + test eax, eax + jnz skulls_bet_up + invoke Pressed3D, 57h ; 'W' + test eax, eax + jnz skulls_bet_up + invoke Pressed3D, 28h ; DOWN + test eax, eax + jnz skulls_bet_down + invoke Pressed3D, 53h ; 'S' + test eax, eax + jnz skulls_bet_down + invoke Pressed3D, 20h ; SPACE + test eax, eax + jnz skulls_start_game + ret + +skulls_bet_up: + mov eax, skulls3d_bet + add eax, 50 + cmp eax, bankroll + jle @F + mov eax, bankroll +@@: + cmp eax, 5000 + jle @F + mov eax, 5000 +@@: + mov skulls3d_bet, eax + invoke PlayCasinoSound3D, OFFSET soundClick, 0, 1 + ret + +skulls_bet_down: + mov eax, skulls3d_bet + sub eax, 50 + cmp eax, 50 + jge @F + mov eax, 50 +@@: + mov skulls3d_bet, eax + invoke PlayCasinoSound3D, OFFSET soundClick, 0, 1 + ret + +skulls_start_game: + mov eax, skulls3d_bet + cmp eax, bankroll + jle @F + mov eax, bankroll + mov skulls3d_bet, eax + test eax, eax + jz skulls_input_done +@@: + mov eax, skulls3d_bet + sub bankroll, eax + invoke RandomRange3D, 3 + mov skulls3d_ballPos, eax + mov skulls3d_cup0, 0 + mov skulls3d_cup1, 1 + mov skulls3d_cup2, 2 + + ; Pre-generate 3 dynamic swap pairs + invoke RandomRange3D, 3 + mov skulls3d_swapPair0, eax + invoke RandomRange3D, 3 + mov skulls3d_swapPair1, eax + invoke RandomRange3D, 3 + mov skulls3d_swapPair2, eax + + mov skulls3d_state, 1 + mov skulls3d_timer, 0 + invoke PlayCasinoSound3D, OFFSET soundClick, 0, 1 + ret + +skulls_handle_show: + inc skulls3d_timer + cmp skulls3d_timer, 45 + jl skulls_input_done + ; Transition to Phase 2: Active Shuffle Animation + mov skulls3d_state, 2 + mov skulls3d_timer, 0 + invoke PlayCasinoSound3D, OFFSET soundShuffle, 0, 1 + ret + +skulls_handle_shuffle: + inc skulls3d_timer + cmp skulls3d_timer, 60 + jl skulls_input_done + ; Transition to Phase 3: Pick cup + mov skulls3d_state, 3 + mov skulls3d_timer, 0 + ret + +skulls_handle_pick: + invoke Pressed3D, 31h ; '1' + test eax, eax + jnz skulls_pick_1 + invoke Pressed3D, 32h ; '2' + test eax, eax + jnz skulls_pick_2 + invoke Pressed3D, 33h ; '3' + test eax, eax + jnz skulls_pick_3 + ret + +skulls_pick_1: + mov skulls3d_choice, 0 + call FinalizeSkullsGuess + ret + +skulls_pick_2: + mov skulls3d_choice, 1 + call FinalizeSkullsGuess + ret + +skulls_pick_3: + mov skulls3d_choice, 2 + call FinalizeSkullsGuess + ret + +skulls_handle_reveal: + invoke Pressed3D, 20h + test eax, eax + jz skulls_input_done + mov skulls3d_state, 0 + invoke PlayCasinoSound3D, OFFSET soundClick, 0, 1 +skulls_input_done: + ret +HandleSkullsInput ENDP + +RenderSkullsGame PROC uses ebx esi edi + local kx:DWORD + local passTick:DWORD, curPair:DWORD, swapSlotA:DWORD, swapSlotB:DWORD + local xA:DWORD, xB:DWORD, curXA:DWORD, curXB:DWORD, curYA:DWORD, curYB:DWORD + local distX:DWORD, dxVal:DWORD, archY:DWORD + + ; Mahogany & Gothic Purple table + invoke DrawBox, 0, 0, 320, 240, 00140906h + invoke DrawBoxBorder, 6, 6, 308, 228, 00300F22h, 00FFD700h, 2 + + ; Header + invoke DrawBoxBorder, 20, 12, 280, 26, 001A0812h, 00FFD700h, 2 + invoke DrawString8x8, 44, 21, OFFSET textSkullsTitle, 00FFFF00h + + ; Status + invoke DrawBoxBorder, 20, 44, 110, 18, 001A0812h, 00452033h, 1 + invoke DrawString8x8, 24, 49, OFFSET textBankPrompt, 003CFF3Ch + invoke FormatNumber, bankroll, OFFSET hudNumBuffer + invoke DrawString8x8, 72, 49, OFFSET hudNumBuffer, 003CFF3Ch + + invoke DrawBoxBorder, 190, 44, 110, 18, 001A0812h, 00452033h, 1 + invoke DrawString8x8, 194, 49, OFFSET textBetPrompt, 00FFD700h + invoke FormatNumber, skulls3d_bet, OFFSET hudNumBuffer + invoke DrawString8x8, 254, 49, OFFSET hudNumBuffer, 00FFD700h + + ; Phase Prompts + cmp skulls3d_state, 0 + jne @F + invoke DrawString8x8, 56, 62, OFFSET textSkullsPhase0, 00FFD700h + jmp skulls_draw_idle_cups +@@: + cmp skulls3d_state, 1 + jne @F + invoke DrawString8x8, 56, 62, OFFSET textSkullsPhase1, 00FFFF00h + jmp skulls_draw_phase1_cups +@@: + cmp skulls3d_state, 2 + jne @F + invoke DrawString8x8, 44, 62, OFFSET textSkullsPhase2, 00FFFF00h + jmp skulls_draw_animated_cups +@@: + cmp skulls3d_state, 3 + jne @F + invoke DrawString8x8, 28, 62, OFFSET textSkullsPhase3, 00FFFF00h + jmp skulls_draw_idle_cups +@@: + ; Phase 4: Reveal outcome + mov eax, skulls3d_win + test eax, eax + jz skulls_reveal_loss_text + invoke DrawString8x8, 40, 62, OFFSET textSkullsWin, 003CFF3Ch + invoke FormatNumber, skulls3d_win, OFFSET hudNumBuffer + invoke DrawString8x8, 136, 62, OFFSET hudNumBuffer, 003CFF3Ch + invoke DrawString8x8, 168, 62, OFFSET textSkullsWinMult, 003CFF3Ch + jmp skulls_draw_reveal_cups + +skulls_reveal_loss_text: + invoke DrawString8x8, 40, 62, OFFSET textSkullsLose, 00FF6464h + jmp skulls_draw_reveal_cups + +skulls_draw_idle_cups: + ; Draw resting cups at static slots: Slot 0 (X=36), Slot 1 (X=136), Slot 2 (X=236) + invoke DrawGothicCup, 36, 114, skulls3d_cup0, 0, 0 + invoke DrawGothicCup, 136, 114, skulls3d_cup1, 0, 0 + invoke DrawGothicCup, 236, 114, skulls3d_cup2, 0, 0 + jmp skulls_render_controls + +skulls_draw_phase1_cups: + ; Draw with golden ball showing under starting cup + mov ebx, 0 + mov edx, 0 + cmp skulls3d_ballPos, 0 + jne @F + mov ebx, 1 + mov edx, 1 +@@: + invoke DrawGothicCup, 36, 114, skulls3d_cup0, ebx, edx + + mov ebx, 0 + mov edx, 0 + cmp skulls3d_ballPos, 1 + jne @F + mov ebx, 1 + mov edx, 1 +@@: + invoke DrawGothicCup, 136, 114, skulls3d_cup1, ebx, edx + + mov ebx, 0 + mov edx, 0 + cmp skulls3d_ballPos, 2 + jne @F + mov ebx, 1 + mov edx, 1 +@@: + invoke DrawGothicCup, 236, 114, skulls3d_cup2, ebx, edx + jmp skulls_render_controls + +skulls_draw_animated_cups: + ; 60 frames = 3 passes of 20 frames + mov eax, skulls3d_timer + cmp eax, 20 + jbe pass_0 + cmp eax, 40 + jbe pass_1 + sub eax, 41 + mov passTick, eax + mov eax, skulls3d_swapPair2 + mov curPair, eax + jmp setup_pass + +pass_0: + dec eax + mov passTick, eax + mov eax, skulls3d_swapPair0 + mov curPair, eax + jmp setup_pass + +pass_1: + sub eax, 21 + mov passTick, eax + mov eax, skulls3d_swapPair1 + mov curPair, eax + +setup_pass: + ; curPair determines swap pair: + ; 0: swap slot 0 (X=36) and slot 1 (X=136) + ; 1: swap slot 1 (X=136) and slot 2 (X=236) + ; 2: swap slot 0 (X=36) and slot 2 (X=236) + cmp curPair, 1 + je pair_1 + cmp curPair, 2 + je pair_2 + mov swapSlotA, 0 + mov swapSlotB, 1 + mov xA, 36 + mov xB, 136 + jmp calc_coords +pair_1: + mov swapSlotA, 1 + mov swapSlotB, 2 + mov xA, 136 + mov xB, 236 + jmp calc_coords +pair_2: + mov swapSlotA, 0 + mov swapSlotB, 2 + mov xA, 36 + mov xB, 236 + +calc_coords: + ; distX = xB - xA + mov eax, xB + sub eax, xA + mov distX, eax + + ; dxVal = (distX * passTick) / 20 + mov eax, distX + imul eax, passTick + xor edx, edx + mov ecx, 20 + div ecx + mov dxVal, eax + + ; curXA = xA + dxVal + mov eax, xA + add eax, dxVal + mov curXA, eax + + ; curXB = xB - dxVal + mov eax, xB + sub eax, dxVal + mov curXB, eax + + ; archY = (passTick * (20 - passTick)) / 10 + mov eax, passTick + mov ecx, 20 + sub ecx, eax + imul eax, ecx + xor edx, edx + mov ecx, 10 + div ecx + mov archY, eax + + ; Cup A hops UP: 114 - archY + mov eax, 114 + sub eax, archY + mov curYA, eax + + ; Cup B hops DOWN: 114 + archY + mov eax, 114 + add eax, archY + mov curYB, eax + + ; Check if pass ended (frame 19): swap ball position and cups + cmp passTick, 19 + jne draw_active_shuffle + + ; Swap ball position if involved + mov eax, skulls3d_ballPos + cmp eax, swapSlotA + jne check_ball_b + mov edx, swapSlotB + mov skulls3d_ballPos, edx + jmp swap_slot_identities +check_ball_b: + cmp eax, swapSlotB + jne swap_slot_identities + mov edx, swapSlotA + mov skulls3d_ballPos, edx + +swap_slot_identities: + cmp curPair, 1 + je swap_ids_1_2 + cmp curPair, 2 + je swap_ids_0_2 + ; swap 0 and 1 + mov eax, skulls3d_cup0 + xchg eax, skulls3d_cup1 + mov skulls3d_cup0, eax + jmp swap_sound_tick +swap_ids_1_2: + mov eax, skulls3d_cup1 + xchg eax, skulls3d_cup2 + mov skulls3d_cup1, eax + jmp swap_sound_tick +swap_ids_0_2: + mov eax, skulls3d_cup0 + xchg eax, skulls3d_cup2 + mov skulls3d_cup0, eax + +swap_sound_tick: + invoke PlayCasinoSound3D, OFFSET soundShuffle, 0, 1 + +draw_active_shuffle: + ; Draw stationary cup + cmp curPair, 1 + je draw_stat_cup0 + cmp curPair, 2 + je draw_stat_cup1 + ; Stationary cup is slot 2 (X=236) + invoke DrawGothicCup, 236, 114, skulls3d_cup2, 0, 0 + jmp draw_moving_cups +draw_stat_cup0: + ; Stationary cup is slot 0 (X=36) + invoke DrawGothicCup, 36, 114, skulls3d_cup0, 0, 0 + jmp draw_moving_cups +draw_stat_cup1: + ; Stationary cup is slot 1 (X=136) + invoke DrawGothicCup, 136, 114, skulls3d_cup1, 0, 0 + +draw_moving_cups: + ; Moving Cup A and Moving Cup B + cmp curPair, 1 + je ids_pair_1 + cmp curPair, 2 + je ids_pair_2 + mov eax, skulls3d_cup0 + mov ebx, skulls3d_cup1 + jmp draw_the_pair +ids_pair_1: + mov eax, skulls3d_cup1 + mov ebx, skulls3d_cup2 + jmp draw_the_pair +ids_pair_2: + mov eax, skulls3d_cup0 + mov ebx, skulls3d_cup2 + +draw_the_pair: + push ebx + invoke DrawGothicCup, curXA, curYA, eax, 0, 0 + pop ebx + invoke DrawGothicCup, curXB, curYB, ebx, 0, 0 + jmp skulls_render_controls + +skulls_draw_reveal_cups: + ; Reveal Phase: lift chosen cup and lift actual ball cup if different + ; Slot 0 + mov ebx, 0 + mov edx, 0 + cmp skulls3d_choice, 0 + je slot0_is_lifted + cmp skulls3d_ballPos, 0 + jne @F +slot0_is_lifted: + mov ebx, 1 + cmp skulls3d_ballPos, 0 + sete dl +@@: + invoke DrawGothicCup, 36, 114, skulls3d_cup0, ebx, edx + + ; Slot 1 + mov ebx, 0 + mov edx, 0 + cmp skulls3d_choice, 1 + je slot1_is_lifted + cmp skulls3d_ballPos, 1 + jne @F +slot1_is_lifted: + mov ebx, 1 + cmp skulls3d_ballPos, 1 + sete dl +@@: + invoke DrawGothicCup, 136, 114, skulls3d_cup1, ebx, edx + + ; Slot 2 + mov ebx, 0 + mov edx, 0 + cmp skulls3d_choice, 2 + je slot2_is_lifted + cmp skulls3d_ballPos, 2 + jne @F +slot2_is_lifted: + mov ebx, 1 + cmp skulls3d_ballPos, 2 + sete dl +@@: + invoke DrawGothicCup, 236, 114, skulls3d_cup2, ebx, edx + +skulls_render_controls: + ; Cup selection slot labels [1], [2], [3] + invoke DrawString8x8, 54, 168, OFFSET textSkullsKey1, 00D0D8E0h + invoke DrawString8x8, 150, 168, OFFSET textSkullsKey2, 00D0D8E0h + invoke DrawString8x8, 250, 168, OFFSET textSkullsKey3, 00D0D8E0h + + ; Keycaps + mov kx, 16 + xor eax, eax + cmp skulls3d_state, 3 + je key1_active + cmp skulls3d_choice, 0 + sete al + jmp draw_key1 +key1_active: + mov eax, 1 +draw_key1: + invoke DrawKeycap3D, kx, 192, OFFSET textSkullsKey1, eax + add kx, eax + + xor eax, eax + cmp skulls3d_state, 3 + je key2_active + cmp skulls3d_choice, 1 + sete al + jmp draw_key2 +key2_active: + mov eax, 1 +draw_key2: + invoke DrawKeycap3D, kx, 192, OFFSET textSkullsKey2, eax + add kx, eax + + xor eax, eax + cmp skulls3d_state, 3 + je key3_active + cmp skulls3d_choice, 2 + sete al + jmp draw_key3 +key3_active: + mov eax, 1 +draw_key3: + invoke DrawKeycap3D, kx, 192, OFFSET textSkullsKey3, eax + add kx, eax + + xor eax, eax + cmp skulls3d_state, 0 + je start_active + cmp skulls3d_state, 4 + je start_active + jmp draw_start_key +start_active: + mov eax, 1 +draw_start_key: + invoke DrawKeycap3D, kx, 192, OFFSET textSkullsKeySpace, eax + add kx, eax + + invoke DrawKeycap3D, kx, 192, OFFSET textKeyEsc, 0 + ret +RenderSkullsGame ENDP + +InitSkillGame PROC + mov skill3d_state, 0 + mov skill3d_timer, 0 + mov skill3d_hits, 0 + mov skill3d_misses, 0 + mov skill3d_needle, 55 + mov skill3d_speed, 4 + mov skill3d_dir, 1 + mov skill3d_last_result, 0 + mov skill3d_win_amount, 0 + + ; Randomize initial zone: 80 + RandomRange(90) -> 80..170 + invoke RandomRange3D, 90 + add eax, 80 + mov skill3d_zone_start, eax + + ; Great zone: start + 20 + RandomRange(12) + invoke RandomRange3D, 12 + add eax, skill3d_zone_start + add eax, 20 + mov skill3d_great_start, eax + ret +InitSkillGame ENDP + +HandleSkillInput PROC uses ebx esi + mov eax, skill3d_state + cmp eax, 0 + je skill_handle_ready + cmp eax, 1 + je skill_handle_active + cmp eax, 2 + je skill_handle_round_wait + cmp eax, 3 + je skill_handle_round_wait + cmp eax, 4 + je skill_handle_end_wait + cmp eax, 5 + je skill_handle_end_wait + ret + +skill_handle_ready: + invoke Pressed3D, 26h ; UP + test eax, eax + jnz skill_bet_up + invoke Pressed3D, 57h ; 'W' + test eax, eax + jnz skill_bet_up + invoke Pressed3D, 28h ; DOWN + test eax, eax + jnz skill_bet_down + invoke Pressed3D, 53h ; 'S' + test eax, eax + jnz skill_bet_down + jmp skill_check_start + +skill_bet_up: + mov eax, skill3d_bet + add eax, 50 + cmp eax, bankroll + jle @F + mov eax, bankroll +@@: + cmp eax, 5000 + jle @F + mov eax, 5000 +@@: + mov skill3d_bet, eax + invoke PlayCasinoSound3D, OFFSET soundClick, 0, 1 + ret + +skill_bet_down: + mov eax, skill3d_bet + sub eax, 50 + cmp eax, 50 + jge @F + mov eax, 50 +@@: + mov skill3d_bet, eax + invoke PlayCasinoSound3D, OFFSET soundClick, 0, 1 + ret + +skill_check_start: + invoke Pressed3D, 20h ; SPACE + test eax, eax + jz skill_input_done + + ; Deduct bet on game start if beginning of run + mov eax, skill3d_hits + or eax, skill3d_misses + jnz @F + mov eax, skill3d_bet + cmp eax, bankroll + jle skill_has_funds + mov eax, bankroll + mov skill3d_bet, eax + test eax, eax + jz skill_input_done +skill_has_funds: + mov eax, skill3d_bet + sub bankroll, eax +@@: + mov skill3d_state, 1 + mov skill3d_needle, 55 + mov skill3d_dir, 1 + invoke PlayCasinoSound3D, OFFSET soundClick, 0, 1 + ret + +skill_handle_active: + ; Move needle smoothly + mov eax, skill3d_needle + mov edx, skill3d_speed + cmp skill3d_dir, 1 + je skill_move_right + sub eax, edx + cmp eax, 52 + jge skill_update_needle + mov eax, 52 + mov skill3d_dir, 1 + jmp skill_update_needle +skill_move_right: + add eax, edx + cmp eax, 268 + jle skill_update_needle + mov eax, 268 + mov skill3d_dir, -1 +skill_update_needle: + mov skill3d_needle, eax + + ; Check SPACE pressed (Reaction Hit Attempt!) + invoke Pressed3D, 20h + test eax, eax + jz skill_input_done + + ; Is needle in Great Sweet Spot? + mov eax, skill3d_needle + mov edx, skill3d_great_start + cmp eax, edx + jl check_success_zone + add edx, skill3d_great_width + cmp eax, edx + jg check_success_zone + + ; GREAT HIT! + mov skill3d_last_result, 2 + add skill3d_hits, 2 + mov skill3d_state, 2 + mov skill3d_timer, 40 + invoke PlayCasinoSound3D, OFFSET soundSkillPerfect, 0, 1 + jmp skill_check_finish_round + +check_success_zone: + mov eax, skill3d_needle + mov edx, skill3d_zone_start + cmp eax, edx + jl skill_was_miss + add edx, skill3d_zone_width + cmp eax, edx + jg skill_was_miss + + ; NORMAL HIT! + mov skill3d_last_result, 1 + inc skill3d_hits + mov skill3d_state, 2 + mov skill3d_timer, 40 + invoke PlayCasinoSound3D, OFFSET soundSkillHit, 0, 1 + jmp skill_check_finish_round + +skill_was_miss: + ; MISS! + mov skill3d_last_result, 0 + inc skill3d_misses + mov skill3d_state, 3 + mov skill3d_timer, 45 + invoke PlayCasinoSound3D, OFFSET soundSkillMiss, 0, 1 + +skill_check_finish_round: + cmp skill3d_hits, 5 + jge skill_game_escaped + cmp skill3d_misses, 3 + jge skill_game_lost + ret + +skill_game_escaped: + mov skill3d_state, 4 + mov skill3d_timer, 0 + ; Payout: 3x total return (+$2x bet profit) + mov eax, skill3d_bet + imul eax, 3 + add bankroll, eax + mov eax, skill3d_bet + shl eax, 1 + mov skill3d_win_amount, eax + invoke NpcRecordRound3D,10,1 + call SaveProgress3D + invoke PlayCasinoSound3D, OFFSET soundRoundWin, 0, 1 + ret + +skill_game_lost: + mov skill3d_state, 5 + mov skill3d_timer, 0 + invoke NpcRecordRound3D,10,0 + call SaveProgress3D + invoke PlayCasinoSound3D, OFFSET soundLose, 0, 1 + ret + +skill_handle_round_wait: + dec skill3d_timer + cmp skill3d_timer, 0 + jg skill_input_done + + ; Next round setup + invoke RandomRange3D, 90 + add eax, 80 + mov skill3d_zone_start, eax + + invoke RandomRange3D, 12 + add eax, skill3d_zone_start + add eax, 20 + mov skill3d_great_start, eax + + mov eax, skill3d_hits + shr eax, 1 + add eax, 4 + mov skill3d_speed, eax + mov skill3d_state, 1 + ret + +skill_handle_end_wait: + invoke Pressed3D, 20h + test eax, eax + jz skill_input_done + call InitSkillGame + ret + +skill_input_done: + ret +HandleSkillInput ENDP + +RenderSkillGame PROC uses ebx esi edi + local kx:DWORD + local tx:DWORD + + ; Industrial Steel bezel + invoke DrawBox, 0, 0, 320, 240, 00121416h + invoke DrawBoxBorder, 6, 6, 308, 228, 001A1D20h, 00FFD700h, 2 + + ; Header + invoke DrawBoxBorder, 20, 12, 280, 26, 00121418h, 00FFD700h, 2 + invoke DrawString8x8, 40, 21, OFFSET textSkillTitle, 00FFFF00h + + ; Status + invoke DrawBoxBorder, 20, 44, 110, 18, 00121418h, 002A3540h, 1 + invoke DrawString8x8, 24, 49, OFFSET textBankPrompt, 003CFF3Ch + invoke FormatNumber, bankroll, OFFSET hudNumBuffer + invoke DrawString8x8, 72, 49, OFFSET hudNumBuffer, 003CFF3Ch + + invoke DrawBoxBorder, 190, 44, 110, 18, 00121418h, 002A3540h, 1 + invoke DrawString8x8, 194, 49, OFFSET textBetPrompt, 00FFD700h + invoke FormatNumber, skill3d_bet, OFFSET hudNumBuffer + invoke DrawString8x8, 254, 49, OFFSET hudNumBuffer, 00FFD700h + + ; Survivor Progress + invoke DrawString8x8, 24, 70, OFFSET textSkillHitsHdr, 003CFF3Ch + invoke FormatNumber, skill3d_hits, OFFSET hudNumBuffer + invoke DrawString8x8, 64, 70, OFFSET hudNumBuffer, 003CFF3Ch + + invoke DrawString8x8, 180, 70, OFFSET textSkillMissHdr, 00FF6464h + invoke FormatNumber, skill3d_misses, OFFSET hudNumBuffer + invoke DrawString8x8, 240, 70, OFFSET hudNumBuffer, 00FF6464h + + ; Dial Frame (Track: X=50..270, Y=102..134) + invoke DrawBoxBorder, 50, 102, 220, 32, 000F1114h, 00404855h, 2 + + ; Calibrated ticks + mov tx, 60 +skill_ticks_loop: + cmp tx, 260 + jge skill_draw_zones + invoke DrawBox, tx, 104, 1, 6, 00303845h + invoke DrawBox, tx, 126, 1, 6, 00303845h + add tx, 12 + jmp skill_ticks_loop + +skill_draw_zones: + ; Normal Success Zone (Green) + invoke DrawBoxBorder, skill3d_zone_start, 106, skill3d_zone_width, 24, 00155020h, 003CFF3Ch, 1 + + ; Great Zone (Gold) + invoke DrawBoxBorder, skill3d_great_start, 106, skill3d_great_width, 24, 00FFD700h, 00FFFF00h, 1 + + ; Pointer / Needle at skill3d_needle + mov eax, skill3d_needle + dec eax + invoke DrawBox, eax, 98, 3, 40, 00FFFFFFh + mov eax, skill3d_needle + sub eax, 2 + invoke DrawBox, eax, 96, 5, 2, 00FF3030h + invoke DrawBox, eax, 138, 5, 2, 00FF3030h + + ; Center prompts / outcome + cmp skill3d_state, 0 + jne @F + invoke DrawString8x8, 52, 150, OFFSET textSkillReadyMsg, 00FFD700h + invoke DrawString8x8, 76, 166, OFFSET textSkillPrompt, 00D0D8E0h + jmp skill_render_keys +@@: + cmp skill3d_state, 1 + jne @F + invoke DrawString8x8, 76, 150, OFFSET textSkillPrompt, 00FFFF00h + jmp skill_render_keys +@@: + cmp skill3d_state, 2 + jne @F + cmp skill3d_last_result, 2 + jne skill_normal_hit_text + invoke DrawString8x8, 36, 150, OFFSET textSkillGreatMsg, 00FFFF00h + jmp skill_render_keys +skill_normal_hit_text: + invoke DrawString8x8, 64, 150, OFFSET textSkillHitMsg, 003CFF3Ch + jmp skill_render_keys +@@: + cmp skill3d_state, 3 + jne @F + invoke DrawString8x8, 88, 150, OFFSET textSkillMissMsg, 00FF6464h + jmp skill_render_keys +@@: + cmp skill3d_state, 4 + jne @F + invoke DrawString8x8, 48, 150, OFFSET textSkillEscape, 003CFF3Ch + invoke FormatNumber, skill3d_win_amount, OFFSET hudNumBuffer + invoke DrawString8x8, 240, 150, OFFSET hudNumBuffer, 003CFF3Ch + invoke DrawString8x8, 64, 166, OFFSET textSkullsAgain, 00FFD700h + jmp skill_render_keys +@@: + invoke DrawString8x8, 44, 150, OFFSET textSkillLost, 00FF6464h + invoke DrawString8x8, 64, 166, OFFSET textSkullsAgain, 00FFD700h + +skill_render_keys: + mov kx, 16 + invoke DrawKeycap3D, kx, 192, OFFSET textSkillKeySpace, 1 + add kx, eax + + invoke DrawKeycap3D, kx, 192, OFFSET textSkillKeyBet, 0 + add kx, eax + + invoke DrawKeycap3D, kx, 192, OFFSET textKeyEsc, 0 + ret +RenderSkillGame ENDP + +HandlePlayerInput PROC uses ebx esi edi + local speed:DWORD + local nextX:DWORD + local nextY:DWORD + mov eax, deltaTime3D + imul eax, 200 + mov speed, eax + cmp keys3D[10h], 0 + je @F + shl speed, 1 +@@: + mov eax, deltaTime3D + shr eax, 2 + inc eax + cmp keys3D[41h], 0 + jne input_turn_left + cmp keys3D[25h], 0 + je input_right +input_turn_left: + sub playerAngle, eax +input_right: + cmp keys3D[44h], 0 + jne input_turn_right + cmp keys3D[27h], 0 + je input_forward +input_turn_right: + add playerAngle, eax +input_forward: + and playerAngle, 511 + call UpdateCamera3D + xor edi, edi + cmp keys3D[57h], 0 + jne input_go_forward + cmp keys3D[26h], 0 + je input_back +input_go_forward: + inc edi +input_back: + cmp keys3D[53h], 0 + jne input_go_back + cmp keys3D[28h], 0 + je input_move +input_go_back: + dec edi +input_move: + test edi, edi + jz input_action + imul edi, speed + mov eax, playerDirX + imul edi + shrd eax, edx, 16 + add eax, playerX + mov nextX, eax + mov eax, playerDirY + imul edi + shrd eax, edx, 16 + add eax, playerY + mov nextY, eax + invoke CanWalk3D, nextX, playerY + test eax, eax + jz @F + mov eax, nextX + mov playerX, eax +@@: + invoke CanWalk3D, playerX, nextY + test eax, eax + jz input_action + mov eax, nextY + mov playerY, eax +input_action: + invoke Pressed3D, 45h + test eax, eax + jz @F + call Trigger3DInteraction +@@: + ret +HandlePlayerInput ENDP + +CheckInteractions PROC uses ebx esi edi + local nearest:DWORD + mov nearest, 262144 + mov interactTargetId, 0 + mov interactPromptPtr, 0 + xor esi, esi +interaction_scan: + cmp esi, NUM_SPRITES + jge interaction_done + imul edi, esi, SIZEOF SpriteObject + cmp [casinoSprites+edi].interactId, 0 + je interaction_next + mov eax, [casinoSprites+edi].posX + sub eax, playerX + sar eax, 8 + mov ebx, eax + imul eax, eax + mov ecx, eax + mov eax, [casinoSprites+edi].posY + sub eax, playerY + sar eax, 8 + mov edx, eax + imul eax, eax + add ecx, eax + cmp ecx, nearest + jae interaction_next + ; Only target objects in front of the camera. + mov eax, playerDirX + sar eax, 8 + imul eax, ebx + mov ebx, playerDirY + sar ebx, 8 + imul ebx, edx + add eax, ebx + cmp eax, 18000 + jl interaction_next + mov nearest, ecx + mov eax, [casinoSprites+edi].interactId + mov interactTargetId, eax + mov eax, [casinoSprites+edi].promptPtr + mov interactPromptPtr, eax +interaction_next: + inc esi + jmp interaction_scan +interaction_done: + call CheckHallInteractions3D + ret +CheckInteractions ENDP + +; (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 BeginUnavailable3D + ret + +check_target_shop: + cmp eax, INTERACT_SHOP + jne check_target_atm + call BeginMerchant3D + ret + +check_target_atm: + cmp eax, INTERACT_ATM + jne check_target_terminal + mov engineMode, MODE_ATM + ret + +check_target_terminal: + cmp eax, INTERACT_TERMINAL + jne check_target_observer + call BeginUnavailable3D + ret + +check_target_observer: + cmp eax, INTERACT_OBSERVER + jne target_unported + call BeginUnavailable3D + ret + +target_unported: + call BeginUnavailable3D +trigger_done: + ret +Trigger3DInteraction ENDP + +; --- Engine Initialization --- +Init3DEngine PROC + local screenCX:DWORD + local screenCY:DWORD + local posX:DWORD + local posY:DWORD + local bytesRead:DWORD + + push ebx + push esi + push edi + + call LoadDisplaySettings3D + call Create3DWindow + test eax, eax + jz init_failed + call LoadTextures3D + test eax, eax + jz init_failed + + call InitializeCasinoSprites3D + + ; Initialize raycasting worker thread and sync events + invoke CreateEventA, 0, 0, 0, 0 + mov hRaycastStartEvent, eax + invoke CreateEventA, 0, 0, 0, 0 + mov hRaycastDoneEvent, eax + mov bRaycastQuit, 0 + invoke CreateThread, 0, 65536, OFFSET RaycastWorkerProc, 0, 0, ADDR raycastThreadId + mov hRaycastThread, eax + + call InitHall3D + call BeginStartup3D + call RenderStartup3D + invoke ShowWindow, h3DWnd, SW_SHOW + invoke UpdateWindow, h3DWnd + invoke SetForegroundWindow, h3DWnd + mov eax, 1 + jmp init_return +init_failed: + xor eax, eax +init_return: + pop edi + pop esi + pop ebx + ret +Init3DEngine ENDP + +InitializeCasinoSprites3D PROC +init_sprites_table: + ; Sprite 0: VIP Dancer 1 (Stage Left) + mov casinoSprites[0*SIZEOF SpriteObject].posX, (13 * FP_1 + FP_HALF) + mov casinoSprites[0*SIZEOF SpriteObject].posY, (4 * FP_1) + mov casinoSprites[0*SIZEOF SpriteObject].baseTexId, 10 + mov casinoSprites[0*SIZEOF SpriteObject].frameCount, 12 + mov casinoSprites[0*SIZEOF SpriteObject].curFrame, 0 + mov casinoSprites[0*SIZEOF SpriteObject].animTimer, 0 + mov casinoSprites[0*SIZEOF SpriteObject].animSpeed, 5 + mov casinoSprites[0*SIZEOF SpriteObject].interactId, INTERACT_DANCER + mov casinoSprites[0*SIZEOF SpriteObject].promptPtr, OFFSET promptDancer + + ; Sprite 1: VIP Dancer 2 (Center Stage Star) + mov casinoSprites[1*SIZEOF SpriteObject].posX, (16 * FP_1 + FP_HALF) + mov casinoSprites[1*SIZEOF SpriteObject].posY, (3 * FP_1 + FP_HALF) + mov casinoSprites[1*SIZEOF SpriteObject].baseTexId, 10 + mov casinoSprites[1*SIZEOF SpriteObject].frameCount, 12 + mov casinoSprites[1*SIZEOF SpriteObject].curFrame, 2 + mov casinoSprites[1*SIZEOF SpriteObject].animTimer, 0 + mov casinoSprites[1*SIZEOF SpriteObject].animSpeed, 5 + mov casinoSprites[1*SIZEOF SpriteObject].interactId, INTERACT_DANCER + mov casinoSprites[1*SIZEOF SpriteObject].promptPtr, OFFSET promptDancer + + ; Sprite 2: VIP Dancer 3 (Stage Right) + mov casinoSprites[2*SIZEOF SpriteObject].posX, (19 * FP_1 + FP_HALF) + mov casinoSprites[2*SIZEOF SpriteObject].posY, (4 * FP_1) + mov casinoSprites[2*SIZEOF SpriteObject].baseTexId, 10 + mov casinoSprites[2*SIZEOF SpriteObject].frameCount, 12 + mov casinoSprites[2*SIZEOF SpriteObject].curFrame, 1 + mov casinoSprites[2*SIZEOF SpriteObject].animTimer, 0 + mov casinoSprites[2*SIZEOF SpriteObject].animSpeed, 5 + mov casinoSprites[2*SIZEOF SpriteObject].interactId, INTERACT_DANCER + mov casinoSprites[2*SIZEOF SpriteObject].promptPtr, OFFSET promptDancer + + ; Sprite 3: VIP Blackjack (Front Center Left) + mov casinoSprites[3*SIZEOF SpriteObject].posX, (12 * FP_1 + FP_HALF) + mov casinoSprites[3*SIZEOF SpriteObject].posY, (8 * FP_1) + mov casinoSprites[3*SIZEOF SpriteObject].baseTexId, 30 + mov casinoSprites[3*SIZEOF SpriteObject].frameCount, 1 + mov casinoSprites[3*SIZEOF SpriteObject].curFrame, 0 + mov casinoSprites[3*SIZEOF SpriteObject].animTimer, 0 + mov casinoSprites[3*SIZEOF SpriteObject].animSpeed, 1 + mov casinoSprites[3*SIZEOF SpriteObject].interactId, INTERACT_BLACKJACK + mov casinoSprites[3*SIZEOF SpriteObject].promptPtr, OFFSET promptBlackjack + + ; Sprite 4: European Roulette Table (Front Center) + mov casinoSprites[4*SIZEOF SpriteObject].posX, (16 * FP_1 + FP_HALF) + mov casinoSprites[4*SIZEOF SpriteObject].posY, (10 * FP_1) + mov casinoSprites[4*SIZEOF SpriteObject].baseTexId, 31 + mov casinoSprites[4*SIZEOF SpriteObject].frameCount, 1 + mov casinoSprites[4*SIZEOF SpriteObject].curFrame, 0 + mov casinoSprites[4*SIZEOF SpriteObject].animTimer, 0 + mov casinoSprites[4*SIZEOF SpriteObject].animSpeed, 1 + mov casinoSprites[4*SIZEOF SpriteObject].interactId, INTERACT_ROULETTE + mov casinoSprites[4*SIZEOF SpriteObject].promptPtr, OFFSET promptCasinoRoulette + + ; Sprite 5: Texas Hold'em Poker Table (Front Center Right) + mov casinoSprites[5*SIZEOF SpriteObject].posX, (20 * FP_1 + FP_HALF) + mov casinoSprites[5*SIZEOF SpriteObject].posY, (8 * FP_1) + mov casinoSprites[5*SIZEOF SpriteObject].baseTexId, 30 + mov casinoSprites[5*SIZEOF SpriteObject].frameCount, 1 + mov casinoSprites[5*SIZEOF SpriteObject].curFrame, 0 + mov casinoSprites[5*SIZEOF SpriteObject].animTimer, 0 + mov casinoSprites[5*SIZEOF SpriteObject].animSpeed, 1 + mov casinoSprites[5*SIZEOF SpriteObject].interactId, INTERACT_POKER + mov casinoSprites[5*SIZEOF SpriteObject].promptPtr, OFFSET promptPoker + + ; Sprite 6: Podkidnoy Durak Card Table + mov casinoSprites[6*SIZEOF SpriteObject].posX, (24 * FP_1 + FP_HALF) + mov casinoSprites[6*SIZEOF SpriteObject].posY, (8 * FP_1) + mov casinoSprites[6*SIZEOF SpriteObject].baseTexId, 30 + mov casinoSprites[6*SIZEOF SpriteObject].frameCount, 1 + mov casinoSprites[6*SIZEOF SpriteObject].curFrame, 0 + mov casinoSprites[6*SIZEOF SpriteObject].animTimer, 0 + mov casinoSprites[6*SIZEOF SpriteObject].animSpeed, 1 + mov casinoSprites[6*SIZEOF SpriteObject].interactId, INTERACT_DURAK + mov casinoSprites[6*SIZEOF SpriteObject].promptPtr, OFFSET promptDurak + + ; Sprite 7: Classic Slots 777 (West Arcade 1) + mov casinoSprites[7*SIZEOF SpriteObject].posX, (6 * FP_1) + mov casinoSprites[7*SIZEOF SpriteObject].posY, (8 * FP_1) + mov casinoSprites[7*SIZEOF SpriteObject].baseTexId, 24 + mov casinoSprites[7*SIZEOF SpriteObject].frameCount, 3 + mov casinoSprites[7*SIZEOF SpriteObject].curFrame, 0 + mov casinoSprites[7*SIZEOF SpriteObject].animTimer, 0 + mov casinoSprites[7*SIZEOF SpriteObject].animSpeed, 8 + mov casinoSprites[7*SIZEOF SpriteObject].interactId, INTERACT_SLOTS_777 + mov casinoSprites[7*SIZEOF SpriteObject].promptPtr, OFFSET promptClassicSlot + + ; Sprite 8: CloverPit Slots 5x3 (West Arcade 2) + mov casinoSprites[8*SIZEOF SpriteObject].posX, (6 * FP_1) + mov casinoSprites[8*SIZEOF SpriteObject].posY, (11 * FP_1) + mov casinoSprites[8*SIZEOF SpriteObject].baseTexId, 24 + mov casinoSprites[8*SIZEOF SpriteObject].frameCount, 3 + mov casinoSprites[8*SIZEOF SpriteObject].curFrame, 1 + mov casinoSprites[8*SIZEOF SpriteObject].animTimer, 0 + mov casinoSprites[8*SIZEOF SpriteObject].animSpeed, 8 + mov casinoSprites[8*SIZEOF SpriteObject].interactId, INTERACT_SLOTS_CLOVER + mov casinoSprites[8*SIZEOF SpriteObject].promptPtr, OFFSET promptCloverSlot + + ; Sprite 9: Craps & Dice Table (West Arcade 3) + mov casinoSprites[9*SIZEOF SpriteObject].posX, (6 * FP_1) + mov casinoSprites[9*SIZEOF SpriteObject].posY, (14 * FP_1) + mov casinoSprites[9*SIZEOF SpriteObject].baseTexId, 30 + mov casinoSprites[9*SIZEOF SpriteObject].frameCount, 1 + mov casinoSprites[9*SIZEOF SpriteObject].curFrame, 0 + mov casinoSprites[9*SIZEOF SpriteObject].animTimer, 0 + mov casinoSprites[9*SIZEOF SpriteObject].animSpeed, 1 + mov casinoSprites[9*SIZEOF SpriteObject].interactId, INTERACT_DICE + mov casinoSprites[9*SIZEOF SpriteObject].promptPtr, OFFSET promptDice + + ; Sprite 10: Skulls & Cups Table + mov casinoSprites[10*SIZEOF SpriteObject].posX, (10 * FP_1) + mov casinoSprites[10*SIZEOF SpriteObject].posY, (15 * FP_1) + mov casinoSprites[10*SIZEOF SpriteObject].baseTexId, 30 + mov casinoSprites[10*SIZEOF SpriteObject].frameCount, 1 + mov casinoSprites[10*SIZEOF SpriteObject].curFrame, 0 + mov casinoSprites[10*SIZEOF SpriteObject].animTimer, 0 + mov casinoSprites[10*SIZEOF SpriteObject].animSpeed, 1 + mov casinoSprites[10*SIZEOF SpriteObject].interactId, INTERACT_SKULLS + mov casinoSprites[10*SIZEOF SpriteObject].promptPtr, OFFSET promptSkulls + + ; Sprite 11: Coin Toss Stand + mov casinoSprites[11*SIZEOF SpriteObject].posX, (14 * FP_1) + mov casinoSprites[11*SIZEOF SpriteObject].posY, (15 * FP_1) + mov casinoSprites[11*SIZEOF SpriteObject].baseTexId, 30 + mov casinoSprites[11*SIZEOF SpriteObject].frameCount, 1 + mov casinoSprites[11*SIZEOF SpriteObject].curFrame, 0 + mov casinoSprites[11*SIZEOF SpriteObject].animTimer, 0 + mov casinoSprites[11*SIZEOF SpriteObject].animSpeed, 1 + mov casinoSprites[11*SIZEOF SpriteObject].interactId, INTERACT_COIN + mov casinoSprites[11*SIZEOF SpriteObject].promptPtr, OFFSET promptCoin + + ; Sprite 12: Skill Check Stand + mov casinoSprites[12*SIZEOF SpriteObject].posX, (18 * FP_1) + mov casinoSprites[12*SIZEOF SpriteObject].posY, (15 * FP_1) + mov casinoSprites[12*SIZEOF SpriteObject].baseTexId, 30 + mov casinoSprites[12*SIZEOF SpriteObject].frameCount, 1 + mov casinoSprites[12*SIZEOF SpriteObject].curFrame, 0 + mov casinoSprites[12*SIZEOF SpriteObject].animTimer, 0 + mov casinoSprites[12*SIZEOF SpriteObject].animSpeed, 1 + mov casinoSprites[12*SIZEOF SpriteObject].interactId, INTERACT_SKILL_CHECK + mov casinoSprites[12*SIZEOF SpriteObject].promptPtr, OFFSET promptSkillCheck + + ; Sprite 13: Umamusume Derby Lounge + mov casinoSprites[13*SIZEOF SpriteObject].posX, (22 * FP_1) + mov casinoSprites[13*SIZEOF SpriteObject].posY, (15 * FP_1) + mov casinoSprites[13*SIZEOF SpriteObject].baseTexId, 30 + mov casinoSprites[13*SIZEOF SpriteObject].frameCount, 1 + mov casinoSprites[13*SIZEOF SpriteObject].curFrame, 0 + mov casinoSprites[13*SIZEOF SpriteObject].animTimer, 0 + mov casinoSprites[13*SIZEOF SpriteObject].animSpeed, 1 + mov casinoSprites[13*SIZEOF SpriteObject].interactId, INTERACT_UMAMUSUME + mov casinoSprites[13*SIZEOF SpriteObject].promptPtr, OFFSET promptUmamusume + + ; Sprite 14: Boutique & Shop (East Wing) + mov casinoSprites[14*SIZEOF SpriteObject].posX, (26 * FP_1) + mov casinoSprites[14*SIZEOF SpriteObject].posY, (12 * FP_1) + mov casinoSprites[14*SIZEOF SpriteObject].baseTexId, 32 + mov casinoSprites[14*SIZEOF SpriteObject].frameCount, 1 + mov casinoSprites[14*SIZEOF SpriteObject].curFrame, 0 + mov casinoSprites[14*SIZEOF SpriteObject].animTimer, 0 + mov casinoSprites[14*SIZEOF SpriteObject].animSpeed, 1 + mov casinoSprites[14*SIZEOF SpriteObject].interactId, INTERACT_SHOP + mov casinoSprites[14*SIZEOF SpriteObject].promptPtr, OFFSET promptShop + + ; Sprite 15: Cashier & ATM (East Wing) + mov casinoSprites[15*SIZEOF SpriteObject].posX, (26 * FP_1) + mov casinoSprites[15*SIZEOF SpriteObject].posY, (16 * FP_1) + mov casinoSprites[15*SIZEOF SpriteObject].baseTexId, 33 + mov casinoSprites[15*SIZEOF SpriteObject].frameCount, 1 + mov casinoSprites[15*SIZEOF SpriteObject].curFrame, 0 + mov casinoSprites[15*SIZEOF SpriteObject].animTimer, 0 + mov casinoSprites[15*SIZEOF SpriteObject].animSpeed, 1 + mov casinoSprites[15*SIZEOF SpriteObject].interactId, INTERACT_ATM + mov casinoSprites[15*SIZEOF SpriteObject].promptPtr, OFFSET promptATM + + ; Sprite 16: Player Terminal (East Wing) + mov casinoSprites[16*SIZEOF SpriteObject].posX, (26 * FP_1) + mov casinoSprites[16*SIZEOF SpriteObject].posY, (20 * FP_1) + mov casinoSprites[16*SIZEOF SpriteObject].baseTexId, 33 + mov casinoSprites[16*SIZEOF SpriteObject].frameCount, 1 + mov casinoSprites[16*SIZEOF SpriteObject].curFrame, 0 + mov casinoSprites[16*SIZEOF SpriteObject].animTimer, 0 + mov casinoSprites[16*SIZEOF SpriteObject].animSpeed, 1 + mov casinoSprites[16*SIZEOF SpriteObject].interactId, INTERACT_TERMINAL + mov casinoSprites[16*SIZEOF SpriteObject].promptPtr, OFFSET promptPlayerTerminal + + ; Sprite 17: Buckshot Roulette (South-West) + mov casinoSprites[17*SIZEOF SpriteObject].posX, (12 * FP_1) + mov casinoSprites[17*SIZEOF SpriteObject].posY, (22 * FP_1) + mov casinoSprites[17*SIZEOF SpriteObject].baseTexId, 30 + mov casinoSprites[17*SIZEOF SpriteObject].frameCount, 1 + mov casinoSprites[17*SIZEOF SpriteObject].curFrame, 0 + mov casinoSprites[17*SIZEOF SpriteObject].animTimer, 0 + mov casinoSprites[17*SIZEOF SpriteObject].animSpeed, 1 + mov casinoSprites[17*SIZEOF SpriteObject].interactId, INTERACT_BUCKSHOT + mov casinoSprites[17*SIZEOF SpriteObject].promptPtr, OFFSET promptBuckshot + + ; Sprite 18: Observer Lounge (South-East) + mov casinoSprites[18*SIZEOF SpriteObject].posX, (20 * FP_1) + mov casinoSprites[18*SIZEOF SpriteObject].posY, (22 * FP_1) + mov casinoSprites[18*SIZEOF SpriteObject].baseTexId, 30 + mov casinoSprites[18*SIZEOF SpriteObject].frameCount, 1 + mov casinoSprites[18*SIZEOF SpriteObject].curFrame, 0 + mov casinoSprites[18*SIZEOF SpriteObject].animTimer, 0 + mov casinoSprites[18*SIZEOF SpriteObject].animSpeed, 1 + mov casinoSprites[18*SIZEOF SpriteObject].interactId, INTERACT_OBSERVER + mov casinoSprites[18*SIZEOF SpriteObject].promptPtr, OFFSET promptObserver + + ; Sprite 19: Russian Roulette (Backroom Entrance) + mov casinoSprites[19*SIZEOF SpriteObject].posX, (16 * FP_1) + mov casinoSprites[19*SIZEOF SpriteObject].posY, (25 * FP_1) + mov casinoSprites[19*SIZEOF SpriteObject].baseTexId, 34 + mov casinoSprites[19*SIZEOF SpriteObject].frameCount, 1 + mov casinoSprites[19*SIZEOF SpriteObject].curFrame, 0 + mov casinoSprites[19*SIZEOF SpriteObject].animTimer, 0 + mov casinoSprites[19*SIZEOF SpriteObject].animSpeed, 1 + mov casinoSprites[19*SIZEOF SpriteObject].interactId, INTERACT_RUSSIAN_ROULETTE + mov casinoSprites[19*SIZEOF SpriteObject].promptPtr, OFFSET promptRussianRoulette + + ; Sprite 20: Online Russian Roulette (Backroom Secret Terminal) + mov casinoSprites[20*SIZEOF SpriteObject].posX, (18 * FP_1) + mov casinoSprites[20*SIZEOF SpriteObject].posY, (25 * FP_1) + mov casinoSprites[20*SIZEOF SpriteObject].baseTexId, 34 + mov casinoSprites[20*SIZEOF SpriteObject].frameCount, 1 + mov casinoSprites[20*SIZEOF SpriteObject].curFrame, 0 + mov casinoSprites[20*SIZEOF SpriteObject].animTimer, 0 + mov casinoSprites[20*SIZEOF SpriteObject].animSpeed, 1 + mov casinoSprites[20*SIZEOF SpriteObject].interactId, INTERACT_ONLINE_RR + mov casinoSprites[20*SIZEOF SpriteObject].promptPtr, OFFSET promptOnlineRR + + ; Sprite 21: Hell Tower Portal (South Wing Deep End) + mov casinoSprites[21*SIZEOF SpriteObject].posX, (16 * FP_1 + FP_HALF) + mov casinoSprites[21*SIZEOF SpriteObject].posY, (29 * FP_1) + mov casinoSprites[21*SIZEOF SpriteObject].baseTexId, 4 + mov casinoSprites[21*SIZEOF SpriteObject].frameCount, 1 + mov casinoSprites[21*SIZEOF SpriteObject].curFrame, 0 + mov casinoSprites[21*SIZEOF SpriteObject].animTimer, 0 + mov casinoSprites[21*SIZEOF SpriteObject].animSpeed, 1 + mov casinoSprites[21*SIZEOF SpriteObject].interactId, INTERACT_HELL_TOWER + mov casinoSprites[21*SIZEOF SpriteObject].promptPtr, OFFSET promptHellTower + ret +InitializeCasinoSprites3D ENDP + +include src_graphics\audio_code.inc +include src_graphics\dice_animation.inc +include src_graphics\russian_roulette.inc +include src_graphics\startup_code.inc +include src_graphics\card_table_assets.inc +include src_graphics\poker_evaluator.inc +include src_graphics\native_poker.inc +include src_graphics\native_blackjack.inc +include src_graphics\native_durak.inc +include src_graphics\card_tables_render.inc +include src_graphics\durak_render.inc +include src_graphics\card_table_input.inc +include src_graphics\scene_animation.inc +include src_graphics\native_slots.inc +include src_graphics\native_clover.inc +include src_graphics\native_coin.inc +include src_graphics\graphic_profiles.inc +include src_graphics\city_arrival_scene.inc +include src_graphics\arrival_scene.inc +include src_graphics\merchant_scene.inc +include src_graphics\hall_scene.inc +include src_graphics\npc_mind.inc +include src_graphics\npc_life.inc +include src_graphics\npc_contracts.inc +include src_graphics\native_wheel.inc +include src_graphics\billiards.inc +include src_graphics\buckshot.inc +include src_graphics\russian_table.inc +include src_graphics\unavailable.inc + +; --- Main Loop of the 3D Casino Engine --- +StartCasino3D PROC uses ebx esi edi + call Init3DEngine + test eax, eax + jz engine_shutdown + invoke GetTickCount + mov rngSeed3D, eax + mov previousTick3D, eax +engine_loop: + invoke PeekMessageA, OFFSET msg3D, 0, 0, 0, PM_REMOVE + test eax, eax + jz dispatch_frame + cmp msg3D.message, WM_QUIT + je engine_shutdown + invoke TranslateMessage, OFFSET msg3D + invoke DispatchMessageA, OFFSET msg3D + jmp engine_loop + +dispatch_frame: + invoke GetTickCount + mov frameStart3D, eax + sub eax, previousTick3D + cmp eax, 50 + jbe @F + mov eax, 50 +@@: + mov deltaTime3D, eax + mov eax, frameStart3D + mov previousTick3D, eax + invoke GetForegroundWindow + cmp eax, h3DWnd + jne engine_idle + invoke IsIconic, h3DWnd + test eax, eax + jnz engine_idle + invoke Pressed3D, 7Ah + test eax, eax + jz @F + call ToggleFullscreen3D +@@: + invoke Pressed3D, 1Bh + test eax, eax + jz engine_tick + cmp engineMode, MODE_INTRO + jne @F + call FinishStartup3D + jmp engine_tick +@@: + cmp engineMode, MODE_ARRIVAL + jne @F + call ArrivalEscape3D + jmp engine_tick +@@: + cmp engineMode, MODE_WALK + jne leave_table + xor paused3D, 1 + jmp engine_tick +leave_table: + call CardTableEscape3D + test eax, eax + jnz engine_tick + call TableBusy3D + test eax, eax + jz leave_idle_table + xor paused3D, 1 + call ClearKeys3D + jmp engine_tick +leave_idle_table: + mov paused3D, 0 + mov engineMode, MODE_WALK + call ClearKeys3D + invoke PlayCasinoSound3D, 0, 0, 0 +engine_tick: + cmp paused3D, 0 + jne draw_pause + mov eax, deltaTime3D + add animationClock3D, eax + cmp engineMode, MODE_INTRO + jne check_arrival_mode + call HandleStartupInput3D + cmp engineMode, MODE_INTRO + jne check_arrival_mode + call RenderStartup3D + jmp present_frame +check_arrival_mode: + cmp engineMode, MODE_ARRIVAL + jne check_walk_mode + call HandleArrival3D + cmp engineMode, MODE_WALK + je check_walk_mode + call RenderArrival3D + jmp present_frame +check_walk_mode: + cmp engineMode, MODE_WALK + jne check_slots_mode + call UpdateHall3D + call UpdateCamera3D + call CheckInteractions + call HandlePlayerInput + call UpdateCamera3D + call RenderCeilingAndFloor + call RenderWalls + call PrepareCityDepth3D + call RenderSprites + call RenderHall3D + call RenderHUD + call RenderMinimap + jmp present_frame +check_slots_mode: + cmp engineMode,MODE_CLOVER + jne @F + call HandleNativeClover3D + call RenderNativeClover3D + jmp present_frame +@@: + cmp engineMode,MODE_NPC_DIALOG + jne @F + call HandleNpcDialog3D + call RenderNpcDialog3D + jmp present_frame +@@: + cmp engineMode, MODE_UNAVAILABLE + jne @F + call HandleUnavailable3D + call RenderUnavailable3D + jmp present_frame +@@: + cmp engineMode, MODE_POOL + jne @F + call HandlePool3D + call RenderPool3D + jmp present_frame +@@: + cmp engineMode, MODE_BAR + jne @F + call HandleBar3D + call RenderBar3D + jmp present_frame +@@: + cmp engineMode, MODE_STAIRS + jne @F + call HandleStairs3D + call RenderStairs3D + jmp present_frame +@@: + cmp engineMode, MODE_SLOTS + jne check_bj_mode + call HandleNativeSlots3D + cmp engineMode,MODE_WALK + je check_walk_mode + call RenderNativeSlots3D + jmp present_frame +check_bj_mode: + cmp engineMode, MODE_BLACKJACK + jne check_poker_mode + call HandleNativeBlackjack3D + cmp engineMode, MODE_WALK + je check_walk_mode + call RenderNativeBlackjack3D + jmp present_frame +check_poker_mode: + cmp engineMode, MODE_POKER + jne check_durak_mode + call HandleNativePoker3D + cmp engineMode, MODE_WALK + je check_walk_mode + call RenderNativePoker3D + jmp present_frame +check_durak_mode: + cmp engineMode, MODE_DURAK + jne check_roul_mode + call HandleNativeDurak3D + cmp engineMode, MODE_WALK + je check_walk_mode + call RenderNativeDurak3D + jmp present_frame +check_roul_mode: + cmp engineMode, MODE_ROULETTE + jne check_shop_mode + call HandleNativeWheel3D + call RenderNativeWheel3D + jmp present_frame +check_shop_mode: + cmp engineMode, MODE_SHOP + jne check_atm_mode + call HandleMerchant3D + call RenderMerchant3D + jmp present_frame +check_atm_mode: + cmp engineMode, MODE_ATM + jne check_coin_mode + call HandleATMInput + call RenderATMGame + jmp present_frame +check_coin_mode: + cmp engineMode, MODE_COIN + jne check_dice_mode + call HandleCoinInput + call RenderCoinGame + jmp present_frame +check_dice_mode: + cmp engineMode, MODE_DICE + jne check_skulls_mode + call HandleDiceInput + call RenderDiceGame + jmp present_frame +check_skulls_mode: + cmp engineMode, MODE_SKULLS + jne check_skill_mode + call HandleSkullsInput + call RenderSkullsGame + jmp present_frame +check_skill_mode: + cmp engineMode, MODE_SKILL + jne check_buckshot_mode + call HandleSkillInput + call RenderSkillGame + jmp present_frame +check_buckshot_mode: + cmp engineMode, MODE_BUCKSHOT + jne check_russian_mode + call HandleBuckshot3D + call RenderBuckshot3D + jmp present_frame +check_russian_mode: + cmp engineMode, MODE_RUSSIAN + jne present_frame + call HandleRussianInput3D + call RenderRussianGame3D + jmp present_frame +draw_pause: + invoke DrawBoxBorder, 28, 36, 264, 168, 00151C21h, 00D8BC6Ah, 2 + invoke DrawString8x8, 44, 48, OFFSET textPause3D, 00FFFFFFh + cmp displayFill3D, 0 + je @F + invoke DrawString8x8, 44, 72, OFFSET textDisplayFill3D, 00D8BC6Ah + jmp pause_draw_quality +@@: + invoke DrawString8x8, 44, 72, OFFSET textDisplayFit3D, 00D8BC6Ah +pause_draw_quality: + invoke DrawString8x8, 44, 92, OFFSET textLowSpec3D, 00D8BC6Ah + mov eax, settingsLowSpec + cmp eax, 0 + jne @F + mov edx, OFFSET textLowSpecOff3D + jmp pause_draw_quality_value +@@: + cmp eax, 1 + jne @F + mov edx, OFFSET textLowSpecEco3D + jmp pause_draw_quality_value +@@: + mov edx, OFFSET textLowSpecQuiet3D +pause_draw_quality_value: + invoke DrawString8x8, 208, 92, edx, 00FFFFFFh + invoke DrawString8x8, 44, 112, OFFSET textVolumeKeys3D, 00D8BC6Ah + invoke DrawString8x8, 44, 130, OFFSET textSoundLevel3D, 00BBBBBBh + invoke FormatNumber, settingsVolume, OFFSET hudNumBuffer + invoke DrawString8x8, 124, 130, OFFSET hudNumBuffer, 00FFFFFFh + invoke DrawString8x8, 44, 150, OFFSET textFullscreenKey3D, 00A0A0A0h + invoke DrawString8x8, 44, 170, OFFSET textResume3D, 00D8BC6Ah + invoke DrawString8x8, 44, 188, OFFSET textQuit3D, 00BBBBBBh + invoke Pressed3D, 31h + test eax, eax + jz @F + xor displayFill3D, 1 + call SaveDisplaySettings3D +@@: + invoke Pressed3D, 32h + test eax, eax + jz @F + inc settingsLowSpec + cmp settingsLowSpec, 3 + jb pause_low_spec_saved + mov settingsLowSpec, 0 +pause_low_spec_saved: + call SaveProgress3D +@@: + invoke Pressed3D, 0BBh + test eax, eax + jz @F + cmp settingsVolume, 10 + jae @F + inc settingsVolume + call ApplySoundVolume + call SaveProgress3D +@@: + invoke Pressed3D, 0BDh + test eax, eax + jz @F + mov eax, settingsVolume + test eax, eax + jz @F + dec settingsVolume + call ApplySoundVolume + call SaveProgress3D +@@: + invoke Pressed3D, 51h + test eax, eax + jz @F + call SaveProgress3D + jmp engine_shutdown +present_frame: + mov eax, engineMode + cmp eax, lastPersistMode3D + je @F + cmp eax, MODE_WALK + jne @F + call SaveProgress3D +@@: + mov eax, engineMode + mov lastPersistMode3D, eax + call Present3D + mov mouseClick3D, 0 + lea edi, pressedKeys3D + xor eax, eax + mov ecx, 64 + rep stosd + invoke GetTickCount + sub eax, frameStart3D + mov ecx, 16 + cmp settingsLowSpec, 1 + jne @F + mov ecx, 24 +@@: + cmp settingsLowSpec, 2 + jne @F + mov ecx, 33 +@@: + cmp eax, ecx + jae engine_loop + sub ecx, eax + invoke Sleep, ecx + jmp engine_loop +engine_idle: + invoke Sleep, 50 + jmp engine_loop +engine_shutdown: + cmp hRaycastThread, 0 + je @F + mov bRaycastQuit, 1 + invoke SetEvent, hRaycastStartEvent + invoke WaitForSingleObject, hRaycastThread, 1000 + invoke CloseHandle, hRaycastThread + invoke CloseHandle, hRaycastStartEvent + invoke CloseHandle, hRaycastDoneEvent + mov hRaycastThread, 0 + mov hRaycastStartEvent, 0 + mov hRaycastDoneEvent, 0 +@@: + call SaveProgress3D + invoke PlayCasinoSound3D, 0, 0, 0 + call FreeRussianAssets3D + call FreeStartupAssets3D + call FreeCardTableAssets3D + call FreeBuckshotAssets3D + call FreeNativeSlots3D + call FreeNativeClover3D + call FreePyramidAssets3D + call FreeArrivalAssets3D + cmp h3DDC, 0 + je @F + invoke ReleaseDC, h3DWnd, h3DDC + mov h3DDC, 0 +@@: + cmp h3DWnd, 0 + je @F + invoke DestroyWindow, h3DWnd + mov h3DWnd, 0 +@@: + ret +StartCasino3D ENDP + +include src_graphics\platform_code.inc + +IFDEF CASINO_ACTION_TEST +include tools\tests\casino_actions_test.inc +ENDIF + diff --git a/poker.asm b/poker.asm index 8479877..19b6ac6 100644 --- a/poker.asm +++ b/poker.asm @@ -102,7 +102,6 @@ closesocket PROTO :DWORD inet_addr PROTO :DWORD WSAGetLastError PROTO MoveCursor PROTO :DWORD, :DWORD -PrintSlotSymbol PROTO :DWORD RandomRange PROTO :DWORD PrintUInt PROTO :DWORD UnlockAchievement PROTO :DWORD, :DWORD @@ -163,7 +162,7 @@ slotComboCount dd 0 slotJackpotHit dd 0 slotComboNames dd 32 dup(0) slotComboMults dd 32 dup(0) -slotComboMasks dd 32 dup(0) +slotComboMasks dd 32 dup(0) slotGrid dd 15 dup(0) slotVisible dd 0 ; === Общая карточная модель: руки игрока, AI и карты на столе === @@ -3895,140 +3894,7 @@ tower_music_play: ret PlayTowerRandomMusic ENDP -; --- PrintSlotCell: вывод текста, цветов, картинок и элементов интерфейса --- -PrintSlotCell PROC uses eax ebx ecx, value:DWORD - invoke PrintStr, OFFSET slotWall - mov eax, slotCurrentCell - mov ebx, 1 - mov ecx, eax - shl ebx, cl - mov eax, slotWinMask - test eax, ebx - je slot_cell_normal - invoke SetColor, COLOR_WARN - invoke PrintStr, OFFSET slotWinLeft - invoke PrintSlotSymbol, value - invoke SetColor, COLOR_WARN - invoke PrintStr, OFFSET slotWinRight - call ResetColor - ret -slot_cell_normal: - invoke PrintStr, OFFSET slotPadOne - invoke PrintSlotSymbol, value - invoke PrintStr, OFFSET slotPadOne - ret -PrintSlotCell ENDP -; --- PrintSlotBlankCell: вывод текста, цветов, картинок и элементов интерфейса --- -PrintSlotBlankCell PROC - invoke PrintStr, OFFSET slotWall - invoke PrintStr, OFFSET slotCellBlank - ret -PrintSlotBlankCell ENDP - -; --- PrintSlotPaddingRow: вывод текста, цветов, картинок и элементов интерфейса --- -PrintSlotPaddingRow PROC - call PrintSlotBlankCell - call PrintSlotBlankCell - call PrintSlotBlankCell - call PrintSlotBlankCell - call PrintSlotBlankCell - invoke PrintStr, OFFSET slotWall - invoke PrintStr, OFFSET nl - ret -PrintSlotPaddingRow ENDP -; --- PrintSlotWindow: вывод текста, цветов, картинок и элементов интерфейса --- -PrintSlotWindow PROC uses eax ebx - call ClearView - invoke PrintTitleColor, OFFSET slotTitle - invoke PrintStr, OFFSET slotBorder - - mov rowIndex, 0 -slot_window_row_loop: - cmp rowIndex, 3 - jae slot_window_done - call PrintSlotPaddingRow - mov ebx, rowIndex - imul ebx, 5 - - cmp slotVisible, 1 - jb slot_blank_col1 - mov slotCurrentCell, ebx - invoke PrintSlotCell, slotGrid[ebx * 4] - jmp slot_col2 -slot_blank_col1: - call PrintSlotBlankCell - -slot_col2: - cmp slotVisible, 2 - jb slot_blank_col2 - mov eax, ebx - inc eax - mov slotCurrentCell, eax - invoke PrintSlotCell, slotGrid[eax * 4] - jmp slot_col3 -slot_blank_col2: - call PrintSlotBlankCell - -slot_col3: - cmp slotVisible, 3 - jb slot_blank_col3 - mov eax, ebx - add eax, 2 - mov slotCurrentCell, eax - invoke PrintSlotCell, slotGrid[eax * 4] - jmp slot_col4 -slot_blank_col3: - call PrintSlotBlankCell - -slot_col4: - cmp slotVisible, 4 - jb slot_blank_col4 - mov eax, ebx - add eax, 3 - mov slotCurrentCell, eax - invoke PrintSlotCell, slotGrid[eax * 4] - jmp slot_col5 -slot_blank_col4: - call PrintSlotBlankCell - -slot_col5: - cmp slotVisible, 5 - jb slot_blank_col5 - mov eax, ebx - add eax, 4 - mov slotCurrentCell, eax - invoke PrintSlotCell, slotGrid[eax * 4] - jmp slot_row_end -slot_blank_col5: - call PrintSlotBlankCell - -slot_row_end: - invoke PrintStr, OFFSET slotWall - invoke PrintStr, OFFSET nl - call PrintSlotPaddingRow - invoke PrintStr, OFFSET slotBorder - inc rowIndex - jmp slot_window_row_loop - -slot_window_done: - ret -PrintSlotWindow ENDP - -; --- FillSlotColumn: слот-машины, барабаны, символы, выплаты и джекпоты --- -FillSlotColumn PROC uses eax ebx, column:DWORD - mov ebx, column - invoke RandomRange, 7 - mov slotGrid[ebx * 4], eax - mov ebx, column - add ebx, 5 - invoke RandomRange, 7 - mov slotGrid[ebx * 4], eax - mov ebx, column - add ebx, 10 - invoke RandomRange, 7 - mov slotGrid[ebx * 4], eax - ret -FillSlotColumn ENDP +; (Legacy terminal Clover slot renderers removed) ; --- PrintUInt: вывод текста, цветов, картинок и элементов интерфейса --- PrintUInt PROC uses eax ebx ecx edx edi, value:DWORD LOCAL buffer[12]:BYTE @@ -8611,374 +8477,42 @@ ai_exchange_done: PokerAIExchange ENDP ; --- AddPlayerBJ: карты, руки, очки и базовая карточная логика --- -AddPlayerBJ PROC uses eax ebx edx - call DrawCard - mov ebx, eax - invoke PrintStr, OFFSET yourCardText - invoke PrintCard, ebx - invoke CardValueBJ, ebx - add playerTotal, eax - cmp eax, 11 - jne no_player_ace - inc playerAces -no_player_ace: - inc playerCards - call AdjustPlayerAces - ret -AddPlayerBJ ENDP -; --- AddDealerBJ: карты, руки, очки и базовая карточная логика --- -AddDealerBJ PROC uses eax ebx - call DrawCard - mov ebx, eax - invoke PrintStr, OFFSET dealerCardText - invoke PrintCard, ebx - invoke CardValueBJ, ebx - add dealerTotal, eax - cmp eax, 11 - jne no_dealer_ace - inc dealerAces -no_dealer_ace: - call AdjustDealerAces +; --- TournamentPlayStage: Fast resolution of ported game stages in Hell Tower --- +TournamentPlayStage PROC uses eax + invoke RandomRange, 100 + cmp eax, 25 + ja tourney_stage_win + mov lastGameResult, 2 ret -AddDealerBJ ENDP +tourney_stage_win: + mov lastGameResult, 1 + ret +TournamentPlayStage ENDP -; --- CompareTotals: служебный блок игровой логики --- -CompareTotals PROC - call PrintScore - cmp playerTotal, 21 - ja player_lost - cmp dealerTotal, 21 - ja dealer_lost - mov eax, playerTotal - cmp eax, dealerTotal - ja player_won - jb player_lost - call PrintDrawEvent - ret -player_won: - call PrintWinEvent - ret -player_lost: - call PrintLoseEvent - ret -dealer_lost: - invoke PrintStr, OFFSET dealerBustText - ret -CompareTotals ENDP - -; --- Game21: карты, руки, очки и базовая карточная логика --- Game21 PROC -start_21: - call ClearView - invoke PrintTitleColor, OFFSET twentyOneTitle - call PromptBet - call ResetDeck - call Reset21Hands - - call DrawPlayer21Hand - call DrawPlayer21Hand - call DrawAI21Hand - call DrawAI21Hand - -player_21_loop: - call ClearView - invoke PrintTitleColor, OFFSET twentyOneTitle - call ShowAllCards21 - - cmp playerTotal, 21 - ja player_21_bust - cmp playerTotal, 21 - je ai_21_turn - - invoke PrintStr, OFFSET hitText - invoke PrintStr, OFFSET cheatMoveText - call ReadKey - cmp al, '1' - je hit_21 - cmp al, 'y' - je hit_21 - cmp al, 'Y' - je hit_21 - cmp al, '3' - je cheat_peek_21_action - cmp al, '4' - je cheat_swap_21_action - jmp ai_21_turn -cheat_peek_21_action: - call CheatPeek21 - jmp player_21_loop -cheat_swap_21_action: - call CheatSwap21 - jmp player_21_loop -hit_21: - cmp playerCnt21, 10 - jae ai_21_turn - call DrawPlayer21Hand - jmp player_21_loop - -player_21_bust: - invoke PrintStr, OFFSET bustText - call PayLose - jmp ask_21_again - -ai_21_turn: -ai_21_cycle: - call ClearView - invoke PrintTitleColor, OFFSET twentyOneTitle - call ShowAllCards21 - - cmp playerTotal, 21 - ja finish_21 - cmp dealerTotal, 21 - je finish_21 - cmp aiDifficulty, 1 - je ai_21_easy - cmp aiDifficulty, 2 - je ai_21_normal - cmp dealerTotal, 12 - jb ai_21_must_hit - - mov eax, dealerTotal - cmp eax, playerTotal - jae finish_21 - - call CountDanger21 - mov eax, dangerLvl21 - mov ebx, 2 - mul ebx - cmp eax, cardsLeft21 - ja finish_21 - jmp ai_21_must_hit - -ai_21_easy: - cmp dealerTotal, 16 - jb ai_21_must_hit - jmp finish_21 - -ai_21_normal: - cmp dealerTotal, 17 - jb ai_21_must_hit - jmp finish_21 - -ai_21_must_hit: - cmp aiCnt21, 10 - jae finish_21 - invoke PrintStr, OFFSET aiMoveText - invoke Sleep, 650 - call DrawAI21Hand - call CalcAIScore21 - cmp dealerTotal, 21 - ja finish_21 - jmp ai_21_cycle - -finish_21: - call AnimateReveal21 - call FinalScreen21 -ask_21_again: - cmp tournamentMode, 1 - je game21_tournament_return - invoke PrintStr, OFFSET againText - call ReadKey - cmp al, 'y' - je start_21 - cmp al, 'Y' - je start_21 -game21_tournament_return: + cmp tournamentStage, 0 + jne tourney_bj + call StartCasino3D + ret +tourney_bj: + call TournamentPlayStage ret Game21 ENDP ; --- GamePoker: покер: оценка комбинаций, ставки, фолды и ИИ --- GamePoker PROC -poker_choose_mode: - call ClearView - invoke PrintTitleColor, OFFSET pokerTitle - invoke PrintStr, OFFSET pokerModeMenuText - call ReadKey - cmp al, '1' - je start_poker - cmp al, '2' - je poker_launch_multitable - cmp al, '0' - je poker_mode_exit - jmp poker_choose_mode - -poker_launch_multitable: - call GameMultiPoker + cmp tournamentStage, 0 + jne tourney_poker + call StartCasino3D ret - -poker_mode_exit: - ret - -start_poker: - call ClearView - invoke PrintTitleColor, OFFSET pokerTitle - call PromptBet - call ResetDeck - call ResetPokerHands - call DealPokerHands - call HardPokerPlayerExchange - call HardPokerAIExchange - -poker_stage_loop: - call ClearView - invoke PrintTitleColor, OFFSET pokerTitle - call ShowPokerTable - call ShowPokerHint - call ShowPokerMoney - cmp communityCnt, 5 - jae poker_showdown - invoke PrintStr, OFFSET pokerDecisionText - invoke PrintStr, OFFSET cheatMoveText - call ReadKey - cmp al, '1' - je poker_play - cmp al, 'y' - je poker_play - cmp al, 'Y' - je poker_play - cmp al, '2' - je poker_raise - cmp al, 'r' - je poker_raise - cmp al, 'R' - je poker_raise - cmp al, '3' - je poker_cheat_peek - cmp al, '4' - je poker_cheat_swap - invoke PrintStr, OFFSET pokerFoldText - call PayLose - jmp ask_poker_again - -poker_cheat_peek: - call CheatPeekPoker - jmp poker_stage_loop -poker_cheat_swap: - call CheatSwapPoker - jmp poker_stage_loop - -poker_raise: - call PromptPokerRaise - cmp eax, 0 - je poker_stage_loop - invoke UnlockAchievement, 200h, OFFSET achPokerRaiseName - invoke PrintStr, OFFSET aiThinkText - invoke Sleep, 700 - call PokerAICallRaise - cmp eax, 0 - jne poker_raise_called - invoke PrintStr, OFFSET pokerAIFoldRaiseText - invoke UnlockAchievement, 400h, OFFSET achPokerBluffName - call PayWin - jmp ask_poker_again -poker_raise_called: - invoke PrintStr, OFFSET pokerAICallRaiseText - invoke Sleep, 700 - jmp poker_next_stage - -poker_play: - invoke PrintStr, OFFSET aiThinkText - invoke Sleep, 700 - call PokerAIDecide - cmp eax, 0 - jne poker_ai_plays - invoke PrintStr, OFFSET pokerAIFoldText - call PayWin - jmp ask_poker_again - -poker_ai_plays: - call PokerAIRaiseMaybe - cmp eax, 0 - je poker_next_stage - invoke PrintStr, OFFSET pokerAIRaiseText - invoke PrintUInt, pokerAIRaiseAmount - invoke PrintStr, OFFSET nl - invoke PrintStr, OFFSET pokerCallRaiseText - call ReadKey - cmp al, '1' - je poker_call_ai_raise - cmp al, 'y' - je poker_call_ai_raise - cmp al, 'Y' - je poker_call_ai_raise - invoke PrintStr, OFFSET pokerFoldToRaiseText - call PayLose - jmp ask_poker_again -poker_call_ai_raise: - mov eax, currentBet - add eax, pokerAIRaiseAmount - cmp eax, bankroll - jbe poker_call_ai_raise_ok - invoke PrintStr, OFFSET tooBigBetText - invoke PrintStr, OFFSET pokerFoldToRaiseText - call PayLose - jmp ask_poker_again -poker_call_ai_raise_ok: - mov currentBet, eax - invoke PrintStr, OFFSET pokerPlayerCallText - invoke PrintUInt, currentBet - invoke PrintStr, OFFSET nl - invoke Sleep, 700 -poker_next_stage: - cmp communityCnt, 5 - jae poker_showdown - invoke PrintStr, OFFSET pokerNextCardText - invoke Sleep, 900 - inc communityCnt - jmp poker_stage_loop - -poker_showdown: - call AnimateRevealPoker - call ShowPokerResult - -ask_poker_again: - cmp tournamentMode, 1 - je poker_tournament_return - invoke PrintStr, OFFSET againText - call ReadKey - cmp al, 'y' - je start_poker - cmp al, 'Y' - je start_poker -poker_tournament_return: +tourney_poker: + call TournamentPlayStage ret GamePoker ENDP ; --- PrintSlotSymbol: вывод текста, цветов, картинок и элементов интерфейса --- -PrintSlotSymbol PROC uses eax, value:DWORD - mov eax, value - cmp eax, 0 - je slot_symbol_green - cmp eax, 1 - je slot_symbol_yellow - cmp eax, 2 - je slot_symbol_red - cmp eax, 3 - je slot_symbol_yellow - cmp eax, 4 - je slot_symbol_cyan - cmp eax, 5 - je slot_symbol_yellow - invoke SetColor, COLOR_BAD - jmp slot_symbol_print -slot_symbol_green: - invoke SetColor, COLOR_MONEY - jmp slot_symbol_print -slot_symbol_yellow: - invoke SetColor, COLOR_WARN - jmp slot_symbol_print -slot_symbol_red: - invoke SetColor, COLOR_BAD - jmp slot_symbol_print -slot_symbol_cyan: - invoke SetColor, COLOR_TITLE -slot_symbol_print: - mov eax, value - invoke PrintStr, slotSymbols[eax * 4] - call ResetColor - ret -PrintSlotSymbol ENDP +; (Legacy terminal PrintSlotSymbol removed) ; --- MoveCursor: служебные функции консоли и случайных чисел --- MoveCursor PROC uses eax edx, xPos:DWORD, yPos:DWORD @@ -8992,347 +8526,13 @@ MoveCursor PROC uses eax edx, xPos:DWORD, yPos:DWORD MoveCursor ENDP ; --- PrintSkullAt: вывод текста, цветов, картинок и элементов интерфейса --- -PrintSkullAt PROC uses eax, xPos:DWORD, yPos:DWORD - mov eax, yPos - invoke MoveCursor, xPos, eax - invoke PrintUtf8, OFFSET skullSeg1 - mov eax, yPos - inc eax - invoke MoveCursor, xPos, eax - invoke PrintUtf8, OFFSET skullSeg2 - mov eax, yPos - add eax, 2 - invoke MoveCursor, xPos, eax - invoke PrintUtf8, OFFSET skullSeg3 - mov eax, yPos - add eax, 3 - invoke MoveCursor, xPos, eax - invoke PrintUtf8, OFFSET skullSeg4 - mov eax, yPos - add eax, 4 - invoke MoveCursor, xPos, eax - invoke PrintUtf8, OFFSET skullSeg5 - mov eax, yPos - add eax, 5 - invoke MoveCursor, xPos, eax - invoke PrintUtf8, OFFSET skullSeg6 - mov eax, yPos - add eax, 6 - invoke MoveCursor, xPos, eax - invoke PrintUtf8, OFFSET skullSeg7 - mov eax, yPos - add eax, 7 - invoke MoveCursor, xPos, eax - invoke PrintUtf8, OFFSET skullSeg8 - ret -PrintSkullAt ENDP - -; --- ShowSkullSlideFrame: звук, интро или покадровая анимация --- -ShowSkullSlideFrame PROC x1:DWORD, y1:DWORD, x2:DWORD, y2:DWORD, x3:DWORD, y3:DWORD - call ClearView - invoke PrintTitleColor, OFFSET skullsTitle - invoke PrintStr, OFFSET skullsShuffleText - invoke PrintSkullAt, x1, y1 - invoke PrintSkullAt, x2, y2 - invoke PrintSkullAt, x3, y3 - invoke Sleep, 220 - ret -ShowSkullSlideFrame ENDP - -; --- AnimateSkullSwap12: игра с черепами и шариком, перемешивание и отрисовка --- -AnimateSkullSwap12 PROC - invoke ShowSkullSlideFrame, 0, 5, 18, 5, 36, 5 - invoke ShowSkullSlideFrame, 4, 6, 14, 4, 36, 5 - invoke ShowSkullSlideFrame, 8, 7, 10, 3, 36, 5 - invoke ShowSkullSlideFrame, 14, 6, 4, 4, 36, 5 - invoke ShowSkullSlideFrame, 18, 5, 0, 5, 36, 5 - ret -AnimateSkullSwap12 ENDP - -; --- AnimateSkullSwap23: игра с черепами и шариком, перемешивание и отрисовка --- -AnimateSkullSwap23 PROC - invoke ShowSkullSlideFrame, 0, 5, 18, 5, 36, 5 - invoke ShowSkullSlideFrame, 0, 5, 22, 6, 32, 4 - invoke ShowSkullSlideFrame, 0, 5, 26, 7, 28, 3 - invoke ShowSkullSlideFrame, 0, 5, 32, 6, 22, 4 - invoke ShowSkullSlideFrame, 0, 5, 36, 5, 18, 5 - ret -AnimateSkullSwap23 ENDP - -; --- AnimateSkullSwap13: игра с черепами и шариком, перемешивание и отрисовка --- -AnimateSkullSwap13 PROC - invoke ShowSkullSlideFrame, 0, 5, 18, 5, 36, 5 - invoke ShowSkullSlideFrame, 8, 7, 18, 5, 28, 3 - invoke ShowSkullSlideFrame, 18, 8, 18, 5, 18, 2 - invoke ShowSkullSlideFrame, 28, 7, 18, 5, 8, 3 - invoke ShowSkullSlideFrame, 36, 5, 18, 5, 0, 5 - ret -AnimateSkullSwap13 ENDP - - -; --- PrintSkullRows: вывод текста, цветов, картинок и элементов интерфейса --- -PrintSkullRows PROC - invoke PrintUtf8, OFFSET skullSeg1 - invoke PrintUtf8, OFFSET skullSeg1 - invoke PrintUtf8, OFFSET skullSeg1 - invoke PrintStr, OFFSET nl - invoke PrintUtf8, OFFSET skullSeg2 - invoke PrintUtf8, OFFSET skullSeg2 - invoke PrintUtf8, OFFSET skullSeg2 - invoke PrintStr, OFFSET nl - invoke PrintUtf8, OFFSET skullSeg3 - invoke PrintUtf8, OFFSET skullSeg3 - invoke PrintUtf8, OFFSET skullSeg3 - invoke PrintStr, OFFSET nl - invoke PrintUtf8, OFFSET skullSeg4 - invoke PrintUtf8, OFFSET skullSeg4 - invoke PrintUtf8, OFFSET skullSeg4 - invoke PrintStr, OFFSET nl - invoke PrintUtf8, OFFSET skullSeg5 - invoke PrintUtf8, OFFSET skullSeg5 - invoke PrintUtf8, OFFSET skullSeg5 - invoke PrintStr, OFFSET nl - invoke PrintUtf8, OFFSET skullSeg6 - invoke PrintUtf8, OFFSET skullSeg6 - invoke PrintUtf8, OFFSET skullSeg6 - invoke PrintStr, OFFSET nl - invoke PrintUtf8, OFFSET skullSeg7 - invoke PrintUtf8, OFFSET skullSeg7 - invoke PrintUtf8, OFFSET skullSeg7 - invoke PrintStr, OFFSET nl - invoke PrintUtf8, OFFSET skullSeg8 - invoke PrintUtf8, OFFSET skullSeg8 - invoke PrintUtf8, OFFSET skullSeg8 - invoke PrintStr, OFFSET nl - ret -PrintSkullRows ENDP -; --- PrintSkulls: вывод текста, цветов, картинок и элементов интерфейса --- -PrintSkulls PROC reveal:DWORD - call PrintSkullRows - invoke PrintStr, OFFSET skullNums - cmp reveal, 0 - je print_skull_blank_ball - mov eax, skullBallPos - cmp eax, 0 - je print_skull_ball_1 - cmp eax, 1 - je print_skull_ball_2 - invoke PrintStr, OFFSET skullBall3 - ret -print_skull_ball_1: - invoke PrintStr, OFFSET skullBall1 - ret -print_skull_ball_2: - invoke PrintStr, OFFSET skullBall2 - ret -print_skull_blank_ball: - invoke PrintStr, OFFSET skullBlankBall - ret -PrintSkulls ENDP -; --- PrintSkullFaces: вывод текста, цветов, картинок и элементов интерфейса --- -PrintSkullFaces PROC - call PrintSkullRows - invoke PrintStr, OFFSET skullBlankBall - ret -PrintSkullFaces ENDP -; --- ShowSkullShuffleFrame: звук, интро или покадровая анимация --- -ShowSkullShuffleFrame PROC pSwapText:DWORD - call ClearView - invoke PrintTitleColor, OFFSET skullsTitle - invoke PrintStr, OFFSET skullsShuffleText - invoke PrintStr, pSwapText - call PrintSkullFaces - invoke Sleep, 400 - ret -ShowSkullShuffleFrame ENDP - -; --- ShuffleSkulls: игра с черепами и шариком, перемешивание и отрисовка --- -ShuffleSkulls PROC uses eax ebx - cmp aiDifficulty, 1 - je skulls_easy_steps - cmp aiDifficulty, 3 - je skulls_hard_steps - -skulls_normal_steps: - invoke RandomRange, 4 - add eax, 9 - jmp skulls_store_steps - -skulls_easy_steps: - invoke RandomRange, 4 - add eax, 5 - jmp skulls_store_steps - -skulls_hard_steps: - invoke RandomRange, 5 - add eax, 12 - -skulls_store_steps: - mov skullMax, eax - mov skullStep, 0 - -shuffle_skulls_loop: - mov eax, skullStep - cmp eax, skullMax - jae shuffle_skulls_done - - cmp skullStep, 0 - je skulls_play_first_move_sound - mov eax, skullMax - dec eax - cmp skullStep, eax - je skulls_play_last_move_sound - jmp skulls_after_move_sound - -skulls_play_first_move_sound: - call PlayStoneSound - invoke Sleep, 180 - jmp skulls_after_move_sound -skulls_play_last_move_sound: - call PlayStoneSound - -skulls_after_move_sound: - invoke RandomRange, 3 - cmp eax, 0 - je shuffle_12 - cmp eax, 1 - je shuffle_23 - jmp shuffle_13 - -shuffle_12: - mov eax, skullBallPos - cmp eax, 0 - je ball_12_to_2 - cmp eax, 1 - je ball_12_to_1 - jmp show_shuffle_12 -ball_12_to_2: - mov skullBallPos, 1 - jmp show_shuffle_12 -ball_12_to_1: - mov skullBallPos, 0 -show_shuffle_12: - call AnimateSkullSwap12 - jmp shuffle_next - -shuffle_23: - mov eax, skullBallPos - cmp eax, 1 - je ball_23_to_3 - cmp eax, 2 - je ball_23_to_2 - jmp show_shuffle_23 -ball_23_to_3: - mov skullBallPos, 2 - jmp show_shuffle_23 -ball_23_to_2: - mov skullBallPos, 1 -show_shuffle_23: - call AnimateSkullSwap23 - jmp shuffle_next - -shuffle_13: - mov eax, skullBallPos - cmp eax, 0 - je ball_13_to_3 - cmp eax, 2 - je ball_13_to_1 - jmp show_shuffle_13 -ball_13_to_3: - mov skullBallPos, 2 - jmp show_shuffle_13 -ball_13_to_1: - mov skullBallPos, 0 -show_shuffle_13: - call AnimateSkullSwap13 - -shuffle_next: - inc skullStep - jmp shuffle_skulls_loop -shuffle_skulls_done: - ret -ShuffleSkulls ENDP - -; --- GameSkulls: игра с черепами и шариком, перемешивание и отрисовка --- GameSkulls PROC -skulls_start: - call ClearView - invoke PrintTitleColor, OFFSET skullsTitle - invoke PrintStr, OFFSET skullsIntroText - call PromptBet - invoke RandomRange, 3 - mov skullBallPos, eax - - call ClearView - invoke PrintTitleColor, OFFSET skullsTitle - invoke PrintStr, OFFSET skullsShowText - invoke PrintSkulls, 1 - invoke Sleep, 1600 - - call ClearView - invoke PrintTitleColor, OFFSET skullsTitle - invoke PrintStr, OFFSET skullsHideText - invoke PrintSkulls, 0 - invoke Sleep, 800 - - call ShuffleSkulls - -skulls_guess_again: - call ClearView - invoke PrintTitleColor, OFFSET skullsTitle - invoke PrintSkulls, 0 - invoke PrintStr, OFFSET skullsGuessText - call ReadKey - cmp al, '1' - je skull_guess_1 - cmp al, '2' - je skull_guess_2 - cmp al, '3' - je skull_guess_3 - invoke PrintStr, OFFSET badChoiceText - call PauseConsole - jmp skulls_guess_again - -skull_guess_1: - mov skullGuess, 0 - jmp skulls_reveal -skull_guess_2: - mov skullGuess, 1 - jmp skulls_reveal -skull_guess_3: - mov skullGuess, 2 - -skulls_reveal: - call ClearView - invoke PrintTitleColor, OFFSET skullsTitle - invoke PrintSkulls, 1 - invoke PrintStr, OFFSET skullsBallText - mov eax, skullBallPos - inc eax - invoke PrintUInt, eax - invoke PrintStr, OFFSET nl - - mov eax, skullGuess - cmp eax, skullBallPos - jne skulls_lost - invoke PrintStr, OFFSET skullsWinText - invoke PaySlotMultiplier, 2 - jmp ask_skulls_again - -skulls_lost: - invoke PrintStr, OFFSET skullsLoseText - call PayLose - -ask_skulls_again: - cmp tournamentMode, 1 - je skulls_tournament_return - invoke PrintStr, OFFSET againText - call ReadKey - cmp al, 'y' - je skulls_start - cmp al, 'Y' - je skulls_start -skulls_tournament_return: + cmp tournamentStage, 0 + jne tourney_skulls + call StartCasino3D + ret +tourney_skulls: + call TournamentPlayStage ret GameSkulls ENDP ; --- PrintRevolver: вывод текста, цветов, картинок и элементов интерфейса --- @@ -9482,640 +8682,34 @@ PrintBang ENDP ; --- GameRoulette: русская рулетка или казино-рулетка --- GameRoulette PROC -roulette_start: - call ClearView - invoke PrintTitleColor, OFFSET rouletteTitle - invoke PrintStr, OFFSET rrIntroText - call PromptBet - call PlayRouletteSpinSound - call SetupRoulette - call AnimateRouletteSpin - -roulette_turn_loop: - call ShowRouletteStatus - cmp rrTurn, 0 - je roulette_player_turn - -roulette_ai_turn: - invoke PrintStr, OFFSET rrAITurnText - invoke Sleep, 900 - call RouletteChamberLoaded - cmp eax, 1 - je roulette_ai_dead - call PlayRouletteDrySound - invoke PrintStr, OFFSET rrClickText - invoke Sleep, 900 - call AdvanceRouletteChamber - mov rrTurn, 0 - jmp roulette_turn_loop - -roulette_player_turn: - invoke PrintStr, OFFSET rrPlayerTurnText - call ReadAnyKey - invoke PrintStr, OFFSET nl - call RouletteChamberLoaded - cmp eax, 1 - je roulette_player_dead - call PlayRouletteDrySound - invoke PrintStr, OFFSET rrClickText - invoke Sleep, 900 - call AdvanceRouletteChamber - mov rrTurn, 1 - jmp roulette_turn_loop - -roulette_player_dead: - call PrintBang - invoke PrintStr, OFFSET rrPlayerLoseText - call PayLose - jmp ask_roulette_again - -roulette_ai_dead: - invoke UnlockAchievement, 1000h, OFFSET achRussianWinName - call PrintBang - invoke PrintStr, OFFSET rrAIShotText - invoke PrintStr, OFFSET rrPayoutText - mov eax, aiDifficulty - inc eax - mov rrPayout, eax - invoke PaySlotMultiplier, rrPayout - -ask_roulette_again: - cmp tournamentMode, 1 - je roulette_tournament_return - invoke PrintStr, OFFSET againText - call ReadKey - cmp al, 'y' - je roulette_start - cmp al, 'Y' - je roulette_start -roulette_tournament_return: + cmp tournamentStage, 0 + jne tourney_rr + call StartCasino3D + ret +tourney_rr: + call TournamentPlayStage ret GameRoulette ENDP ; --- ShowBuckshotFrame: звук, интро или покадровая анимация --- -ShowBuckshotFrame PROC pFrame:DWORD, frameDelay:DWORD - call ClearView - invoke PrintTitleColor, OFFSET buckshotTitle - invoke SetColor, COLOR_CARD - invoke PrintStr, pFrame - call ResetColor - invoke Sleep, frameDelay - ret -ShowBuckshotFrame ENDP - -; --- AnimateBuckshotLoad: аккаунты, файлы сохранений и загрузка профиля --- -AnimateBuckshotLoad PROC - invoke ShowBuckshotFrame, OFFSET bsShotgunLoad1, 180 - invoke ShowBuckshotFrame, OFFSET bsShotgunLoad2, 260 - invoke ShowBuckshotFrame, OFFSET bsShotgunLoad3, 260 - ret -AnimateBuckshotLoad ENDP - -; --- AnimateBuckshotFire: Buckshot Roulette: патроны, предметы, ходы игрока и ИИ --- -AnimateBuckshotFire PROC - invoke ShowBuckshotFrame, OFFSET bsShotgunFire, 220 - ret -AnimateBuckshotFire ENDP - -; --- AnimateBuckshotDry: Buckshot Roulette: патроны, предметы, ходы игрока и ИИ --- -AnimateBuckshotDry PROC - invoke ShowBuckshotFrame, OFFSET bsShotgunDry, 180 - ret -AnimateBuckshotDry ENDP -; --- BuckshotGiveItems: Buckshot Roulette: патроны, предметы, ходы игрока и ИИ --- -BuckshotGiveItems PROC uses eax - invoke RandomRange, 2 - inc eax - mov bsPlayerGlass, eax - invoke RandomRange, 2 - mov bsPlayerSaw, eax - invoke RandomRange, 2 - inc eax - mov bsPlayerBeer, eax - invoke RandomRange, 2 - mov bsPlayerCuffs, eax - invoke RandomRange, 2 - inc eax - mov bsAIGlass, eax - invoke RandomRange, 2 - mov bsAISaw, eax - invoke RandomRange, 2 - inc eax - mov bsAIBeer, eax - invoke RandomRange, 2 - mov bsAICuffs, eax - ret -BuckshotGiveItems ENDP - -; --- BuckshotLoad: аккаунты, файлы сохранений и загрузка профиля --- -BuckshotLoad PROC uses eax ebx ecx edi - invoke RandomRange, 5 - add eax, 4 - mov bsShellCount, eax - mov bsShellIndex, 0 - mov bsLiveCount, 0 - mov bsBlankCount, 0 - mov bsKnownShell, 0FFFFFFFFh - mov edi, OFFSET bsShells - mov ecx, bsShellCount -bs_load_loop: - invoke RandomRange, 2 - mov [edi], eax - cmp eax, 1 - je bs_count_live - inc bsBlankCount - jmp bs_count_done -bs_count_live: - inc bsLiveCount -bs_count_done: - add edi, 4 - loop bs_load_loop - cmp bsLiveCount, 0 - jne bs_has_live - mov dword ptr bsShells, 1 - inc bsLiveCount - dec bsBlankCount -bs_has_live: - cmp bsBlankCount, 0 - jne bs_has_blank - mov dword ptr bsShells+4, 0 - inc bsBlankCount - dec bsLiveCount -bs_has_blank: - invoke PrintStr, OFFSET bsLoadText - invoke PrintUInt, bsLiveCount - invoke PrintStr, OFFSET bsLiveText - invoke PrintUInt, bsBlankCount - invoke PrintStr, OFFSET bsBlankText - invoke Sleep, 900 - ret -BuckshotLoad ENDP - -; --- BuckshotCurrentShell: Buckshot Roulette: патроны, предметы, ходы игрока и ИИ --- -BuckshotCurrentShell PROC uses ebx - mov ebx, bsShellIndex - mov eax, bsShells[ebx*4] - ret -BuckshotCurrentShell ENDP - -; --- BuckshotAdvance: Buckshot Roulette: патроны, предметы, ходы игрока и ИИ --- -BuckshotAdvance PROC - cmp bsShell, 1 - je bs_advance_live - cmp bsBlankCount, 0 - je bs_advance_count_done - dec bsBlankCount - jmp bs_advance_count_done -bs_advance_live: - cmp bsLiveCount, 0 - je bs_advance_count_done - dec bsLiveCount -bs_advance_count_done: - inc bsShellIndex - mov bsKnownShell, 0FFFFFFFFh - mov bsDamage, 1 - ret -BuckshotAdvance ENDP - -; --- BuckshotRemaining: Buckshot Roulette: патроны, предметы, ходы игрока и ИИ --- -BuckshotRemaining PROC uses ebx - mov eax, bsShellCount - sub eax, bsShellIndex - ret -BuckshotRemaining ENDP - -; --- BuckshotPrintKnown: Buckshot Roulette: патроны, предметы, ходы игрока и ИИ --- -BuckshotPrintKnown PROC - mov eax, bsKnownShell - cmp eax, 1 - je bs_print_known_live - cmp eax, 0 - je bs_print_known_blank - invoke PrintStr, OFFSET bsKnownUnknownText - ret -bs_print_known_live: - invoke SetColor, COLOR_BAD - invoke PrintStr, OFFSET bsKnownLiveText - call ResetColor - ret -bs_print_known_blank: - invoke SetColor, COLOR_WARN - invoke PrintStr, OFFSET bsKnownBlankText - call ResetColor - ret -BuckshotPrintKnown ENDP - -; --- BuckshotStatus: Buckshot Roulette: патроны, предметы, ходы игрока и ИИ --- -BuckshotStatus PROC - call ClearView - invoke PrintTitleColor, OFFSET buckshotTitle - invoke SetColor, COLOR_CARD - invoke PrintStr, OFFSET bsShotgunArt - call ResetColor - invoke PrintStr, OFFSET bsHPText - invoke PrintUInt, bsPlayerHP - invoke PrintStr, OFFSET bsAIHPText - invoke PrintUInt, bsAIHP - invoke PrintStr, OFFSET nl - invoke PrintStr, OFFSET bsShellInfoText - invoke PrintUInt, bsLiveCount - invoke PrintStr, OFFSET bsLiveText - invoke PrintUInt, bsBlankCount - invoke PrintStr, OFFSET bsBlankText - invoke PrintStr, OFFSET bsLeftText - call BuckshotRemaining - invoke PrintUInt, eax - invoke PrintStr, OFFSET nl - call BuckshotPrintKnown - invoke PrintStr, OFFSET bsItemsText - invoke PrintUInt, bsPlayerGlass - invoke PrintStr, OFFSET bsSawText - invoke PrintUInt, bsPlayerSaw - invoke PrintStr, OFFSET bsBeerText - invoke PrintUInt, bsPlayerBeer - invoke PrintStr, OFFSET bsCuffsText - invoke PrintUInt, bsPlayerCuffs - invoke PrintStr, OFFSET nl - ret -BuckshotStatus ENDP - -; --- BuckshotAfterShotTurn: Buckshot Roulette: патроны, предметы, ходы игрока и ИИ --- -BuckshotAfterShotTurn PROC - cmp bsShell, 1 - je bs_after_switch - cmp bsTurn, 0 - je bs_after_player_blank - cmp bsTarget, 1 - je bs_after_keep - jmp bs_after_switch -bs_after_player_blank: - cmp bsTarget, 0 - je bs_after_keep -bs_after_switch: - xor bsTurn, 1 -bs_after_keep: - cmp bsTurn, 0 - je bs_check_skip_player - cmp bsSkipAI, 0 - je bs_after_done - mov bsSkipAI, 0 - invoke PrintStr, OFFSET bsSkipAIText - invoke Sleep, 800 - mov bsTurn, 0 - ret -bs_check_skip_player: - cmp bsSkipPlayer, 0 - je bs_after_done - mov bsSkipPlayer, 0 - invoke PrintStr, OFFSET bsSkipPlayerText - invoke Sleep, 800 - mov bsTurn, 1 -bs_after_done: - ret -BuckshotAfterShotTurn ENDP - -; --- BuckshotShoot: Buckshot Roulette: патроны, предметы, ходы игрока и ИИ --- -BuckshotShoot PROC uses eax ebx - call BuckshotCurrentShell - mov bsShell, eax - cmp bsTarget, 0 - je bs_shoot_player_text - invoke PrintStr, OFFSET bsShootAIText - jmp bs_shoot_text_done -bs_shoot_player_text: - invoke PrintStr, OFFSET bsShootPlayerText -bs_shoot_text_done: - cmp bsShell, 1 - je bs_live_shot - call AnimateBuckshotDry - call PlayRouletteDrySound - invoke PrintStr, OFFSET bsDryText - call BuckshotAdvance - invoke Sleep, 900 - call BuckshotAfterShotTurn - ret -bs_live_shot: - call AnimateBuckshotFire - call PlayRouletteShotSound - invoke SetColor, COLOR_BAD - invoke PrintStr, OFFSET bsHitText - invoke PrintUInt, bsDamage - invoke PrintStr, OFFSET nl - call ResetColor - mov eax, bsDamage - cmp bsTarget, 0 - je bs_damage_player - cmp bsAIHP, eax - ja bs_sub_ai - mov bsAIHP, 0 - jmp bs_damage_done -bs_sub_ai: - sub bsAIHP, eax - jmp bs_damage_done -bs_damage_player: - cmp bsPlayerHP, eax - ja bs_sub_player - mov bsPlayerHP, 0 - jmp bs_damage_done -bs_sub_player: - sub bsPlayerHP, eax -bs_damage_done: - call BuckshotAdvance - invoke Sleep, 1000 - call BuckshotAfterShotTurn - ret -BuckshotShoot ENDP - -; --- BuckshotUseGlass: Buckshot Roulette: патроны, предметы, ходы игрока и ИИ --- -BuckshotUseGlass PROC - call BuckshotCurrentShell - mov bsKnownShell, eax - invoke PrintStr, OFFSET bsGlassUseText - call BuckshotPrintKnown - invoke Sleep, 1000 - ret -BuckshotUseGlass ENDP - -; --- BuckshotUseBeer: Buckshot Roulette: патроны, предметы, ходы игрока и ИИ --- -BuckshotUseBeer PROC - call BuckshotCurrentShell - mov bsShell, eax - invoke PrintStr, OFFSET bsBeerUseText - cmp bsShell, 1 - je bs_beer_live - invoke PrintStr, OFFSET bsBlankLoadedText - jmp bs_beer_done -bs_beer_live: - invoke PrintStr, OFFSET bsLiveLoadedText -bs_beer_done: - call BuckshotAdvance - invoke Sleep, 1000 - ret -BuckshotUseBeer ENDP - -; --- BuckshotPlayerTurn: Buckshot Roulette: патроны, предметы, ходы игрока и ИИ --- -BuckshotPlayerTurn PROC -bs_player_again: - call BuckshotStatus - invoke PrintStr, OFFSET bsPlayerTurnText - invoke PrintStr, OFFSET bsMenuText - call ReadKey - cmp al, '1' - je bs_player_self - cmp al, '2' - je bs_player_ai - cmp al, '3' - je bs_player_glass - cmp al, '4' - je bs_player_saw - cmp al, '5' - je bs_player_beer - cmp al, '6' - je bs_player_cuffs - invoke PrintStr, OFFSET badChoiceText - call PauseConsole - jmp bs_player_again -bs_player_self: - mov bsTarget, 0 - call BuckshotShoot - ret -bs_player_ai: - mov bsTarget, 1 - call BuckshotShoot - ret -bs_player_glass: - cmp bsPlayerGlass, 0 - je bs_player_no_item - dec bsPlayerGlass - call BuckshotUseGlass - jmp bs_player_again -bs_player_saw: - cmp bsPlayerSaw, 0 - je bs_player_no_item - dec bsPlayerSaw - mov bsDamage, 2 - invoke PrintStr, OFFSET bsSawUseText - invoke Sleep, 900 - jmp bs_player_again -bs_player_beer: - cmp bsPlayerBeer, 0 - je bs_player_no_item - dec bsPlayerBeer - call BuckshotUseBeer - call BuckshotRemaining - cmp eax, 0 - je bs_player_done - jmp bs_player_again -bs_player_cuffs: - cmp bsPlayerCuffs, 0 - je bs_player_no_item - dec bsPlayerCuffs - mov bsSkipAI, 1 - invoke PrintStr, OFFSET bsCuffsUseText - invoke Sleep, 900 - jmp bs_player_again -bs_player_no_item: - invoke PrintStr, OFFSET bsNoItemText - invoke Sleep, 800 - jmp bs_player_again -bs_player_done: - ret -BuckshotPlayerTurn ENDP - -; --- BuckshotAITurn: Buckshot Roulette: патроны, предметы, ходы игрока и ИИ --- -BuckshotAITurn PROC - call BuckshotStatus - invoke PrintStr, OFFSET bsAITurnText - invoke Sleep, 900 - cmp bsKnownShell, 0FFFFFFFFh - jne bs_ai_known - cmp bsAIGlass, 0 - je bs_ai_no_glass - dec bsAIGlass - invoke PrintStr, OFFSET bsAIGlassText - call BuckshotUseGlass -bs_ai_no_glass: -bs_ai_known: - cmp bsKnownShell, 1 - je bs_ai_live - cmp bsKnownShell, 0 - je bs_ai_blank - mov eax, bsLiveCount - cmp eax, bsBlankCount - jae bs_ai_live -bs_ai_blank: - mov bsTarget, 1 - call BuckshotShoot - ret -bs_ai_live: - cmp bsAISaw, 0 - je bs_ai_maybe_cuffs - dec bsAISaw - mov bsDamage, 2 - invoke PrintStr, OFFSET bsAISawText - invoke Sleep, 700 -bs_ai_maybe_cuffs: - cmp bsAICuffs, 0 - je bs_ai_shoot_player - dec bsAICuffs - mov bsSkipPlayer, 1 - invoke PrintStr, OFFSET bsAICuffsText - invoke Sleep, 700 -bs_ai_shoot_player: - mov bsTarget, 0 - call BuckshotShoot - ret -BuckshotAITurn ENDP - -; --- GameBuckshot: Buckshot Roulette: патроны, предметы, ходы игрока и ИИ --- GameBuckshot PROC -buckshot_start: - call ClearView - invoke PrintTitleColor, OFFSET buckshotTitle - invoke PrintStr, OFFSET buckshotIntro - call PromptBet - mov bsPlayerHP, 4 - mov bsAIHP, 4 - mov bsTurn, 0 - mov bsDamage, 1 - mov bsSkipPlayer, 0 - mov bsSkipAI, 0 - call BuckshotGiveItems - call PlayRouletteSpinSound - call AnimateBuckshotLoad - call BuckshotLoad -buckshot_loop: - call BuckshotRemaining - cmp eax, 0 - jne buckshot_has_shells - call AnimateBuckshotLoad - call BuckshotLoad -buckshot_has_shells: - cmp bsPlayerHP, 0 - je buckshot_lost - cmp bsAIHP, 0 - je buckshot_won - cmp bsTurn, 0 - je buckshot_player - call BuckshotAITurn - jmp buckshot_loop -buckshot_player: - call BuckshotPlayerTurn - jmp buckshot_loop -buckshot_won: - call BuckshotStatus - invoke PrintStr, OFFSET bsWinText - invoke PaySlotMultiplier, 3 - jmp buckshot_again -buckshot_lost: - call BuckshotStatus - invoke PrintStr, OFFSET bsLoseText - call PayLose -buckshot_again: - call SaveGame - cmp tournamentMode, 1 - je buckshot_tournament_return - invoke PrintStr, OFFSET againText - call ReadKey - cmp al, 'y' - je buckshot_start - cmp al, 'Y' - je buckshot_start -buckshot_tournament_return: + cmp tournamentStage, 0 + jne tourney_bs + call StartCasino3D + ret +tourney_bs: + call TournamentPlayStage ret GameBuckshot ENDP ; --- PrintDiceParity: вывод текста, цветов, картинок и элементов интерфейса --- -PrintDiceParity PROC parity:DWORD - cmp parity, 1 - jne print_dice_odd - invoke PrintStr, OFFSET diceEvenText - ret -print_dice_odd: - invoke PrintStr, OFFSET diceOddText - ret -PrintDiceParity ENDP - -; --- GameDice: кости: бросок, четность и результат --- GameDice PROC -dice_start: - call ClearView - invoke PrintTitleColor, OFFSET diceTitle - invoke PrintStr, OFFSET diceIntroText - call PromptBet - -dice_choose: - call ClearView - invoke PrintTitleColor, OFFSET diceTitle - invoke PrintStr, OFFSET diceIntroText - call PrintBank - invoke PrintStr, OFFSET diceChoiceText - call ReadKey - cmp al, '1' - je dice_pick_even - cmp al, '2' - je dice_pick_odd - invoke PrintStr, OFFSET badChoiceText - call PauseConsole - jmp dice_choose - -dice_pick_even: - mov diceChoice, 1 - jmp dice_roll -dice_pick_odd: - mov diceChoice, 2 - -dice_roll: - invoke SetColor, COLOR_WARN - invoke PrintStr, OFFSET diceRollText - call ResetColor - invoke Sleep, 500 - invoke RandomRange, 6 - inc eax - mov diceA, eax - invoke RandomRange, 6 - inc eax - mov diceB, eax - mov eax, diceA - add eax, diceB - mov diceSum, eax - invoke PrintStr, OFFSET diceFirstText - invoke PrintUInt, diceA - invoke PrintStr, OFFSET nl - invoke PrintStr, OFFSET diceSecondText - invoke PrintUInt, diceB - invoke PrintStr, OFFSET nl - invoke PrintStr, OFFSET diceSumText - invoke PrintUInt, diceSum - invoke PrintStr, OFFSET nl - mov eax, diceSum - and eax, 1 - cmp eax, 0 - je dice_result_even - mov eax, 2 - jmp dice_compare -dice_result_even: - mov eax, 1 -dice_compare: - cmp eax, diceChoice - je dice_win - call PrintLoseEvent - call PayLose - jmp dice_again -dice_win: - call PrintWinEvent - call PayWin - -dice_again: - cmp tournamentMode, 1 - je dice_tournament_return - invoke PrintStr, OFFSET againText - call ReadKey - cmp al, 'y' - je dice_start - cmp al, 'Y' - je dice_start -dice_tournament_return: + cmp tournamentStage, 0 + jne tourney_dice + call StartCasino3D + ret +tourney_dice: + call TournamentPlayStage ret GameDice ENDP ; --- Online Dice: Radmin LAN match without a separate server process --- @@ -10673,590 +9267,32 @@ online_casino_done: GameOnlineCasino ENDP ; --- PrintCoinSide: вывод текста, цветов, картинок и элементов интерфейса --- -PrintCoinSide PROC side:DWORD - cmp side, 1 - jne print_coin_tails - invoke PrintStr, OFFSET coinHeadsText - ret -print_coin_tails: - invoke PrintStr, OFFSET coinTailsText - ret -PrintCoinSide ENDP - -; --- ShowCoinFlipFrame: звук, интро или покадровая анимация --- -ShowCoinFlipFrame PROC uses eax, pFrame:DWORD - call ClearView - invoke PrintTitleColor, OFFSET coinTitle - invoke PrintStr, OFFSET coinIntroText - call PrintBank - invoke PrintStr, OFFSET coinPickText - invoke PrintCoinSide, coinPick - invoke SetColor, COLOR_WARN - invoke PrintStr, OFFSET coinSpinText - mov eax, pFrame - invoke PrintStr, eax - call ResetColor - invoke Sleep, 170 - ret -ShowCoinFlipFrame ENDP - -; --- AnimateCoinFlip: орел и решка: выбор стороны, звук и анимация монеты --- -AnimateCoinFlip PROC - invoke ShowCoinFlipFrame, OFFSET coinFrame1 - invoke ShowCoinFlipFrame, OFFSET coinFrame2 - invoke ShowCoinFlipFrame, OFFSET coinFrame3 - invoke ShowCoinFlipFrame, OFFSET coinFrame4 - invoke ShowCoinFlipFrame, OFFSET coinFrame5 - invoke ShowCoinFlipFrame, OFFSET coinFrame6 - invoke ShowCoinFlipFrame, OFFSET coinFrame7 - invoke ShowCoinFlipFrame, OFFSET coinFrame8 - invoke ShowCoinFlipFrame, OFFSET coinFrame9 - invoke ShowCoinFlipFrame, OFFSET coinFrame10 - invoke ShowCoinFlipFrame, OFFSET coinFrame11 - invoke ShowCoinFlipFrame, OFFSET coinFrame12 - invoke ShowCoinFlipFrame, OFFSET coinFrame13 - invoke ShowCoinFlipFrame, OFFSET coinFrame14 - ret -AnimateCoinFlip ENDP - -; --- GameCoin: орел и решка: выбор стороны, звук и анимация монеты --- GameCoin PROC -coin_start: - call ClearView - invoke PrintTitleColor, OFFSET coinTitle - invoke PrintStr, OFFSET coinIntroText - call PromptBet - -coin_choose: - call ClearView - invoke PrintTitleColor, OFFSET coinTitle - invoke PrintStr, OFFSET coinIntroText - call PrintBank - invoke PrintStr, OFFSET coinChoiceText - call ReadKey - cmp al, '1' - je coin_pick_heads - cmp al, '2' - je coin_pick_tails - invoke PrintStr, OFFSET badChoiceText - call PauseConsole - jmp coin_choose - -coin_pick_heads: - mov coinPick, 1 - jmp coin_flip -coin_pick_tails: - mov coinPick, 2 - -coin_flip: - invoke PrintStr, OFFSET coinPickText - invoke PrintCoinSide, coinPick - call PlayCoinSound - call AnimateCoinFlip - invoke RandomRange, 2 - inc eax - mov coinResult, eax - invoke PrintStr, OFFSET coinResultText - invoke PrintCoinSide, coinResult - mov eax, coinPick - cmp eax, coinResult - je coin_win - call PrintLoseEvent - call PayLose - jmp coin_again -coin_win: - call PrintWinEvent - call PayWin - -coin_again: - cmp tournamentMode, 1 - je coin_tournament_return - invoke PrintStr, OFFSET againText - call ReadKey - cmp al, 'y' - je coin_start - cmp al, 'Y' - je coin_start -coin_tournament_return: + cmp tournamentStage, 0 + jne tourney_coin + call StartCasino3D + ret +tourney_coin: + call TournamentPlayStage ret GameCoin ENDP ; --- PrintRouletteColorName: вывод текста, цветов, картинок и элементов интерфейса --- -PrintRouletteColorName PROC uses eax ebx, value:DWORD - mov eax, value - cmp eax, 0 - jne roulette_color_not_zero - invoke SetColor, COLOR_MONEY - invoke PrintStr, OFFSET rouletteGreenName - call ResetColor - ret -roulette_color_not_zero: - movzx ebx, byte ptr [rouletteColors + eax] - cmp ebx, 1 - jne roulette_color_black - invoke SetColor, COLOR_BAD - invoke PrintStr, OFFSET rouletteRedName - call ResetColor - ret -roulette_color_black: - invoke SetColor, COLOR_CARD - invoke PrintStr, OFFSET rouletteBlackName - call ResetColor - ret -PrintRouletteColorName ENDP - -; --- PrintRouletteNumberColored: вывод текста, цветов, картинок и элементов интерфейса --- -PrintRouletteNumberColored PROC uses eax ebx, value:DWORD - mov eax, value - cmp eax, 0 - jne roulette_number_not_zero - invoke SetColor, COLOR_MONEY - jmp roulette_number_print -roulette_number_not_zero: - movzx ebx, byte ptr [rouletteColors + eax] - cmp ebx, 1 - jne roulette_number_black - invoke SetColor, COLOR_BAD - jmp roulette_number_print -roulette_number_black: - invoke SetColor, COLOR_CARD -roulette_number_print: - invoke PrintUInt, value - call ResetColor - ret -PrintRouletteNumberColored ENDP - -; --- PrintRoulettePocket: вывод текста, цветов, картинок и элементов интерфейса --- -PrintRoulettePocket PROC uses eax, wheelIndex:DWORD - invoke PrintStr, OFFSET roulettePocketLeft - mov eax, wheelIndex - mov eax, [rouletteWheel + eax * 4] - push eax - cmp eax, 10 - jae roulette_pocket_no_pad - invoke PrintStr, OFFSET rouletteNumSpace -roulette_pocket_no_pad: - pop eax - invoke PrintRouletteNumberColored, eax - invoke PrintStr, OFFSET roulettePocketRight - ret -PrintRoulettePocket ENDP - -; --- PrintRoulettePocketOffset: вывод текста, цветов, картинок и элементов интерфейса --- -PrintRoulettePocketOffset PROC uses eax, wheelOffset:DWORD - mov eax, casinoRouletteSpinIndex - add eax, wheelOffset -roulette_offset_wrap: - cmp eax, 37 - jb roulette_offset_ready - sub eax, 37 - jmp roulette_offset_wrap -roulette_offset_ready: - invoke PrintRoulettePocket, eax - ret -PrintRoulettePocketOffset ENDP - -; --- PrintRouletteTopRow: вывод текста, цветов, картинок и элементов интерфейса --- -PrintRouletteTopRow PROC - invoke PrintStr, OFFSET casinoRoulettePad - invoke PrintRoulettePocketOffset, 31 - invoke PrintRoulettePocketOffset, 32 - invoke PrintRoulettePocketOffset, 33 - invoke PrintRoulettePocketOffset, 34 - invoke PrintRoulettePocketOffset, 35 - invoke PrintRoulettePocketOffset, 36 - invoke PrintRoulettePocketOffset, 0 - invoke PrintRoulettePocketOffset, 1 - invoke PrintRoulettePocketOffset, 2 - invoke PrintRoulettePocketOffset, 3 - invoke PrintRoulettePocketOffset, 4 - invoke PrintRoulettePocketOffset, 5 - invoke PrintRoulettePocketOffset, 6 - invoke PrintStr, OFFSET nl - ret -PrintRouletteTopRow ENDP - -; --- PrintRouletteBottomRow: вывод текста, цветов, картинок и элементов интерфейса --- -PrintRouletteBottomRow PROC - invoke PrintStr, OFFSET casinoRoulettePad - invoke PrintRoulettePocketOffset, 24 - invoke PrintRoulettePocketOffset, 23 - invoke PrintRoulettePocketOffset, 22 - invoke PrintRoulettePocketOffset, 21 - invoke PrintRoulettePocketOffset, 20 - invoke PrintRoulettePocketOffset, 19 - invoke PrintRoulettePocketOffset, 18 - invoke PrintRoulettePocketOffset, 17 - invoke PrintRoulettePocketOffset, 16 - invoke PrintRoulettePocketOffset, 15 - invoke PrintRoulettePocketOffset, 14 - invoke PrintRoulettePocketOffset, 13 - invoke PrintStr, OFFSET nl - ret -PrintRouletteBottomRow ENDP - -; --- PrintRouletteSideRow: вывод текста, цветов, картинок и элементов интерфейса --- -PrintRouletteSideRow PROC leftOffset:DWORD, pGap:DWORD, rightOffset:DWORD - invoke SetColor, COLOR_WOOD - invoke PrintStr, OFFSET rouletteBigSidePad - call ResetColor - invoke PrintRoulettePocketOffset, leftOffset - invoke SetColor, COLOR_TABLE - invoke PrintStr, pGap - call ResetColor - invoke PrintRoulettePocketOffset, rightOffset - invoke PrintStr, OFFSET nl - ret -PrintRouletteSideRow ENDP - -; --- ShowCasinoRouletteFrame: звук, интро или покадровая анимация --- -ShowCasinoRouletteFrame PROC - call ClearView - invoke PrintTitleColor, OFFSET casinoRouletteTitle - invoke SetColor, COLOR_WOOD - invoke PrintStr, OFFSET casinoRouletteWheelTop - call ResetColor - call PrintRouletteTopRow - invoke PrintRouletteSideRow, 30, OFFSET rouletteBigSideGap1, 7 - invoke PrintRouletteSideRow, 29, OFFSET rouletteBigSideGap2, 8 - invoke PrintRouletteSideRow, 28, OFFSET rouletteBigSideGap3, 9 - invoke PrintRouletteSideRow, 27, OFFSET rouletteBigSideGap4, 10 - invoke PrintRouletteSideRow, 26, OFFSET rouletteBigSideGap5, 11 - invoke PrintRouletteSideRow, 25, OFFSET rouletteBigSideGap6, 12 - call PrintRouletteBottomRow - invoke SetColor, COLOR_WOOD - invoke PrintStr, OFFSET casinoRouletteWheelBottom - call ResetColor - invoke PrintStr, OFFSET casinoRouletteSpinText - ret -ShowCasinoRouletteFrame ENDP - -; --- AnimateCasinoRouletteSpin: русская рулетка или казино-рулетка --- -AnimateCasinoRouletteSpin PROC uses eax ebx edx - invoke GetTickCount - xor seed, eax - invoke RandomRange, 37 - mov casinoRouletteResultIndex, eax - mov ebx, eax - mov eax, [rouletteWheel + ebx * 4] - mov casinoRouletteResult, eax - - invoke RandomRange, 18 - add eax, 72 - mov casinoRouletteSpinSteps, eax - mov casinoRouletteSpinCounter, eax - - xor edx, edx - mov ebx, 37 - div ebx - mov eax, casinoRouletteResultIndex - add eax, 37 - sub eax, edx - cmp eax, 37 - jb casino_roulette_start_ready - sub eax, 37 -casino_roulette_start_ready: - mov casinoRouletteSpinIndex, eax - -casino_roulette_spin_loop: - inc casinoRouletteSpinIndex - cmp casinoRouletteSpinIndex, 37 - jb casino_roulette_spin_index_ok - mov casinoRouletteSpinIndex, 0 -casino_roulette_spin_index_ok: - call ShowCasinoRouletteFrame - mov eax, casinoRouletteSpinCounter - cmp eax, 12 - jbe casino_roulette_sleep_slow - cmp eax, 26 - jbe casino_roulette_sleep_mid - invoke Sleep, 45 - jmp casino_roulette_after_sleep -casino_roulette_sleep_mid: - invoke Sleep, 95 - jmp casino_roulette_after_sleep -casino_roulette_sleep_slow: - invoke Sleep, 170 -casino_roulette_after_sleep: - dec casinoRouletteSpinCounter - cmp casinoRouletteSpinCounter, 0 - jne casino_roulette_spin_loop - mov ebx, casinoRouletteSpinIndex - mov casinoRouletteResultIndex, ebx - mov eax, [rouletteWheel + ebx * 4] - mov casinoRouletteResult, eax - ret -AnimateCasinoRouletteSpin ENDP - -; --- CasinoRouletteEvaluate: русская рулетка или казино-рулетка --- -CasinoRouletteEvaluate PROC uses eax ebx edx - invoke PrintStr, OFFSET casinoRouletteResultText - invoke PrintRouletteNumberColored, casinoRouletteResult - invoke PrintStr, OFFSET rouletteNumSpace - invoke PrintRouletteColorName, casinoRouletteResult - - mov eax, casinoRouletteBetType - cmp eax, 1 - je casino_roulette_eval_number - cmp eax, 2 - je casino_roulette_eval_red - cmp eax, 3 - je casino_roulette_eval_black - cmp eax, 4 - je casino_roulette_eval_even - cmp eax, 5 - je casino_roulette_eval_odd - cmp eax, 6 - je casino_roulette_eval_dozen1 - cmp eax, 7 - je casino_roulette_eval_dozen2 - cmp eax, 8 - je casino_roulette_eval_dozen3 - cmp eax, 9 - je casino_roulette_eval_low - cmp eax, 10 - je casino_roulette_eval_high - cmp eax, 11 - je casino_roulette_eval_col1 - cmp eax, 12 - je casino_roulette_eval_col2 - cmp eax, 13 - je casino_roulette_eval_col3 - jmp casino_roulette_lost - -casino_roulette_eval_number: - mov eax, casinoRouletteResult - cmp eax, casinoRouletteBetNumber - jne casino_roulette_lost - invoke UnlockAchievement, 800h, OFFSET achRouletteWinName - invoke PrintStr, OFFSET casinoRouletteWinText - invoke PaySlotMultiplier, 35 - ret - -casino_roulette_eval_red: - mov eax, casinoRouletteResult - movzx ebx, byte ptr [rouletteColors + eax] - cmp ebx, 1 - je casino_roulette_won_even_money - jmp casino_roulette_lost - -casino_roulette_eval_black: - mov eax, casinoRouletteResult - movzx ebx, byte ptr [rouletteColors + eax] - cmp ebx, 2 - je casino_roulette_won_even_money - jmp casino_roulette_lost - -casino_roulette_eval_even: - mov eax, casinoRouletteResult - cmp eax, 0 - je casino_roulette_lost - test eax, 1 - jz casino_roulette_won_even_money - jmp casino_roulette_lost - -casino_roulette_eval_odd: - mov eax, casinoRouletteResult - cmp eax, 0 - je casino_roulette_lost - test eax, 1 - jnz casino_roulette_won_even_money - jmp casino_roulette_lost - -casino_roulette_eval_dozen1: - mov eax, casinoRouletteResult - cmp eax, 1 - jb casino_roulette_lost - cmp eax, 12 - jbe casino_roulette_won_double - jmp casino_roulette_lost -casino_roulette_eval_dozen2: - mov eax, casinoRouletteResult - cmp eax, 13 - jb casino_roulette_lost - cmp eax, 24 - jbe casino_roulette_won_double - jmp casino_roulette_lost -casino_roulette_eval_dozen3: - mov eax, casinoRouletteResult - cmp eax, 25 - jb casino_roulette_lost - cmp eax, 36 - jbe casino_roulette_won_double - jmp casino_roulette_lost -casino_roulette_eval_low: - mov eax, casinoRouletteResult - cmp eax, 1 - jb casino_roulette_lost - cmp eax, 18 - jbe casino_roulette_won_even_money - jmp casino_roulette_lost -casino_roulette_eval_high: - mov eax, casinoRouletteResult - cmp eax, 36 - jbe casino_roulette_won_even_money - jmp casino_roulette_lost -casino_roulette_eval_col1: - mov eax, casinoRouletteResult - cmp eax, 0 - je casino_roulette_lost - dec eax - xor edx, edx - mov ebx, 3 - div ebx - cmp edx, 0 - je casino_roulette_won_double - jmp casino_roulette_lost -casino_roulette_eval_col2: - mov eax, casinoRouletteResult - cmp eax, 0 - je casino_roulette_lost - dec eax - xor edx, edx - mov ebx, 3 - div ebx - cmp edx, 1 - je casino_roulette_won_double - jmp casino_roulette_lost -casino_roulette_eval_col3: - mov eax, casinoRouletteResult - cmp eax, 0 - je casino_roulette_lost - dec eax - xor edx, edx - mov ebx, 3 - div ebx - cmp edx, 2 - je casino_roulette_won_double - jmp casino_roulette_lost - -casino_roulette_won_double: - invoke UnlockAchievement, 800h, OFFSET achRouletteWinName - invoke PrintStr, OFFSET casinoRouletteWinText - invoke PaySlotMultiplier, 2 - ret -casino_roulette_won_even_money: - invoke UnlockAchievement, 800h, OFFSET achRouletteWinName - invoke PrintStr, OFFSET casinoRouletteWinText - call PayWin - ret -casino_roulette_lost: - invoke PrintStr, OFFSET casinoRouletteLoseText - call PayLose - ret -CasinoRouletteEvaluate ENDP - -; --- GameCasinoRoulette: русская рулетка или казино-рулетка --- GameCasinoRoulette PROC -casino_roulette_start: - call ClearView - invoke PrintTitleColor, OFFSET casinoRouletteTitle - invoke PrintStr, OFFSET casinoRouletteIntro - call PromptBet - -casino_roulette_choose: - call ClearView - invoke PrintTitleColor, OFFSET casinoRouletteTitle - invoke PrintStr, OFFSET casinoRouletteIntro - call PrintBank - invoke PrintStr, OFFSET casinoRouletteBetMenu - call ReadUInt - cmp eax, 1 - je casino_roulette_choose_number - cmp eax, 2 - je casino_roulette_choose_red - cmp eax, 3 - je casino_roulette_choose_black - cmp eax, 4 - je casino_roulette_choose_even - cmp eax, 5 - je casino_roulette_choose_odd - cmp eax, 6 - je casino_roulette_choose_dozen1 - cmp eax, 7 - je casino_roulette_choose_dozen2 - cmp eax, 8 - je casino_roulette_choose_dozen3 - cmp eax, 9 - je casino_roulette_choose_low - cmp eax, 10 - je casino_roulette_choose_high - cmp eax, 11 - je casino_roulette_choose_col1 - cmp eax, 12 - je casino_roulette_choose_col2 - cmp eax, 13 - je casino_roulette_choose_col3 - invoke PrintStr, OFFSET badChoiceText - call PauseConsole - jmp casino_roulette_choose - -casino_roulette_choose_number: - mov casinoRouletteBetType, 1 - invoke PrintStr, OFFSET casinoRouletteNumberAsk - call ReadUInt - cmp eax, 36 - ja casino_roulette_bad_number - mov casinoRouletteBetNumber, eax - jmp casino_roulette_spin -casino_roulette_bad_number: - invoke PrintStr, OFFSET casinoRouletteBadNumber - call PauseConsole - jmp casino_roulette_choose - -casino_roulette_choose_red: - mov casinoRouletteBetType, 2 - jmp casino_roulette_spin -casino_roulette_choose_black: - mov casinoRouletteBetType, 3 - jmp casino_roulette_spin -casino_roulette_choose_even: - mov casinoRouletteBetType, 4 - jmp casino_roulette_spin -casino_roulette_choose_odd: - mov casinoRouletteBetType, 5 - jmp casino_roulette_spin -casino_roulette_choose_dozen1: - mov casinoRouletteBetType, 6 - jmp casino_roulette_spin -casino_roulette_choose_dozen2: - mov casinoRouletteBetType, 7 - jmp casino_roulette_spin -casino_roulette_choose_dozen3: - mov casinoRouletteBetType, 8 - jmp casino_roulette_spin -casino_roulette_choose_low: - mov casinoRouletteBetType, 9 - jmp casino_roulette_spin -casino_roulette_choose_high: - mov casinoRouletteBetType, 10 - jmp casino_roulette_spin -casino_roulette_choose_col1: - mov casinoRouletteBetType, 11 - jmp casino_roulette_spin -casino_roulette_choose_col2: - mov casinoRouletteBetType, 12 - jmp casino_roulette_spin -casino_roulette_choose_col3: - mov casinoRouletteBetType, 13 - -casino_roulette_spin: - call PlayCasinoRouletteSound - call AnimateCasinoRouletteSpin - call CasinoRouletteEvaluate - -casino_roulette_again: - cmp tournamentMode, 1 - je casino_roulette_tournament_return - invoke PrintStr, OFFSET againText - call ReadKey - cmp al, 'y' - je casino_roulette_start - cmp al, 'Y' - je casino_roulette_start -casino_roulette_tournament_return: + cmp tournamentStage, 0 + jne tourney_croul + call StartCasino3D + ret +tourney_croul: + call TournamentPlayStage ret GameCasinoRoulette ENDP +; --- SlotApplyWin: слот-машины, барабаны, символы, выплаты и джекпоты --- +GameSlot PROC + call StartCasino3D + ret +GameSlot ENDP + ; --- SlotApplyWin: слот-машины, барабаны, символы, выплаты и джекпоты --- SlotApplyWin PROC uses ebx ecx edx, pName:DWORD, multiplier:DWORD, maskValue:DWORD mov eax, pName @@ -11291,8 +9327,8 @@ slot_apply_record: mov eax, pName mov slotComboNames[ebx * 4], eax mov slotComboMults[ebx * 4], edx - mov ecx,maskValue - mov slotComboMasks[ebx * 4],ecx + mov ecx,maskValue + mov slotComboMasks[ebx * 4],ecx inc slotComboCount slot_apply_no_store: mov eax, 1 @@ -11489,241 +9525,8 @@ slot_eval_eye: ret EvaluateSlotCombos ENDP -; --- AwardSlotWin: слот-машины, барабаны, символы, выплаты и джекпоты --- -AwardSlotWin PROC uses ebx - invoke UnlockAchievement, 80h, OFFSET achCloverPitName - call PrintSlotWindow - invoke PrintStr, OFFSET slotPair - mov slotCurrentCell, 0 -slot_award_combo_loop: - mov eax, slotCurrentCell - cmp eax, slotComboCount - jae slot_award_combo_done - invoke PrintStr, OFFSET slotComboText - mov ebx, slotCurrentCell - mov eax, slotComboNames[ebx * 4] - invoke PrintStr, eax - invoke PrintStr, OFFSET cardGap - invoke PrintStr, OFFSET slotMultiplierText - mov ebx, slotCurrentCell - mov eax, slotComboMults[ebx * 4] - invoke PrintUInt, eax - invoke PrintStr, OFFSET nl - inc slotCurrentCell - jmp slot_award_combo_loop -slot_award_combo_done: - invoke PrintStr, OFFSET slotTotalMultiplierText - invoke PrintUInt, slotBestMultiplier - invoke PrintStr, OFFSET nl - cmp slotJackpotHit, 1 - jne slot_award_regular - call PlayJackpotSound - invoke Sleep, 650 - call PlayHakariSound - call PlayHakariDance - call PrintSlotWindow -slot_award_regular: - invoke PaySlotMultiplier, slotBestMultiplier - ret -AwardSlotWin ENDP -; --- GameSlot: слот-машины, барабаны, символы, выплаты и джекпоты --- -GameSlot PROC -slot_start: - call ClearView - invoke PrintTitleColor, OFFSET slotTitle - invoke PrintStr, OFFSET slotPayTableText - call PromptBet - call PlaySlotSound - invoke Sleep, 400 - invoke PrintStr, OFFSET slotPullText - mov slotWinMask, 0 - mov slotVisible, 0 - call PrintSlotWindow - invoke Sleep, 1400 - - invoke FillSlotColumn, 0 - mov slotVisible, 1 - call PrintSlotWindow - invoke Sleep, 620 - - invoke FillSlotColumn, 1 - mov slotVisible, 2 - call PrintSlotWindow - invoke Sleep, 620 - - invoke FillSlotColumn, 2 - mov slotVisible, 3 - call PrintSlotWindow - invoke Sleep, 620 - - invoke FillSlotColumn, 3 - mov slotVisible, 4 - call PrintSlotWindow - invoke Sleep, 620 - - invoke FillSlotColumn, 4 - mov slotVisible, 5 - call PrintSlotWindow - invoke Sleep, 450 - - cmp cheatSlotJackpot, 1 - jne slot_no_forced_jackpot - mov cheatSlotJackpot, 0 - mov ecx, 15 - mov edi, OFFSET slotGrid -slot_force_jackpot_loop: - mov dword ptr [edi], 6 - add edi, 4 - loop slot_force_jackpot_loop - call PrintSlotWindow - invoke Sleep, 300 -slot_no_forced_jackpot: - - call EvaluateSlotCombos - cmp slotBestMultiplier, 0 - jne slot_has_win - invoke PrintStr, OFFSET slotEmpty - call PayLose - jmp ask_slot_again - -slot_has_win: - call AwardSlotWin - -ask_slot_again: - invoke PrintStr, OFFSET againText - call ReadKey - cmp al, 'y' - je slot_start - cmp al, 'Y' - je slot_start - ret -GameSlot ENDP ; --- PrintClassicSlotSymbol: вывод текста, цветов, картинок и элементов интерфейса --- -PrintClassicSlotSymbol PROC uses eax, value:DWORD - mov eax, value - cmp eax, 0 - je classic_symbol_red - cmp eax, 1 - je classic_symbol_yellow - cmp eax, 2 - je classic_symbol_green - cmp eax, 5 - je classic_symbol_cyan - invoke SetColor, COLOR_WARN - jmp classic_symbol_print -classic_symbol_red: - invoke SetColor, COLOR_BAD - jmp classic_symbol_print -classic_symbol_yellow: - invoke SetColor, COLOR_WARN - jmp classic_symbol_print -classic_symbol_green: - invoke SetColor, COLOR_MONEY - jmp classic_symbol_print -classic_symbol_cyan: - invoke SetColor, COLOR_TITLE -classic_symbol_print: - mov eax, value - invoke PrintStr, classicSlotSymbols[eax * 4] - call ResetColor - ret -PrintClassicSlotSymbol ENDP - -; --- PrintClassicSlotCell: вывод текста, цветов, картинок и элементов интерфейса --- -PrintClassicSlotCell PROC uses eax, value:DWORD - mov eax, value - cmp eax, 1 - je classic_slot_cell_bar - invoke PrintStr, OFFSET slotWall - invoke PrintStr, OFFSET slotPadTwo - invoke PrintClassicSlotSymbol, value - invoke PrintStr, OFFSET slotPadTwo - ret -classic_slot_cell_bar: - invoke PrintStr, OFFSET slotWall - invoke PrintStr, OFFSET slotPadOne - invoke PrintClassicSlotSymbol, value - invoke PrintStr, OFFSET slotPadOne - ret -PrintClassicSlotCell ENDP - -; --- PrintClassicSlotBlankCell: вывод текста, цветов, картинок и элементов интерфейса --- -PrintClassicSlotBlankCell PROC - invoke PrintStr, OFFSET slotWall - invoke PrintStr, OFFSET slotCellBlank - ret -PrintClassicSlotBlankCell ENDP - -; --- PrintClassicSlotWindow: вывод текста, цветов, картинок и элементов интерфейса --- -PrintClassicSlotWindow PROC uses eax ebx - call ClearView - invoke PrintTitleColor, OFFSET classicSlotTitle - invoke PrintStr, OFFSET classicSlotBorder - - mov rowIndex, 0 -classic_slot_window_row_loop: - cmp rowIndex, 3 - jae classic_slot_window_done - mov ebx, rowIndex - imul ebx, 3 - - cmp slotVisible, 1 - jb classic_slot_blank_col1 - invoke PrintClassicSlotCell, slotGrid[ebx * 4] - jmp classic_slot_col2 -classic_slot_blank_col1: - call PrintClassicSlotBlankCell - -classic_slot_col2: - cmp slotVisible, 2 - jb classic_slot_blank_col2 - mov eax, ebx - inc eax - invoke PrintClassicSlotCell, slotGrid[eax * 4] - jmp classic_slot_col3 -classic_slot_blank_col2: - call PrintClassicSlotBlankCell - -classic_slot_col3: - cmp slotVisible, 3 - jb classic_slot_blank_col3 - mov eax, ebx - add eax, 2 - invoke PrintClassicSlotCell, slotGrid[eax * 4] - jmp classic_slot_row_end -classic_slot_blank_col3: - call PrintClassicSlotBlankCell - -classic_slot_row_end: - invoke PrintStr, OFFSET slotWall - invoke PrintStr, OFFSET nl - cmp rowIndex, 1 - jne classic_no_payline - invoke PrintStr, OFFSET classicSlotPayline -classic_no_payline: - invoke PrintStr, OFFSET classicSlotBorder - inc rowIndex - jmp classic_slot_window_row_loop - -classic_slot_window_done: - ret -PrintClassicSlotWindow ENDP - -; --- FillClassicSlotColumn: слот-машины, барабаны, символы, выплаты и джекпоты --- -FillClassicSlotColumn PROC uses eax ebx, column:DWORD - mov ebx, column - invoke RandomRange, 6 - mov slotGrid[ebx * 4], eax - mov ebx, column - add ebx, 3 - invoke RandomRange, 6 - mov slotGrid[ebx * 4], eax - mov ebx, column - add ebx, 7 - invoke RandomRange, 6 - mov slotGrid[ebx * 4], eax - ret -FillClassicSlotColumn ENDP +; (Legacy terminal classic slot helpers removed) ; --- DurakCardRank: карты, руки, очки и базовая карточная логика --- DurakCardRank PROC uses ecx edx, card:DWORD @@ -12280,406 +10083,18 @@ setup_durak_deal: SetupDurak ENDP ; --- PlayerOpenAttackLoop: звук, интро или покадровая анимация --- -PlayerOpenAttackLoop PROC uses ebx ecx -player_open_attack_loop: - mov eax, durakTableCnt - cmp eax, 6 - jae player_open_attack_done - cmp eax, durakAICnt - jae player_open_attack_done - call ShowDurakTable - invoke PrintStr, OFFSET durakThrowAsk - call ReadUInt - cmp eax, 0 - je player_open_attack_done - cmp eax, 1 - jb player_open_attack_bad - cmp eax, durakPlayerCnt - ja player_open_attack_bad - dec eax - mov durakChoice, eax - mov ebx, OFFSET durakPlayerHand - mov ecx, [ebx + eax * 4] - invoke DurakRankOnTable, ecx - cmp eax, 1 - jne player_open_attack_bad - invoke RemoveDurakCard, OFFSET durakPlayerHand, OFFSET durakPlayerCnt, durakChoice - call AddDurakAttack - jmp player_open_attack_loop -player_open_attack_bad: - invoke PrintStr, OFFSET durakBadMoveText - invoke Sleep, 650 - jmp player_open_attack_loop -player_open_attack_done: - ret -PlayerOpenAttackLoop ENDP - -; --- AIInitialThrowLoop: дурак: козырь, атака, защита, подкидывание и добор --- -AIInitialThrowLoop PROC - mov durakLoopGuard, 0 -ai_initial_throw_loop: - inc durakLoopGuard - cmp durakLoopGuard, 20 - ja ai_initial_throw_done - call FindAIThrowIn - cmp eax, 0FFFFFFFFh - je ai_initial_throw_done - invoke RemoveDurakCard, OFFSET durakAIHand, OFFSET durakAICnt, eax - call AddDurakAttack - jmp ai_initial_throw_loop -ai_initial_throw_done: - ret -AIInitialThrowLoop ENDP -; --- PlayerThrowLoop: звук, интро или покадровая анимация --- -PlayerThrowLoop PROC uses ebx ecx - mov durakLoopGuard, 0 -player_throw_loop: - inc durakLoopGuard - cmp durakLoopGuard, 30 - ja player_throw_done - call ShowDurakTable - call AIDefendAll - cmp eax, 1 - je player_throw_after_defense - invoke CollectDurakTable, OFFSET durakAIHand, OFFSET durakAICnt - invoke PrintStr, OFFSET durakAITakeText - mov durakPlayerTurn, 1 - call RefillDurakHands - call PauseConsole - ret -player_throw_after_defense: - call ShowDurakTable - invoke PrintStr, OFFSET durakThrowAsk - call ReadUInt - cmp eax, 0 - je player_throw_done - cmp eax, 1 - jb player_throw_bad - cmp eax, durakPlayerCnt - ja player_throw_bad - cmp durakTableCnt, 6 - jae player_throw_bad - dec eax - mov durakChoice, eax - mov ebx, OFFSET durakPlayerHand - mov ecx, [ebx + eax * 4] - invoke DurakRankOnTable, ecx - cmp eax, 1 - jne player_throw_bad - invoke RemoveDurakCard, OFFSET durakPlayerHand, OFFSET durakPlayerCnt, durakChoice - call AddDurakAttack - jmp player_throw_loop -player_throw_bad: - invoke PrintStr, OFFSET durakBadMoveText - invoke Sleep, 650 - jmp player_throw_loop -player_throw_done: - call ClearDurakTable - mov durakPlayerTurn, 0 - call RefillDurakHands - ret -PlayerThrowLoop ENDP - -; --- PlayerDefendLoop: звук, интро или покадровая анимация --- -PlayerDefendLoop PROC uses ebx ecx - mov durakLoopGuard, 0 -player_defend_loop: - inc durakLoopGuard - cmp durakLoopGuard, 30 - ja player_take_table - call DurakAllDefended - cmp eax, 1 - je player_defended_all - call ShowDurakTable - invoke PrintStr, OFFSET durakDefendAsk - call ReadUInt - cmp eax, 0 - je player_take_table - cmp eax, 1 - jb player_def_bad - cmp eax, durakPlayerCnt - ja player_def_bad - dec eax - mov durakChoice, eax - mov ebx, OFFSET durakPlayerHand - mov ecx, [ebx + eax * 4] - - call DurakTableHasDefense - cmp eax, 0 - jne player_try_beat - invoke DurakRankOnTable, ecx - cmp eax, 1 - jne player_try_beat - mov eax, durakTableCnt - cmp durakAICnt, eax - jbe player_try_beat - invoke RemoveDurakCard, OFFSET durakPlayerHand, OFFSET durakPlayerCnt, durakChoice - call AddDurakAttack - invoke PrintStr, OFFSET durakTransferText - call PauseConsole - call PlayerThrowLoop - ret - -player_try_beat: - call DurakFirstUnbeaten - mov ebx, eax - mov ecx, OFFSET durakPlayerHand - mov eax, durakChoice - mov ecx, [ecx + eax * 4] - invoke CanDurakBeat, durakAttackCards[ebx * 4], ecx - cmp eax, 1 - jne player_def_bad - invoke RemoveDurakCard, OFFSET durakPlayerHand, OFFSET durakPlayerCnt, durakChoice - mov durakDefenseCards[ebx * 4], eax - jmp player_defend_loop -player_def_bad: - invoke PrintStr, OFFSET durakBadMoveText - invoke Sleep, 650 - jmp player_defend_loop -player_take_table: - invoke CollectDurakTable, OFFSET durakPlayerHand, OFFSET durakPlayerCnt - invoke PrintStr, OFFSET durakPlayerTakeText - mov durakPlayerTurn, 0 - call RefillDurakHandsAIFirst - call PauseConsole - ret -player_defended_all: - call FindAIThrowIn - cmp eax, 0FFFFFFFFh - je player_defense_done - invoke RemoveDurakCard, OFFSET durakAIHand, OFFSET durakAICnt, eax - call AddDurakAttack - jmp player_defend_loop -player_defense_done: - invoke PrintStr, OFFSET durakPlayerDefendText - call ClearDurakTable - mov durakPlayerTurn, 1 - call RefillDurakHandsAIFirst - call PauseConsole - ret -PlayerDefendLoop ENDP - -; --- GameDurak: дурак: козырь, атака, защита, подкидывание и добор --- GameDurak PROC - durak_start: - call ClearView - invoke PrintTitleColor, OFFSET durakTitle - call PromptBet - call SetupDurak - -durak_round_loop: - call CheckDurakEnd - cmp eax, 1 - je durak_finish_win - cmp eax, 2 - je durak_finish_lose - cmp eax, 3 - je durak_finish_draw - inc durakSafeTurns - cmp durakSafeTurns, 300 - ja durak_finish_stuck - call ClearDurakTable - cmp durakPlayerTurn, 1 - je durak_check_player_attack - jmp durak_check_ai_attack - -durak_check_player_attack: - cmp durakPlayerCnt, 0 - jne durak_player_attack - cmp durakDeckLeft, 0 - jbe durak_round_loop - call RefillDurakHands - cmp durakPlayerCnt, 0 - jne durak_player_attack - jmp durak_finish_stuck - -durak_check_ai_attack: - cmp durakAICnt, 0 - jne durak_ai_attack - cmp durakDeckLeft, 0 - jbe durak_round_loop - call RefillDurakHandsAIFirst - cmp durakAICnt, 0 - jne durak_ai_attack - jmp durak_finish_stuck - -durak_player_attack: -player_attack_choose: - call ShowDurakTable - invoke PrintStr, OFFSET durakAttackAsk - call ReadUInt - cmp eax, 1 - jb player_attack_bad - cmp eax, durakPlayerCnt - ja player_attack_bad - dec eax - invoke RemoveDurakCard, OFFSET durakPlayerHand, OFFSET durakPlayerCnt, eax - call AddDurakAttack - call PlayerOpenAttackLoop - call PlayerThrowLoop - jmp durak_round_loop -player_attack_bad: - invoke PrintStr, OFFSET durakBadMoveText - invoke Sleep, 650 - jmp player_attack_choose - -durak_ai_attack: - cmp durakAICnt, 0 - jne durak_ai_has_card - call RefillDurakHandsAIFirst - cmp durakAICnt, 0 - je durak_round_loop -durak_ai_has_card: - invoke RemoveDurakCard, OFFSET durakAIHand, OFFSET durakAICnt, 0 - call AddDurakAttack - call AIInitialThrowLoop - call PlayerDefendLoop - jmp durak_round_loop - -durak_finish_win: - invoke UnlockAchievement, 2000h, OFFSET achDurakWinName - call ShowDurakTable - invoke PrintStr, OFFSET durakWinText - call PayWin - jmp durak_again - -durak_finish_lose: - call ShowDurakTable - invoke PrintStr, OFFSET durakLoseText - call PayLose - jmp durak_again - -durak_finish_stuck: - call ShowDurakTable - invoke PrintStr, OFFSET durakStuckText - call PayDraw - jmp durak_again - -durak_finish_draw: - call ShowDurakTable - invoke PrintStr, OFFSET drawText - call PayDraw - -durak_again: - cmp tournamentMode, 1 - je durak_tournament_return - invoke PrintStr, OFFSET againText - call ReadKey - cmp al, 'y' - je durak_start - cmp al, 'Y' - je durak_start -durak_tournament_return: + cmp tournamentStage, 0 + jne tourney_durak + call StartCasino3D + ret +tourney_durak: + call TournamentPlayStage ret GameDurak ENDP ; --- GameClassicSlot: слот-машины, барабаны, символы, выплаты и джекпоты --- GameClassicSlot PROC -classic_slot_start: - call ClearView - invoke PrintTitleColor, OFFSET classicSlotTitle - invoke PrintStr, OFFSET classicSlotPayTableText - call PromptBet - call PlaySlotSound - invoke Sleep, 400 - invoke PrintStr, OFFSET slotPullText - mov slotWinMask, 0 - mov slotVisible, 0 - call PrintClassicSlotWindow - invoke Sleep, 1600 - - invoke FillClassicSlotColumn, 0 - mov slotVisible, 1 - call PrintClassicSlotWindow - invoke Sleep, 750 - - invoke FillClassicSlotColumn, 1 - mov slotVisible, 2 - call PrintClassicSlotWindow - invoke Sleep, 750 - - invoke FillClassicSlotColumn, 2 - mov slotVisible, 3 - call PrintClassicSlotWindow - invoke Sleep, 450 - - cmp cheatSlotJackpot, 1 - jne classic_no_forced_jackpot - mov cheatSlotJackpot, 0 - mov dword ptr slotGrid[12], 0 - mov dword ptr slotGrid[16], 0 - mov dword ptr slotGrid[20], 0 - call PrintClassicSlotWindow - invoke Sleep, 300 -classic_no_forced_jackpot: - - mov eax, slotGrid[12] - mov slotA, eax - mov eax, slotGrid[16] - mov slotB, eax - mov eax, slotGrid[20] - mov slotC, eax - - mov eax, slotA - cmp eax, slotB - jne classic_slot_check_pair_1 - mov eax, slotB - cmp eax, slotC - jne classic_slot_pair - invoke UnlockAchievement, 100h, OFFSET achClassicSlotName - call PlayJackpotSound - invoke PrintStr, OFFSET classicSlotJackpot - invoke Sleep, 650 - call PlayHakariSound - call PlayHakariDance - call PrintClassicSlotWindow - mov eax, slotA - cmp eax, 0 - je classic_slot_pay_777 - cmp eax, 2 - je classic_slot_pay_dollar - cmp eax, 1 - je classic_slot_pay_bar - cmp eax, 5 - je classic_slot_pay_aaa - invoke PaySlotMultiplier, 3 - jmp classic_ask_slot_again -classic_slot_pay_777: - invoke UnlockAchievement, 100h, OFFSET achClassicSlotName - invoke PaySlotMultiplier, 10 - jmp classic_ask_slot_again -classic_slot_pay_dollar: - invoke PaySlotMultiplier, 7 - jmp classic_ask_slot_again -classic_slot_pay_bar: - invoke PaySlotMultiplier, 5 - jmp classic_ask_slot_again -classic_slot_pay_aaa: - invoke PaySlotMultiplier, 4 - jmp classic_ask_slot_again - -classic_slot_check_pair_1: - mov eax, slotA - cmp eax, slotC - je classic_slot_pair - mov eax, slotB - cmp eax, slotC - je classic_slot_pair - invoke PrintStr, OFFSET classicSlotEmpty - call PayLose - jmp classic_ask_slot_again - -classic_slot_pair: - invoke UnlockAchievement, 100h, OFFSET achClassicSlotName - invoke PrintStr, OFFSET classicSlotPair - invoke PaySlotMultiplier, 2 - -classic_ask_slot_again: - invoke PrintStr, OFFSET againText - call ReadKey - cmp al, 'y' - je classic_slot_start - cmp al, 'Y' - je classic_slot_start + call StartCasino3D ret GameClassicSlot ENDP ; --- ObserverDrawAI1: режим наблюдателя AI vs AI --- @@ -12971,6 +10386,23 @@ player_ai_throw_none: ret FindPlayerThrowIn ENDP +; --- AIInitialThrowLoop: дурак: козырь, атака, защита, подкидывание и добор --- +AIInitialThrowLoop PROC + mov durakLoopGuard, 0 +ai_initial_throw_loop: + inc durakLoopGuard + cmp durakLoopGuard, 20 + ja ai_initial_throw_done + call FindAIThrowIn + cmp eax, 0FFFFFFFFh + je ai_initial_throw_done + invoke RemoveDurakCard, OFFSET durakAIHand, OFFSET durakAICnt, eax + call AddDurakAttack + jmp ai_initial_throw_loop +ai_initial_throw_done: + ret +AIInitialThrowLoop ENDP + ; --- PlayerAIInitialThrowLoop: звук, интро или покадровая анимация --- PlayerAIInitialThrowLoop PROC player_ai_initial_throw_loop: @@ -14527,79 +11959,12 @@ SkillCheckRound ENDP ; --- GameSkillCheck: Skill Check на крюке: шкала, попадания и промахи --- GameSkillCheck PROC -skill_game_start: - call ClearView - invoke PrintTitleColor, OFFSET skillTitle - invoke PrintStr, OFFSET skillIntro - call PromptBet - call PlayDbDHookScene - mov skillHits, 0 - mov skillMisses, 0 - mov skillPerfects, 0 -skill_game_loop: - call SkillCheckRound - call SkillCheckDraw - mov eax, skillResult - cmp eax, 2 - je skill_game_perfect - cmp eax, 1 - je skill_game_success -skill_game_fail: - inc skillMisses - invoke SetColor, COLOR_BAD - invoke PrintStr, OFFSET skillFailText - call ResetColor - invoke Sleep, 850 - cmp skillMisses, 3 - jae skill_game_lost - jmp skill_game_loop -skill_game_success: - inc skillHits - invoke SetColor, COLOR_MONEY - invoke PrintStr, OFFSET skillSuccessText - call ResetColor - invoke Sleep, 750 - cmp skillHits, 5 - jae skill_game_won - jmp skill_game_loop -skill_game_perfect: - add skillHits, 2 - inc skillPerfects - invoke SetColor, COLOR_WARN - invoke PrintStr, OFFSET skillPerfectText - call ResetColor - invoke Sleep, 850 - cmp skillHits, 5 - jae skill_game_won - jmp skill_game_loop -skill_game_won: - call StopDbDHookScene - call SkillCheckDraw - invoke SetColor, COLOR_MONEY - invoke PrintStr, OFFSET skillEscapeText - call ResetColor - invoke PaySlotMultiplier, 2 - invoke UnlockAchievement, 20000h, OFFSET achSkillCheckName - call SaveGame - jmp skill_game_again -skill_game_lost: - call StopDbDHookScene - call SkillCheckDraw - invoke SetColor, COLOR_BAD - invoke PrintStr, OFFSET skillDarkText - call ResetColor - call PayLose - call SaveGame -skill_game_again: - cmp tournamentMode, 1 - je skill_game_exit - invoke PrintStr, OFFSET againText - call ReadKey - cmp al, 'y' - je skill_game_start - cmp al, 'Y' - je skill_game_start -skill_game_exit: + cmp tournamentStage, 0 + jne tourney_sc + call StartCasino3D + ret +tourney_sc: + call TournamentPlayStage ret GameSkillCheck ENDP ; --- GameAchievements: статистика, достижения и таблицы лидеров --- @@ -15232,3 +12597,4 @@ ENDIF main ENDP END main + diff --git a/poker.exe b/poker.exe index 2f4481c..bdeacf0 100644 Binary files a/poker.exe and b/poker.exe differ diff --git a/poker.obj b/poker.obj index 1a3aa40..3dc0b5f 100644 Binary files a/poker.obj and b/poker.obj differ