From b255493506e8b5f2afe17b1a5338d87fd16effa7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=D0=98=D0=B3=D0=BE=D1=80=D1=8C=20=D0=A4=D0=B5=D0=B4=D0=BE?= =?UTF-8?q?=D1=81=D0=B5=D0=B5=D0=B2?= Date: Wed, 30 Sep 2026 20:49:52 +0300 Subject: [PATCH] fix(audio,ui): eliminate gunshot sound bugs, implement rich custom 2.5D graphics for minigames, add visual test suite --- build/graphics/poker.exe | Bin 210432 -> 212992 bytes casino3d.inc | 1438 ++++++++++----- docs/previews_minigames/coin_preview.png | Bin 0 -> 6011 bytes docs/previews_minigames/dice_preview.png | Bin 0 -> 5522 bytes docs/previews_minigames/skulls_preview.png | Bin 0 -> 5121 bytes docs/previews_minigames/test_basic.png | Bin 0 -> 2157 bytes poker.exe | Bin 210432 -> 212992 bytes tools/README.md | 3 + tools/generators/generate_rich_minigames.py | 1790 +++++++++++++++++++ tools/tests/test_minigames_render.py | 379 ++++ 10 files changed, 3127 insertions(+), 483 deletions(-) create mode 100644 docs/previews_minigames/coin_preview.png create mode 100644 docs/previews_minigames/dice_preview.png create mode 100644 docs/previews_minigames/skulls_preview.png create mode 100644 docs/previews_minigames/test_basic.png create mode 100644 tools/generators/generate_rich_minigames.py create mode 100644 tools/tests/test_minigames_render.py diff --git a/build/graphics/poker.exe b/build/graphics/poker.exe index fd5115f7f4d6c2f3f4730916f1cd609fde0c72b0..dfd78203aba6ff9ae84ab0eb5f0c7b3c1f4b7f06 100644 GIT binary patch delta 71794 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 aFhWgdZdNm2Xdmaftf{`x$#{CH^Zx_E;b@ou diff --git a/casino3d.inc b/casino3d.inc index 96f7064..549c02a 100644 --- a/casino3d.inc +++ b/casino3d.inc @@ -149,11 +149,15 @@ sz3DWindowTitle db "Assembler Casino - 2.5D",0 szTexturesRelPath db "assets\textures\casino3d-hd.bin",0 szTexturesFullPath db 260 dup(0) -soundCoin db "assets\audio\Çâîí ïàäàþùåé ìîíåòû.wav",0 +soundCoin db "assets\audio\Çâóê ìîíåòû áðîøåííîé â âîçäóõ è óïàâøåé íà ïîâåðõíîñòü.wav",0 +soundCoinDing db "assets\audio\Çâóê ìîíåòû â èãðå Ultrakill.wav",0 soundCards db "assets\audio\playing_cards_deck_flick_through_001_20485.wav",0 soundRoulette db "assets\audio\roulette-wheel-throw-2.wav",0 -soundJackpot db "assets\audio\Äæåêïîò.wav",0 -soundClick db "assets\audio\b05e1ac8be34248.wav",0 +soundJackpot db "assets\audio\Äæýê ïîò.wav",0 +soundVictory db "assets\audio\victory-tf2.wav",0 +soundClick db "assets\audio\revolverdryfirec.wav",0 +soundShuffle db "assets\audio\moving-stone.wav",0 +soundLose db "assets\audio\Ïðîèãðûø.wav",0 playerX dd (16 * FP_1 + FP_HALF) playerY dd (16 * FP_1 + FP_HALF) @@ -288,65 +292,81 @@ coin3d_result dd 1 ; 1 = coin3d_streak dd 0 coin3d_win dd 0 -coinRxAnimTable db 22, 18, 12, 4, 12, 18, 22, 18, 12, 4 +coinRxAnimTable db 26, 22, 16, 6, 16, 22, 26, 22, 16, 6 -textCoinTitle db "ÌÎÍÅÒÊÀ (ÎÐ¨Ë / ÐÅØÊÀ)",0 +; --- Native 2.5D Coin Flip --- +textCoinTitle db "* * * Ç Î Ë Î Ò À ß Ì Î Í Å Ò À * * *",0 textCoinHeads db "ÎШË",0 textCoinTails db "ÐÅØÊÀ",0 textCoinStreak db "ÑÅÐÈß: ",0 textCoinSide1 db "[1] ÎШË",0 textCoinSide2 db "[2] ÐÅØÊÀ",0 -textCoinFlipping db "ÌÎÍÅÒÀ  ÂÎÇÄÓÕÅ...",0 -textCoinWin db "ÂÛÈÃÐÛØ! +$",0 -textCoinLose db "ÏÐÎÈÃÐÛØ!",0 -textCoinControls1 db "[1/2] ÑÒÎÐÎÍÀ [ÏÐÎÁÅË] ÁÐÎÑÎÊ",0 -textCoinControls2 db "[ÂÂÅÐÕ/ÂÍÈÇ] ÑÒÀÂÊÀ [ESC] ÂÛÕÎÄ",0 +textCoinFlipping db "ÌÎÍÅÒÀ  ÏÎ˨ÒÅ...",0 +textCoinWin db "ÂÛÈÃÐÛØ: +$",0 +textCoinLose db "ÍÅ ÓÃÀÄÀË!",0 +textCoinKey1 db "1:ÎШË",0 +textCoinKey2 db "2:ÐÅØÊÀ",0 +textCoinKeySpace db "ÏÐÎÁÅË:ÁÐÎÑÎÊ",0 +textCoinStreakFmt db "ÑÅÐÈß: [X] [X] [X] [ ] [ ] x4!",0 ; --- Native 2.5D Dice Game --- dice3d_bet dd 50 dice3d_choice dd 1 ; 1 = ׸ò, 2 = Íå÷åò dice3d_state dd 0 ; 0 = Idle, 1 = Rolling, 2 = Result dice3d_timer dd 0 -dice3d_val1 dd 3 -dice3d_val2 dd 4 -dice3d_sum dd 7 +dice3d_val1 dd 4 +dice3d_val2 dd 6 +dice3d_sum dd 10 dice3d_win dd 0 -textDiceTitle db "ÊÎÑÒÈ (CRAPS) - ×¨Ò / ÍÅ×ÅÒ",0 +textDiceTitle db "=== G R A N D C R A P S ===",0 +textDiceSubtitle db "[ PASS LINE ] [ ANY CRAPS ]",0 textDiceEven db "[1] רÒ",0 textDiceOdd db "[2] ÍÅ×ÅÒ",0 -textDiceTally db "ÊÎÑÒÈ: ",0 +textDiceEvenNums db "2 4 6 8 10",0 +textDiceOddNums db "3 5 7 9 11",0 +textDiceSumHdr db "ÑÓÌÌÀ: ",0 textDicePlus db " + ",0 textDiceEqual db " = ",0 textDiceEvenResult db " (רÒ)",0 textDiceOddResult db " (ÍÅ×ÅÒ)",0 -textDiceRolling db "ÁÐÎÑÎÊ ÊÎÑÒÅÉ...",0 -textDiceWin db "ÂÛÈÃÐÛØ! +$",0 +textDiceRolling db "ÊÎÑÒÈ ËÅÒßÒ ÏÎ ÑÓÊÍÓ...",0 +textDiceWin db "ÂÛÈÃÐÛØ: +$",0 +textDiceWinMult db "! (x2)",0 textDiceLose db "ÏÐÎÈÃÐÛØ!",0 -textDiceControls1 db "[1] ×¨Ò [2] ÍÅ×ÅÒ [ÏÐÎÁÅË] ÁÐÎÑÎÊ",0 -textDiceControls2 db "[ÂÂÅÐÕ/ÂÍÈÇ] ÑÒÀÂÊÀ [ESC] ÂÛÕÎÄ",0 +textDiceKey1 db "1:רÒ",0 +textDiceKey2 db "2:ÍÅ×ÅÒ",0 +textDiceKeySpace db "ÏÐÎÁÅË:ÁÐÎÑÎÊ",0 ; --- Native 2.5D Skulls Game --- skulls3d_bet dd 50 skulls3d_state dd 0 ; 0 = Idle, 1 = Show ball, 2 = Shuffle, 3 = Pick, 4 = Reveal skulls3d_timer dd 0 -skulls3d_ballPos dd 0 ; 0, 1, 2 -skulls3d_choice dd 0 ; 0, 1, 2 +skulls3d_ballPos dd 1 ; 0, 1, 2 +skulls3d_choice dd 1 ; 0, 1, 2 skulls3d_win dd 0 skulls3d_swapPair0 dd 0 skulls3d_swapPair1 dd 1 skulls3d_swapPair2 dd 2 -textSkullsTitle db "ÍÀϨÐÑÒÊÈ (×ÅÐÅÏÀ È ÊÓÁÊÈ)",0 -textSkullsPhase0 db "ÂÛÁÅÐÈÒÅ ÑÒÀÂÊÓ È ÍÀÆÌÈÒÅ [ÏÐÎÁÅË]",0 -textSkullsPhase1 db "ÇÀÏÎÌÍÈÒÅ, ÃÄÅ ØÀÐÈÊ!",0 +textSkullsTitle db "+ + + Í À Ï ¨ Ð Ñ Ò Ê È + + +",0 +textSkullsPhase0 db "ÄÅËÀÉ ÑÒÀÂÊÓ È ÆÌÈ [ÏÐÎÁÅË]",0 +textSkullsPhase1 db "ÑÌÎÒÐÈ, ÃÄÅ ÇÎËÎÒÎÉ ØÀÐ...",0 textSkullsPhase2 db "ÊÐÓ×Ó, ÂÅÐ×Ó, ÇÀÏÓÒÀÒÜ ÕÎ×Ó...",0 -textSkullsPhase3 db "ÃÄÅ ØÀÐÈÊ? ÍÀÆÌÈÒÅ [1], [2] ÈËÈ [3]!",0 -textSkullsWin db "ÂÛ ÓÃÀÄÀËÈ! ÄÆÅÊÏÎÒ x3! +$",0 -textSkullsLose db "ÍÅ ÓÃÀÄÀËÈ! ØÀÐÈÊ ÁÛË ÍÅ ÇÄÅÑÜ!",0 +textSkullsPhase3 db "ÃÄÅ ØÀÐ? ÂÛÁÈÐÀÉ: [1], [2] ÈËÈ [3]!",0 +textSkullsWin db "ÂÅÐÍÎ! ÂÛÏËÀÒÀ x3! +$",0 +textSkullsLose db "ÌÈÌÎ! ØÀÐ ÁÛË Â ÄÐÓÃÎÌ ÌÅÑÒÅ!",0 textSkullsAgain db "[ÏÐÎÁÅË] - ÑÛÃÐÀÒÜ ÅÙ¨ ÐÀÇ",0 -textSkullsControls1 db "[1/2/3] ÂÛÁÎÐ ÊÓÁÊÀ [ÏÐÎÁÅË] ÑÒÀÐÒ",0 -textSkullsControls2 db "[ÂÂÅÐÕ/ÂÍÈÇ] ÑÒÀÂÊÀ [ESC] ÂÛÕÎÄ",0 +textSkullsKey1 db "1:ÊÓÁÎÊ",0 +textSkullsKey2 db "2:ÊÓÁÎÊ",0 +textSkullsKey3 db "3:ÊÓÁÎÊ",0 +textSkullsKeySpace db "ÏÐÎÁÅË",0 + +; --- Shared UI Strings --- +textKeyEsc db "ESC",0 +textBankPrompt db "ÁÀÍÊ: $",0 +textBetPrompt db "ÑÒÀÂÊÀ: $",0 +textBetHint db " [W/S]",0 shopMsg db 128 dup(0) atmMsg db 128 dup(0) @@ -2630,15 +2650,102 @@ RenderATMGame PROC ret RenderATMGame ENDP +; ============================================================================== +; ============================================================================== +; SHARED RICH UI PROCEDURES +; ============================================================================== +DrawKeycap3D PROC uses ebx esi edi, x:DWORD, y:DWORD, strPtr:DWORD, isActive:DWORD + LOCAL capW:DWORD + ; Compute string length + mov esi, strPtr + xor ecx, ecx +@@: + mov al, [esi+ecx] + test al, al + jz @F + inc ecx + jmp @B +@@: + shl ecx, 3 ; length * 8 + add ecx, 8 ; padding 8px + mov capW, ecx + + ; Drop shadow + mov eax, x + mov edx, y + add edx, 2 + invoke DrawBox, eax, edx, capW, 13, 0008080Ch + + ; Body & Border + mov eax, 00606870h ; default border + mov edx, 001A1C22h ; default fill + cmp isActive, 0 + je @F + mov eax, 0000FFFFh ; active gold border + mov edx, 001B4B22h ; active dark green fill +@@: + invoke DrawBoxBorder, x, y, capW, 13, edx, eax, 1 + + ; String text + mov eax, 00D0D8E0h + cmp isActive, 0 + je @F + mov eax, 0000FFFFh +@@: + mov edx, x + add edx, 4 + mov ecx, y + add ecx, 3 + invoke DrawString8x8, edx, ecx, strPtr, eax + mov eax, capW + ret +DrawKeycap3D ENDP + +DrawChipStack PROC uses ebx esi edi, x:DWORD, y:DWORD, chipCount:DWORD + xor esi, esi +chip_loop: + cmp esi, chipCount + jge chip_done + mov eax, esi + shl eax, 2 ; esi * 4 + mov edx, y + sub edx, eax ; cy = y - esi*4 + + ; Shadow + mov eax, x + add eax, 2 + mov ecx, edx + add ecx, 5 + invoke DrawBox, eax, ecx, 20, 2, 00041006h + + ; Chip body + invoke DrawBoxBorder, x, edx, 24, 6, 001515B8h, 00FFFFFFh, 1 + + ; White stripe inlays + mov eax, x + add eax, 4 + mov ecx, edx + add ecx, 1 + invoke DrawBox, eax, ecx, 3, 4, 00FFFFFFh + mov eax, x + add eax, 17 + invoke DrawBox, eax, ecx, 3, 4, 00FFFFFFh + + inc esi + jmp chip_loop +chip_done: + ret +DrawChipStack ENDP + ; ============================================================================== ; IN-ENGINE 2.5D MINI-GAME: COIN FLIP (ÌÎÍÅÒÊÀ) ; ============================================================================== -DrawCoinEllipse PROC uses ebx esi edi cxVal:DWORD, cyVal:DWORD, rxVal:DWORD, ryVal:DWORD, outerColor:DWORD, innerColor:DWORD - local curDY:DWORD, curDX:DWORD, rxSq:DWORD, rySq:DWORD, rxRySq:DWORD, threshSq:DWORD +DrawDetailedCoin PROC uses ebx esi edi, cxVal:DWORD, cyVal:DWORD, rxVal:DWORD, ryVal:DWORD, outerColor:DWORD, innerColor:DWORD, reliefType:DWORD + LOCAL curDY:DWORD, curDX:DWORD, rxSq:DWORD, rySq:DWORD, rxRySq:DWORD, threshSq:DWORD cmp rxVal, 0 - jle ellipse_done + jle coin_draw_ret cmp ryVal, 0 - jle ellipse_done + jle coin_draw_ret mov eax, rxVal imul eax, eax @@ -2661,19 +2768,19 @@ DrawCoinEllipse PROC uses ebx esi edi cxVal:DWORD, cyVal:DWORD, rxVal:DWORD, ryV neg eax mov curDY, eax -ellipse_y_loop: +coin_y_loop: mov eax, curDY cmp eax, ryVal - jg ellipse_done + jg check_coin_relief mov eax, rxVal neg eax mov curDX, eax -ellipse_x_loop: +coin_x_loop: mov eax, curDX cmp eax, rxVal - jg next_ellipse_y + jg next_coin_y mov eax, curDX imul eax, eax @@ -2683,7 +2790,7 @@ ellipse_x_loop: imul ebx, rxSq add eax, ebx cmp eax, rxRySq - jg next_ellipse_x + jg next_coin_x mov ecx, innerColor cmp eax, threshSq @@ -2696,17 +2803,163 @@ ellipse_x_loop: add edx, curDY invoke DrawPixel, eax, edx, ecx -next_ellipse_x: +next_coin_x: inc curDX - jmp ellipse_x_loop + jmp coin_x_loop -next_ellipse_y: +next_coin_y: inc curDY - jmp ellipse_y_loop + jmp coin_y_loop -ellipse_done: +check_coin_relief: + cmp rxVal, 14 + jl coin_draw_ret + cmp reliefType, 1 + je draw_eagle_relief + cmp reliefType, 2 + je draw_wreath_relief + jmp coin_draw_ret + +draw_eagle_relief: + ; Crown + mov eax, cxVal + sub eax, 3 + mov edx, cyVal + sub edx, 14 + invoke DrawBox, eax, edx, 7, 2, 00007A9Ah + mov eax, cxVal + sub eax, 4 + mov edx, cyVal + sub edx, 12 + invoke DrawBox, eax, edx, 9, 2, 00007A9Ah + + ; Body & Head + mov eax, cxVal + sub eax, 2 + mov edx, cyVal + sub edx, 9 + invoke DrawBox, eax, edx, 5, 12, 00007A9Ah + mov eax, cxVal + dec eax + mov edx, cyVal + sub edx, 8 + invoke DrawBox, eax, edx, 3, 10, 0000D7FFh + + ; Wings + mov eax, cxVal + sub eax, 10 + mov edx, cyVal + sub edx, 8 + invoke DrawBox, eax, edx, 7, 3, 00007A9Ah + mov eax, cxVal + sub eax, 13 + mov edx, cyVal + sub edx, 5 + invoke DrawBox, eax, edx, 10, 3, 00007A9Ah + mov eax, cxVal + sub eax, 11 + mov edx, cyVal + sub edx, 2 + invoke DrawBox, eax, edx, 7, 3, 00007A9Ah + + mov eax, cxVal + add eax, 4 + mov edx, cyVal + sub edx, 8 + invoke DrawBox, eax, edx, 7, 3, 00007A9Ah + mov eax, cxVal + add eax, 4 + mov edx, cyVal + sub edx, 5 + invoke DrawBox, eax, edx, 10, 3, 00007A9Ah + mov eax, cxVal + add eax, 5 + mov edx, cyVal + sub edx, 2 + invoke DrawBox, eax, edx, 7, 3, 00007A9Ah + + ; Tail + mov eax, cxVal + sub eax, 4 + mov edx, cyVal + add edx, 4 + invoke DrawBox, eax, edx, 9, 3, 00007A9Ah + mov eax, cxVal + sub eax, 3 + mov edx, cyVal + add edx, 7 + invoke DrawBox, eax, edx, 7, 3, 00007A9Ah + jmp coin_draw_ret + +draw_wreath_relief: + ; Roman numeral 'I' + mov eax, cxVal + sub eax, 5 + mov edx, cyVal + sub edx, 10 + invoke DrawBox, eax, edx, 11, 3, 00007A9Ah + mov eax, cxVal + sub eax, 2 + mov edx, cyVal + sub edx, 7 + invoke DrawBox, eax, edx, 5, 14, 00007A9Ah + mov eax, cxVal + dec eax + mov edx, cyVal + sub edx, 6 + invoke DrawBox, eax, edx, 3, 12, 0000D7FFh + mov eax, cxVal + sub eax, 6 + mov edx, cyVal + add edx, 7 + invoke DrawBox, eax, edx, 13, 3, 00007A9Ah + + ; Laurel dots left & right + mov eax, cxVal + sub eax, 12 + mov edx, cyVal + sub edx, 10 + invoke DrawBox, eax, edx, 2, 2, 00007A9Ah + mov eax, cxVal + add eax, 11 + mov edx, cyVal + sub edx, 10 + invoke DrawBox, eax, edx, 2, 2, 00007A9Ah + + mov eax, cxVal + sub eax, 12 + mov edx, cyVal + sub edx, 5 + invoke DrawBox, eax, edx, 2, 2, 00007A9Ah + mov eax, cxVal + add eax, 11 + mov edx, cyVal + sub edx, 5 + invoke DrawBox, eax, edx, 2, 2, 00007A9Ah + + mov eax, cxVal + sub eax, 12 + mov edx, cyVal + invoke DrawBox, eax, edx, 2, 2, 00007A9Ah + mov eax, cxVal + add eax, 11 + mov edx, cyVal + invoke DrawBox, eax, edx, 2, 2, 00007A9Ah + + mov eax, cxVal + sub eax, 12 + mov edx, cyVal + add edx, 5 + invoke DrawBox, eax, edx, 2, 2, 00007A9Ah + mov eax, cxVal + add eax, 11 + mov edx, cyVal + add edx, 5 + invoke DrawBox, eax, edx, 2, 2, 00007A9Ah + +coin_draw_ret: ret -DrawCoinEllipse ENDP +DrawDetailedCoin ENDP InitCoinGame PROC mov coin3d_state, 0 @@ -2723,7 +2976,7 @@ HandleCoinInput PROC cmp coin3d_state, 1 je coin_input_done - invoke Pressed3D, 20h ; SPACE + invoke Pressed3D, 20h ; SPACE -> Flip! test eax, eax jz check_coin_side mov eax, bankroll @@ -2734,11 +2987,13 @@ HandleCoinInput PROC mov coin3d_state, 1 mov coin3d_timer, 0 mov coin3d_win, 0 - invoke PlaySoundA, OFFSET soundClick, 0, 1 + invoke PlaySoundA, OFFSET soundCoin, 0, 1 jmp coin_input_done + coin_no_cash: invoke CopyString3D, OFFSET msgNeedMoney, OFFSET flashMessage mov flashTimer, 60 + invoke PlaySoundA, OFFSET soundClick, 0, 1 jmp coin_input_done check_coin_side: @@ -2746,11 +3001,13 @@ check_coin_side: test eax, eax jz @F mov coin3d_side, 1 + invoke PlaySoundA, OFFSET soundClick, 0, 1 @@: invoke Pressed3D, 32h ; '2' test eax, eax jz check_coin_bet_adjust mov coin3d_side, 2 + invoke PlaySoundA, OFFSET soundClick, 0, 1 check_coin_bet_adjust: invoke Pressed3D, 26h ; UP @@ -2760,6 +3017,7 @@ check_coin_bet_adjust: test eax, eax jz check_coin_bet_down coin_inc_bet: + invoke PlaySoundA, OFFSET soundClick, 0, 1 cmp coin3d_bet, 500 jge coin_input_done cmp coin3d_bet, 250 @@ -2771,25 +3029,6 @@ coin_inc_bet: cmp coin3d_bet, 25 jge coin_set_50 jmp coin_set_25 - -check_coin_bet_down: - invoke Pressed3D, 28h ; DOWN - test eax, eax - jnz coin_dec_bet - invoke Pressed3D, 53h ; S - test eax, eax - jz coin_input_done -coin_dec_bet: - cmp coin3d_bet, 25 - jle coin_set_10 - cmp coin3d_bet, 50 - jle coin_set_25 - cmp coin3d_bet, 100 - jle coin_set_50 - cmp coin3d_bet, 250 - jle coin_set_100 - jmp coin_set_250 - coin_set_500: mov coin3d_bet, 500 jmp coin_input_done @@ -2805,62 +3044,113 @@ coin_set_50: coin_set_25: mov coin3d_bet, 25 jmp coin_input_done + +check_coin_bet_down: + invoke Pressed3D, 28h ; DOWN + test eax, eax + jnz coin_dec_bet + invoke Pressed3D, 53h ; S + test eax, eax + jz coin_input_done +coin_dec_bet: + invoke PlaySoundA, OFFSET soundClick, 0, 1 + cmp coin3d_bet, 25 + jle coin_set_10 + cmp coin3d_bet, 50 + jle coin_set_25 + cmp coin3d_bet, 100 + jle coin_set_50 + cmp coin3d_bet, 250 + jle coin_set_100 + mov coin3d_bet, 250 + jmp coin_input_done coin_set_10: mov coin3d_bet, 10 - jmp coin_input_done coin_input_done: ret HandleCoinInput ENDP RenderCoinGame PROC uses ebx esi edi - local cyVal:DWORD, rxVal:DWORD + LOCAL cyVal:DWORD, rxVal:DWORD, curX:DWORD - ; Background & Bezel - invoke DrawBox, 0, 0, SCREEN_W, SCREEN_H, 00140D18h - invoke DrawBoxBorder, 10, 10, 300, 220, 0022142Ah, 0000D7FFh, 3 + ; Cabinet Bezel (Mahogany wood & leather) + invoke DrawBox, 0, 0, 320, 240, 00060914h + invoke DrawBoxBorder, 6, 6, 308, 228, 000F1522h, 001B2E48h, 3 + + ; Corner Brass Rivets + invoke DrawBox, 12, 12, 3, 3, 0000D7FFh + invoke DrawPixel, 13, 13, 00FFFFFFh + invoke DrawBox, 306, 12, 3, 3, 0000D7FFh + invoke DrawPixel, 307, 13, 00FFFFFFh + invoke DrawBox, 12, 226, 3, 3, 0000D7FFh + invoke DrawPixel, 13, 227, 00FFFFFFh + invoke DrawBox, 306, 226, 3, 3, 0000D7FFh + invoke DrawPixel, 307, 227, 00FFFFFFh ; Illuminated Marquee Header - invoke DrawBoxBorder, 25, 18, 270, 26, 000D0812h, 0000FFFFh, 2 - invoke DrawString8x8, 72, 27, OFFSET textCoinTitle, 0000D7FFh + invoke DrawBoxBorder, 24, 12, 272, 26, 000A101Ch, 0000D7FFh, 2 + invoke DrawString8x8, 48, 21, OFFSET textCoinTitle, 0000FFFFh - ; Streak Display - invoke DrawString8x8, 28, 50, OFFSET textCoinStreak, 0000D7FFh - invoke FormatNumber, coin3d_streak, OFFSET hudNumBuffer - invoke DrawString8x8, 84, 50, OFFSET hudNumBuffer, 0050FF50h + ; Bulb lights on marquee border + mov curX, 28 +coin_bulbs: + cmp curX, 292 + jge coin_meters + invoke DrawPixel, curX, 13, 0000FFFFh + invoke DrawPixel, curX, 36, 0000D7FFh + add curX, 12 + jmp coin_bulbs - ; Side Panel: [1] ÎÐ¨Ë - mov eax, 00120D16h - mov edx, 00505050h - mov ecx, 00808080h +coin_meters: + ; Status Meters: Bank & Bet + invoke DrawBoxBorder, 20, 44, 114, 18, 000A1A0Eh, 001A4B22h, 1 + invoke DrawString8x8, 24, 49, OFFSET textBankPrompt, 0050FF50h + invoke FormatNumber, bankroll, OFFSET hudNumBuffer + invoke DrawString8x8, 72, 49, OFFSET hudNumBuffer, 0050FF50h + + invoke DrawBoxBorder, 186, 44, 114, 18, 001A100Ah, 003A2814h, 1 + invoke DrawString8x8, 190, 49, OFFSET textBetPrompt, 0000D7FFh + invoke FormatNumber, coin3d_bet, OFFSET hudNumBuffer + invoke DrawString8x8, 254, 49, OFFSET hudNumBuffer, 0000D7FFh + invoke DrawString8x8, 278, 49, OFFSET textBetHint, 00808080h + + ; Center Velvet Platter + invoke DrawCircle, 160, 110, 46, 000090C0h + invoke DrawCircle, 160, 110, 44, 0000D7FFh + invoke DrawCircle, 160, 110, 41, 00180824h + + ; Selection Podiums: [1] ÎÐ¨Ë + mov eax, 00121620h + mov edx, 00404855h + mov ecx, 0090A0B0h cmp coin3d_side, 1 jne @F - mov eax, 001E3520h + mov eax, 001C3822h mov edx, 0000FFFFh mov ecx, 0000FFFFh @@: push ecx - invoke DrawBoxBorder, 24, 70, 68, 38, eax, edx, 2 + invoke DrawBoxBorder, 20, 72, 76, 52, eax, edx, 2 pop ecx - invoke DrawString8x8, 28, 85, OFFSET textCoinSide1, ecx + invoke DrawString8x8, 28, 78, OFFSET textCoinSide1, ecx + invoke DrawDetailedCoin, 58, 106, 12, 12, 0000A0D0h, 0000D7FFh, 1 - ; Side Panel: [2] ÐÅØÊÀ - mov eax, 00120D16h - mov edx, 00505050h - mov ecx, 00808080h + ; Selection Podiums: [2] ÐÅØÊÀ + mov eax, 00121620h + mov edx, 00404855h + mov ecx, 0090A0B0h cmp coin3d_side, 2 jne @F - mov eax, 001E3520h + mov eax, 001C3822h mov edx, 0000FFFFh mov ecx, 0000FFFFh @@: push ecx - invoke DrawBoxBorder, 228, 70, 68, 38, eax, edx, 2 + invoke DrawBoxBorder, 224, 72, 76, 52, eax, edx, 2 pop ecx - invoke DrawString8x8, 232, 85, OFFSET textCoinSide2, ecx - - ; Center coin pedestal arena - invoke DrawBoxBorder, 102, 54, 116, 84, 000F0A12h, 00504030h, 1 + invoke DrawString8x8, 232, 78, OFFSET textCoinSide2, ecx + invoke DrawDetailedCoin, 262, 106, 12, 12, 000080A0h, 0000B0D0h, 2 ; Flipping animation logic cmp coin3d_state, 1 @@ -2868,13 +3158,15 @@ RenderCoinGame PROC uses ebx esi edi inc coin3d_timer - ; Parabolic toss: cy = 96 - (t * (40 - t)) / 16 + ; Parabolic toss: cy = 110 - (t * (40 - t)) / 14 mov eax, coin3d_timer mov ecx, 40 sub ecx, eax imul eax, ecx - shr eax, 4 - mov edx, 96 + xor edx, edx + mov ecx, 14 + div ecx + mov edx, 110 sub edx, eax mov cyVal, edx @@ -2886,8 +3178,8 @@ RenderCoinGame PROC uses ebx esi edi movzx eax, BYTE PTR [coinRxAnimTable + edx] mov rxVal, eax - invoke DrawCoinEllipse, 160, cyVal, rxVal, 22, 0000D7FFh, 0000B0E0h - invoke DrawString8x8, 84, 142, OFFSET textCoinFlipping, 0000FFFFh + invoke DrawDetailedCoin, 160, cyVal, rxVal, 26, 0000A0D0h, 0000D7FFh, 0 + invoke DrawString8x8, 88, 160, OFFSET textCoinFlipping, 0000FFFFh cmp coin3d_timer, 40 jl coin_draw_controls @@ -2910,147 +3202,177 @@ RenderCoinGame PROC uses ebx esi edi inc coin3d_streak cmp coin3d_streak, 3 jl @F - invoke PlaySoundA, OFFSET soundJackpot, 0, 1 + invoke PlaySoundA, OFFSET soundVictory, 0, 1 jmp coin_draw_controls @@: - invoke PlaySoundA, OFFSET soundCoin, 0, 1 + invoke PlaySoundA, OFFSET soundCoinDing, 0, 1 jmp coin_draw_controls coin_flip_lost: mov coin3d_streak, 0 mov coin3d_win, 0 - invoke PlaySoundA, OFFSET soundClick, 0, 1 + invoke PlaySoundA, OFFSET soundLose, 0, 1 jmp coin_draw_controls coin_at_rest: - ; Draw coin resting at (160, 96) - invoke DrawCoinEllipse, 160, 96, 24, 24, 0000D7FFh, 0000B0E0h - invoke DrawCoinEllipse, 160, 96, 20, 20, 0000FFFFh, 000090D0h - - ; Draw side text inside coin + ; Draw coin resting in velvet dish + mov edx, coin3d_side cmp coin3d_state, 2 - jne coin_show_picked_side - cmp coin3d_result, 1 jne @F - invoke DrawString8x8, 144, 92, OFFSET textCoinHeads, 00000030h - jmp coin_show_splash + mov edx, coin3d_result @@: - invoke DrawString8x8, 140, 92, OFFSET textCoinTails, 00000030h - jmp coin_show_splash + invoke DrawDetailedCoin, 160, 110, 26, 26, 0000A0D0h, 0000D7FFh, edx -coin_show_picked_side: - cmp coin3d_side, 1 - jne @F - invoke DrawString8x8, 144, 92, OFFSET textCoinHeads, 00000030h - jmp coin_draw_controls -@@: - invoke DrawString8x8, 140, 92, OFFSET textCoinTails, 00000030h - jmp coin_draw_controls + ; Outcome / Streak Display + cmp coin3d_state, 2 + jne coin_show_streak -coin_show_splash: cmp coin3d_win, 0 - je coin_show_loss - invoke DrawString8x8, 90, 142, OFFSET textCoinWin, 0000FFFFh + je coin_show_lose + invoke DrawBoxBorder, 44, 154, 232, 20, 000E141Eh, 0050FF50h, 1 + invoke DrawString8x8, 64, 160, OFFSET textCoinWin, 0050FF50h invoke FormatNumber, coin3d_win, OFFSET hudNumBuffer - invoke DrawString8x8, 178, 142, OFFSET hudNumBuffer, 0000FFFFh + invoke DrawString8x8, 152, 160, OFFSET hudNumBuffer, 0050FF50h jmp coin_draw_controls -coin_show_loss: - invoke DrawString8x8, 126, 142, OFFSET textCoinLose, 000000FFh +coin_show_lose: + invoke DrawBoxBorder, 44, 154, 232, 20, 000E141Eh, 000000FFh, 1 + invoke DrawString8x8, 114, 160, OFFSET textCoinLose, 008080FFh + jmp coin_draw_controls + +coin_show_streak: + invoke DrawBoxBorder, 44, 154, 232, 20, 000E141Eh, 0000D7FFh, 1 + invoke DrawString8x8, 52, 160, OFFSET textCoinStreakFmt, 0000FFFFh coin_draw_controls: - ; Bottom Control Panel - invoke DrawBoxBorder, 20, 165, 280, 58, 00151515h, 0000D7FFh, 1 - invoke DrawString8x8, 28, 170, OFFSET textBank3D, 0000D7FFh - invoke FormatNumber, bankroll, OFFSET hudNumBuffer - invoke DrawString8x8, 88, 170, OFFSET hudNumBuffer, 0000FFFFh + ; Keycaps Control Bar + invoke DrawBox, 16, 194, 288, 1, 001E2E40h - invoke DrawString8x8, 180, 170, OFFSET textBet3D, 0000D7FFh - invoke FormatNumber, coin3d_bet, OFFSET hudNumBuffer - invoke DrawString8x8, 236, 170, OFFSET hudNumBuffer, 0050FF50h + mov eax, 0 + cmp coin3d_side, 1 + sete al + invoke DrawKeycap3D, 22, 202, OFFSET textCoinKey1, eax - invoke DrawString8x8, 28, 186, OFFSET textCoinControls1, 00FFFFFFh - invoke DrawString8x8, 28, 202, OFFSET textCoinControls2, 00A0A0A0h + mov eax, 0 + cmp coin3d_side, 2 + sete al + invoke DrawKeycap3D, 88, 202, OFFSET textCoinKey2, eax + + invoke DrawKeycap3D, 160, 202, OFFSET textCoinKeySpace, 1 + invoke DrawKeycap3D, 274, 202, OFFSET textKeyEsc, 0 ret RenderCoinGame ENDP ; ============================================================================== ; IN-ENGINE 2.5D MINI-GAME: DICE / CRAPS (ÊÎÑÒÈ) ; ============================================================================== -DrawDieCube PROC uses ebx esi edi x:DWORD, y:DWORD, cubeSize:DWORD, valNum:DWORD - local pipColor:DWORD - mov pipColor, 001515C0h - - invoke DrawBoxBorder, x, y, cubeSize, cubeSize, 00F4F6F8h, 00303038h, 2 - +DrawCrapsDie PROC uses ebx esi edi, x:DWORD, y:DWORD, sizeVal:DWORD, valNum:DWORD + ; Drop shadow on green felt mov eax, x - add eax, cubeSize + add eax, 3 mov edx, y - add edx, 2 - invoke DrawBox, eax, edx, 2, cubeSize, 0008140Ah + add edx, sizeVal + invoke DrawBox, eax, edx, sizeVal, 3, 00031408h mov eax, x - add eax, 2 + add eax, sizeVal mov edx, y - add edx, cubeSize - invoke DrawBox, eax, edx, cubeSize, 2, 0008140Ah + add edx, 3 + invoke DrawBox, eax, edx, 3, sizeVal, 00031408h + ; Ivory body & dark border + invoke DrawBoxBorder, x, y, sizeVal, sizeVal, 00F0F4FAh, 00353540h, 1 + + ; Bevel highlight top & left + mov eax, sizeVal + sub eax, 2 + mov edx, x + inc edx + mov ecx, y + inc ecx + invoke DrawBox, edx, ecx, eax, 1, 00FFFFFFh + invoke DrawBox, edx, ecx, 1, eax, 00FFFFFFh + + ; Bevel shadow bottom & right + mov edx, x + inc edx + mov ecx, y + add ecx, sizeVal + sub ecx, 2 + invoke DrawBox, edx, ecx, eax, 1, 00C0C6D0h + mov edx, x + add edx, sizeVal + sub edx, 2 + mov ecx, y + inc ecx + invoke DrawBox, edx, ecx, 1, eax, 00C0C6D0h + + ; Casino Ruby Red circular pips (radius 3) cmp valNum, 1 - je draw_die_center + je draw_die_c cmp valNum, 3 - je draw_die_center + je draw_die_c cmp valNum, 5 - je draw_die_center - jmp check_die_corners -draw_die_center: + je draw_die_c + jmp check_die_pips_corners + +draw_die_c: mov eax, x add eax, 18 mov edx, y add edx, 18 - invoke DrawCircle, eax, edx, 2, pipColor + invoke DrawCircle, eax, edx, 3, 001515C8h + dec eax + dec edx + invoke DrawPixel, eax, edx, 00FFFFFFh -check_die_corners: +check_die_pips_corners: cmp valNum, 2 - jl die_render_done + jl die_pips_done mov eax, x add eax, 9 mov edx, y add edx, 9 - invoke DrawCircle, eax, edx, 2, pipColor + invoke DrawCircle, eax, edx, 3, 001515C8h mov eax, x - add eax, 27 + add eax, sizeVal + sub eax, 10 mov edx, y - add edx, 27 - invoke DrawCircle, eax, edx, 2, pipColor + add edx, sizeVal + sub edx, 10 + invoke DrawCircle, eax, edx, 3, 001515C8h cmp valNum, 4 - jl die_render_done + jl die_pips_done mov eax, x - add eax, 27 + add eax, sizeVal + sub eax, 10 mov edx, y add edx, 9 - invoke DrawCircle, eax, edx, 2, pipColor + invoke DrawCircle, eax, edx, 3, 001515C8h mov eax, x add eax, 9 mov edx, y - add edx, 27 - invoke DrawCircle, eax, edx, 2, pipColor + add edx, sizeVal + sub edx, 10 + invoke DrawCircle, eax, edx, 3, 001515C8h cmp valNum, 6 - jl die_render_done + jl die_pips_done mov eax, x add eax, 9 mov edx, y add edx, 18 - invoke DrawCircle, eax, edx, 2, pipColor + invoke DrawCircle, eax, edx, 3, 001515C8h mov eax, x - add eax, 27 + add eax, sizeVal + sub eax, 10 mov edx, y add edx, 18 - invoke DrawCircle, eax, edx, 2, pipColor + invoke DrawCircle, eax, edx, 3, 001515C8h -die_render_done: +die_pips_done: ret -DrawDieCube ENDP +DrawCrapsDie ENDP InitDiceGame PROC mov dice3d_state, 0 @@ -3067,7 +3389,7 @@ HandleDiceInput PROC cmp dice3d_state, 1 je dice_input_done - invoke Pressed3D, 20h ; SPACE + invoke Pressed3D, 20h ; SPACE -> Roll! test eax, eax jz check_dice_choice mov eax, bankroll @@ -3078,11 +3400,13 @@ HandleDiceInput PROC mov dice3d_state, 1 mov dice3d_timer, 0 mov dice3d_win, 0 - invoke PlaySoundA, OFFSET soundClick, 0, 1 + invoke PlaySoundA, OFFSET soundCards, 0, 1 jmp dice_input_done + dice_no_cash: invoke CopyString3D, OFFSET msgNeedMoney, OFFSET flashMessage mov flashTimer, 60 + invoke PlaySoundA, OFFSET soundClick, 0, 1 jmp dice_input_done check_dice_choice: @@ -3090,11 +3414,13 @@ check_dice_choice: test eax, eax jz @F mov dice3d_choice, 1 + invoke PlaySoundA, OFFSET soundClick, 0, 1 @@: invoke Pressed3D, 32h ; '2' test eax, eax jz check_dice_bet_adjust mov dice3d_choice, 2 + invoke PlaySoundA, OFFSET soundClick, 0, 1 check_dice_bet_adjust: invoke Pressed3D, 26h ; UP @@ -3104,6 +3430,7 @@ check_dice_bet_adjust: test eax, eax jz check_dice_bet_down dice_inc_bet: + invoke PlaySoundA, OFFSET soundClick, 0, 1 cmp dice3d_bet, 500 jge dice_input_done cmp dice3d_bet, 250 @@ -3115,25 +3442,6 @@ dice_inc_bet: cmp dice3d_bet, 25 jge dice_set_50 jmp dice_set_25 - -check_dice_bet_down: - invoke Pressed3D, 28h ; DOWN - test eax, eax - jnz dice_dec_bet - invoke Pressed3D, 53h ; S - test eax, eax - jz dice_input_done -dice_dec_bet: - cmp dice3d_bet, 25 - jle dice_set_10 - cmp dice3d_bet, 50 - jle dice_set_25 - cmp dice3d_bet, 100 - jle dice_set_50 - cmp dice3d_bet, 250 - jle dice_set_100 - jmp dice_set_250 - dice_set_500: mov dice3d_bet, 500 jmp dice_input_done @@ -3149,58 +3457,115 @@ dice_set_50: dice_set_25: mov dice3d_bet, 25 jmp dice_input_done + +check_dice_bet_down: + invoke Pressed3D, 28h ; DOWN + test eax, eax + jnz dice_dec_bet + invoke Pressed3D, 53h ; S + test eax, eax + jz dice_input_done +dice_dec_bet: + invoke PlaySoundA, OFFSET soundClick, 0, 1 + cmp dice3d_bet, 25 + jle dice_set_10 + cmp dice3d_bet, 50 + jle dice_set_25 + cmp dice3d_bet, 100 + jle dice_set_50 + cmp dice3d_bet, 250 + jle dice_set_100 + mov dice3d_bet, 250 + jmp dice_input_done dice_set_10: mov dice3d_bet, 10 - jmp dice_input_done dice_input_done: ret HandleDiceInput ENDP RenderDiceGame PROC uses ebx esi edi - local d1X:DWORD, d1Y:DWORD, d2X:DWORD, d2Y:DWORD + LOCAL d1X:DWORD, d1Y:DWORD, d2X:DWORD, d2Y:DWORD, bxX:DWORD - ; Background & Bezel - invoke DrawBox, 0, 0, SCREEN_W, SCREEN_H, 000C2612h - invoke DrawBoxBorder, 10, 10, 300, 220, 0014381Ah, 0000D7FFh, 3 + ; Craps Emerald Felt & Oak Armrest + invoke DrawBox, 0, 0, 320, 240, 00082E12h + invoke DrawBoxBorder, 4, 4, 312, 232, 00093816h, 00122244h, 3 + invoke DrawBoxBorder, 8, 8, 304, 224, 000A3F19h, 0005140Ah, 2 - ; Illuminated Marquee Header - invoke DrawBoxBorder, 25, 18, 270, 26, 000A1F0Eh, 0000FFFFh, 2 - invoke DrawString8x8, 52, 27, OFFSET textDiceTitle, 0000D7FFh + ; Pyramidal diamond craps backboard texture + mov bxX, 12 +craps_bumper: + cmp bxX, 308 + jge craps_felt_markings + mov eax, bxX + add eax, 4 + invoke DrawBox, eax, 11, 4, 4, 00041006h + mov eax, bxX + add eax, 5 + invoke DrawPixel, eax, 12, 000F4820h + add bxX, 12 + jmp craps_bumper - ; Choice Panels - mov eax, 000E2614h - mov edx, 00505050h - mov ecx, 00808080h +craps_felt_markings: + ; Table Markings printed in gold directly on felt + invoke DrawString8x8, 72, 20, OFFSET textDiceTitle, 0000D7FFh + invoke DrawString8x8, 68, 32, OFFSET textDiceSubtitle, 0000B0A0h + + ; Meters: Bank & Bet + invoke DrawBoxBorder, 16, 46, 108, 16, 0006240Eh, 000E5022h, 1 + invoke DrawString8x8, 20, 50, OFFSET textBankPrompt, 0050FF50h + invoke FormatNumber, bankroll, OFFSET hudNumBuffer + invoke DrawString8x8, 68, 50, OFFSET hudNumBuffer, 0050FF50h + + invoke DrawBoxBorder, 196, 46, 108, 16, 0006240Eh, 000E5022h, 1 + invoke DrawString8x8, 200, 50, OFFSET textBetPrompt, 0000D7FFh + invoke FormatNumber, dice3d_bet, OFFSET hudNumBuffer + invoke DrawString8x8, 264, 50, OFFSET hudNumBuffer, 0000D7FFh + + ; Betting Zone Left: [1] ×¨Ò + mov eax, 00073014h + mov edx, 001A602Ah + mov ecx, 0080B090h cmp dice3d_choice, 1 jne @F - mov eax, 001C4824h + mov eax, 000B441Dh mov edx, 0000FFFFh mov ecx, 0000FFFFh @@: push ecx - invoke DrawBoxBorder, 24, 55, 76, 36, eax, edx, 2 + invoke DrawBoxBorder, 16, 68, 88, 54, eax, edx, 2 pop ecx - invoke DrawString8x8, 34, 68, OFFSET textDiceEven, ecx + invoke DrawString8x8, 24, 74, OFFSET textDiceEven, ecx + invoke DrawString8x8, 20, 86, OFFSET textDiceEvenNums, 0000D7FFh + cmp dice3d_choice, 1 + jne @F + invoke DrawChipStack, 48, 110, 4 +@@: - mov eax, 000E2614h - mov edx, 00505050h - mov ecx, 00808080h + ; Betting Zone Right: [2] ÍÅ×ÅÒ + mov eax, 00073014h + mov edx, 001A602Ah + mov ecx, 0080B090h cmp dice3d_choice, 2 jne @F - mov eax, 001C4824h + mov eax, 000B441Dh mov edx, 0000FFFFh mov ecx, 0000FFFFh @@: push ecx - invoke DrawBoxBorder, 220, 55, 76, 36, eax, edx, 2 + invoke DrawBoxBorder, 216, 68, 88, 54, eax, edx, 2 pop ecx - invoke DrawString8x8, 226, 68, OFFSET textDiceOdd, ecx + invoke DrawString8x8, 224, 74, OFFSET textDiceOdd, ecx + invoke DrawString8x8, 224, 86, OFFSET textDiceOddNums, 00508060h + cmp dice3d_choice, 2 + jne @F + invoke DrawChipStack, 248, 110, 4 +@@: - ; Dice Table Box - invoke DrawBoxBorder, 104, 52, 112, 54, 0009200Dh, 00305030h, 1 + ; Center Dice Field + invoke DrawBoxBorder, 112, 68, 96, 54, 00072E13h, 00145826h, 1 - ; Rolling animation logic + ; Rolling Animation Logic cmp dice3d_state, 1 jne dice_at_rest @@ -3211,19 +3576,17 @@ RenderDiceGame PROC uses ebx esi edi and eax, 3 sub eax, 1 - mov edx, 112 + mov edx, 120 add edx, eax mov d1X, edx - - mov edx, 60 + mov edx, 76 sub edx, eax mov d1Y, edx - mov edx, 172 + mov edx, 164 sub edx, eax mov d2X, edx - - mov edx, 62 + mov edx, 78 add edx, eax mov d2Y, edx @@ -3236,15 +3599,14 @@ RenderDiceGame PROC uses ebx esi edi inc eax mov dice3d_val2, eax @@: - invoke DrawDieCube, d1X, d1Y, 36, dice3d_val1 - invoke DrawDieCube, d2X, d2Y, 36, dice3d_val2 - - invoke DrawString8x8, 96, 132, OFFSET textDiceRolling, 0000FFFFh + invoke DrawCrapsDie, d1X, d1Y, 36, dice3d_val1 + invoke DrawCrapsDie, d2X, d2Y, 36, dice3d_val2 + invoke DrawString8x8, 76, 138, OFFSET textDiceRolling, 0000FFFFh cmp dice3d_timer, 36 jl dice_draw_controls - ; Roll completed! + ; Settle dice! mov dice3d_state, 2 invoke RandomRange3D, 6 inc eax @@ -3257,108 +3619,228 @@ RenderDiceGame PROC uses ebx esi edi add eax, dice3d_val2 mov dice3d_sum, eax + ; Check choice vs sum parity + mov eax, dice3d_sum test eax, 1 jz dice_sum_is_even - mov ecx, 2 ; Odd - jmp check_dice_win + + ; Odd + cmp dice3d_choice, 2 + je dice_roll_won + jmp dice_roll_lost + dice_sum_is_even: - mov ecx, 1 ; Even + cmp dice3d_choice, 1 + je dice_roll_won -check_dice_win: - cmp ecx, dice3d_choice - jne dice_roll_lost +dice_roll_lost: + mov dice3d_win, 0 + invoke PlaySoundA, OFFSET soundLose, 0, 1 + jmp dice_draw_controls +dice_roll_won: mov eax, dice3d_bet shl eax, 1 mov dice3d_win, eax add bankroll, eax - invoke PlaySoundA, OFFSET soundCoin, 0, 1 - jmp dice_draw_controls - -dice_roll_lost: - mov dice3d_win, 0 - invoke PlaySoundA, OFFSET soundClick, 0, 1 + invoke PlaySoundA, OFFSET soundVictory, 0, 1 jmp dice_draw_controls dice_at_rest: - invoke DrawDieCube, 112, 60, 36, dice3d_val1 - invoke DrawDieCube, 172, 60, 36, dice3d_val2 + invoke DrawCrapsDie, 120, 76, 36, dice3d_val1 + invoke DrawCrapsDie, 164, 76, 36, dice3d_val2 cmp dice3d_state, 2 jne dice_draw_controls - ; Score Tally - invoke DrawString8x8, 80, 112, OFFSET textDiceTally, 0000D7FFh + ; Scoreboard Plaque + invoke DrawBoxBorder, 36, 130, 248, 30, 00051D0Ch, 0000D7FFh, 1 + invoke DrawString8x8, 44, 135, OFFSET textDiceSumHdr, 0000D7FFh invoke FormatNumber, dice3d_val1, OFFSET hudNumBuffer - invoke DrawString8x8, 136, 112, OFFSET hudNumBuffer, 00FFFFFFh - invoke DrawString8x8, 146, 112, OFFSET textDicePlus, 0000D7FFh + invoke DrawString8x8, 100, 135, OFFSET hudNumBuffer, 00FFFFFFh + invoke DrawString8x8, 110, 135, OFFSET textDicePlus, 0000D7FFh invoke FormatNumber, dice3d_val2, OFFSET hudNumBuffer - invoke DrawString8x8, 170, 112, OFFSET hudNumBuffer, 00FFFFFFh - invoke DrawString8x8, 180, 112, OFFSET textDiceEqual, 0000D7FFh + invoke DrawString8x8, 134, 135, OFFSET hudNumBuffer, 00FFFFFFh + invoke DrawString8x8, 144, 135, OFFSET textDiceEqual, 0000D7FFh invoke FormatNumber, dice3d_sum, OFFSET hudNumBuffer - invoke DrawString8x8, 204, 112, OFFSET hudNumBuffer, 0000FFFFh + invoke DrawString8x8, 168, 135, OFFSET hudNumBuffer, 0000FFFFh mov eax, dice3d_sum test eax, 1 - jz @F - invoke DrawString8x8, 222, 112, OFFSET textDiceOddResult, 00FF8080h - jmp dice_show_outcome + jnz @F + invoke DrawString8x8, 186, 135, OFFSET textDiceEvenResult, 0080FF80h + jmp dice_show_win_msg @@: - invoke DrawString8x8, 222, 112, OFFSET textDiceEvenResult, 0080FF80h + invoke DrawString8x8, 186, 135, OFFSET textDiceOddResult, 00FF8080h -dice_show_outcome: +dice_show_win_msg: cmp dice3d_win, 0 je dice_show_loss - invoke DrawString8x8, 90, 132, OFFSET textDiceWin, 0000FFFFh + invoke DrawString8x8, 68, 147, OFFSET textDiceWin, 0050FF50h invoke FormatNumber, dice3d_win, OFFSET hudNumBuffer - invoke DrawString8x8, 178, 132, OFFSET hudNumBuffer, 0000FFFFh + invoke DrawString8x8, 156, 147, OFFSET hudNumBuffer, 0050FF50h + invoke DrawString8x8, 188, 147, OFFSET textDiceWinMult, 0050FF50h jmp dice_draw_controls + dice_show_loss: - invoke DrawString8x8, 126, 132, OFFSET textDiceLose, 000000FFh + invoke DrawString8x8, 116, 147, OFFSET textDiceLose, 008080FFh dice_draw_controls: - invoke DrawBoxBorder, 20, 165, 280, 58, 00151515h, 0000D7FFh, 1 - invoke DrawString8x8, 28, 170, OFFSET textBank3D, 0000D7FFh - invoke FormatNumber, bankroll, OFFSET hudNumBuffer - invoke DrawString8x8, 88, 170, OFFSET hudNumBuffer, 0000FFFFh + invoke DrawBox, 16, 188, 288, 1, 00104820h - invoke DrawString8x8, 180, 170, OFFSET textBet3D, 0000D7FFh - invoke FormatNumber, dice3d_bet, OFFSET hudNumBuffer - invoke DrawString8x8, 236, 170, OFFSET hudNumBuffer, 0050FF50h + mov eax, 0 + cmp dice3d_choice, 1 + sete al + invoke DrawKeycap3D, 20, 198, OFFSET textDiceKey1, eax - invoke DrawString8x8, 28, 186, OFFSET textDiceControls1, 00FFFFFFh - invoke DrawString8x8, 28, 202, OFFSET textDiceControls2, 00A0A0A0h + mov eax, 0 + cmp dice3d_choice, 2 + sete al + invoke DrawKeycap3D, 82, 198, OFFSET textDiceKey2, eax + + invoke DrawKeycap3D, 160, 198, OFFSET textDiceKeySpace, 1 + invoke DrawKeycap3D, 274, 198, OFFSET textKeyEsc, 0 ret RenderDiceGame ENDP ; ============================================================================== ; IN-ENGINE 2.5D MINI-GAME: SKULLS & CUPS (ÍÀϨÐÑÒÊÈ) ; ============================================================================== -DrawCup PROC uses ebx esi edi x:DWORD, y:DWORD, cupNumChar:DWORD - invoke DrawBox, x + 14, y, 16, 4, 0000C8E8h - invoke DrawBoxBorder, x + 8, y + 4, 28, 12, 00221A30h, 0000D7FFh, 2 - invoke DrawBoxBorder, x + 4, y + 16, 36, 16, 00221A30h, 0000D7FFh, 2 - invoke DrawBoxBorder, x + 2, y + 32, 40, 8, 002A2038h, 0000FFFFh, 2 +DrawGlowingOrb PROC uses ebx esi edi, cxVal:DWORD, cyVal:DWORD + invoke DrawCircle, cxVal, cyVal, 14, 00081E2Eh + invoke DrawCircle, cxVal, cyVal, 11, 00103A58h + invoke DrawCircle, cxVal, cyVal, 8, 001A588Ah + invoke DrawCircle, cxVal, cyVal, 6, 0000B0E0h + invoke DrawCircle, cxVal, cyVal, 4, 0000E0FFh + mov eax, cxVal + dec eax + mov edx, cyVal + dec edx + invoke DrawCircle, eax, edx, 2, 00A0FFFFh + mov eax, cxVal + sub eax, 2 + mov edx, cyVal + sub edx, 2 + invoke DrawPixel, eax, edx, 00FFFFFFh + ret +DrawGlowingOrb ENDP +DrawGothicCup PROC uses ebx esi edi, x:DWORD, y:DWORD, cupId:DWORD, isLifted:DWORD, hasBall:DWORD + LOCAL liftY:DWORD + + mov eax, y + cmp isLifted, 0 + je @F + sub eax, 28 +@@: + mov liftY, eax + + ; Drop shadow on purple velvet + cmp isLifted, 0 + jne @F + mov eax, x + add eax, 6 + mov edx, y + add edx, 42 + invoke DrawBox, eax, edx, 36, 4, 000A0410h + jmp draw_cup_body +@@: + mov eax, x + add eax, 10 + mov edx, y + add edx, 42 + invoke DrawBox, eax, edx, 28, 2, 0012061Ah + + ; Draw orb if lifted and has ball + cmp hasBall, 0 + je draw_cup_body + mov eax, x + add eax, 24 + mov edx, y + add edx, 26 + invoke DrawGlowingOrb, eax, edx + +draw_cup_body: + ; Base + mov eax, x + add eax, 6 + mov edx, liftY + add edx, 36 + invoke DrawBoxBorder, eax, edx, 36, 6, 00221A30h, 0000B0D0h, 1 + + ; Stem mov eax, x add eax, 18 - mov edx, y - add edx, 18 - invoke DrawChar8x8, eax, edx, cupNumChar, 0000FFFFh - ret -DrawCup ENDP - -DrawGoldenBall PROC uses ebx esi edi x:DWORD, y:DWORD - invoke DrawCircle, x, y, 7, 0000A5D8h - invoke DrawCircle, x, y, 6, 0000D7FFh - invoke DrawCircle, x, y, 4, 0000FFFFh + mov edx, liftY + add edx, 28 + invoke DrawBox, eax, edx, 12, 8, 00332545h mov eax, x - sub eax, 2 - mov edx, y - sub edx, 2 - invoke DrawCircle, eax, edx, 1, 00FFFFFFh + add eax, 22 + mov edx, liftY + add edx, 28 + invoke DrawBox, eax, edx, 4, 8, 0055406Eh + + ; Bowl + mov eax, x + add eax, 8 + mov edx, liftY + add edx, 8 + invoke DrawBoxBorder, eax, edx, 32, 20, 002D1E40h, 0000D7FFh, 1 + mov eax, x + add eax, 14 + mov edx, liftY + add edx, 10 + invoke DrawBox, eax, edx, 6, 16, 00503570h + mov eax, x + add eax, 17 + mov edx, liftY + add edx, 10 + invoke DrawBox, eax, edx, 3, 16, 007850A0h + + ; Flared Rim + mov eax, x + add eax, 4 + mov edx, liftY + add edx, 2 + invoke DrawBoxBorder, eax, edx, 40, 7, 00150A20h, 0000FFFFh, 1 + mov eax, x + add eax, 12 + mov edx, liftY + add edx, 4 + invoke DrawBox, eax, edx, 16, 2, 0000FFFFh + + ; Skull Insignia on Bowl + mov eax, x + add eax, 21 + mov edx, liftY + add edx, 12 + invoke DrawBox, eax, edx, 6, 5, 0000D7FFh + mov eax, x + add eax, 22 + mov edx, liftY + add edx, 17 + invoke DrawBox, eax, edx, 4, 3, 0000D7FFh + mov eax, x + add eax, 22 + mov edx, liftY + add edx, 14 + invoke DrawPixel, eax, edx, 00150A20h + mov eax, x + add eax, 24 + mov edx, liftY + add edx, 14 + invoke DrawPixel, eax, edx, 00150A20h + + ; Cup ID Badge + mov eax, x + add eax, 21 + mov edx, liftY + add edx, 24 + mov ecx, cupId + add ecx, '0' + invoke DrawChar8x8, eax, edx, ecx, 0000FFFFh ret -DrawGoldenBall ENDP +DrawGothicCup ENDP InitSkullsGame PROC mov skulls3d_state, 0 @@ -3368,25 +3850,28 @@ InitSkullsGame PROC jge @F mov skulls3d_bet, 50 @@: + invoke RandomRange3D, 3 + mov skulls3d_ballPos, eax ret InitSkullsGame ENDP -FinalizeSkullsGuess PROC +FinalizeSkullsGuess PROC uses ebx mov skulls3d_state, 4 mov eax, skulls3d_choice cmp eax, skulls3d_ballPos jne skulls_guess_lost + ; Won 3x! mov eax, skulls3d_bet imul eax, 3 mov skulls3d_win, eax add bankroll, eax - invoke PlaySoundA, OFFSET soundJackpot, 0, 1 + invoke PlaySoundA, OFFSET soundVictory, 0, 1 ret skulls_guess_lost: mov skulls3d_win, 0 - invoke PlaySoundA, OFFSET soundClick, 0, 1 + invoke PlaySoundA, OFFSET soundLose, 0, 1 ret FinalizeSkullsGuess ENDP @@ -3396,10 +3881,10 @@ HandleSkullsInput PROC cmp skulls3d_state, 2 je skulls_input_done - cmp skulls3d_state, 0 - jne check_skulls_in_phase3 + cmp skulls3d_state, 3 + je check_skulls_pick - ; Phase 0: Idle / betting + ; State 0 or 4: Can start new round or adjust bet invoke Pressed3D, 20h ; SPACE test eax, eax jz check_skulls_bet_adjust @@ -3412,22 +3897,27 @@ HandleSkullsInput PROC invoke RandomRange3D, 3 mov skulls3d_ballPos, eax + + invoke RandomRange3D, 3 + mov skulls3d_swapPair0, eax + invoke RandomRange3D, 3 + mov skulls3d_swapPair1, eax + invoke RandomRange3D, 3 + mov skulls3d_swapPair2, eax + mov skulls3d_state, 1 mov skulls3d_timer, 0 mov skulls3d_win, 0 - invoke PlaySoundA, OFFSET soundCoin, 0, 1 + invoke PlaySoundA, OFFSET soundShuffle, 0, 1 jmp skulls_input_done skulls_no_cash: invoke CopyString3D, OFFSET msgNeedMoney, OFFSET flashMessage mov flashTimer, 60 + invoke PlaySoundA, OFFSET soundClick, 0, 1 jmp skulls_input_done -check_skulls_in_phase3: - cmp skulls3d_state, 3 - jne check_skulls_in_phase4 - - ; Phase 3: Pick cup +check_skulls_pick: invoke Pressed3D, 31h ; '1' test eax, eax jz @F @@ -3449,14 +3939,6 @@ check_skulls_in_phase3: call FinalizeSkullsGuess jmp skulls_input_done -check_skulls_in_phase4: - ; Phase 4: Play again or adjust bet - invoke Pressed3D, 20h ; SPACE - test eax, eax - jz check_skulls_bet_adjust - mov skulls3d_state, 0 - jmp skulls_input_done - check_skulls_bet_adjust: invoke Pressed3D, 26h ; UP test eax, eax @@ -3465,6 +3947,7 @@ check_skulls_bet_adjust: test eax, eax jz check_skulls_bet_down skulls_inc_bet: + invoke PlaySoundA, OFFSET soundClick, 0, 1 cmp skulls3d_bet, 500 jge skulls_input_done cmp skulls3d_bet, 250 @@ -3476,25 +3959,6 @@ skulls_inc_bet: cmp skulls3d_bet, 25 jge skulls_set_50 jmp skulls_set_25 - -check_skulls_bet_down: - invoke Pressed3D, 28h ; DOWN - test eax, eax - jnz skulls_dec_bet - invoke Pressed3D, 53h ; S - test eax, eax - jz skulls_input_done -skulls_dec_bet: - cmp skulls3d_bet, 25 - jle skulls_set_10 - cmp skulls3d_bet, 50 - jle skulls_set_25 - cmp skulls3d_bet, 100 - jle skulls_set_50 - cmp skulls3d_bet, 250 - jle skulls_set_100 - jmp skulls_set_250 - skulls_set_500: mov skulls3d_bet, 500 jmp skulls_input_done @@ -3510,26 +3974,60 @@ skulls_set_50: skulls_set_25: mov skulls3d_bet, 25 jmp skulls_input_done + +check_skulls_bet_down: + invoke Pressed3D, 28h ; DOWN + test eax, eax + jnz skulls_dec_bet + invoke Pressed3D, 53h ; S + test eax, eax + jz skulls_input_done +skulls_dec_bet: + invoke PlaySoundA, OFFSET soundClick, 0, 1 + cmp skulls3d_bet, 25 + jle skulls_set_10 + cmp skulls3d_bet, 50 + jle skulls_set_25 + cmp skulls3d_bet, 100 + jle skulls_set_50 + cmp skulls3d_bet, 250 + jle skulls_set_100 + mov skulls3d_bet, 250 + jmp skulls_input_done skulls_set_10: mov skulls3d_bet, 10 - jmp skulls_input_done skulls_input_done: ret HandleSkullsInput ENDP RenderSkullsGame PROC uses ebx esi edi - local passTick:DWORD, curPair:DWORD, swapSlotA:DWORD, swapSlotB:DWORD - local xA:DWORD, xB:DWORD, curXA:DWORD, curXB:DWORD, curYA:DWORD, curYB:DWORD - local distX:DWORD, dxVal:DWORD, archY:DWORD + 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 - ; Background & Bezel - invoke DrawBox, 0, 0, SCREEN_W, SCREEN_H, 00100E18h - invoke DrawBoxBorder, 10, 10, 300, 220, 001A1828h, 0000D7FFh, 3 + ; Dark Gothic Tavern Table with Royal Velvet + invoke DrawBox, 0, 0, 320, 240, 000D0612h + invoke DrawBoxBorder, 4, 4, 312, 232, 00160B20h, 00321845h, 3 + invoke DrawBoxBorder, 8, 8, 304, 224, 00220F30h, 0000D7FFh, 1 - ; Illuminated Marquee Header - invoke DrawBoxBorder, 25, 18, 270, 26, 000C0A14h, 0000FFFFh, 2 - invoke DrawString8x8, 56, 27, OFFSET textSkullsTitle, 0000D7FFh + ; Header + invoke DrawBoxBorder, 24, 12, 272, 24, 0012081Ah, 0000D7FFh, 2 + invoke DrawString8x8, 64, 20, OFFSET textSkullsTitle, 0000FFFFh + + ; Meters: Bank & Bet + invoke DrawBoxBorder, 20, 42, 114, 16, 000D0616h, 00401858h, 1 + invoke DrawString8x8, 24, 46, OFFSET textBankPrompt, 0050FF50h + invoke FormatNumber, bankroll, OFFSET hudNumBuffer + invoke DrawString8x8, 72, 46, OFFSET hudNumBuffer, 0050FF50h + + invoke DrawBoxBorder, 186, 42, 114, 16, 000D0616h, 00401858h, 1 + invoke DrawString8x8, 190, 46, OFFSET textBetPrompt, 0000D7FFh + invoke FormatNumber, skulls3d_bet, OFFSET hudNumBuffer + invoke DrawString8x8, 254, 46, OFFSET hudNumBuffer, 0000D7FFh + + ; Velvet Table Runner + invoke DrawBoxBorder, 16, 64, 288, 120, 001A0B25h, 00452060h, 1 ; Dispatch based on phase cmp skulls3d_state, 1 @@ -3542,52 +4040,31 @@ RenderSkullsGame PROC uses ebx esi edi je skulls_render_phase4 ; Phase 0: Idle / Betting - invoke DrawCup, 50, 105, '1' - invoke DrawCup, 138, 105, '2' - invoke DrawCup, 226, 105, '3' - invoke DrawString8x8, 24, 48, OFFSET textSkullsPhase0, 0000D7FFh + invoke DrawString8x8, 56, 70, OFFSET textSkullsPhase0, 0000D7FFh + invoke DrawGothicCup, 48, 108, 1, 0, 0 + invoke DrawGothicCup, 136, 108, 2, 0, 0 + invoke DrawGothicCup, 224, 108, 3, 0, 0 jmp skulls_draw_controls skulls_render_phase1: inc skulls3d_timer + invoke DrawString8x8, 56, 70, OFFSET textSkullsPhase1, 0000FFFFh - ; Draw golden ball under starting cup - mov eax, skulls3d_ballPos - cmp eax, 0 - je p1_ball_0 - cmp eax, 1 - je p1_ball_1 - invoke DrawGoldenBall, 248, 120 - jmp p1_draw_cups -p1_ball_0: - invoke DrawGoldenBall, 72, 120 - jmp p1_draw_cups -p1_ball_1: - invoke DrawGoldenBall, 160, 120 - -p1_draw_cups: - mov edx, 105 + ; Draw cups with ballPos cup lifted + mov eax, 0 cmp skulls3d_ballPos, 0 - jne @F - mov edx, 70 -@@: - invoke DrawCup, 50, edx, '1' + sete al + invoke DrawGothicCup, 48, 108, 1, eax, eax - mov edx, 105 + mov eax, 0 cmp skulls3d_ballPos, 1 - jne @F - mov edx, 70 -@@: - invoke DrawCup, 138, edx, '2' + sete al + invoke DrawGothicCup, 136, 108, 2, eax, eax - mov edx, 105 + mov eax, 0 cmp skulls3d_ballPos, 2 - jne @F - mov edx, 70 -@@: - invoke DrawCup, 226, edx, '3' - - invoke DrawString8x8, 76, 48, OFFSET textSkullsPhase1, 0000FFFFh + sete al + invoke DrawGothicCup, 224, 108, 3, eax, eax cmp skulls3d_timer, 40 jl skulls_draw_controls @@ -3595,12 +4072,7 @@ p1_draw_cups: ; Start Phase 2 (Shuffle) mov skulls3d_state, 2 mov skulls3d_timer, 0 - invoke RandomRange3D, 3 - mov skulls3d_swapPair0, eax - invoke RandomRange3D, 3 - mov skulls3d_swapPair1, eax - invoke RandomRange3D, 3 - mov skulls3d_swapPair2, eax + invoke PlaySoundA, OFFSET soundShuffle, 0, 1 jmp skulls_draw_controls skulls_render_phase2: @@ -3637,20 +4109,20 @@ setup_pass_pair: je pair_2 mov swapSlotA, 0 mov swapSlotB, 1 - mov xA, 50 - mov xB, 138 + mov xA, 48 + mov xB, 136 jmp calc_swap_coords pair_1: mov swapSlotA, 1 mov swapSlotB, 2 - mov xA, 138 - mov xB, 226 + mov xA, 136 + mov xB, 224 jmp calc_swap_coords pair_2: mov swapSlotA, 0 mov swapSlotB, 2 - mov xA, 50 - mov xB, 226 + mov xA, 48 + mov xB, 224 calc_swap_coords: mov eax, xB @@ -3672,6 +4144,7 @@ calc_swap_coords: sub eax, dxVal mov curXB, eax + ; Arch height: archY = (t * (20 - t)) / 25 mov eax, passTick mov ecx, 20 sub ecx, eax @@ -3681,138 +4154,137 @@ calc_swap_coords: div ecx mov archY, eax - mov eax, 105 - sub eax, archY - mov curYA, eax + mov edx, 108 + sub edx, archY + mov curYA, edx ; upper arc - mov eax, 105 - add eax, archY - mov curYB, eax + mov edx, 108 + add edx, archY + mov curYB, edx ; lower arc - cmp passTick, 19 - jne @F - mov eax, skulls3d_ballPos - cmp eax, swapSlotA - jne check_ball_b - mov eax, swapSlotB - mov skulls3d_ballPos, eax - jmp ball_swap_done -check_ball_b: - cmp eax, swapSlotB - jne ball_swap_done - mov eax, swapSlotA - mov skulls3d_ballPos, eax -ball_swap_done: - invoke PlaySoundA, OFFSET soundClick, 0, 1 -@@: + invoke DrawString8x8, 56, 70, OFFSET textSkullsPhase2, 0000FFFFh + + ; Depth sorted rendering: Background cup (upper arc) draws FIRST, Foreground cup (lower arc) draws OVER it! + invoke DrawGothicCup, curXA, curYA, 1, 0, 0 + invoke DrawGothicCup, curXB, curYB, 2, 0, 0 + + ; Draw remaining static cup cmp curPair, 1 je draw_stat_0 cmp curPair, 2 je draw_stat_1 - invoke DrawCup, 226, 105, '3' - jmp draw_moving_cups + invoke DrawGothicCup, 224, 108, 3, 0, 0 + jmp check_pass_finish draw_stat_0: - invoke DrawCup, 50, 105, '1' - jmp draw_moving_cups + invoke DrawGothicCup, 48, 108, 1, 0, 0 + jmp check_pass_finish draw_stat_1: - invoke DrawCup, 138, 105, '2' + invoke DrawGothicCup, 136, 108, 2, 0, 0 -draw_moving_cups: - mov edx, '1' - add edx, swapSlotA - invoke DrawCup, curXA, curYA, edx +check_pass_finish: + cmp skulls3d_timer, 20 + je do_pass_swap + cmp skulls3d_timer, 40 + je do_pass_swap + cmp skulls3d_timer, 60 + je do_pass_swap + jmp skulls_draw_controls - mov edx, '1' - add edx, swapSlotB - invoke DrawCup, curXB, curYB, edx +do_pass_swap: + ; Update ballPos if involved in swap + mov eax, skulls3d_ballPos + cmp eax, swapSlotA + jne check_swap_b + mov eax, swapSlotB + mov skulls3d_ballPos, eax + jmp ball_swap_done +check_swap_b: + cmp eax, swapSlotB + jne ball_swap_done + mov eax, swapSlotA + mov skulls3d_ballPos, eax - invoke DrawString8x8, 40, 48, OFFSET textSkullsPhase2, 0000FFFFh +ball_swap_done: + invoke PlaySoundA, OFFSET soundShuffle, 0, 1 cmp skulls3d_timer, 60 jl skulls_draw_controls + + ; Shuffle complete -> Move to Pick phase mov skulls3d_state, 3 mov skulls3d_timer, 0 jmp skulls_draw_controls skulls_render_phase3: - invoke DrawCup, 50, 105, '1' - invoke DrawCup, 138, 105, '2' - invoke DrawCup, 226, 105, '3' - invoke DrawString8x8, 16, 48, OFFSET textSkullsPhase3, 0000FFFFh + invoke DrawString8x8, 40, 70, OFFSET textSkullsPhase3, 0000FFFFh + invoke DrawGothicCup, 48, 108, 1, 0, 0 + invoke DrawGothicCup, 136, 108, 2, 0, 0 + invoke DrawGothicCup, 224, 108, 3, 0, 0 jmp skulls_draw_controls skulls_render_phase4: - mov eax, skulls3d_ballPos - cmp eax, 0 - je p4_ball_0 - cmp eax, 1 - je p4_ball_1 - invoke DrawGoldenBall, 248, 120 - jmp p4_draw_cups -p4_ball_0: - invoke DrawGoldenBall, 72, 120 - jmp p4_draw_cups -p4_ball_1: - invoke DrawGoldenBall, 160, 120 - -p4_draw_cups: - mov edx, 105 - cmp skulls3d_choice, 0 - je @F - cmp skulls3d_ballPos, 0 - jne draw_cup0 -@@: - mov edx, 70 -draw_cup0: - invoke DrawCup, 50, edx, '1' - - mov edx, 105 - cmp skulls3d_choice, 1 - je @F - cmp skulls3d_ballPos, 1 - jne draw_cup1 -@@: - mov edx, 70 -draw_cup1: - invoke DrawCup, 138, edx, '2' - - mov edx, 105 - cmp skulls3d_choice, 2 - je @F - cmp skulls3d_ballPos, 2 - jne draw_cup2 -@@: - mov edx, 70 -draw_cup2: - invoke DrawCup, 226, edx, '3' - + ; Reveal phase cmp skulls3d_win, 0 - je p4_splash_lose - invoke DrawString8x8, 24, 48, OFFSET textSkullsWin, 0000FFFFh + je skulls_show_loss + invoke DrawString8x8, 48, 70, OFFSET textSkullsWin, 0050FF50h invoke FormatNumber, skulls3d_win, OFFSET hudNumBuffer - invoke DrawString8x8, 236, 48, OFFSET hudNumBuffer, 0000FFFFh - jmp p4_again_hint -p4_splash_lose: - invoke DrawString8x8, 36, 48, OFFSET textSkullsLose, 000000FFh -p4_again_hint: - invoke DrawString8x8, 56, 138, OFFSET textSkullsAgain, 0000D7FFh + invoke DrawString8x8, 216, 70, OFFSET hudNumBuffer, 0050FF50h + jmp skulls_p4_cups + +skulls_show_loss: + invoke DrawString8x8, 40, 70, OFFSET textSkullsLose, 008080FFh + +skulls_p4_cups: + ; Draw chosen cup lifted + mov eax, 0 + cmp skulls3d_choice, 0 + sete al + mov edx, 0 + cmp skulls3d_ballPos, 0 + sete dl + invoke DrawGothicCup, 48, 108, 1, eax, edx + + mov eax, 0 + cmp skulls3d_choice, 1 + sete al + mov edx, 0 + cmp skulls3d_ballPos, 1 + sete dl + invoke DrawGothicCup, 136, 108, 2, eax, edx + + mov eax, 0 + cmp skulls3d_choice, 2 + sete al + mov edx, 0 + cmp skulls3d_ballPos, 2 + sete dl + invoke DrawGothicCup, 224, 108, 3, eax, edx + + invoke DrawString8x8, 64, 168, OFFSET textSkullsAgain, 0000D7FFh skulls_draw_controls: - invoke DrawBoxBorder, 20, 165, 280, 58, 00151515h, 0000D7FFh, 1 - invoke DrawString8x8, 28, 170, OFFSET textBank3D, 0000D7FFh - invoke FormatNumber, bankroll, OFFSET hudNumBuffer - invoke DrawString8x8, 88, 170, OFFSET hudNumBuffer, 0000FFFFh + invoke DrawBox, 16, 190, 288, 1, 003A1850h - invoke DrawString8x8, 180, 170, OFFSET textBet3D, 0000D7FFh - invoke FormatNumber, skulls3d_bet, OFFSET hudNumBuffer - invoke DrawString8x8, 236, 170, OFFSET hudNumBuffer, 0050FF50h + mov eax, 0 + cmp skulls3d_choice, 0 + sete al + invoke DrawKeycap3D, 18, 200, OFFSET textSkullsKey1, eax - invoke DrawString8x8, 24, 186, OFFSET textSkullsControls1, 00FFFFFFh - invoke DrawString8x8, 24, 202, OFFSET textSkullsControls2, 00A0A0A0h + mov eax, 0 + cmp skulls3d_choice, 1 + sete al + invoke DrawKeycap3D, 82, 200, OFFSET textSkullsKey2, eax + + mov eax, 0 + cmp skulls3d_choice, 2 + sete al + invoke DrawKeycap3D, 146, 200, OFFSET textSkullsKey3, eax + + invoke DrawKeycap3D, 212, 200, OFFSET textSkullsKeySpace, 1 + invoke DrawKeycap3D, 274, 200, OFFSET textKeyEsc, 0 ret RenderSkullsGame ENDP -; --- Player Input & Movement Physics --- HandlePlayerInput PROC uses ebx esi edi local speed:DWORD local nextX:DWORD diff --git a/docs/previews_minigames/coin_preview.png b/docs/previews_minigames/coin_preview.png new file mode 100644 index 0000000000000000000000000000000000000000..64d7668e1831608c5e9cab0c927d727a35e61890 GIT binary patch literal 6011 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 Ibqu)jUsk@me*gdg literal 0 HcmV?d00001 diff --git a/docs/previews_minigames/dice_preview.png b/docs/previews_minigames/dice_preview.png new file mode 100644 index 0000000000000000000000000000000000000000..a9758b68feb850049f8c7dbc756065b1f955addc GIT binary patch literal 5522 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 literal 0 HcmV?d00001 diff --git a/docs/previews_minigames/skulls_preview.png b/docs/previews_minigames/skulls_preview.png new file mode 100644 index 0000000000000000000000000000000000000000..400d5bdcb76465dd02c535379fac83ad436feeb4 GIT binary patch literal 5121 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 Vg5?kVK>FX;UmiY4IuLs4{{TTp`l-VA83>ldn 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 aFhWgdZdNm2Xdmaftf{`x$#{CH^Zx_E;b@ou diff --git a/tools/README.md b/tools/README.md index 482ffda..9ffc82e 100644 --- a/tools/README.md +++ b/tools/README.md @@ -43,6 +43,7 @@ Offline build tools that process raw images, generate lookup tables, and compose | `build_all_3d.py` | Python | Offline assembly file generator that synthesizes the complete `casino3d.inc` raycaster engine in CP1251. | | `generate_unified_casino3d.py` | Python | Alternative unified generator for `casino3d.inc` with full sprite definitions and game interaction hooks. | | `generate_casino3d.py`
`build_engine.py`
`make_casino3d.py` | Python | Lightweight orchestration scripts for triggering `casino3d.inc` regeneration in CP1251 encoding. | +| `generate_rich_minigames.py` | Python | Patches `casino3d.inc` with rich, custom 2.5D graphics and fixed audio for Coin, Craps, and Skulls. | | `patch_poker_asm.py` | Python | Helper utility to patch `poker.asm` with 3D engine hooks, player save anchors, and mutex management. | --- @@ -53,7 +54,9 @@ Verification scripts, simulation harnesses, and runtime helpers: | Tool | Language | Purpose & Usage | |------|----------|-----------------| +| `test_minigames_render.py` | Python (Pillow) | Visual simulation test suite that rasterizes 2.5D minigame UI frames and saves PNG previews to `docs/previews_minigames/`. Usage: `python tools/tests/test_minigames_render.py`. | | `simulate_render.py` | Python (Pillow) | Software CPU simulation of the 3D raycaster renderer. Reads `casino3d_data.inc` and texture binary, performs DDA raycasting, depth-sorting of 28 casino sprites, and saves the rendered view to `docs/render_view.png`. Usage: `python tools/tests/simulate_render.py`. | | `release_smoke_check.ps1` | PowerShell | Automated smoke test for release readiness: verifies file presence, launcher SHA-256 hashes, CP1251 source markers, and absence of deprecated assets. Usage: `powershell -File tools/tests/release_smoke_check.ps1`. | | `build_graphics.ps1` | PowerShell | Builds the Windows subsystem executable `build/graphics/poker.exe` using MASM32/MSVC toolchain. Usage: `powershell -File tools/tests/build_graphics.ps1`. | | `achievement_popup.bat` | Batch (CP1251) | Standalone console achievement notification popup called by `poker.exe`. Reads achievement text from `runtime/achievement.txt` and renders a decorative banner with rarity colors (COMMON, RARE, EPIC, LEGENDARY). | + diff --git a/tools/generators/generate_rich_minigames.py b/tools/generators/generate_rich_minigames.py new file mode 100644 index 0000000..739d449 --- /dev/null +++ b/tools/generators/generate_rich_minigames.py @@ -0,0 +1,1790 @@ +# -*- coding: utf-8 -*- +""" +Generator script to patch casino3d.inc with rich, custom 2.5D graphics +and fixed audio for Coin Flip, Craps/Dice, and Skulls & Cups. +""" +from pathlib import Path + +REPO_ROOT = Path(__file__).resolve().parents[2] +CASINO_INC = REPO_ROOT / 'casino3d.inc' + +# Read original casino3d.inc +with open(CASINO_INC, 'rb') as f: + raw_content = f.read() + +# 1. Fix Audio Declarations (around line 150) +old_audio_block = ( + b'soundCoin db "assets\\audio\\\xc7\xe2\xee\xed \xef\xe0\xe4\xe0\xfe\xf9\xe5\xe9 \xec\xee\xed\xe5\xf2\xfb.wav",0\r\n' + b'soundCards db "assets\\audio\\playing_cards_deck_flick_through_001_20485.wav",0\r\n' + b'soundRoulette db "assets\\audio\\roulette-wheel-throw-2.wav",0\r\n' + b'soundJackpot db "assets\\audio\\\xc4\xe6\xe5\xea\xef\xee\xf2.wav",0\r\n' + b'soundClick db "assets\\audio\\b05e1ac8be34248.wav",0' +) + +new_audio_block = ( + b'soundCoin db "assets\\audio\\\xc7\xe2\xf3\xea \xec\xee\xed\xe5\xf2\xfb \xe1\xf0\xee\xf8\xe5\xed\xed\xee\xe9 \xe2 \xe2\xee\xe7\xe4\xf3\xf5 \xe8 \xf3\xef\xe0\xe2\xf8\xe5\xe9 \xed\xe0 \xef\xee\xe2\xe5\xf0\xf5\xed\xee\xf1\xf2\xfc.wav",0\r\n' + b'soundCoinDing db "assets\\audio\\\xc7\xe2\xf3\xea \xec\xee\xed\xe5\xf2\xfb \xe2 \xe8\xe3\xf0\xe5 Ultrakill.wav",0\r\n' + b'soundCards db "assets\\audio\\playing_cards_deck_flick_through_001_20485.wav",0\r\n' + b'soundRoulette db "assets\\audio\\roulette-wheel-throw-2.wav",0\r\n' + b'soundJackpot db "assets\\audio\\\xc4\xe6\xfd\xea \xef\xee\xf2.wav",0\r\n' + b'soundVictory db "assets\\audio\\victory-tf2.wav",0\r\n' + b'soundClick db "assets\\audio\\revolverdryfirec.wav",0\r\n' + b'soundShuffle db "assets\\audio\\moving-stone.wav",0\r\n' + b'soundLose db "assets\\audio\\\xcf\xf0\xee\xe8\xe3\xf0\xfb\xf8.wav",0' +) + +if old_audio_block in raw_content: + raw_content = raw_content.replace(old_audio_block, new_audio_block, 1) + print("[OK] Replaced audio block (removed gunshots, fixed real sound paths)") +else: + print("[WARN] Audio block pattern not found verbatim, checking sub-patterns...") + if b'soundClick db "assets\\audio\\b05e1ac8be34248.wav",0' in raw_content: + raw_content = raw_content.replace( + b'soundClick db "assets\\audio\\b05e1ac8be34248.wav",0', + b'soundClick db "assets\\audio\\revolverdryfirec.wav",0\r\n' + b'soundShuffle db "assets\\audio\\moving-stone.wav",0\r\n' + b'soundLose db "assets\\audio\\\xcf\xf0\xee\xe8\xe3\xf0\xfb\xf8.wav",0\r\n' + b'soundVictory db "assets\\audio\\victory-tf2.wav",0\r\n' + b'soundCoinDing db "assets\\audio\\\xc7\xe2\xf3\xea \xec\xee\xed\xe5\xf2\xfb \xe2 \xe8\xe3\xf0\xe5 Ultrakill.wav",0' + ) + print("[OK] Replaced soundClick and added soundShuffle / soundLose") + +# 2. Update string constants (around line 290) +# Find start of coinRxAnimTable and end before shopMsg +pos_coin_table = raw_content.find(b'coinRxAnimTable db') +pos_shop_msg = raw_content.find(b'shopMsg db 128 dup(0)') + +assert pos_coin_table != -1 and pos_shop_msg != -1, "Could not locate text strings section" + +new_strings_text = """coinRxAnimTable db 26, 22, 16, 6, 16, 22, 26, 22, 16, 6 + +; --- Native 2.5D Coin Flip --- +textCoinTitle db "* * * \xc7 \xce \xcb \xce \xd2 \xc0 \xdf \xcc \xce \xcd \xc5 \xd2 \xc0 * * *",0 +textCoinHeads db "\xce\xd0\xa8\xcb",0 +textCoinTails db "\xd0\xc5\xd8\xca\xc0",0 +textCoinStreak db "\xd1\xc5\xd0\xc8\xdf: ",0 +textCoinSide1 db "[1] \xce\xd0\xa8\xcb",0 +textCoinSide2 db "[2] \xd0\xc5\xd8\xca\xc0",0 +textCoinFlipping db "\xcc\xce\xcd\xc5\xd2\xc0 \xc2 \xcf\xce\xcb\xa8\xd2\xc5...",0 +textCoinWin db "\xc2\xdb\xc8\xc3\xd0\xdb\xd8: +$",0 +textCoinLose db "\xcd\xc5 \xd3\xc3\xc0\xc4\xc0\xcb!",0 +textCoinKey1 db "1:\xce\xd0\xa8\xcb",0 +textCoinKey2 db "2:\xd0\xc5\xd8\xca\xc0",0 +textCoinKeySpace db "\xcf\xd0\xce\xc1\xc5\xcb:\xc1\xd0\xce\xd1\xce\xca",0 +textCoinStreakFmt db "\xd1\xc5\xd0\xc8\xdf: [X] [X] [X] [ ] [ ] x4!",0 + +; --- Native 2.5D Dice Game --- +dice3d_bet dd 50 +dice3d_choice dd 1 ; 1 = \xd7\xb8\xf2, 2 = \xcd\xe5\xf7\xe5\xf2 +dice3d_state dd 0 ; 0 = Idle, 1 = Rolling, 2 = Result +dice3d_timer dd 0 +dice3d_val1 dd 4 +dice3d_val2 dd 6 +dice3d_sum dd 10 +dice3d_win dd 0 + +textDiceTitle db "=== G R A N D C R A P S ===",0 +textDiceSubtitle db "[ PASS LINE ] [ ANY CRAPS ]",0 +textDiceEven db "[1] \xd7\xa8\xd2",0 +textDiceOdd db "[2] \xcd\xc5\xd7\xc5\xd2",0 +textDiceEvenNums db "2 4 6 8 10",0 +textDiceOddNums db "3 5 7 9 11",0 +textDiceSumHdr db "\xd1\xd3\xcc\xcc\xc0: ",0 +textDicePlus db " + ",0 +textDiceEqual db " = ",0 +textDiceEvenResult db " (\xd7\xa8\xd2)",0 +textDiceOddResult db " (\xcd\xc5\xd7\xc5\xd2)",0 +textDiceRolling db "\xca\xce\xd1\xd2\xc8 \xcb\xc5\xd2\xdf\xd2 \xcf\xce \xd1\xd3\xca\xcd\xd3...",0 +textDiceWin db "\xc2\xdb\xc8\xc3\xd0\xdb\xd8: +$",0 +textDiceWinMult db "! (x2)",0 +textDiceLose db "\xcf\xd0\xce\xc8\xc3\xd0\xdb\xd8!",0 +textDiceKey1 db "1:\xd7\xa8\xd2",0 +textDiceKey2 db "2:\xcd\xc5\xd7\xc5\xd2",0 +textDiceKeySpace db "\xcf\xd0\xce\xc1\xc5\xcb:\xc1\xd0\xce\xd1\xce\xca",0 + +; --- Native 2.5D Skulls Game --- +skulls3d_bet dd 50 +skulls3d_state dd 0 ; 0 = Idle, 1 = Show ball, 2 = Shuffle, 3 = Pick, 4 = Reveal +skulls3d_timer dd 0 +skulls3d_ballPos dd 1 ; 0, 1, 2 +skulls3d_choice dd 1 ; 0, 1, 2 +skulls3d_win dd 0 +skulls3d_swapPair0 dd 0 +skulls3d_swapPair1 dd 1 +skulls3d_swapPair2 dd 2 + +textSkullsTitle db "+ + + \xcd \xc0 \xcf \xa8 \xd0 \xd1 \xd2 \xca \xc8 + + +",0 +textSkullsPhase0 db "\xc4\xc5\xcb\xc0\xc9 \xd1\xd2\xc0\xc2\xca\xd3 \xc8 \xc6\xcc\xc8 [\xcf\xd0\xce\xc1\xc5\xcb]",0 +textSkullsPhase1 db "\xd1\xcc\xce\xd2\xd0\xc8, \xc3\xc4\xc5 \xc7\xce\xcb\xce\xd2\xce\xc9 \xd8\xc0\xd0...",0 +textSkullsPhase2 db "\xca\xd0\xd3\xd7\xd3, \xc2\xc5\xd0\xd7\xd3, \xc7\xc0\xcf\xd3\xd2\xc0\xd2\xdc \xd5\xce\xd7\xd3...",0 +textSkullsPhase3 db "\xc3\xc4\xc5 \xd8\xc0\xd0? \xc2\xdb\xc1\xc8\xd0\xc0\xc9: [1], [2] \xc8\xcb\xc8 [3]!",0 +textSkullsWin db "\xc2\xc5\xd0\xcd\xce! \xc2\xdb\xcf\xcb\xc0\xd2\xc0 x3! +$",0 +textSkullsLose db "\xcc\xc8\xcc\xce! \xd8\xc0\xd0 \xc1\xdb\xcb \xc2 \xc4\xd0\xd3\xc3\xce\xcc \xcc\xc5\xd1\xd2\xc5!",0 +textSkullsAgain db "[\xcf\xd0\xce\xc1\xc5\xcb] - \xd1\xdb\xc3\xd0\xc0\xd2\xdc \xc5\xd9\xa8 \xd0\xc0\xc7",0 +textSkullsKey1 db "1:\xca\xd3\xc1\xce\xca",0 +textSkullsKey2 db "2:\xca\xd3\xc1\xce\xca",0 +textSkullsKey3 db "3:\xca\xd3\xc1\xce\xca",0 +textSkullsKeySpace db "\xcf\xd0\xce\xc1\xc5\xcb",0 + +; --- Shared UI Strings --- +textKeyEsc db "ESC",0 +textBankPrompt db "\xc1\xc0\xcd\xca: $",0 +textBetPrompt db "\xd1\xd2\xc0\xc2\xca\xc0: $",0 +textBetHint db " [W/S]",0 + +""" + +raw_content = raw_content[:pos_coin_table] + new_strings_text.encode('latin1') + raw_content[pos_shop_msg:] +print("[OK] Replaced string constants section with rich game strings") + +# 3. Replace procedural drawing and rendering block +# Find start of '; IN-ENGINE 2.5D MINI-GAME: COIN FLIP' and end before 'HandlePlayerInput PROC' +pos_games_start = raw_content.find(b'; IN-ENGINE 2.5D MINI-GAME: COIN FLIP') +pos_player_input = raw_content.find(b'HandlePlayerInput PROC') + +assert pos_games_start != -1 and pos_player_input != -1, "Could not locate games procedures section" + +new_games_code = r"""; ============================================================================== +; SHARED RICH UI PROCEDURES +; ============================================================================== +DrawKeycap3D PROC uses ebx esi edi, x:DWORD, y:DWORD, strPtr:DWORD, isActive:DWORD + LOCAL capW:DWORD + ; Compute string length + mov esi, strPtr + xor ecx, ecx +@@: + mov al, [esi+ecx] + test al, al + jz @F + inc ecx + jmp @B +@@: + shl ecx, 3 ; length * 8 + add ecx, 8 ; padding 8px + mov capW, ecx + + ; Drop shadow + mov eax, x + mov edx, y + add edx, 2 + invoke DrawBox, eax, edx, capW, 13, 0008080Ch + + ; Body & Border + mov eax, 00606870h ; default border + mov edx, 001A1C22h ; default fill + cmp isActive, 0 + je @F + mov eax, 0000FFFFh ; active gold border + mov edx, 001B4B22h ; active dark green fill +@@: + invoke DrawBoxBorder, x, y, capW, 13, edx, eax, 1 + + ; String text + mov eax, 00D0D8E0h + cmp isActive, 0 + je @F + mov eax, 0000FFFFh +@@: + mov edx, x + add edx, 4 + mov ecx, y + add ecx, 3 + invoke DrawString8x8, edx, ecx, strPtr, eax + mov eax, capW + ret +DrawKeycap3D ENDP + +DrawChipStack PROC uses ebx esi edi, x:DWORD, y:DWORD, chipCount:DWORD + xor esi, esi +chip_loop: + cmp esi, chipCount + jge chip_done + mov eax, esi + shl eax, 2 ; esi * 4 + mov edx, y + sub edx, eax ; cy = y - esi*4 + + ; Shadow + mov eax, x + add eax, 2 + mov ecx, edx + add ecx, 5 + invoke DrawBox, eax, ecx, 20, 2, 00041006h + + ; Chip body + invoke DrawBoxBorder, x, edx, 24, 6, 001515B8h, 00FFFFFFh, 1 + + ; White stripe inlays + mov eax, x + add eax, 4 + mov ecx, edx + add ecx, 1 + invoke DrawBox, eax, ecx, 3, 4, 00FFFFFFh + mov eax, x + add eax, 17 + invoke DrawBox, eax, ecx, 3, 4, 00FFFFFFh + + inc esi + jmp chip_loop +chip_done: + ret +DrawChipStack ENDP + +; ============================================================================== +; IN-ENGINE 2.5D MINI-GAME: COIN FLIP (МО�ЕТК�) +; ============================================================================== +DrawDetailedCoin PROC uses ebx esi edi, cxVal:DWORD, cyVal:DWORD, rxVal:DWORD, ryVal:DWORD, outerColor:DWORD, innerColor:DWORD, reliefType:DWORD + LOCAL curDY:DWORD, curDX:DWORD, rxSq:DWORD, rySq:DWORD, rxRySq:DWORD, threshSq:DWORD + cmp rxVal, 0 + jle coin_draw_ret + cmp ryVal, 0 + jle coin_draw_ret + + mov eax, rxVal + imul eax, eax + mov rxSq, eax + + mov eax, ryVal + imul eax, eax + mov rySq, eax + + mov eax, rxSq + imul eax, rySq + mov rxRySq, eax + + mov eax, rxRySq + shr eax, 2 + imul eax, 3 + mov threshSq, eax + + mov eax, ryVal + neg eax + mov curDY, eax + +coin_y_loop: + mov eax, curDY + cmp eax, ryVal + jg check_coin_relief + + mov eax, rxVal + neg eax + mov curDX, eax + +coin_x_loop: + mov eax, curDX + cmp eax, rxVal + jg next_coin_y + + mov eax, curDX + imul eax, eax + imul eax, rySq + mov ebx, curDY + imul ebx, ebx + imul ebx, rxSq + add eax, ebx + cmp eax, rxRySq + jg next_coin_x + + mov ecx, innerColor + cmp eax, threshSq + jb @F + mov ecx, outerColor +@@: + mov eax, cxVal + add eax, curDX + mov edx, cyVal + add edx, curDY + invoke DrawPixel, eax, edx, ecx + +next_coin_x: + inc curDX + jmp coin_x_loop + +next_coin_y: + inc curDY + jmp coin_y_loop + +check_coin_relief: + cmp rxVal, 14 + jl coin_draw_ret + cmp reliefType, 1 + je draw_eagle_relief + cmp reliefType, 2 + je draw_wreath_relief + jmp coin_draw_ret + +draw_eagle_relief: + ; Crown + mov eax, cxVal + sub eax, 3 + mov edx, cyVal + sub edx, 14 + invoke DrawBox, eax, edx, 7, 2, 00007A9Ah + mov eax, cxVal + sub eax, 4 + mov edx, cyVal + sub edx, 12 + invoke DrawBox, eax, edx, 9, 2, 00007A9Ah + + ; Body & Head + mov eax, cxVal + sub eax, 2 + mov edx, cyVal + sub edx, 9 + invoke DrawBox, eax, edx, 5, 12, 00007A9Ah + mov eax, cxVal + dec eax + mov edx, cyVal + sub edx, 8 + invoke DrawBox, eax, edx, 3, 10, 0000D7FFh + + ; Wings + mov eax, cxVal + sub eax, 10 + mov edx, cyVal + sub edx, 8 + invoke DrawBox, eax, edx, 7, 3, 00007A9Ah + mov eax, cxVal + sub eax, 13 + mov edx, cyVal + sub edx, 5 + invoke DrawBox, eax, edx, 10, 3, 00007A9Ah + mov eax, cxVal + sub eax, 11 + mov edx, cyVal + sub edx, 2 + invoke DrawBox, eax, edx, 7, 3, 00007A9Ah + + mov eax, cxVal + add eax, 4 + mov edx, cyVal + sub edx, 8 + invoke DrawBox, eax, edx, 7, 3, 00007A9Ah + mov eax, cxVal + add eax, 4 + mov edx, cyVal + sub edx, 5 + invoke DrawBox, eax, edx, 10, 3, 00007A9Ah + mov eax, cxVal + add eax, 5 + mov edx, cyVal + sub edx, 2 + invoke DrawBox, eax, edx, 7, 3, 00007A9Ah + + ; Tail + mov eax, cxVal + sub eax, 4 + mov edx, cyVal + add edx, 4 + invoke DrawBox, eax, edx, 9, 3, 00007A9Ah + mov eax, cxVal + sub eax, 3 + mov edx, cyVal + add edx, 7 + invoke DrawBox, eax, edx, 7, 3, 00007A9Ah + jmp coin_draw_ret + +draw_wreath_relief: + ; Roman numeral 'I' + mov eax, cxVal + sub eax, 5 + mov edx, cyVal + sub edx, 10 + invoke DrawBox, eax, edx, 11, 3, 00007A9Ah + mov eax, cxVal + sub eax, 2 + mov edx, cyVal + sub edx, 7 + invoke DrawBox, eax, edx, 5, 14, 00007A9Ah + mov eax, cxVal + dec eax + mov edx, cyVal + sub edx, 6 + invoke DrawBox, eax, edx, 3, 12, 0000D7FFh + mov eax, cxVal + sub eax, 6 + mov edx, cyVal + add edx, 7 + invoke DrawBox, eax, edx, 13, 3, 00007A9Ah + + ; Laurel dots left & right + mov eax, cxVal + sub eax, 12 + mov edx, cyVal + sub edx, 10 + invoke DrawBox, eax, edx, 2, 2, 00007A9Ah + mov eax, cxVal + add eax, 11 + mov edx, cyVal + sub edx, 10 + invoke DrawBox, eax, edx, 2, 2, 00007A9Ah + + mov eax, cxVal + sub eax, 12 + mov edx, cyVal + sub edx, 5 + invoke DrawBox, eax, edx, 2, 2, 00007A9Ah + mov eax, cxVal + add eax, 11 + mov edx, cyVal + sub edx, 5 + invoke DrawBox, eax, edx, 2, 2, 00007A9Ah + + mov eax, cxVal + sub eax, 12 + mov edx, cyVal + invoke DrawBox, eax, edx, 2, 2, 00007A9Ah + mov eax, cxVal + add eax, 11 + mov edx, cyVal + invoke DrawBox, eax, edx, 2, 2, 00007A9Ah + + mov eax, cxVal + sub eax, 12 + mov edx, cyVal + add edx, 5 + invoke DrawBox, eax, edx, 2, 2, 00007A9Ah + mov eax, cxVal + add eax, 11 + mov edx, cyVal + add edx, 5 + invoke DrawBox, eax, edx, 2, 2, 00007A9Ah + +coin_draw_ret: + ret +DrawDetailedCoin ENDP + +InitCoinGame PROC + mov coin3d_state, 0 + mov coin3d_timer, 0 + mov coin3d_win, 0 + cmp coin3d_bet, 10 + jge @F + mov coin3d_bet, 50 +@@: + ret +InitCoinGame ENDP + +HandleCoinInput PROC + cmp coin3d_state, 1 + je coin_input_done + + invoke Pressed3D, 20h ; SPACE -> Flip! + test eax, eax + jz check_coin_side + mov eax, bankroll + cmp eax, coin3d_bet + jl coin_no_cash + sub eax, coin3d_bet + mov bankroll, eax + mov coin3d_state, 1 + mov coin3d_timer, 0 + mov coin3d_win, 0 + invoke PlaySoundA, OFFSET soundCoin, 0, 1 + jmp coin_input_done + +coin_no_cash: + invoke CopyString3D, OFFSET msgNeedMoney, OFFSET flashMessage + mov flashTimer, 60 + invoke PlaySoundA, OFFSET soundClick, 0, 1 + jmp coin_input_done + +check_coin_side: + invoke Pressed3D, 31h ; '1' + test eax, eax + jz @F + mov coin3d_side, 1 + invoke PlaySoundA, OFFSET soundClick, 0, 1 +@@: + invoke Pressed3D, 32h ; '2' + test eax, eax + jz check_coin_bet_adjust + mov coin3d_side, 2 + invoke PlaySoundA, OFFSET soundClick, 0, 1 + +check_coin_bet_adjust: + invoke Pressed3D, 26h ; UP + test eax, eax + jnz coin_inc_bet + invoke Pressed3D, 57h ; W + test eax, eax + jz check_coin_bet_down +coin_inc_bet: + invoke PlaySoundA, OFFSET soundClick, 0, 1 + cmp coin3d_bet, 500 + jge coin_input_done + cmp coin3d_bet, 250 + jge coin_set_500 + cmp coin3d_bet, 100 + jge coin_set_250 + cmp coin3d_bet, 50 + jge coin_set_100 + cmp coin3d_bet, 25 + jge coin_set_50 + jmp coin_set_25 +coin_set_500: + mov coin3d_bet, 500 + jmp coin_input_done +coin_set_250: + mov coin3d_bet, 250 + jmp coin_input_done +coin_set_100: + mov coin3d_bet, 100 + jmp coin_input_done +coin_set_50: + mov coin3d_bet, 50 + jmp coin_input_done +coin_set_25: + mov coin3d_bet, 25 + jmp coin_input_done + +check_coin_bet_down: + invoke Pressed3D, 28h ; DOWN + test eax, eax + jnz coin_dec_bet + invoke Pressed3D, 53h ; S + test eax, eax + jz coin_input_done +coin_dec_bet: + invoke PlaySoundA, OFFSET soundClick, 0, 1 + cmp coin3d_bet, 25 + jle coin_set_10 + cmp coin3d_bet, 50 + jle coin_set_25 + cmp coin3d_bet, 100 + jle coin_set_50 + cmp coin3d_bet, 250 + jle coin_set_100 + mov coin3d_bet, 250 + jmp coin_input_done +coin_set_10: + mov coin3d_bet, 10 + +coin_input_done: + ret +HandleCoinInput ENDP + +RenderCoinGame PROC uses ebx esi edi + LOCAL cyVal:DWORD, rxVal:DWORD, curX:DWORD + + ; Cabinet Bezel (Mahogany wood & leather) + invoke DrawBox, 0, 0, 320, 240, 00060914h + invoke DrawBoxBorder, 6, 6, 308, 228, 000F1522h, 001B2E48h, 3 + + ; Corner Brass Rivets + invoke DrawBox, 12, 12, 3, 3, 0000D7FFh + invoke DrawPixel, 13, 13, 00FFFFFFh + invoke DrawBox, 306, 12, 3, 3, 0000D7FFh + invoke DrawPixel, 307, 13, 00FFFFFFh + invoke DrawBox, 12, 226, 3, 3, 0000D7FFh + invoke DrawPixel, 13, 227, 00FFFFFFh + invoke DrawBox, 306, 226, 3, 3, 0000D7FFh + invoke DrawPixel, 307, 227, 00FFFFFFh + + ; Illuminated Marquee Header + invoke DrawBoxBorder, 24, 12, 272, 26, 000A101Ch, 0000D7FFh, 2 + invoke DrawString8x8, 48, 21, OFFSET textCoinTitle, 0000FFFFh + + ; Bulb lights on marquee border + mov curX, 28 +coin_bulbs: + cmp curX, 292 + jge coin_meters + invoke DrawPixel, curX, 13, 0000FFFFh + invoke DrawPixel, curX, 36, 0000D7FFh + add curX, 12 + jmp coin_bulbs + +coin_meters: + ; Status Meters: Bank & Bet + invoke DrawBoxBorder, 20, 44, 114, 18, 000A1A0Eh, 001A4B22h, 1 + invoke DrawString8x8, 24, 49, OFFSET textBankPrompt, 0050FF50h + invoke FormatNumber, bankroll, OFFSET hudNumBuffer + invoke DrawString8x8, 72, 49, OFFSET hudNumBuffer, 0050FF50h + + invoke DrawBoxBorder, 186, 44, 114, 18, 001A100Ah, 003A2814h, 1 + invoke DrawString8x8, 190, 49, OFFSET textBetPrompt, 0000D7FFh + invoke FormatNumber, coin3d_bet, OFFSET hudNumBuffer + invoke DrawString8x8, 254, 49, OFFSET hudNumBuffer, 0000D7FFh + invoke DrawString8x8, 278, 49, OFFSET textBetHint, 00808080h + + ; Center Velvet Platter + invoke DrawCircle, 160, 110, 46, 000090C0h + invoke DrawCircle, 160, 110, 44, 0000D7FFh + invoke DrawCircle, 160, 110, 41, 00180824h + + ; Selection Podiums: [1] ОР�Л + mov eax, 00121620h + mov edx, 00404855h + mov ecx, 0090A0B0h + cmp coin3d_side, 1 + jne @F + mov eax, 001C3822h + mov edx, 0000FFFFh + mov ecx, 0000FFFFh +@@: + push ecx + invoke DrawBoxBorder, 20, 72, 76, 52, eax, edx, 2 + pop ecx + invoke DrawString8x8, 28, 78, OFFSET textCoinSide1, ecx + invoke DrawDetailedCoin, 58, 106, 12, 12, 0000A0D0h, 0000D7FFh, 1 + + ; Selection Podiums: [2] РЕШК� + mov eax, 00121620h + mov edx, 00404855h + mov ecx, 0090A0B0h + cmp coin3d_side, 2 + jne @F + mov eax, 001C3822h + mov edx, 0000FFFFh + mov ecx, 0000FFFFh +@@: + push ecx + invoke DrawBoxBorder, 224, 72, 76, 52, eax, edx, 2 + pop ecx + invoke DrawString8x8, 232, 78, OFFSET textCoinSide2, ecx + invoke DrawDetailedCoin, 262, 106, 12, 12, 000080A0h, 0000B0D0h, 2 + + ; Flipping animation logic + cmp coin3d_state, 1 + jne coin_at_rest + + inc coin3d_timer + + ; Parabolic toss: cy = 110 - (t * (40 - t)) / 14 + mov eax, coin3d_timer + mov ecx, 40 + sub ecx, eax + imul eax, ecx + xor edx, edx + mov ecx, 14 + div ecx + mov edx, 110 + sub edx, eax + mov cyVal, edx + + ; Width rx from lookup table: (t % 10) + mov eax, coin3d_timer + xor edx, edx + mov ecx, 10 + div ecx + movzx eax, BYTE PTR [coinRxAnimTable + edx] + mov rxVal, eax + + invoke DrawDetailedCoin, 160, cyVal, rxVal, 26, 0000A0D0h, 0000D7FFh, 0 + invoke DrawString8x8, 88, 160, OFFSET textCoinFlipping, 0000FFFFh + + cmp coin3d_timer, 40 + jl coin_draw_controls + + ; Flip complete! + mov coin3d_state, 2 + invoke RandomRange3D, 2 + inc eax + mov coin3d_result, eax + + mov eax, coin3d_result + cmp eax, coin3d_side + jne coin_flip_lost + + ; Won! + mov eax, coin3d_bet + shl eax, 1 + mov coin3d_win, eax + add bankroll, eax + inc coin3d_streak + cmp coin3d_streak, 3 + jl @F + invoke PlaySoundA, OFFSET soundVictory, 0, 1 + jmp coin_draw_controls +@@: + invoke PlaySoundA, OFFSET soundCoinDing, 0, 1 + jmp coin_draw_controls + +coin_flip_lost: + mov coin3d_streak, 0 + mov coin3d_win, 0 + invoke PlaySoundA, OFFSET soundLose, 0, 1 + jmp coin_draw_controls + +coin_at_rest: + ; Draw coin resting in velvet dish + mov edx, coin3d_side + cmp coin3d_state, 2 + jne @F + mov edx, coin3d_result +@@: + invoke DrawDetailedCoin, 160, 110, 26, 26, 0000A0D0h, 0000D7FFh, edx + + ; Outcome / Streak Display + cmp coin3d_state, 2 + jne coin_show_streak + + cmp coin3d_win, 0 + je coin_show_lose + invoke DrawBoxBorder, 44, 154, 232, 20, 000E141Eh, 0050FF50h, 1 + invoke DrawString8x8, 64, 160, OFFSET textCoinWin, 0050FF50h + invoke FormatNumber, coin3d_win, OFFSET hudNumBuffer + invoke DrawString8x8, 152, 160, OFFSET hudNumBuffer, 0050FF50h + jmp coin_draw_controls + +coin_show_lose: + invoke DrawBoxBorder, 44, 154, 232, 20, 000E141Eh, 000000FFh, 1 + invoke DrawString8x8, 114, 160, OFFSET textCoinLose, 008080FFh + jmp coin_draw_controls + +coin_show_streak: + invoke DrawBoxBorder, 44, 154, 232, 20, 000E141Eh, 0000D7FFh, 1 + invoke DrawString8x8, 52, 160, OFFSET textCoinStreakFmt, 0000FFFFh + +coin_draw_controls: + ; Keycaps Control Bar + invoke DrawBox, 16, 194, 288, 1, 001E2E40h + + mov eax, 0 + cmp coin3d_side, 1 + sete al + invoke DrawKeycap3D, 22, 202, OFFSET textCoinKey1, eax + + mov eax, 0 + cmp coin3d_side, 2 + sete al + invoke DrawKeycap3D, 88, 202, OFFSET textCoinKey2, eax + + invoke DrawKeycap3D, 160, 202, OFFSET textCoinKeySpace, 1 + invoke DrawKeycap3D, 274, 202, OFFSET textKeyEsc, 0 + ret +RenderCoinGame ENDP + +; ============================================================================== +; IN-ENGINE 2.5D MINI-GAME: DICE / CRAPS (КОСТИ) +; ============================================================================== +DrawCrapsDie PROC uses ebx esi edi, x:DWORD, y:DWORD, sizeVal:DWORD, valNum:DWORD + ; Drop shadow on green felt + mov eax, x + add eax, 3 + mov edx, y + add edx, sizeVal + invoke DrawBox, eax, edx, sizeVal, 3, 00031408h + mov eax, x + add eax, sizeVal + mov edx, y + add edx, 3 + invoke DrawBox, eax, edx, 3, sizeVal, 00031408h + + ; Ivory body & dark border + invoke DrawBoxBorder, x, y, sizeVal, sizeVal, 00F0F4FAh, 00353540h, 1 + + ; Bevel highlight top & left + mov eax, sizeVal + sub eax, 2 + mov edx, x + inc edx + mov ecx, y + inc ecx + invoke DrawBox, edx, ecx, eax, 1, 00FFFFFFh + invoke DrawBox, edx, ecx, 1, eax, 00FFFFFFh + + ; Bevel shadow bottom & right + mov edx, x + inc edx + mov ecx, y + add ecx, sizeVal + sub ecx, 2 + invoke DrawBox, edx, ecx, eax, 1, 00C0C6D0h + mov edx, x + add edx, sizeVal + sub edx, 2 + mov ecx, y + inc ecx + invoke DrawBox, edx, ecx, 1, eax, 00C0C6D0h + + ; Casino Ruby Red circular pips (radius 3) + cmp valNum, 1 + je draw_die_c + cmp valNum, 3 + je draw_die_c + cmp valNum, 5 + je draw_die_c + jmp check_die_pips_corners + +draw_die_c: + mov eax, x + add eax, 18 + mov edx, y + add edx, 18 + invoke DrawCircle, eax, edx, 3, 001515C8h + dec eax + dec edx + invoke DrawPixel, eax, edx, 00FFFFFFh + +check_die_pips_corners: + cmp valNum, 2 + jl die_pips_done + mov eax, x + add eax, 9 + mov edx, y + add edx, 9 + invoke DrawCircle, eax, edx, 3, 001515C8h + mov eax, x + add eax, sizeVal + sub eax, 10 + mov edx, y + add edx, sizeVal + sub edx, 10 + invoke DrawCircle, eax, edx, 3, 001515C8h + + cmp valNum, 4 + jl die_pips_done + mov eax, x + add eax, sizeVal + sub eax, 10 + mov edx, y + add edx, 9 + invoke DrawCircle, eax, edx, 3, 001515C8h + mov eax, x + add eax, 9 + mov edx, y + add edx, sizeVal + sub edx, 10 + invoke DrawCircle, eax, edx, 3, 001515C8h + + cmp valNum, 6 + jl die_pips_done + mov eax, x + add eax, 9 + mov edx, y + add edx, 18 + invoke DrawCircle, eax, edx, 3, 001515C8h + mov eax, x + add eax, sizeVal + sub eax, 10 + mov edx, y + add edx, 18 + invoke DrawCircle, eax, edx, 3, 001515C8h + +die_pips_done: + ret +DrawCrapsDie ENDP + +InitDiceGame PROC + mov dice3d_state, 0 + mov dice3d_timer, 0 + mov dice3d_win, 0 + cmp dice3d_bet, 10 + jge @F + mov dice3d_bet, 50 +@@: + ret +InitDiceGame ENDP + +HandleDiceInput PROC + cmp dice3d_state, 1 + je dice_input_done + + invoke Pressed3D, 20h ; SPACE -> Roll! + test eax, eax + jz check_dice_choice + mov eax, bankroll + cmp eax, dice3d_bet + jl dice_no_cash + sub eax, dice3d_bet + mov bankroll, eax + mov dice3d_state, 1 + mov dice3d_timer, 0 + mov dice3d_win, 0 + invoke PlaySoundA, OFFSET soundCards, 0, 1 + jmp dice_input_done + +dice_no_cash: + invoke CopyString3D, OFFSET msgNeedMoney, OFFSET flashMessage + mov flashTimer, 60 + invoke PlaySoundA, OFFSET soundClick, 0, 1 + jmp dice_input_done + +check_dice_choice: + invoke Pressed3D, 31h ; '1' + test eax, eax + jz @F + mov dice3d_choice, 1 + invoke PlaySoundA, OFFSET soundClick, 0, 1 +@@: + invoke Pressed3D, 32h ; '2' + test eax, eax + jz check_dice_bet_adjust + mov dice3d_choice, 2 + invoke PlaySoundA, OFFSET soundClick, 0, 1 + +check_dice_bet_adjust: + invoke Pressed3D, 26h ; UP + test eax, eax + jnz dice_inc_bet + invoke Pressed3D, 57h ; W + test eax, eax + jz check_dice_bet_down +dice_inc_bet: + invoke PlaySoundA, OFFSET soundClick, 0, 1 + cmp dice3d_bet, 500 + jge dice_input_done + cmp dice3d_bet, 250 + jge dice_set_500 + cmp dice3d_bet, 100 + jge dice_set_250 + cmp dice3d_bet, 50 + jge dice_set_100 + cmp dice3d_bet, 25 + jge dice_set_50 + jmp dice_set_25 +dice_set_500: + mov dice3d_bet, 500 + jmp dice_input_done +dice_set_250: + mov dice3d_bet, 250 + jmp dice_input_done +dice_set_100: + mov dice3d_bet, 100 + jmp dice_input_done +dice_set_50: + mov dice3d_bet, 50 + jmp dice_input_done +dice_set_25: + mov dice3d_bet, 25 + jmp dice_input_done + +check_dice_bet_down: + invoke Pressed3D, 28h ; DOWN + test eax, eax + jnz dice_dec_bet + invoke Pressed3D, 53h ; S + test eax, eax + jz dice_input_done +dice_dec_bet: + invoke PlaySoundA, OFFSET soundClick, 0, 1 + cmp dice3d_bet, 25 + jle dice_set_10 + cmp dice3d_bet, 50 + jle dice_set_25 + cmp dice3d_bet, 100 + jle dice_set_50 + cmp dice3d_bet, 250 + jle dice_set_100 + mov dice3d_bet, 250 + jmp dice_input_done +dice_set_10: + mov dice3d_bet, 10 + +dice_input_done: + ret +HandleDiceInput ENDP + +RenderDiceGame PROC uses ebx esi edi + LOCAL d1X:DWORD, d1Y:DWORD, d2X:DWORD, d2Y:DWORD, bxX:DWORD + + ; Craps Emerald Felt & Oak Armrest + invoke DrawBox, 0, 0, 320, 240, 00082E12h + invoke DrawBoxBorder, 4, 4, 312, 232, 00093816h, 00122244h, 3 + invoke DrawBoxBorder, 8, 8, 304, 224, 000A3F19h, 0005140Ah, 2 + + ; Pyramidal diamond craps backboard texture + mov bxX, 12 +craps_bumper: + cmp bxX, 308 + jge craps_felt_markings + mov eax, bxX + add eax, 4 + invoke DrawBox, eax, 11, 4, 4, 00041006h + mov eax, bxX + add eax, 5 + invoke DrawPixel, eax, 12, 000F4820h + add bxX, 12 + jmp craps_bumper + +craps_felt_markings: + ; Table Markings printed in gold directly on felt + invoke DrawString8x8, 72, 20, OFFSET textDiceTitle, 0000D7FFh + invoke DrawString8x8, 68, 32, OFFSET textDiceSubtitle, 0000B0A0h + + ; Meters: Bank & Bet + invoke DrawBoxBorder, 16, 46, 108, 16, 0006240Eh, 000E5022h, 1 + invoke DrawString8x8, 20, 50, OFFSET textBankPrompt, 0050FF50h + invoke FormatNumber, bankroll, OFFSET hudNumBuffer + invoke DrawString8x8, 68, 50, OFFSET hudNumBuffer, 0050FF50h + + invoke DrawBoxBorder, 196, 46, 108, 16, 0006240Eh, 000E5022h, 1 + invoke DrawString8x8, 200, 50, OFFSET textBetPrompt, 0000D7FFh + invoke FormatNumber, dice3d_bet, OFFSET hudNumBuffer + invoke DrawString8x8, 264, 50, OFFSET hudNumBuffer, 0000D7FFh + + ; Betting Zone Left: [1] Ч�Т + mov eax, 00073014h + mov edx, 001A602Ah + mov ecx, 0080B090h + cmp dice3d_choice, 1 + jne @F + mov eax, 000B441Dh + mov edx, 0000FFFFh + mov ecx, 0000FFFFh +@@: + push ecx + invoke DrawBoxBorder, 16, 68, 88, 54, eax, edx, 2 + pop ecx + invoke DrawString8x8, 24, 74, OFFSET textDiceEven, ecx + invoke DrawString8x8, 20, 86, OFFSET textDiceEvenNums, 0000D7FFh + cmp dice3d_choice, 1 + jne @F + invoke DrawChipStack, 48, 110, 4 +@@: + + ; Betting Zone Right: [2] �ЕЧЕТ + mov eax, 00073014h + mov edx, 001A602Ah + mov ecx, 0080B090h + cmp dice3d_choice, 2 + jne @F + mov eax, 000B441Dh + mov edx, 0000FFFFh + mov ecx, 0000FFFFh +@@: + push ecx + invoke DrawBoxBorder, 216, 68, 88, 54, eax, edx, 2 + pop ecx + invoke DrawString8x8, 224, 74, OFFSET textDiceOdd, ecx + invoke DrawString8x8, 224, 86, OFFSET textDiceOddNums, 00508060h + cmp dice3d_choice, 2 + jne @F + invoke DrawChipStack, 248, 110, 4 +@@: + + ; Center Dice Field + invoke DrawBoxBorder, 112, 68, 96, 54, 00072E13h, 00145826h, 1 + + ; Rolling Animation Logic + cmp dice3d_state, 1 + jne dice_at_rest + + inc dice3d_timer + + ; Tumbling jitter offsets + mov eax, dice3d_timer + and eax, 3 + sub eax, 1 + + mov edx, 120 + add edx, eax + mov d1X, edx + mov edx, 76 + sub edx, eax + mov d1Y, edx + + mov edx, 164 + sub edx, eax + mov d2X, edx + mov edx, 78 + add edx, eax + mov d2Y, edx + + test dice3d_timer, 1 + jz @F + invoke RandomRange3D, 6 + inc eax + mov dice3d_val1, eax + invoke RandomRange3D, 6 + inc eax + mov dice3d_val2, eax +@@: + invoke DrawCrapsDie, d1X, d1Y, 36, dice3d_val1 + invoke DrawCrapsDie, d2X, d2Y, 36, dice3d_val2 + invoke DrawString8x8, 76, 138, OFFSET textDiceRolling, 0000FFFFh + + cmp dice3d_timer, 36 + jl dice_draw_controls + + ; Settle dice! + mov dice3d_state, 2 + invoke RandomRange3D, 6 + inc eax + mov dice3d_val1, eax + invoke RandomRange3D, 6 + inc eax + mov dice3d_val2, eax + + mov eax, dice3d_val1 + add eax, dice3d_val2 + mov dice3d_sum, eax + + ; Check choice vs sum parity + mov eax, dice3d_sum + test eax, 1 + jz dice_sum_is_even + + ; Odd + cmp dice3d_choice, 2 + je dice_roll_won + jmp dice_roll_lost + +dice_sum_is_even: + cmp dice3d_choice, 1 + je dice_roll_won + +dice_roll_lost: + mov dice3d_win, 0 + invoke PlaySoundA, OFFSET soundLose, 0, 1 + jmp dice_draw_controls + +dice_roll_won: + mov eax, dice3d_bet + shl eax, 1 + mov dice3d_win, eax + add bankroll, eax + invoke PlaySoundA, OFFSET soundVictory, 0, 1 + jmp dice_draw_controls + +dice_at_rest: + invoke DrawCrapsDie, 120, 76, 36, dice3d_val1 + invoke DrawCrapsDie, 164, 76, 36, dice3d_val2 + + cmp dice3d_state, 2 + jne dice_draw_controls + + ; Scoreboard Plaque + invoke DrawBoxBorder, 36, 130, 248, 30, 00051D0Ch, 0000D7FFh, 1 + invoke DrawString8x8, 44, 135, OFFSET textDiceSumHdr, 0000D7FFh + invoke FormatNumber, dice3d_val1, OFFSET hudNumBuffer + invoke DrawString8x8, 100, 135, OFFSET hudNumBuffer, 00FFFFFFh + invoke DrawString8x8, 110, 135, OFFSET textDicePlus, 0000D7FFh + invoke FormatNumber, dice3d_val2, OFFSET hudNumBuffer + invoke DrawString8x8, 134, 135, OFFSET hudNumBuffer, 00FFFFFFh + invoke DrawString8x8, 144, 135, OFFSET textDiceEqual, 0000D7FFh + invoke FormatNumber, dice3d_sum, OFFSET hudNumBuffer + invoke DrawString8x8, 168, 135, OFFSET hudNumBuffer, 0000FFFFh + + mov eax, dice3d_sum + test eax, 1 + jnz @F + invoke DrawString8x8, 186, 135, OFFSET textDiceEvenResult, 0080FF80h + jmp dice_show_win_msg +@@: + invoke DrawString8x8, 186, 135, OFFSET textDiceOddResult, 00FF8080h + +dice_show_win_msg: + cmp dice3d_win, 0 + je dice_show_loss + invoke DrawString8x8, 68, 147, OFFSET textDiceWin, 0050FF50h + invoke FormatNumber, dice3d_win, OFFSET hudNumBuffer + invoke DrawString8x8, 156, 147, OFFSET hudNumBuffer, 0050FF50h + invoke DrawString8x8, 188, 147, OFFSET textDiceWinMult, 0050FF50h + jmp dice_draw_controls + +dice_show_loss: + invoke DrawString8x8, 116, 147, OFFSET textDiceLose, 008080FFh + +dice_draw_controls: + invoke DrawBox, 16, 188, 288, 1, 00104820h + + mov eax, 0 + cmp dice3d_choice, 1 + sete al + invoke DrawKeycap3D, 20, 198, OFFSET textDiceKey1, eax + + mov eax, 0 + cmp dice3d_choice, 2 + sete al + invoke DrawKeycap3D, 82, 198, OFFSET textDiceKey2, eax + + invoke DrawKeycap3D, 160, 198, OFFSET textDiceKeySpace, 1 + invoke DrawKeycap3D, 274, 198, OFFSET textKeyEsc, 0 + ret +RenderDiceGame ENDP + +; ============================================================================== +; IN-ENGINE 2.5D MINI-GAME: SKULLS & CUPS (��П�РСТКИ) +; ============================================================================== +DrawGlowingOrb PROC uses ebx esi edi, cxVal:DWORD, cyVal:DWORD + invoke DrawCircle, cxVal, cyVal, 14, 00081E2Eh + invoke DrawCircle, cxVal, cyVal, 11, 00103A58h + invoke DrawCircle, cxVal, cyVal, 8, 001A588Ah + invoke DrawCircle, cxVal, cyVal, 6, 0000B0E0h + invoke DrawCircle, cxVal, cyVal, 4, 0000E0FFh + mov eax, cxVal + dec eax + mov edx, cyVal + dec edx + invoke DrawCircle, eax, edx, 2, 00A0FFFFh + mov eax, cxVal + sub eax, 2 + mov edx, cyVal + sub edx, 2 + invoke DrawPixel, eax, edx, 00FFFFFFh + ret +DrawGlowingOrb ENDP + +DrawGothicCup PROC uses ebx esi edi, x:DWORD, y:DWORD, cupId:DWORD, isLifted:DWORD, hasBall:DWORD + LOCAL liftY:DWORD + + mov eax, y + cmp isLifted, 0 + je @F + sub eax, 28 +@@: + mov liftY, eax + + ; Drop shadow on purple velvet + cmp isLifted, 0 + jne @F + mov eax, x + add eax, 6 + mov edx, y + add edx, 42 + invoke DrawBox, eax, edx, 36, 4, 000A0410h + jmp draw_cup_body +@@: + mov eax, x + add eax, 10 + mov edx, y + add edx, 42 + invoke DrawBox, eax, edx, 28, 2, 0012061Ah + + ; Draw orb if lifted and has ball + cmp hasBall, 0 + je draw_cup_body + mov eax, x + add eax, 24 + mov edx, y + add edx, 26 + invoke DrawGlowingOrb, eax, edx + +draw_cup_body: + ; Base + mov eax, x + add eax, 6 + mov edx, liftY + add edx, 36 + invoke DrawBoxBorder, eax, edx, 36, 6, 00221A30h, 0000B0D0h, 1 + + ; Stem + mov eax, x + add eax, 18 + mov edx, liftY + add edx, 28 + invoke DrawBox, eax, edx, 12, 8, 00332545h + mov eax, x + add eax, 22 + mov edx, liftY + add edx, 28 + invoke DrawBox, eax, edx, 4, 8, 0055406Eh + + ; Bowl + mov eax, x + add eax, 8 + mov edx, liftY + add edx, 8 + invoke DrawBoxBorder, eax, edx, 32, 20, 002D1E40h, 0000D7FFh, 1 + mov eax, x + add eax, 14 + mov edx, liftY + add edx, 10 + invoke DrawBox, eax, edx, 6, 16, 00503570h + mov eax, x + add eax, 17 + mov edx, liftY + add edx, 10 + invoke DrawBox, eax, edx, 3, 16, 007850A0h + + ; Flared Rim + mov eax, x + add eax, 4 + mov edx, liftY + add edx, 2 + invoke DrawBoxBorder, eax, edx, 40, 7, 00150A20h, 0000FFFFh, 1 + mov eax, x + add eax, 12 + mov edx, liftY + add edx, 4 + invoke DrawBox, eax, edx, 16, 2, 0000FFFFh + + ; Skull Insignia on Bowl + mov eax, x + add eax, 21 + mov edx, liftY + add edx, 12 + invoke DrawBox, eax, edx, 6, 5, 0000D7FFh + mov eax, x + add eax, 22 + mov edx, liftY + add edx, 17 + invoke DrawBox, eax, edx, 4, 3, 0000D7FFh + mov eax, x + add eax, 22 + mov edx, liftY + add edx, 14 + invoke DrawPixel, eax, edx, 00150A20h + mov eax, x + add eax, 24 + mov edx, liftY + add edx, 14 + invoke DrawPixel, eax, edx, 00150A20h + + ; Cup ID Badge + mov eax, x + add eax, 21 + mov edx, liftY + add edx, 24 + mov ecx, cupId + add ecx, '0' + invoke DrawChar8x8, eax, edx, ecx, 0000FFFFh + ret +DrawGothicCup ENDP + +InitSkullsGame PROC + mov skulls3d_state, 0 + mov skulls3d_timer, 0 + mov skulls3d_win, 0 + cmp skulls3d_bet, 10 + jge @F + mov skulls3d_bet, 50 +@@: + invoke RandomRange3D, 3 + mov skulls3d_ballPos, eax + ret +InitSkullsGame ENDP + +FinalizeSkullsGuess PROC uses ebx + mov skulls3d_state, 4 + mov eax, skulls3d_choice + cmp eax, skulls3d_ballPos + jne skulls_guess_lost + + ; Won 3x! + mov eax, skulls3d_bet + imul eax, 3 + mov skulls3d_win, eax + add bankroll, eax + invoke PlaySoundA, OFFSET soundVictory, 0, 1 + ret + +skulls_guess_lost: + mov skulls3d_win, 0 + invoke PlaySoundA, OFFSET soundLose, 0, 1 + ret +FinalizeSkullsGuess ENDP + +HandleSkullsInput PROC + cmp skulls3d_state, 1 + je skulls_input_done + cmp skulls3d_state, 2 + je skulls_input_done + + cmp skulls3d_state, 3 + je check_skulls_pick + + ; State 0 or 4: Can start new round or adjust bet + invoke Pressed3D, 20h ; SPACE + test eax, eax + jz check_skulls_bet_adjust + + mov eax, bankroll + cmp eax, skulls3d_bet + jl skulls_no_cash + sub eax, skulls3d_bet + mov bankroll, eax + + invoke RandomRange3D, 3 + mov skulls3d_ballPos, eax + + invoke RandomRange3D, 3 + mov skulls3d_swapPair0, eax + invoke RandomRange3D, 3 + mov skulls3d_swapPair1, eax + invoke RandomRange3D, 3 + mov skulls3d_swapPair2, eax + + mov skulls3d_state, 1 + mov skulls3d_timer, 0 + mov skulls3d_win, 0 + invoke PlaySoundA, OFFSET soundShuffle, 0, 1 + jmp skulls_input_done + +skulls_no_cash: + invoke CopyString3D, OFFSET msgNeedMoney, OFFSET flashMessage + mov flashTimer, 60 + invoke PlaySoundA, OFFSET soundClick, 0, 1 + jmp skulls_input_done + +check_skulls_pick: + invoke Pressed3D, 31h ; '1' + test eax, eax + jz @F + mov skulls3d_choice, 0 + call FinalizeSkullsGuess + jmp skulls_input_done +@@: + invoke Pressed3D, 32h ; '2' + test eax, eax + jz @F + mov skulls3d_choice, 1 + call FinalizeSkullsGuess + jmp skulls_input_done +@@: + invoke Pressed3D, 33h ; '3' + test eax, eax + jz skulls_input_done + mov skulls3d_choice, 2 + call FinalizeSkullsGuess + jmp skulls_input_done + +check_skulls_bet_adjust: + invoke Pressed3D, 26h ; UP + test eax, eax + jnz skulls_inc_bet + invoke Pressed3D, 57h ; W + test eax, eax + jz check_skulls_bet_down +skulls_inc_bet: + invoke PlaySoundA, OFFSET soundClick, 0, 1 + cmp skulls3d_bet, 500 + jge skulls_input_done + cmp skulls3d_bet, 250 + jge skulls_set_500 + cmp skulls3d_bet, 100 + jge skulls_set_250 + cmp skulls3d_bet, 50 + jge skulls_set_100 + cmp skulls3d_bet, 25 + jge skulls_set_50 + jmp skulls_set_25 +skulls_set_500: + mov skulls3d_bet, 500 + jmp skulls_input_done +skulls_set_250: + mov skulls3d_bet, 250 + jmp skulls_input_done +skulls_set_100: + mov skulls3d_bet, 100 + jmp skulls_input_done +skulls_set_50: + mov skulls3d_bet, 50 + jmp skulls_input_done +skulls_set_25: + mov skulls3d_bet, 25 + jmp skulls_input_done + +check_skulls_bet_down: + invoke Pressed3D, 28h ; DOWN + test eax, eax + jnz skulls_dec_bet + invoke Pressed3D, 53h ; S + test eax, eax + jz skulls_input_done +skulls_dec_bet: + invoke PlaySoundA, OFFSET soundClick, 0, 1 + cmp skulls3d_bet, 25 + jle skulls_set_10 + cmp skulls3d_bet, 50 + jle skulls_set_25 + cmp skulls3d_bet, 100 + jle skulls_set_50 + cmp skulls3d_bet, 250 + jle skulls_set_100 + mov skulls3d_bet, 250 + jmp skulls_input_done +skulls_set_10: + mov skulls3d_bet, 10 + +skulls_input_done: + ret +HandleSkullsInput ENDP + +RenderSkullsGame PROC uses ebx esi edi + LOCAL passTick:DWORD, curPair:DWORD, swapSlotA:DWORD, swapSlotB:DWORD + LOCAL xA:DWORD, xB:DWORD, curXA:DWORD, curXB:DWORD, curYA:DWORD, curYB:DWORD + LOCAL distX:DWORD, dxVal:DWORD, archY:DWORD + + ; Dark Gothic Tavern Table with Royal Velvet + invoke DrawBox, 0, 0, 320, 240, 000D0612h + invoke DrawBoxBorder, 4, 4, 312, 232, 00160B20h, 00321845h, 3 + invoke DrawBoxBorder, 8, 8, 304, 224, 00220F30h, 0000D7FFh, 1 + + ; Header + invoke DrawBoxBorder, 24, 12, 272, 24, 0012081Ah, 0000D7FFh, 2 + invoke DrawString8x8, 64, 20, OFFSET textSkullsTitle, 0000FFFFh + + ; Meters: Bank & Bet + invoke DrawBoxBorder, 20, 42, 114, 16, 000D0616h, 00401858h, 1 + invoke DrawString8x8, 24, 46, OFFSET textBankPrompt, 0050FF50h + invoke FormatNumber, bankroll, OFFSET hudNumBuffer + invoke DrawString8x8, 72, 46, OFFSET hudNumBuffer, 0050FF50h + + invoke DrawBoxBorder, 186, 42, 114, 16, 000D0616h, 00401858h, 1 + invoke DrawString8x8, 190, 46, OFFSET textBetPrompt, 0000D7FFh + invoke FormatNumber, skulls3d_bet, OFFSET hudNumBuffer + invoke DrawString8x8, 254, 46, OFFSET hudNumBuffer, 0000D7FFh + + ; Velvet Table Runner + invoke DrawBoxBorder, 16, 64, 288, 120, 001A0B25h, 00452060h, 1 + + ; Dispatch based on phase + cmp skulls3d_state, 1 + je skulls_render_phase1 + cmp skulls3d_state, 2 + je skulls_render_phase2 + cmp skulls3d_state, 3 + je skulls_render_phase3 + cmp skulls3d_state, 4 + je skulls_render_phase4 + + ; Phase 0: Idle / Betting + invoke DrawString8x8, 56, 70, OFFSET textSkullsPhase0, 0000D7FFh + invoke DrawGothicCup, 48, 108, 1, 0, 0 + invoke DrawGothicCup, 136, 108, 2, 0, 0 + invoke DrawGothicCup, 224, 108, 3, 0, 0 + jmp skulls_draw_controls + +skulls_render_phase1: + inc skulls3d_timer + invoke DrawString8x8, 56, 70, OFFSET textSkullsPhase1, 0000FFFFh + + ; Draw cups with ballPos cup lifted + mov eax, 0 + cmp skulls3d_ballPos, 0 + sete al + invoke DrawGothicCup, 48, 108, 1, eax, eax + + mov eax, 0 + cmp skulls3d_ballPos, 1 + sete al + invoke DrawGothicCup, 136, 108, 2, eax, eax + + mov eax, 0 + cmp skulls3d_ballPos, 2 + sete al + invoke DrawGothicCup, 224, 108, 3, eax, eax + + cmp skulls3d_timer, 40 + jl skulls_draw_controls + + ; Start Phase 2 (Shuffle) + mov skulls3d_state, 2 + mov skulls3d_timer, 0 + invoke PlaySoundA, OFFSET soundShuffle, 0, 1 + jmp skulls_draw_controls + +skulls_render_phase2: + inc skulls3d_timer + + mov eax, skulls3d_timer + cmp eax, 20 + jbe pass_0 + cmp eax, 40 + jbe pass_1 + sub eax, 41 + mov passTick, eax + mov eax, skulls3d_swapPair2 + mov curPair, eax + jmp setup_pass_pair + +pass_0: + dec eax + mov passTick, eax + mov eax, skulls3d_swapPair0 + mov curPair, eax + jmp setup_pass_pair + +pass_1: + sub eax, 21 + mov passTick, eax + mov eax, skulls3d_swapPair1 + mov curPair, eax + +setup_pass_pair: + cmp curPair, 1 + je pair_1 + cmp curPair, 2 + je pair_2 + mov swapSlotA, 0 + mov swapSlotB, 1 + mov xA, 48 + mov xB, 136 + jmp calc_swap_coords +pair_1: + mov swapSlotA, 1 + mov swapSlotB, 2 + mov xA, 136 + mov xB, 224 + jmp calc_swap_coords +pair_2: + mov swapSlotA, 0 + mov swapSlotB, 2 + mov xA, 48 + mov xB, 224 + +calc_swap_coords: + mov eax, xB + sub eax, xA + mov distX, eax + + mov eax, distX + imul eax, passTick + xor edx, edx + mov ecx, 20 + div ecx + mov dxVal, eax + + mov eax, xA + add eax, dxVal + mov curXA, eax + + mov eax, xB + sub eax, dxVal + mov curXB, eax + + ; Arch height: archY = (t * (20 - t)) / 25 + mov eax, passTick + mov ecx, 20 + sub ecx, eax + imul eax, ecx + xor edx, edx + mov ecx, 25 + div ecx + mov archY, eax + + mov edx, 108 + sub edx, archY + mov curYA, edx ; upper arc + + mov edx, 108 + add edx, archY + mov curYB, edx ; lower arc + + invoke DrawString8x8, 56, 70, OFFSET textSkullsPhase2, 0000FFFFh + + ; Depth sorted rendering: Background cup (upper arc) draws FIRST, Foreground cup (lower arc) draws OVER it! + invoke DrawGothicCup, curXA, curYA, 1, 0, 0 + invoke DrawGothicCup, curXB, curYB, 2, 0, 0 + + ; Draw remaining static cup + cmp curPair, 1 + je draw_stat_0 + cmp curPair, 2 + je draw_stat_1 + invoke DrawGothicCup, 224, 108, 3, 0, 0 + jmp check_pass_finish +draw_stat_0: + invoke DrawGothicCup, 48, 108, 1, 0, 0 + jmp check_pass_finish +draw_stat_1: + invoke DrawGothicCup, 136, 108, 2, 0, 0 + +check_pass_finish: + cmp skulls3d_timer, 20 + je do_pass_swap + cmp skulls3d_timer, 40 + je do_pass_swap + cmp skulls3d_timer, 60 + je do_pass_swap + jmp skulls_draw_controls + +do_pass_swap: + ; Update ballPos if involved in swap + mov eax, skulls3d_ballPos + cmp eax, swapSlotA + jne check_swap_b + mov eax, swapSlotB + mov skulls3d_ballPos, eax + jmp ball_swap_done +check_swap_b: + cmp eax, swapSlotB + jne ball_swap_done + mov eax, swapSlotA + mov skulls3d_ballPos, eax + +ball_swap_done: + invoke PlaySoundA, OFFSET soundShuffle, 0, 1 + + cmp skulls3d_timer, 60 + jl skulls_draw_controls + + ; Shuffle complete -> Move to Pick phase + mov skulls3d_state, 3 + mov skulls3d_timer, 0 + jmp skulls_draw_controls + +skulls_render_phase3: + invoke DrawString8x8, 40, 70, OFFSET textSkullsPhase3, 0000FFFFh + invoke DrawGothicCup, 48, 108, 1, 0, 0 + invoke DrawGothicCup, 136, 108, 2, 0, 0 + invoke DrawGothicCup, 224, 108, 3, 0, 0 + jmp skulls_draw_controls + +skulls_render_phase4: + ; Reveal phase + cmp skulls3d_win, 0 + je skulls_show_loss + invoke DrawString8x8, 48, 70, OFFSET textSkullsWin, 0050FF50h + invoke FormatNumber, skulls3d_win, OFFSET hudNumBuffer + invoke DrawString8x8, 216, 70, OFFSET hudNumBuffer, 0050FF50h + jmp skulls_p4_cups + +skulls_show_loss: + invoke DrawString8x8, 40, 70, OFFSET textSkullsLose, 008080FFh + +skulls_p4_cups: + ; Draw chosen cup lifted + mov eax, 0 + cmp skulls3d_choice, 0 + sete al + mov edx, 0 + cmp skulls3d_ballPos, 0 + sete dl + invoke DrawGothicCup, 48, 108, 1, eax, edx + + mov eax, 0 + cmp skulls3d_choice, 1 + sete al + mov edx, 0 + cmp skulls3d_ballPos, 1 + sete dl + invoke DrawGothicCup, 136, 108, 2, eax, edx + + mov eax, 0 + cmp skulls3d_choice, 2 + sete al + mov edx, 0 + cmp skulls3d_ballPos, 2 + sete dl + invoke DrawGothicCup, 224, 108, 3, eax, edx + + invoke DrawString8x8, 64, 168, OFFSET textSkullsAgain, 0000D7FFh + +skulls_draw_controls: + invoke DrawBox, 16, 190, 288, 1, 003A1850h + + mov eax, 0 + cmp skulls3d_choice, 0 + sete al + invoke DrawKeycap3D, 18, 200, OFFSET textSkullsKey1, eax + + mov eax, 0 + cmp skulls3d_choice, 1 + sete al + invoke DrawKeycap3D, 82, 200, OFFSET textSkullsKey2, eax + + mov eax, 0 + cmp skulls3d_choice, 2 + sete al + invoke DrawKeycap3D, 146, 200, OFFSET textSkullsKey3, eax + + invoke DrawKeycap3D, 212, 200, OFFSET textSkullsKeySpace, 1 + invoke DrawKeycap3D, 274, 200, OFFSET textKeyEsc, 0 + ret +RenderSkullsGame ENDP + +""" + +raw_content = raw_content[:pos_games_start] + new_games_code.encode('cp1251') + raw_content[pos_player_input:] +print("[OK] Replaced games implementation block with rich 2.5D procedures") + +# Write out patched casino3d.inc +with open(CASINO_INC, 'wb') as f: + f.write(raw_content) + +print(f"[SUCCESS] casino3d.inc patched successfully! New byte length: {len(raw_content)}") diff --git a/tools/tests/test_minigames_render.py b/tools/tests/test_minigames_render.py new file mode 100644 index 0000000..e4fbd5e --- /dev/null +++ b/tools/tests/test_minigames_render.py @@ -0,0 +1,379 @@ +# -*- coding: utf-8 -*- +import math +from pathlib import Path +from PIL import Image + +REPO_ROOT = Path(__file__).resolve().parents[2] +OUTPUT_DIR = REPO_ROOT / 'docs' / 'previews_minigames' +OUTPUT_DIR.mkdir(parents=True, exist_ok=True) + +# Parse font8x8.inc +font_path = REPO_ROOT / 'font8x8.inc' +font_bytes = bytearray(256 * 8) +with open(font_path, 'r', encoding='latin1') as f: + text = f.read() + +import re +matches = re.findall(r'0([0-9A-Fa-f]{2})h', text) +for i, m in enumerate(matches[:256*8]): + font_bytes[i] = int(m, 16) + +SCREEN_W = 640 +SCREEN_H = 480 + +class RasterBuffer: + def __init__(self): + self.pixels = [(0, 0, 0)] * (SCREEN_W * SCREEN_H) + + def to_rgb(self, c): + # 0x00BBGGRR format + r = c & 0xFF + g = (c >> 8) & 0xFF + b = (c >> 16) & 0xFF + return (r, g, b) + + def draw_box(self, x, y, w, h, color): + px = x * 2 + py = y * 2 + pw = w * 2 + ph = h * 2 + rgb = self.to_rgb(color) + for row in range(py, min(py + ph, SCREEN_H)): + if row < 0: + continue + base = row * SCREEN_W + for col in range(px, min(px + pw, SCREEN_W)): + if col < 0: + continue + self.pixels[base + col] = rgb + + def draw_box_border(self, x, y, w, h, fill_color, border_color, b_width): + self.draw_box(x, y, w, h, border_color) + self.draw_box(x + b_width, y + b_width, w - b_width * 2, h - b_width * 2, fill_color) + + def draw_pixel(self, x, y, color): + self.draw_box(x, y, 1, 1, color) + + def draw_circle(self, cx, cy, radius, color): + r_sq = radius * radius + for dy in range(-radius, radius + 1): + for dx in range(-radius, radius + 1): + if dx * dx + dy * dy <= r_sq: + self.draw_pixel(cx + dx, cy + dy, color) + + def draw_char(self, x, y, ch, color): + if isinstance(ch, str): + try: + code = ch.encode('cp1251')[0] + except: + code = ord(ch) & 0xFF + else: + code = ch & 0xFF + + glyph_offset = code * 8 + for row in range(8): + row_bits = font_bytes[glyph_offset + row] + for col in range(8): + if row_bits & (0x80 >> col): + self.draw_pixel(x + col, y + row, color) + + def draw_string(self, x, y, s, color): + cur_x = x + for ch in s: + self.draw_char(cur_x, y, ch, color) + cur_x += 8 + + def draw_keycap(self, x, y, text, is_active=False): + w = len(text) * 8 + 8 + h = 13 + if is_active: + border_c = 0x0000FFFF + fill_c = 0x001B4B22 + txt_c = 0x0000FFFF + else: + border_c = 0x00606870 + fill_c = 0x001A1C22 + txt_c = 0x00D0D8E0 + self.draw_box(x, y + 2, w, h, 0x0008080C) # shadow + self.draw_box_border(x, y, w, h, fill_c, border_c, 1) + self.draw_string(x + 4, y + 3, text, txt_c) + return w + 4 + + def draw_chip_stack(self, x, y, count=3): + # Draw stack of 3D casino clay chips + for i in range(count): + cy = y - i * 4 + self.draw_box(x + 2, cy + 5, 20, 2, 0x00041006) # shadow + self.draw_box_border(x, cy, 24, 6, 0x001515B8, 0x00FFFFFF, 1) + # white stripe inlays + self.draw_box(x + 4, cy + 1, 3, 4, 0x00FFFFFF) + self.draw_box(x + 17, cy + 1, 3, 4, 0x00FFFFFF) + + def draw_coin_ellipse(self, cx, cy, rx, ry, outer_color, inner_color, relief=0): + if rx <= 0 or ry <= 0: + return + rx_sq = rx * rx + ry_sq = ry * ry + rx_ry_sq = rx_sq * ry_sq + thresh_sq = (rx_ry_sq * 3) // 4 + for dy in range(-ry, ry + 1): + cur_y = cy + dy + for dx in range(-rx, rx + 1): + cur_x = cx + dx + val = dx * dx * ry_sq + dy * dy * rx_sq + if val <= rx_ry_sq: + if val >= thresh_sq: + self.draw_pixel(cur_x, cur_y, outer_color) + else: + self.draw_pixel(cur_x, cur_y, inner_color) + + if rx >= 14 and relief == 1: + gold_dark = 0x00007A9A + # Imperial Eagle + self.draw_box(cx - 3, cy - 14, 7, 2, gold_dark) + self.draw_box(cx - 4, cy - 12, 9, 2, gold_dark) + self.draw_box(cx - 2, cy - 9, 5, 12, gold_dark) + self.draw_box(cx - 1, cy - 8, 3, 10, 0x0000D7FF) + self.draw_box(cx - 10, cy - 8, 7, 3, gold_dark) + self.draw_box(cx - 13, cy - 5, 10, 3, gold_dark) + self.draw_box(cx - 11, cy - 2, 7, 3, gold_dark) + self.draw_box(cx + 4, cy - 8, 7, 3, gold_dark) + self.draw_box(cx + 4, cy - 5, 10, 3, gold_dark) + self.draw_box(cx + 5, cy - 2, 7, 3, gold_dark) + self.draw_box(cx - 4, cy + 4, 9, 3, gold_dark) + self.draw_box(cx - 3, cy + 7, 7, 3, gold_dark) + elif rx >= 14 and relief == 2: + gold_dark = 0x00007A9A + # Roman numeral 'I' + self.draw_box(cx - 5, cy - 10, 11, 3, gold_dark) + self.draw_box(cx - 2, cy - 7, 5, 14, gold_dark) + self.draw_box(cx - 1, cy - 6, 3, 12, 0x0000D7FF) + self.draw_box(cx - 6, cy + 7, 13, 3, gold_dark) + for w_dy in [-10, -5, 0, 5, 9]: + self.draw_box(cx - 12, cy + w_dy, 2, 2, gold_dark) + self.draw_box(cx + 11, cy + w_dy, 2, 2, gold_dark) + + def draw_craps_die(self, x, y, size, val): + self.draw_box(x + 3, y + size, size, 3, 0x00031408) + self.draw_box(x + size, y + 3, 3, size, 0x00031408) + body_color = 0x00F0F4FA + bevel_color = 0x00C0C6D0 + border_color = 0x00353540 + self.draw_box_border(x, y, size, size, body_color, border_color, 1) + self.draw_box(x + 1, y + 1, size - 2, 1, 0x00FFFFFF) + self.draw_box(x + 1, y + 1, 1, size - 2, 0x00FFFFFF) + self.draw_box(x + 1, y + size - 2, size - 2, 1, bevel_color) + self.draw_box(x + size - 2, y + 1, 1, size - 2, bevel_color) + + pip_c = 0x001515C8 + pip_r = 3 + if val in [1, 3, 5]: + self.draw_circle(x + size // 2, y + size // 2, pip_r, pip_c) + self.draw_pixel(x + size // 2 - 1, y + size // 2 - 1, 0x00FFFFFF) + if val >= 2: + self.draw_circle(x + 9, y + 9, pip_r, pip_c) + self.draw_circle(x + size - 10, y + size - 10, pip_r, pip_c) + if val >= 4: + self.draw_circle(x + size - 10, y + 9, pip_r, pip_c) + self.draw_circle(x + 9, y + size - 10, pip_r, pip_c) + if val == 6: + self.draw_circle(x + 9, y + size // 2, pip_r, pip_c) + self.draw_circle(x + size - 10, y + size // 2, pip_r, pip_c) + + def draw_gothic_cup(self, x, y, cup_id, is_lifted=False, has_ball=False): + lift_y = y - 36 if is_lifted else y + if not is_lifted: + self.draw_box(x + 6, y + 42, 36, 4, 0x000A0410) + else: + self.draw_box(x + 10, y + 42, 28, 2, 0x0012061A) + + if is_lifted and has_ball: + self.draw_glowing_orb(x + 24, y + 26) + + self.draw_box_border(x + 6, lift_y + 36, 36, 6, 0x00221A30, 0x0000B0D0, 1) + self.draw_box(x + 18, lift_y + 28, 12, 8, 0x00332545) + self.draw_box(x + 22, lift_y + 28, 4, 8, 0x0055406E) + self.draw_box_border(x + 8, lift_y + 8, 32, 20, 0x002D1E40, 0x0000D7FF, 1) + self.draw_box(x + 14, lift_y + 10, 6, 16, 0x00503570) + self.draw_box(x + 17, lift_y + 10, 3, 16, 0x007850A0) + self.draw_box_border(x + 4, lift_y + 2, 40, 7, 0x00150A20, 0x0000FFFF, 1) + self.draw_box(x + 12, lift_y + 4, 16, 2, 0x0000FFFF) + + self.draw_box(x + 21, lift_y + 12, 6, 5, 0x0000D7FF) + self.draw_box(x + 22, lift_y + 17, 4, 3, 0x0000D7FF) + self.draw_pixel(x + 22, lift_y + 14, 0x00150A20) + self.draw_pixel(x + 24, lift_y + 14, 0x00150A20) + self.draw_string(x + 21, lift_y + 24, str(cup_id), 0x0000FFFF) + + def draw_glowing_orb(self, cx, cy): + self.draw_circle(cx, cy, 14, 0x00081E2E) + self.draw_circle(cx, cy, 11, 0x00103A58) + self.draw_circle(cx, cy, 8, 0x001A588A) + self.draw_circle(cx, cy, 6, 0x0000B0E0) + self.draw_circle(cx, cy, 4, 0x0000E0FF) + self.draw_circle(cx - 1, cy - 1, 2, 0x00A0FFFF) + self.draw_pixel(cx - 2, cy - 2, 0x00FFFFFF) + + def save(self, filename): + img = Image.new('RGB', (SCREEN_W, SCREEN_H)) + img.putdata(self.pixels) + out_path = OUTPUT_DIR / filename + img.save(out_path) + print(f"Saved {out_path}") + +# ============================================================================== +# 1. RENDER COIN GAME +# ============================================================================== +def render_coin(filename='coin_preview.png'): + b = RasterBuffer() + b.draw_box(0, 0, 320, 240, 0x00060914) # Mahogany cabinet + b.draw_box_border(6, 6, 308, 228, 0x000F1522, 0x001B2E48, 3) + for cx in [12, 306]: + for cy in [12, 226]: + b.draw_box(cx, cy, 3, 3, 0x0000D7FF) + b.draw_pixel(cx + 1, cy + 1, 0x00FFFFFF) + + b.draw_box_border(20, 12, 280, 26, 0x000A101C, 0x0000D7FF, 2) + b.draw_string(44, 21, '*** З О Л О Т � Я М О � Е Т � ***', 0x0000FFFF) + for bx in range(24, 296, 12): + b.draw_pixel(bx, 13, 0x0000FFFF) + b.draw_pixel(bx, 36, 0x0000D7FF) + + # Status meters + b.draw_box_border(20, 44, 110, 18, 0x000A1A0E, 0x001A4B22, 1) + b.draw_string(24, 49, 'Б��К: $12500', 0x0050FF50) + b.draw_box_border(190, 44, 110, 18, 0x001A100A, 0x003A2814, 1) + b.draw_string(194, 49, 'СТ�ВК�: $50 [W/S]', 0x0000D7FF) + + # Center Dish + b.draw_circle(160, 110, 46, 0x000090C0) + b.draw_circle(160, 110, 44, 0x0000D7FF) + b.draw_circle(160, 110, 41, 0x00180824) + + # Coin at rest (Heads) + b.draw_coin_ellipse(160, 110, 26, 26, 0x0000A0D0, 0x0000D7FF, relief=1) + + # Left: [1] ОРЕЛ (Active) + b.draw_box_border(20, 72, 76, 52, 0x001C3822, 0x0000FFFF, 2) + b.draw_string(28, 78, '[1] ОР�Л', 0x0000FFFF) + b.draw_coin_ellipse(58, 106, 12, 12, 0x0000A0D0, 0x0000D7FF, relief=1) + + # Right: [2] РЕШК� + b.draw_box_border(224, 72, 76, 52, 0x00121620, 0x00404855, 1) + b.draw_string(232, 78, '[2] РЕШК�', 0x0090A0B0) + b.draw_coin_ellipse(262, 106, 12, 12, 0x000080A0, 0x0000B0D0, relief=2) + + # Streak + b.draw_box_border(44, 154, 232, 20, 0x000E141E, 0x0000D7FF, 1) + b.draw_string(52, 160, 'СЕРИЯ: [X] [X] [X] [ ] [ ] x4!', 0x0000FFFF) + + # Keycaps + b.draw_box(16, 194, 288, 1, 0x001E2E40) + b.draw_keycap(22, 202, '1:ОР�Л', is_active=True) + b.draw_keycap(88, 202, '2:РЕШК�') + b.draw_keycap(160, 202, 'ПРОБЕЛ:БРОСОК', is_active=True) + b.draw_keycap(274, 202, 'ESC') + b.save(filename) + +# ============================================================================== +# 2. RENDER DICE GAME +# ============================================================================== +def render_dice(filename='dice_preview.png'): + b = RasterBuffer() + # Emerald felt + b.draw_box(0, 0, 320, 240, 0x00082E12) + # Oak wood border & leather bumper + b.draw_box_border(4, 4, 312, 232, 0x00093816, 0x00122244, 3) + b.draw_box_border(8, 8, 304, 224, 0x000A3F19, 0x0005140A, 2) + + # Pyramidal backboard rubber diamond texture along top + for bx in range(12, 308, 12): + b.draw_box(bx + 4, 11, 4, 4, 0x00041006) + b.draw_pixel(bx + 5, 12, 0x000F4820) + + # Header + b.draw_string(48, 20, '==== G R A N D C R A P S T A B L E ====', 0x0000D7FF) + b.draw_string(72, 32, '[ PASS LINE ] [ ANY CRAPS ]', 0x0000B0A0) + + # Status + b.draw_box_border(16, 46, 100, 16, 0x0006240E, 0x000E5022, 1) + b.draw_string(20, 50, 'Б��К: $12500', 0x0050FF50) + b.draw_box_border(204, 46, 100, 16, 0x0006240E, 0x000E5022, 1) + b.draw_string(208, 50, 'СТ�ВК�: $50 [W/S]', 0x0000D7FF) + + # Betting Zones + # Left: [1] ЧЕТ (Active with chip stack!) + b.draw_box_border(16, 68, 88, 54, 0x000B441D, 0x0000FFFF, 2) + b.draw_string(24, 74, '[1] Ч�Т', 0x0000FFFF) + b.draw_string(20, 86, '2 4 6 8 10 12', 0x0000D7FF) + b.draw_chip_stack(48, 110, count=4) + + # Right: [2] �ЕЧЕТ + b.draw_box_border(216, 68, 88, 54, 0x00073014, 0x001A602A, 1) + b.draw_string(224, 74, '[2] �ЕЧЕТ', 0x0080B090) + b.draw_string(222, 86, '3 5 7 9 11', 0x00508060) + + # Center Dice Field + b.draw_box_border(112, 68, 96, 54, 0x00072E13, 0x00145826, 1) + # Draw Two Precision Dice + b.draw_craps_die(120, 76, 36, 4) + b.draw_craps_die(164, 76, 36, 6) + + # Score Plaque + b.draw_box_border(36, 130, 248, 30, 0x00051D0C, 0x0000D7FF, 1) + b.draw_string(44, 135, 'СУММ�: 4 + 6 = 10 (Ч�Т)', 0x0000FFFF) + b.draw_string(68, 147, 'ВЫИГРЫШ: +$100! (x2)', 0x0050FF50) + + # Keycaps + b.draw_box(16, 188, 288, 1, 0x00104820) + b.draw_keycap(20, 198, '1:Ч�Т', is_active=True) + b.draw_keycap(82, 198, '2:�ЕЧЕТ') + b.draw_keycap(160, 198, 'ПРОБЕЛ:БРОСОК', is_active=True) + b.draw_keycap(274, 198, 'ESC') + b.save(filename) + +# ============================================================================== +# 3. RENDER SKULLS GAME +# ============================================================================== +def render_skulls(filename='skulls_preview.png'): + b = RasterBuffer() + # Dark gothic table with purple velvet + b.draw_box(0, 0, 320, 240, 0x000D0612) + b.draw_box_border(4, 4, 312, 232, 0x00160B20, 0x00321845, 3) + b.draw_box_border(8, 8, 304, 224, 0x00220F30, 0x0000D7FF, 1) + + # Header + b.draw_box_border(24, 12, 272, 24, 0x0012081A, 0x0000D7FF, 2) + b.draw_string(48, 20, '+ + + � � П � Р С Т К И С К В Е Р � Ы + + +', 0x0000FFFF) + + # Status + b.draw_box_border(20, 42, 110, 16, 0x000D0616, 0x00401858, 1) + b.draw_string(24, 46, 'Б��К: $12500', 0x0050FF50) + b.draw_box_border(190, 42, 110, 16, 0x000D0616, 0x00401858, 1) + b.draw_string(194, 46, 'СТ�ВК�: $50 [W/S]', 0x0000D7FF) + + # Table Runner + b.draw_box_border(16, 66, 288, 114, 0x001A0B25, 0x00452060, 1) + + # Narrative banner + b.draw_string(40, 74, 'СЛЕДИ З� ЗОЛОТЫМ ОКОМ СУДЬБЫ...', 0x0000FFFF) + + # Draw 3 Gothic Cups (Cup 2 is lifted revealing glowing orb!) + b.draw_gothic_cup(48, 100, 1, is_lifted=False) + b.draw_gothic_cup(136, 100, 2, is_lifted=True, has_ball=True) + b.draw_gothic_cup(224, 100, 3, is_lifted=False) + + # Keycaps + b.draw_box(16, 190, 288, 1, 0x003A1850) + b.draw_keycap(18, 200, '1:КУБОК') + b.draw_keycap(82, 200, '2:КУБОК', is_active=True) + b.draw_keycap(146, 200, '3:КУБОК') + b.draw_keycap(212, 200, 'ПРОБЕЛ', is_active=True) + b.draw_keycap(274, 200, 'ESC') + b.save(filename) + +if __name__ == '__main__': + render_coin() + render_dice() + render_skulls() + print("All 3 minigames previews rendered successfully!")