# -*- coding: utf-8 -*- """ Generator script to patch casino3d.inc with rich, custom 2.5D graphics, fixed audio, authentic palette (00RRGGBBh Little-Endian DIB), and native 2.5D minigames: - Coin Flip (Монетка) - Grand Craps / Dice (Кости) - Gothic Skulls & Cups (Напёрстки) - Dead by Daylight Skill Check (Проверка реакции) """ import shutil from pathlib import Path REPO_ROOT = Path(__file__).resolve().parents[2] CASINO_INC = REPO_ROOT / 'casino3d.inc' BACKUP_INC = REPO_ROOT / 'backups' / 'casino3d_before_full_fix.inc' # 1. Back up casino3d.inc BACKUP_INC.parent.mkdir(parents=True, exist_ok=True) shutil.copyfile(CASINO_INC, BACKUP_INC) print(f"[OK] Backed up casino3d.inc to {BACKUP_INC}") with open(CASINO_INC, 'rb') as f: raw_content = f.read() # 2. Add MODE_SKILL equ 9 if b'MODE_SKILL equ 9' not in raw_content: raw_content = raw_content.replace( b'MODE_SKULLS equ 8', b'MODE_SKULLS equ 8\r\nMODE_SKILL equ 9' ) print("[OK] Added MODE_SKILL equ 9") # 3. Audio block replacement old_audio = ( b'soundClick db "assets\\audio\\b05e1ac8be34248.wav",0' ) if old_audio in raw_content: new_audio = ( 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' ) raw_content = raw_content.replace(old_audio, new_audio) print("[OK] Replaced audio definitions") # 4. Strings and variables section replacement 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 = """coinRxAnimTable db 26, 22, 16, 6, 16, 22, 26, 22, 16, 6 ; --- Native 2.5D Coin Flip --- coin3d_bet dd 50 coin3d_choice dd 1 ; 1 = Орёл, 2 = Решка coin3d_state dd 0 ; 0 = Idle, 1 = Flipping, 2 = Result coin3d_timer dd 0 coin3d_result dd 1 ; 1 = Орёл, 2 = Решка coin3d_streak dd 0 coin3d_win dd 0 textCoinTitle db "* * * З О Л О Т А Я М О Н Е Т А * * *",0 textCoinHeads db "ОРЁЛ",0 textCoinTails db "РЕШКА",0 textCoinSide1 db "[1] ОРЁЛ",0 textCoinSide2 db "[2] РЕШКА",0 textCoinFlipping db "МОНЕТА В ПОЛЁТЕ...",0 textCoinWin db "ПОБЕДА: +$",0 textCoinLose db "НЕ УГАДАЛИ!",0 textCoinStreakFmt db "СЕРИЯ ПОБЕД: x",0 textCoinSelected db "ВЫБРАНО",0 textCoinKey1 db "[1] ОРЁЛ",0 textCoinKey2 db "[2] РЕШКА",0 textCoinKeySpace db "[SPACE] БРОСОК",0 ; --- Native 2.5D Dice Game --- dice3d_bet dd 50 dice3d_choice dd 1 ; 1 = Чёт, 2 = Нечет dice3d_state dd 0 ; 0 = Idle, 1 = Rolling, 2 = Result dice3d_timer dd 0 dice3d_val1 dd 4 dice3d_val2 dd 6 dice3d_sum dd 10 dice3d_win dd 0 textDiceTitle db "=== G R A N D C R A P S ===",0 textDiceEven db "[1] ЧЁТ",0 textDiceOdd db "[2] НЕЧЕТ",0 textDiceEvenNums db "2 4 6 8 10 12",0 textDiceOddNums db "3 5 7 9 11",0 textDiceSumHdr db "СУММА: ",0 textDicePlus db " + ",0 textDiceEqual db " = ",0 textDiceEvenResult db " (ЧЁТ)",0 textDiceOddResult db " (НЕЧЕТ)",0 textDiceRolling db "КОСТИ ЛЕТЯТ ПО СУКНУ...",0 textDiceWin db "ВЫИГРЫШ: +$",0 textDiceWinMult db "! (x2)",0 textDiceLose db "ПРОИГРЫШ!",0 textDiceKey1 db "[1] ЧЁТ",0 textDiceKey2 db "[2] НЕЧЕТ",0 textDiceKeySpace db "[SPACE] БРОСОК",0 ; --- Native 2.5D Skulls Game --- skulls3d_bet dd 50 skulls3d_state dd 0 ; 0 = Idle, 1 = Show ball, 2 = Shuffle, 3 = Pick, 4 = Reveal skulls3d_timer dd 0 skulls3d_ballPos dd 1 ; 0, 1, 2 skulls3d_choice dd 1 ; 0, 1, 2 skulls3d_win dd 0 skulls3d_swapPair0 dd 0 skulls3d_swapPair1 dd 1 skulls3d_swapPair2 dd 2 textSkullsTitle db "* * * Н А П Ё Р С Т К И : Ч Е Р Е П А * * *",0 textSkullsPhase0 db "ДЕЛАЙ СТАВКУ И ЖМИ [ПРОБЕЛ]",0 textSkullsPhase1 db "СМОТРИ, ГДЕ ЗОЛОТОЙ ШАР...",0 textSkullsPhase2 db "КРУЧУ, ВЕРЧУ, ЗАПУТАТЬ ХОЧУ...",0 textSkullsPhase3 db "ГДЕ ШАР? ВЫБИРАЙ: [1], [2] ИЛИ [3]!",0 textSkullsWin db "ВЫИГРЫШ: +$",0 textSkullsWinMult db "! (x3) ВЫ УГАДАЛИ!",0 textSkullsLose db "МИМО! ШАР БЫЛ В ДРУГОМ МЕСТЕ!",0 textSkullsAgain db "[ПРОБЕЛ] - СЫГРАТЬ ЕЩЁ РАЗ",0 textSkullsKey1 db "[1]",0 textSkullsKey2 db "[2]",0 textSkullsKey3 db "[3]",0 textSkullsKeySpace db "[SPACE] СТАРТ",0 ; --- Native 2.5D Skill Check (Dead by Daylight Survivor Check) --- skill3d_bet dd 50 skill3d_state dd 0 ; 0=Ready, 1=Active, 2=Hit Result, 3=Miss Result, 4=Escaped, 5=Defeated skill3d_timer dd 0 skill3d_needle dd 55 ; Needle X (52..268) skill3d_speed dd 4 skill3d_dir dd 1 ; 1=Right, -1=Left skill3d_zone_start dd 140 skill3d_zone_width dd 48 skill3d_great_start dd 176 skill3d_great_width dd 12 skill3d_hits dd 0 skill3d_misses dd 0 skill3d_last_result dd 0 skill3d_win_amount dd 0 textSkillTitle db "=== S K I L L C H E C K ===",0 textSkillHitsHdr db "ХИТ: ",0 textSkillMissHdr db "ПРОМАХ: ",0 textSkillReadyMsg db "НАЖМИТЕ [ПРОБЕЛ] ДЛЯ СТАРТА",0 textSkillPrompt db "НАЖМИТЕ [ПРОБЕЛ] В ЗОНЕ!",0 textSkillHitMsg db "ХИТ! ТОЧНОЕ ПОПАДАНИЕ!",0 textSkillGreatMsg db "ОТЛИЧНО! GREAT SKILL CHECK! +БОНУС!",0 textSkillMissMsg db "ПРОМАХ! ТРЕВОГА!",0 textSkillEscape db "ПОБЕГ УСПЕШЕН! ВЫИГРЫШ: +$",0 textSkillLost db "ВЫ ПОЙМАНЫ! ПРОИГРЫШ СТАВКИ!",0 textSkillKeySpace db "[SPACE] РЕАКЦИЯ",0 textSkillKeyBet db "[ВВЕРХ/ВНИЗ]",0 ; --- Shared UI Strings --- textKeyEsc db "[ESC]",0 textBankPrompt db "БАНК: $",0 textBetPrompt db "СТАВКА: $",0 textBetHint db " [W/S]",0 """ raw_content = raw_content[:pos_coin_table] + new_strings.encode('cp1251') + raw_content[pos_shop_msg:] print("[OK] Replaced strings and variables") # 5. Replace minigame procedural drawing & game logic pos_games_start = raw_content.find(b'; ==============================================================================\r\n; SHARED RICH UI PROCEDURES') if pos_games_start == -1: pos_games_start = raw_content.find(b'; SHARED RICH UI PROCEDURES') if pos_games_start == -1: 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 keyW:DWORD mov esi, strPtr xor ecx, ecx keycap_len: mov al, [esi+ecx] test al, al jz keycap_len_done inc ecx jmp keycap_len keycap_len_done: shl ecx, 3 add ecx, 8 mov keyW, ecx ; Drop shadow mov eax, y add eax, 2 invoke DrawBox, x, eax, keyW, 13, 0008080Ch ; Border and Fill cmp isActive, 0 je keycap_inactive mov eax, 00FFFF00h ; Bright Yellow active border mov edx, 001B4B22h ; Casino Green active fill mov ebx, 00FFFF00h ; Bright Yellow active text jmp keycap_draw_box keycap_inactive: mov eax, 00606870h ; Slate inactive border mov edx, 001A1C22h ; Charcoal inactive fill mov ebx, 00D0D8E0h ; Silver inactive text keycap_draw_box: push ebx invoke DrawBoxBorder, x, y, keyW, 13, edx, eax, 1 pop ebx ; Text label mov eax, x add eax, 4 mov edx, y add edx, 3 invoke DrawString8x8, eax, edx, strPtr, ebx mov eax, keyW add eax, 4 ret DrawKeycap3D ENDP DrawChipStack PROC uses ebx esi edi, x:DWORD, y:DWORD, chipCount:DWORD mov edi, chipCount xor esi, esi chip_loop: cmp esi, edi jge chip_done mov eax, esi shl eax, 2 mov edx, y sub edx, eax ; Shadow mov eax, x add eax, 2 mov ecx, edx add ecx, 5 invoke DrawBox, eax, ecx, 20, 2, 00061004h ; Red Clay Chip body with white rim invoke DrawBoxBorder, x, edx, 24, 6, 00B81515h, 00FFFFFFh, 1 ; White stripe inlays mov eax, x add eax, 4 mov ecx, edx add ecx, 1 invoke DrawBox, eax, ecx, 3, 4, 00FFFFFFh mov eax, x add eax, 17 mov ecx, edx add ecx, 1 invoke DrawBox, eax, ecx, 3, 4, 00FFFFFFh inc esi jmp chip_loop chip_done: ret DrawChipStack ENDP DrawDetailedCoin PROC uses ebx esi edi, cxVal:DWORD, cyVal:DWORD, rxVal:DWORD, ryVal:DWORD, outerColor:DWORD, innerColor:DWORD, reliefType:DWORD local rxSq:DWORD local rySq:DWORD local rxRySq:DWORD local threshSq:DWORD local curDy:DWORD local curDx:DWORD local curX:DWORD local curY:DWORD mov eax, rxVal cmp eax, 0 jle coin_draw_done mov eax, ryVal cmp eax, 0 jle coin_draw_done mov eax, rxVal imul eax, rxVal mov rxSq, eax mov eax, ryVal imul eax, ryVal mov rySq, eax imul eax, rxSq mov rxRySq, eax ; 3/4 threshold for rim bevel mov ecx, 3 imul eax, ecx shr eax, 2 mov threshSq, eax ; Scan rows mov eax, ryVal neg eax mov curDy, eax coin_row_loop: mov eax, curDy cmp eax, ryVal jg coin_relief_check mov edx, cyVal add edx, curDy mov curY, edx ; Scan columns mov eax, rxVal neg eax mov curDx, eax coin_col_loop: mov eax, curDx cmp eax, rxVal jg coin_col_next_row mov ecx, cxVal add ecx, curDx mov curX, ecx ; val = dx*dx*rySq + dy*dy*rxSq mov eax, curDx imul eax, curDx imul eax, rySq mov ebx, eax mov eax, curDy imul eax, curDy imul eax, rxSq add eax, ebx cmp eax, rxRySq ja coin_pixel_outside cmp eax, threshSq jb coin_draw_inner invoke DrawPixel, curX, curY, outerColor jmp coin_pixel_outside coin_draw_inner: invoke DrawPixel, curX, curY, innerColor coin_pixel_outside: inc curDx jmp coin_col_loop coin_col_next_row: inc curDy jmp coin_row_loop coin_relief_check: cmp rxVal, 14 jl coin_draw_done cmp reliefType, 1 je coin_draw_eagle cmp reliefType, 2 je coin_draw_numeral jmp coin_draw_done coin_draw_eagle: ; Imperial Eagle relief (Dark Gold 009A7A00h / Bright 00FFD700h) mov eax, cxVal sub eax, 3 mov edx, cyVal sub edx, 14 invoke DrawBox, eax, edx, 7, 2, 009A7A00h mov eax, cxVal sub eax, 4 mov edx, cyVal sub edx, 12 invoke DrawBox, eax, edx, 9, 2, 009A7A00h mov eax, cxVal sub eax, 2 mov edx, cyVal sub edx, 9 invoke DrawBox, eax, edx, 5, 12, 009A7A00h mov eax, cxVal sub eax, 1 mov edx, cyVal sub edx, 8 invoke DrawBox, eax, edx, 3, 10, 00FFD700h mov eax, cxVal sub eax, 10 mov edx, cyVal sub edx, 8 invoke DrawBox, eax, edx, 7, 3, 009A7A00h mov eax, cxVal sub eax, 13 mov edx, cyVal sub edx, 5 invoke DrawBox, eax, edx, 10, 3, 009A7A00h mov eax, cxVal sub eax, 11 mov edx, cyVal sub edx, 2 invoke DrawBox, eax, edx, 7, 3, 009A7A00h mov eax, cxVal add eax, 4 mov edx, cyVal sub edx, 8 invoke DrawBox, eax, edx, 7, 3, 009A7A00h mov eax, cxVal add eax, 4 mov edx, cyVal sub edx, 5 invoke DrawBox, eax, edx, 10, 3, 009A7A00h mov eax, cxVal add eax, 5 mov edx, cyVal sub edx, 2 invoke DrawBox, eax, edx, 7, 3, 009A7A00h mov eax, cxVal sub eax, 4 mov edx, cyVal add edx, 4 invoke DrawBox, eax, edx, 9, 3, 009A7A00h mov eax, cxVal sub eax, 3 mov edx, cyVal add edx, 7 invoke DrawBox, eax, edx, 7, 3, 009A7A00h jmp coin_draw_done coin_draw_numeral: ; Roman numeral 'I' & laurel mov eax, cxVal sub eax, 5 mov edx, cyVal sub edx, 10 invoke DrawBox, eax, edx, 11, 3, 009A7A00h mov eax, cxVal sub eax, 2 mov edx, cyVal sub edx, 7 invoke DrawBox, eax, edx, 5, 14, 009A7A00h mov eax, cxVal sub eax, 1 mov edx, cyVal sub edx, 6 invoke DrawBox, eax, edx, 3, 12, 00FFD700h mov eax, cxVal sub eax, 6 mov edx, cyVal add edx, 7 invoke DrawBox, eax, edx, 13, 3, 009A7A00h ; Laurel dots mov eax, cxVal sub eax, 12 mov edx, cyVal sub edx, 8 invoke DrawBox, eax, edx, 2, 2, 009A7A00h mov eax, cxVal add eax, 11 mov edx, cyVal sub edx, 8 invoke DrawBox, eax, edx, 2, 2, 009A7A00h mov eax, cxVal sub eax, 12 mov edx, cyVal invoke DrawBox, eax, edx, 2, 2, 009A7A00h mov eax, cxVal add eax, 11 mov edx, cyVal invoke DrawBox, eax, edx, 2, 2, 009A7A00h mov eax, cxVal sub eax, 12 mov edx, cyVal add edx, 8 invoke DrawBox, eax, edx, 2, 2, 009A7A00h mov eax, cxVal add eax, 11 mov edx, cyVal add edx, 8 invoke DrawBox, eax, edx, 2, 2, 009A7A00h coin_draw_done: ret DrawDetailedCoin ENDP ; ============================================================================== ; IN-ENGINE 2.5D MINI-GAME: COIN FLIP ; ============================================================================== InitCoinGame PROC mov coin3d_state, 0 mov coin3d_timer, 0 mov coin3d_streak, 0 mov coin3d_win, 0 ret InitCoinGame ENDP HandleCoinInput PROC cmp coin3d_state, 0 je coin_handle_idle cmp coin3d_state, 1 je coin_handle_flipping cmp coin3d_state, 2 je coin_handle_result ret coin_handle_idle: invoke Pressed3D, 26h ; UP test eax, eax jnz coin_bet_up invoke Pressed3D, 57h ; 'W' test eax, eax jnz coin_bet_up invoke Pressed3D, 28h ; DOWN test eax, eax jnz coin_bet_down invoke Pressed3D, 53h ; 'S' test eax, eax jnz coin_bet_down invoke Pressed3D, 31h ; '1' test eax, eax jnz coin_pick_1 invoke Pressed3D, 32h ; '2' test eax, eax jnz coin_pick_2 invoke Pressed3D, 20h ; SPACE test eax, eax jnz coin_start_flip ret coin_bet_up: mov eax, coin3d_bet add eax, 50 cmp eax, bankroll jle @F mov eax, bankroll @@: cmp eax, 5000 jle @F mov eax, 5000 @@: mov coin3d_bet, eax invoke PlaySoundA, OFFSET soundClick, 0, 1 ret coin_bet_down: mov eax, coin3d_bet sub eax, 50 cmp eax, 50 jge @F mov eax, 50 @@: mov coin3d_bet, eax invoke PlaySoundA, OFFSET soundClick, 0, 1 ret coin_pick_1: mov coin3d_choice, 1 invoke PlaySoundA, OFFSET soundClick, 0, 1 ret coin_pick_2: mov coin3d_choice, 2 invoke PlaySoundA, OFFSET soundClick, 0, 1 ret coin_start_flip: mov eax, coin3d_bet cmp eax, bankroll jle @F mov eax, bankroll mov coin3d_bet, eax test eax, eax jz coin_done @@: mov eax, coin3d_bet sub bankroll, eax mov coin3d_state, 1 mov coin3d_timer, 40 invoke PlaySoundA, OFFSET soundCoin, 0, 1 ret coin_handle_flipping: dec coin3d_timer cmp coin3d_timer, 0 jg coin_done invoke RandomRange3D, 2 inc eax mov coin3d_result, eax mov edx, coin3d_choice cmp eax, edx jne coin_flip_lost ; Won! inc coin3d_streak mov eax, coin3d_bet shl eax, 1 add bankroll, eax mov coin3d_win, eax mov coin3d_state, 2 invoke PlaySoundA, OFFSET soundCoinDing, 0, 1 ret coin_flip_lost: mov coin3d_streak, 0 mov coin3d_win, 0 mov coin3d_state, 2 invoke PlaySoundA, OFFSET soundLose, 0, 1 ret coin_handle_result: invoke Pressed3D, 20h test eax, eax jz coin_done mov coin3d_state, 0 invoke PlaySoundA, OFFSET soundClick, 0, 1 coin_done: ret HandleCoinInput ENDP RenderCoinGame PROC uses ebx esi edi local cyVal:DWORD local rxVal:DWORD local kx:DWORD ; Background & Cabinet border invoke DrawBox, 0, 0, 320, 240, 00140906h invoke DrawBoxBorder, 6, 6, 308, 228, 0022150Fh, 00482E1Bh, 3 ; Header invoke DrawBoxBorder, 20, 12, 280, 26, 001C100Ah, 00FFD700h, 2 invoke DrawString8x8, 44, 21, OFFSET textCoinTitle, 00FFFF00h ; Corner rivets invoke DrawBox, 12, 12, 3, 3, 00FFD700h invoke DrawBox, 306, 12, 3, 3, 00FFD700h invoke DrawBox, 12, 226, 3, 3, 00FFD700h invoke DrawBox, 306, 226, 3, 3, 00FFD700h ; Status meters invoke DrawBoxBorder, 20, 44, 110, 18, 000E1A0Ah, 00224B1Ah, 1 invoke DrawString8x8, 24, 49, OFFSET textBankPrompt, 003CFF3Ch invoke FormatNumber, bankroll, OFFSET hudNumBuffer invoke DrawString8x8, 72, 49, OFFSET hudNumBuffer, 003CFF3Ch invoke DrawBoxBorder, 190, 44, 110, 18, 001A100Ah, 003A2814h, 1 invoke DrawString8x8, 194, 49, OFFSET textBetPrompt, 00FFD700h invoke FormatNumber, coin3d_bet, OFFSET hudNumBuffer invoke DrawString8x8, 254, 49, OFFSET hudNumBuffer, 00FFD700h ; Left: Heads cmp coin3d_choice, 1 jne coin_left_inactive invoke DrawBoxBorder, 20, 72, 76, 68, 00101828h, 00FFFF00h, 2 invoke DrawString8x8, 30, 78, OFFSET textCoinSide1, 00FFFF00h invoke DrawDetailedCoin, 58, 106, 14, 14, 00D0A000h, 00FFD700h, 1 invoke DrawString8x8, 24, 126, OFFSET textCoinSelected, 003CFF3Ch jmp coin_right_side coin_left_inactive: invoke DrawBoxBorder, 20, 72, 76, 68, 000A101Ch, 00404855h, 1 invoke DrawString8x8, 30, 78, OFFSET textCoinSide1, 00D0D8E0h invoke DrawDetailedCoin, 58, 106, 14, 14, 009A7A00h, 00D0A000h, 1 coin_right_side: ; Right: Tails cmp coin3d_choice, 2 jne coin_right_inactive invoke DrawBoxBorder, 224, 72, 76, 68, 00101828h, 00FFFF00h, 2 invoke DrawString8x8, 234, 78, OFFSET textCoinSide2, 00FFFF00h invoke DrawDetailedCoin, 262, 106, 14, 14, 00D0A000h, 00FFD700h, 2 invoke DrawString8x8, 228, 126, OFFSET textCoinSelected, 003CFF3Ch jmp coin_center_area coin_right_inactive: invoke DrawBoxBorder, 224, 72, 76, 68, 000A101Ch, 00404855h, 1 invoke DrawString8x8, 234, 78, OFFSET textCoinSide2, 00D0D8E0h invoke DrawDetailedCoin, 262, 106, 14, 14, 009A7A00h, 00D0A000h, 2 coin_center_area: ; Center spotlight invoke DrawCircle, 160, 110, 48, 00121620h invoke DrawCircle, 160, 110, 44, 00FFD700h invoke DrawCircle, 160, 110, 42, 000E141Eh cmp coin3d_state, 1 je coin_render_flipping cmp coin3d_state, 2 je coin_render_result ; Idle coin invoke DrawDetailedCoin, 160, 110, 26, 26, 00D0A000h, 00FFD700h, coin3d_choice jmp coin_render_keys coin_render_flipping: mov eax, coin3d_timer and eax, 7 movzx eax, byte ptr [coinRxAnimTable + eax] mov rxVal, eax invoke DrawDetailedCoin, 160, 110, rxVal, 26, 00D0A000h, 00FFD700h, 0 invoke DrawString8x8, 88, 160, OFFSET textCoinFlipping, 00FFFF00h jmp coin_render_keys coin_render_result: invoke DrawDetailedCoin, 160, 110, 26, 26, 00D0A000h, 00FFD700h, coin3d_result mov eax, coin3d_result cmp eax, coin3d_choice jne coin_render_loss_msg ; Win banner invoke DrawBoxBorder, 44, 154, 232, 22, 000E141Eh, 003CFF3Ch, 1 invoke DrawString8x8, 64, 161, OFFSET textCoinWin, 003CFF3Ch invoke FormatNumber, coin3d_win, OFFSET hudNumBuffer invoke DrawString8x8, 152, 161, OFFSET hudNumBuffer, 003CFF3Ch jmp coin_render_keys coin_render_loss_msg: invoke DrawBoxBorder, 44, 154, 232, 22, 000E141Eh, 00C81414h, 1 invoke DrawString8x8, 114, 161, OFFSET textCoinLose, 00FF6464h coin_render_keys: mov kx, 16 xor eax, eax cmp coin3d_choice, 1 sete al invoke DrawKeycap3D, kx, 192, OFFSET textCoinKey1, eax add kx, eax xor eax, eax cmp coin3d_choice, 2 sete al invoke DrawKeycap3D, kx, 192, OFFSET textCoinKey2, eax add kx, eax invoke DrawKeycap3D, kx, 192, OFFSET textCoinKeySpace, 1 add kx, eax invoke DrawKeycap3D, kx, 192, OFFSET textKeyEsc, 0 ret RenderCoinGame ENDP ; ============================================================================== ; IN-ENGINE 2.5D MINI-GAME: CRAPS / DICE ; ============================================================================== DrawCrapsDie PROC uses ebx esi edi, x:DWORD, y:DWORD, sizeVal:DWORD, valNum:DWORD ; Drop shadow mov eax, x add eax, 3 mov edx, y add edx, sizeVal invoke DrawBox, eax, edx, sizeVal, 3, 00081403h mov eax, x add eax, sizeVal mov edx, y add edx, 3 invoke DrawBox, eax, edx, 3, sizeVal, 00081403h ; Ivory body & bevel invoke DrawBoxBorder, x, y, sizeVal, sizeVal, 00FAF4F0h, 00403535h, 1 mov eax, x inc eax mov edx, y inc edx mov ecx, sizeVal sub ecx, 2 invoke DrawBox, eax, edx, ecx, 1, 00FFFFFFh invoke DrawBox, eax, edx, 1, ecx, 00FFFFFFh ; Ruby pips (00C81515h) mov eax, valNum test al, 1 jz @F ; Center pip mov eax, x add eax, 18 mov edx, y add edx, 18 invoke DrawCircle, eax, edx, 3, 00C81515h dec eax dec edx invoke DrawPixel, eax, edx, 00FFFFFFh @@: cmp valNum, 2 jl die_pips_done mov eax, x add eax, 9 mov edx, y add edx, 9 invoke DrawCircle, eax, edx, 3, 00C81515h mov eax, x add eax, 27 mov edx, y add edx, 27 invoke DrawCircle, eax, edx, 3, 00C81515h cmp valNum, 4 jl die_pips_done mov eax, x add eax, 27 mov edx, y add edx, 9 invoke DrawCircle, eax, edx, 3, 00C81515h mov eax, x add eax, 9 mov edx, y add edx, 27 invoke DrawCircle, eax, edx, 3, 00C81515h cmp valNum, 6 jl die_pips_done mov eax, x add eax, 9 mov edx, y add edx, 18 invoke DrawCircle, eax, edx, 3, 00C81515h mov eax, x add eax, 27 mov edx, y add edx, 18 invoke DrawCircle, eax, edx, 3, 00C81515h die_pips_done: ret DrawCrapsDie ENDP InitDiceGame PROC mov dice3d_state, 0 mov dice3d_timer, 0 mov dice3d_win, 0 ret InitDiceGame ENDP HandleDiceInput PROC cmp dice3d_state, 0 je dice_handle_idle cmp dice3d_state, 1 je dice_handle_rolling cmp dice3d_state, 2 je dice_handle_result ret dice_handle_idle: invoke Pressed3D, 26h ; UP test eax, eax jnz dice_bet_up invoke Pressed3D, 57h ; 'W' test eax, eax jnz dice_bet_up invoke Pressed3D, 28h ; DOWN test eax, eax jnz dice_bet_down invoke Pressed3D, 53h ; 'S' test eax, eax jnz dice_bet_down invoke Pressed3D, 31h ; '1' test eax, eax jnz dice_pick_1 invoke Pressed3D, 32h ; '2' test eax, eax jnz dice_pick_2 invoke Pressed3D, 20h ; SPACE test eax, eax jnz dice_start_roll ret dice_bet_up: mov eax, dice3d_bet add eax, 50 cmp eax, bankroll jle @F mov eax, bankroll @@: cmp eax, 5000 jle @F mov eax, 5000 @@: mov dice3d_bet, eax invoke PlaySoundA, OFFSET soundClick, 0, 1 ret dice_bet_down: mov eax, dice3d_bet sub eax, 50 cmp eax, 50 jge @F mov eax, 50 @@: mov dice3d_bet, eax invoke PlaySoundA, OFFSET soundClick, 0, 1 ret dice_pick_1: mov dice3d_choice, 1 invoke PlaySoundA, OFFSET soundClick, 0, 1 ret dice_pick_2: mov dice3d_choice, 2 invoke PlaySoundA, OFFSET soundClick, 0, 1 ret dice_start_roll: mov eax, dice3d_bet cmp eax, bankroll jle @F mov eax, bankroll mov dice3d_bet, eax test eax, eax jz dice_done @@: mov eax, dice3d_bet sub bankroll, eax mov dice3d_state, 1 mov dice3d_timer, 35 invoke PlaySoundA, OFFSET soundCards, 0, 1 ret dice_handle_rolling: dec dice3d_timer cmp dice3d_timer, 0 jg dice_randomize_tumble ; Roll finished! invoke RandomRange3D, 6 inc eax mov dice3d_val1, eax invoke RandomRange3D, 6 inc eax mov dice3d_val2, eax mov edx, dice3d_val1 add edx, eax mov dice3d_sum, edx ; Parity check mov eax, edx and eax, 1 jnz dice_sum_is_odd ; Even mov eax, 1 jmp dice_check_win dice_sum_is_odd: mov eax, 2 dice_check_win: cmp eax, dice3d_choice jne dice_roll_lost ; Won! mov eax, dice3d_bet shl eax, 1 add bankroll, eax mov dice3d_win, eax mov dice3d_state, 2 invoke PlaySoundA, OFFSET soundVictory, 0, 1 ret dice_roll_lost: mov dice3d_win, 0 mov dice3d_state, 2 invoke PlaySoundA, OFFSET soundLose, 0, 1 ret dice_randomize_tumble: invoke RandomRange3D, 6 inc eax mov dice3d_val1, eax invoke RandomRange3D, 6 inc eax mov dice3d_val2, eax ret dice_handle_result: invoke Pressed3D, 20h test eax, eax jz dice_done mov dice3d_state, 0 invoke PlaySoundA, OFFSET soundClick, 0, 1 dice_done: ret HandleDiceInput ENDP RenderDiceGame PROC uses ebx esi edi local kx:DWORD ; Mahogany frame & Deep Felt Green table invoke DrawBox, 0, 0, 320, 240, 00140906h invoke DrawBoxBorder, 6, 6, 308, 228, 000A3816h, 00FFD700h, 2 ; Header invoke DrawBoxBorder, 20, 12, 280, 26, 00072E13h, 00FFD700h, 2 invoke DrawString8x8, 48, 21, OFFSET textDiceTitle, 00FFFF00h ; Status invoke DrawBoxBorder, 20, 44, 110, 18, 00072E13h, 001B4B22h, 1 invoke DrawString8x8, 24, 49, OFFSET textBankPrompt, 003CFF3Ch invoke FormatNumber, bankroll, OFFSET hudNumBuffer invoke DrawString8x8, 72, 49, OFFSET hudNumBuffer, 003CFF3Ch invoke DrawBoxBorder, 190, 44, 110, 18, 00072E13h, 001B4B22h, 1 invoke DrawString8x8, 194, 49, OFFSET textBetPrompt, 00FFD700h invoke FormatNumber, dice3d_bet, OFFSET hudNumBuffer invoke DrawString8x8, 254, 49, OFFSET hudNumBuffer, 00FFD700h ; [1] ЧЁТ cmp dice3d_choice, 1 jne dice_even_inactive invoke DrawBoxBorder, 16, 70, 88, 48, 00072E13h, 00FFFF00h, 2 invoke DrawString8x8, 30, 76, OFFSET textDiceEven, 00FFFF00h invoke DrawString8x8, 22, 90, OFFSET textDiceEvenNums, 00FFD700h invoke DrawString8x8, 26, 104, OFFSET textCoinSelected, 003CFF3Ch jmp dice_odd_side dice_even_inactive: invoke DrawBoxBorder, 16, 70, 88, 48, 00072E13h, 001B4B22h, 1 invoke DrawString8x8, 30, 76, OFFSET textDiceEven, 00D0D8E0h invoke DrawString8x8, 22, 90, OFFSET textDiceEvenNums, 0080B090h dice_odd_side: ; [2] НЕЧЕТ cmp dice3d_choice, 2 jne dice_odd_inactive invoke DrawBoxBorder, 216, 70, 88, 48, 00072E13h, 00FFFF00h, 2 invoke DrawString8x8, 226, 76, OFFSET textDiceOdd, 00FFFF00h invoke DrawString8x8, 224, 90, OFFSET textDiceOddNums, 00FFD700h invoke DrawString8x8, 226, 104, OFFSET textCoinSelected, 003CFF3Ch jmp dice_center_cubes dice_odd_inactive: invoke DrawBoxBorder, 216, 70, 88, 48, 00072E13h, 001B4B22h, 1 invoke DrawString8x8, 226, 76, OFFSET textDiceOdd, 00D0D8E0h invoke DrawString8x8, 224, 90, OFFSET textDiceOddNums, 0080B090h dice_center_cubes: ; 2 Dice in center invoke DrawCrapsDie, 116, 76, 36, dice3d_val1 invoke DrawCrapsDie, 168, 76, 36, dice3d_val2 cmp dice3d_state, 1 je dice_render_rolling cmp dice3d_state, 2 je dice_render_result jmp dice_render_keys dice_render_rolling: invoke DrawString8x8, 76, 138, OFFSET textDiceRolling, 00FFFF00h jmp dice_render_keys dice_render_result: invoke DrawBoxBorder, 36, 130, 248, 36, 00072E13h, 00FFD700h, 1 invoke DrawString8x8, 44, 135, OFFSET textDiceSumHdr, 00FFD700h invoke FormatNumber, dice3d_val1, OFFSET hudNumBuffer invoke DrawString8x8, 92, 135, OFFSET hudNumBuffer, 00FFFF00h invoke DrawString8x8, 110, 135, OFFSET textDicePlus, 00FFD700h invoke FormatNumber, dice3d_val2, OFFSET hudNumBuffer invoke DrawString8x8, 126, 135, OFFSET hudNumBuffer, 00FFFF00h invoke DrawString8x8, 144, 135, OFFSET textDiceEqual, 00FFD700h invoke FormatNumber, dice3d_sum, OFFSET hudNumBuffer invoke DrawString8x8, 168, 135, OFFSET hudNumBuffer, 00FFFF00h mov eax, dice3d_sum and eax, 1 jnz dice_render_odd_res invoke DrawString8x8, 186, 135, OFFSET textDiceEvenResult, 003CFF3Ch jmp dice_render_outcome dice_render_odd_res: invoke DrawString8x8, 186, 135, OFFSET textDiceOddResult, 003CFF3Ch dice_render_outcome: mov eax, dice3d_win test eax, eax jz dice_render_loss_outcome invoke DrawString8x8, 68, 150, OFFSET textDiceWin, 003CFF3Ch invoke FormatNumber, dice3d_win, OFFSET hudNumBuffer invoke DrawString8x8, 156, 150, OFFSET hudNumBuffer, 003CFF3Ch invoke DrawString8x8, 188, 150, OFFSET textDiceWinMult, 003CFF3Ch jmp dice_render_keys dice_render_loss_outcome: invoke DrawString8x8, 116, 150, OFFSET textDiceLose, 00FF6464h dice_render_keys: mov kx, 16 xor eax, eax cmp dice3d_choice, 1 sete al invoke DrawKeycap3D, kx, 192, OFFSET textDiceKey1, eax add kx, eax xor eax, eax cmp dice3d_choice, 2 sete al invoke DrawKeycap3D, kx, 192, OFFSET textDiceKey2, eax add kx, eax invoke DrawKeycap3D, kx, 192, OFFSET textDiceKeySpace, 1 add kx, eax invoke DrawKeycap3D, kx, 192, OFFSET textKeyEsc, 0 ret RenderDiceGame ENDP ; ============================================================================== ; IN-ENGINE 2.5D MINI-GAME: SKULLS & CUPS (НАПЁРСТКИ) ; ============================================================================== DrawGlowingOrb PROC uses ebx esi edi, cxVal:DWORD, cyVal:DWORD invoke DrawCircle, cxVal, cyVal, 14, 002E1E08h invoke DrawCircle, cxVal, cyVal, 11, 00583A10h invoke DrawCircle, cxVal, cyVal, 8, 008A581Ah invoke DrawCircle, cxVal, cyVal, 6, 00D0B000h invoke DrawCircle, cxVal, cyVal, 4, 00FFE000h mov eax, cxVal dec eax mov edx, cyVal dec edx invoke DrawCircle, eax, edx, 2, 00FFFF80h dec eax dec edx invoke DrawPixel, eax, edx, 00FFFFFFh ret DrawGlowingOrb ENDP DrawGothicCup PROC uses ebx esi edi, x:DWORD, y:DWORD, cupId:DWORD, isLifted:DWORD, hasBall:DWORD local liftY:DWORD mov eax, y cmp isLifted, 0 je @F sub eax, 36 @@: mov liftY, eax ; Drop shadow cmp isLifted, 0 jne cup_shadow_lifted mov eax, x add eax, 6 mov edx, y add edx, 42 invoke DrawBox, eax, edx, 36, 4, 0010040Ah jmp cup_ball_check cup_shadow_lifted: mov eax, x add eax, 10 mov edx, y add edx, 42 invoke DrawBox, eax, edx, 28, 2, 001A0612h cup_ball_check: cmp isLifted, 0 je cup_body_draw cmp hasBall, 0 je cup_body_draw mov eax, x add eax, 24 mov edx, y add edx, 26 invoke DrawGlowingOrb, eax, edx cup_body_draw: ; Base pedestal mov eax, x add eax, 6 mov edx, liftY add edx, 36 invoke DrawBoxBorder, eax, edx, 36, 6, 00301A22h, 00D0B000h, 1 ; Stem mov eax, x add eax, 18 mov edx, liftY add edx, 28 invoke DrawBox, eax, edx, 12, 8, 00452533h mov eax, x add eax, 22 invoke DrawBox, eax, edx, 4, 8, 006E4055h ; Goblet Bowl mov eax, x add eax, 8 mov edx, liftY add edx, 8 invoke DrawBoxBorder, eax, edx, 32, 20, 00401E2Dh, 00FFD700h, 1 mov eax, x add eax, 14 mov edx, liftY add edx, 10 invoke DrawBox, eax, edx, 6, 16, 00703550h mov eax, x add eax, 17 invoke DrawBox, eax, edx, 3, 16, 00A05078h ; Golden Rim mov eax, x add eax, 4 mov edx, liftY add edx, 2 invoke DrawBoxBorder, eax, edx, 40, 7, 00200A15h, 00FFFF00h, 1 mov eax, x add eax, 12 mov edx, liftY add edx, 4 invoke DrawBox, eax, edx, 16, 2, 00FFFF00h ; Skull face emblem mov eax, x add eax, 21 mov edx, liftY add edx, 12 invoke DrawBox, eax, edx, 6, 5, 00FFD700h mov eax, x add eax, 22 mov edx, liftY add edx, 17 invoke DrawBox, eax, edx, 4, 3, 00FFD700h mov eax, x add eax, 22 mov edx, liftY add edx, 14 invoke DrawPixel, eax, edx, 00200A15h mov eax, x add eax, 24 invoke DrawPixel, eax, edx, 00200A15h ; Cup number label mov eax, x add eax, 21 mov edx, liftY add edx, 24 mov ecx, cupId add ecx, '1' invoke DrawChar8x8, eax, edx, ecx, 00FFFF00h ret DrawGothicCup ENDP InitSkullsGame PROC mov skulls3d_state, 0 mov skulls3d_timer, 0 mov skulls3d_win, 0 invoke RandomRange3D, 3 mov skulls3d_ballPos, eax mov skulls3d_choice, 1 ret InitSkullsGame ENDP FinalizeSkullsGuess PROC uses ebx mov eax, skulls3d_choice cmp eax, skulls3d_ballPos jne skulls_guess_wrong ; Won! 3x payout mov eax, skulls3d_bet imul eax, 3 add bankroll, eax mov skulls3d_win, eax mov skulls3d_state, 4 invoke PlaySoundA, OFFSET soundJackpot, 0, 1 ret skulls_guess_wrong: mov skulls3d_win, 0 mov skulls3d_state, 4 invoke PlaySoundA, OFFSET soundLose, 0, 1 ret FinalizeSkullsGuess ENDP HandleSkullsInput PROC cmp skulls3d_state, 0 je skulls_handle_idle cmp skulls3d_state, 1 je skulls_handle_show cmp skulls3d_state, 2 je skulls_handle_shuffle cmp skulls3d_state, 3 je skulls_handle_pick cmp skulls3d_state, 4 je skulls_handle_reveal ret skulls_handle_idle: invoke Pressed3D, 26h ; UP test eax, eax jnz skulls_bet_up invoke Pressed3D, 57h ; 'W' test eax, eax jnz skulls_bet_up invoke Pressed3D, 28h ; DOWN test eax, eax jnz skulls_bet_down invoke Pressed3D, 53h ; 'S' test eax, eax jnz skulls_bet_down invoke Pressed3D, 20h ; SPACE test eax, eax jnz skulls_start_game ret skulls_bet_up: mov eax, skulls3d_bet add eax, 50 cmp eax, bankroll jle @F mov eax, bankroll @@: cmp eax, 5000 jle @F mov eax, 5000 @@: mov skulls3d_bet, eax invoke PlaySoundA, OFFSET soundClick, 0, 1 ret skulls_bet_down: mov eax, skulls3d_bet sub eax, 50 cmp eax, 50 jge @F mov eax, 50 @@: mov skulls3d_bet, eax invoke PlaySoundA, OFFSET soundClick, 0, 1 ret skulls_start_game: mov eax, skulls3d_bet cmp eax, bankroll jle @F mov eax, bankroll mov skulls3d_bet, eax test eax, eax jz skulls_done @@: mov eax, skulls3d_bet sub bankroll, eax invoke RandomRange3D, 3 mov skulls3d_ballPos, eax mov skulls3d_state, 1 mov skulls3d_timer, 45 invoke PlaySoundA, OFFSET soundShuffle, 0, 1 ret skulls_handle_show: dec skulls3d_timer cmp skulls3d_timer, 0 jg skulls_done mov skulls3d_state, 2 mov skulls3d_timer, 60 invoke PlaySoundA, OFFSET soundShuffle, 0, 1 ret skulls_handle_shuffle: dec skulls3d_timer cmp skulls3d_timer, 0 jg skulls_done invoke RandomRange3D, 3 mov skulls3d_ballPos, eax mov skulls3d_state, 3 ret skulls_handle_pick: invoke Pressed3D, 31h ; '1' test eax, eax jnz skulls_pick_1 invoke Pressed3D, 32h ; '2' test eax, eax jnz skulls_pick_2 invoke Pressed3D, 33h ; '3' test eax, eax jnz skulls_pick_3 ret skulls_pick_1: mov skulls3d_choice, 0 call FinalizeSkullsGuess ret skulls_pick_2: mov skulls3d_choice, 1 call FinalizeSkullsGuess ret skulls_pick_3: mov skulls3d_choice, 2 call FinalizeSkullsGuess ret skulls_handle_reveal: invoke Pressed3D, 20h test eax, eax jz skulls_done mov skulls3d_state, 0 invoke PlaySoundA, OFFSET soundClick, 0, 1 skulls_done: ret HandleSkullsInput ENDP RenderSkullsGame PROC uses ebx esi edi local kx:DWORD ; Mahogany & Gothic Purple table invoke DrawBox, 0, 0, 320, 240, 00140906h invoke DrawBoxBorder, 6, 6, 308, 228, 00300F22h, 00FFD700h, 2 ; Header invoke DrawBoxBorder, 20, 12, 280, 26, 001A0812h, 00FFD700h, 2 invoke DrawString8x8, 40, 21, OFFSET textSkullsTitle, 00FFFF00h ; Status invoke DrawBoxBorder, 20, 44, 110, 18, 001A0812h, 00452033h, 1 invoke DrawString8x8, 24, 49, OFFSET textBankPrompt, 003CFF3Ch invoke FormatNumber, bankroll, OFFSET hudNumBuffer invoke DrawString8x8, 72, 49, OFFSET hudNumBuffer, 003CFF3Ch invoke DrawBoxBorder, 190, 44, 110, 18, 001A0812h, 00452033h, 1 invoke DrawString8x8, 194, 49, OFFSET textBetPrompt, 00FFD700h invoke FormatNumber, skulls3d_bet, OFFSET hudNumBuffer invoke DrawString8x8, 254, 49, OFFSET hudNumBuffer, 00FFD700h ; Subtitle phase prompts cmp skulls3d_state, 0 jne @F invoke DrawString8x8, 56, 62, OFFSET textSkullsPhase0, 00FFD700h jmp skulls_render_cups @@: cmp skulls3d_state, 1 jne @F invoke DrawString8x8, 56, 62, OFFSET textSkullsPhase1, 00FFFF00h jmp skulls_render_cups @@: cmp skulls3d_state, 2 jne @F invoke DrawString8x8, 56, 62, OFFSET textSkullsPhase2, 00FFFF00h jmp skulls_render_cups @@: cmp skulls3d_state, 3 jne @F invoke DrawString8x8, 40, 62, OFFSET textSkullsPhase3, 00FFFF00h jmp skulls_render_cups @@: ; Reveal outcome mov eax, skulls3d_win test eax, eax jz skulls_show_loss_text invoke DrawString8x8, 40, 62, OFFSET textSkullsWin, 003CFF3Ch invoke FormatNumber, skulls3d_win, OFFSET hudNumBuffer invoke DrawString8x8, 136, 62, OFFSET hudNumBuffer, 003CFF3Ch invoke DrawString8x8, 168, 62, OFFSET textSkullsWinMult, 003CFF3Ch jmp skulls_render_cups skulls_show_loss_text: invoke DrawString8x8, 40, 62, OFFSET textSkullsLose, 00FF6464h skulls_render_cups: ; Draw Cup 1 (X=36, Y=114) mov ebx, 0 mov edx, 0 cmp skulls3d_state, 1 jne @F cmp skulls3d_ballPos, 0 jne @F mov ebx, 1 mov edx, 1 @@: cmp skulls3d_state, 4 jne @F cmp skulls3d_choice, 0 sete bl cmp skulls3d_ballPos, 0 sete dl @@: invoke DrawGothicCup, 36, 114, 0, ebx, edx ; Draw Cup 2 (X=136, Y=114) mov ebx, 0 mov edx, 0 cmp skulls3d_state, 1 jne @F cmp skulls3d_ballPos, 1 jne @F mov ebx, 1 mov edx, 1 @@: cmp skulls3d_state, 4 jne @F cmp skulls3d_choice, 1 sete bl cmp skulls3d_ballPos, 1 sete dl @@: invoke DrawGothicCup, 136, 114, 1, ebx, edx ; Draw Cup 3 (X=236, Y=114) mov ebx, 0 mov edx, 0 cmp skulls3d_state, 1 jne @F cmp skulls3d_ballPos, 2 jne @F mov ebx, 1 mov edx, 1 @@: cmp skulls3d_state, 4 jne @F cmp skulls3d_choice, 2 sete bl cmp skulls3d_ballPos, 2 sete dl @@: invoke DrawGothicCup, 236, 114, 2, ebx, edx ; Cup selection indicators invoke DrawString8x8, 54, 168, OFFSET textSkullsKey1, 00D0D8E0h invoke DrawString8x8, 150, 168, OFFSET textSkullsKey2, 00D0D8E0h invoke DrawString8x8, 250, 168, OFFSET textSkullsKey3, 00D0D8E0h ; Keycaps mov kx, 16 xor eax, eax cmp skulls3d_choice, 0 sete al invoke DrawKeycap3D, kx, 192, OFFSET textSkullsKey1, eax add kx, eax xor eax, eax cmp skulls3d_choice, 1 sete al invoke DrawKeycap3D, kx, 192, OFFSET textSkullsKey2, eax add kx, eax xor eax, eax cmp skulls3d_choice, 2 sete al invoke DrawKeycap3D, kx, 192, OFFSET textSkullsKey3, eax add kx, eax invoke DrawKeycap3D, kx, 192, OFFSET textSkullsKeySpace, 1 add kx, eax invoke DrawKeycap3D, kx, 192, OFFSET textKeyEsc, 0 ret RenderSkullsGame ENDP ; ============================================================================== ; IN-ENGINE 2.5D MINI-GAME: SKILL CHECK (DEAD BY DAYLIGHT SURVIVOR CHECK) ; ============================================================================== InitSkillGame PROC mov skill3d_state, 0 mov skill3d_timer, 0 mov skill3d_hits, 0 mov skill3d_misses, 0 mov skill3d_needle, 55 mov skill3d_speed, 4 mov skill3d_dir, 1 mov skill3d_last_result, 0 mov skill3d_win_amount, 0 ; Randomize initial zone: 80 + RandomRange(90) -> 80..170 invoke RandomRange3D, 90 add eax, 80 mov skill3d_zone_start, eax ; Great zone: start + 20 + RandomRange(12) invoke RandomRange3D, 12 add eax, skill3d_zone_start add eax, 20 mov skill3d_great_start, eax ret InitSkillGame ENDP HandleSkillInput PROC uses ebx esi mov eax, skill3d_state cmp eax, 0 je skill_handle_ready cmp eax, 1 je skill_handle_active cmp eax, 2 je skill_handle_round_wait cmp eax, 3 je skill_handle_round_wait cmp eax, 4 je skill_handle_end_wait cmp eax, 5 je skill_handle_end_wait ret skill_handle_ready: invoke Pressed3D, 26h ; UP test eax, eax jnz skill_bet_up invoke Pressed3D, 57h ; 'W' test eax, eax jnz skill_bet_up invoke Pressed3D, 28h ; DOWN test eax, eax jnz skill_bet_down invoke Pressed3D, 53h ; 'S' test eax, eax jnz skill_bet_down jmp skill_check_start skill_bet_up: mov eax, skill3d_bet add eax, 50 cmp eax, bankroll jle @F mov eax, bankroll @@: cmp eax, 5000 jle @F mov eax, 5000 @@: mov skill3d_bet, eax invoke PlaySoundA, OFFSET soundClick, 0, 1 ret skill_bet_down: mov eax, skill3d_bet sub eax, 50 cmp eax, 50 jge @F mov eax, 50 @@: mov skill3d_bet, eax invoke PlaySoundA, OFFSET soundClick, 0, 1 ret skill_check_start: invoke Pressed3D, 20h ; SPACE test eax, eax jz skill_input_done ; Deduct bet on game start if beginning of run mov eax, skill3d_hits or eax, skill3d_misses jnz @F mov eax, skill3d_bet cmp eax, bankroll jle skill_has_funds mov eax, bankroll mov skill3d_bet, eax test eax, eax jz skill_input_done skill_has_funds: mov eax, skill3d_bet sub bankroll, eax @@: mov skill3d_state, 1 mov skill3d_needle, 55 mov skill3d_dir, 1 invoke PlaySoundA, OFFSET soundClick, 0, 1 ret skill_handle_active: ; Move needle smoothly mov eax, skill3d_needle mov edx, skill3d_speed cmp skill3d_dir, 1 je skill_move_right sub eax, edx cmp eax, 52 jge skill_update_needle mov eax, 52 mov skill3d_dir, 1 jmp skill_update_needle skill_move_right: add eax, edx cmp eax, 268 jle skill_update_needle mov eax, 268 mov skill3d_dir, -1 skill_update_needle: mov skill3d_needle, eax ; Check SPACE pressed (Reaction Hit Attempt!) invoke Pressed3D, 20h test eax, eax jz skill_input_done ; Is needle in Great Sweet Spot? mov eax, skill3d_needle mov edx, skill3d_great_start cmp eax, edx jl check_success_zone add edx, skill3d_great_width cmp eax, edx jg check_success_zone ; GREAT HIT! mov skill3d_last_result, 2 add skill3d_hits, 2 mov skill3d_state, 2 mov skill3d_timer, 40 invoke PlaySoundA, OFFSET soundCoinDing, 0, 1 jmp skill_check_finish_round check_success_zone: mov eax, skill3d_needle mov edx, skill3d_zone_start cmp eax, edx jl skill_was_miss add edx, skill3d_zone_width cmp eax, edx jg skill_was_miss ; NORMAL HIT! mov skill3d_last_result, 1 inc skill3d_hits mov skill3d_state, 2 mov skill3d_timer, 40 invoke PlaySoundA, OFFSET soundVictory, 0, 1 jmp skill_check_finish_round skill_was_miss: ; MISS! mov skill3d_last_result, 0 inc skill3d_misses mov skill3d_state, 3 mov skill3d_timer, 45 invoke PlaySoundA, OFFSET soundLose, 0, 1 skill_check_finish_round: cmp skill3d_hits, 5 jge skill_game_escaped cmp skill3d_misses, 3 jge skill_game_lost ret skill_game_escaped: mov skill3d_state, 4 mov skill3d_timer, 0 ; Payout: 3x total return (+$2x bet profit) mov eax, skill3d_bet imul eax, 3 add bankroll, eax mov eax, skill3d_bet shl eax, 1 mov skill3d_win_amount, eax invoke PlaySoundA, OFFSET soundJackpot, 0, 1 ret skill_game_lost: mov skill3d_state, 5 mov skill3d_timer, 0 invoke PlaySoundA, OFFSET soundLose, 0, 1 ret skill_handle_round_wait: dec skill3d_timer cmp skill3d_timer, 0 jg skill_input_done ; Next round setup invoke RandomRange3D, 90 add eax, 80 mov skill3d_zone_start, eax invoke RandomRange3D, 12 add eax, skill3d_zone_start add eax, 20 mov skill3d_great_start, eax mov eax, skill3d_hits shr eax, 1 add eax, 4 mov skill3d_speed, eax mov skill3d_state, 1 ret skill_handle_end_wait: invoke Pressed3D, 20h test eax, eax jz skill_input_done call InitSkillGame ret skill_input_done: ret HandleSkillInput ENDP RenderSkillGame PROC uses ebx esi edi local kx:DWORD local tx:DWORD ; Industrial Steel bezel invoke DrawBox, 0, 0, 320, 240, 00121416h invoke DrawBoxBorder, 6, 6, 308, 228, 001A1D20h, 00FFD700h, 2 ; Header invoke DrawBoxBorder, 20, 12, 280, 26, 00121418h, 00FFD700h, 2 invoke DrawString8x8, 40, 21, OFFSET textSkillTitle, 00FFFF00h ; Status invoke DrawBoxBorder, 20, 44, 110, 18, 00121418h, 002A3540h, 1 invoke DrawString8x8, 24, 49, OFFSET textBankPrompt, 003CFF3Ch invoke FormatNumber, bankroll, OFFSET hudNumBuffer invoke DrawString8x8, 72, 49, OFFSET hudNumBuffer, 003CFF3Ch invoke DrawBoxBorder, 190, 44, 110, 18, 00121418h, 002A3540h, 1 invoke DrawString8x8, 194, 49, OFFSET textBetPrompt, 00FFD700h invoke FormatNumber, skill3d_bet, OFFSET hudNumBuffer invoke DrawString8x8, 254, 49, OFFSET hudNumBuffer, 00FFD700h ; Survivor Progress invoke DrawString8x8, 24, 70, OFFSET textSkillHitsHdr, 003CFF3Ch invoke FormatNumber, skill3d_hits, OFFSET hudNumBuffer invoke DrawString8x8, 64, 70, OFFSET hudNumBuffer, 003CFF3Ch invoke DrawString8x8, 180, 70, OFFSET textSkillMissHdr, 00FF6464h invoke FormatNumber, skill3d_misses, OFFSET hudNumBuffer invoke DrawString8x8, 240, 70, OFFSET hudNumBuffer, 00FF6464h ; Dial Frame (Track: X=50..270, Y=102..134) invoke DrawBoxBorder, 50, 102, 220, 32, 000F1114h, 00404855h, 2 ; Calibrated ticks mov tx, 60 skill_ticks_loop: cmp tx, 260 jge skill_draw_zones invoke DrawBox, tx, 104, 1, 6, 00303845h invoke DrawBox, tx, 126, 1, 6, 00303845h add tx, 12 jmp skill_ticks_loop skill_draw_zones: ; Normal Success Zone (Green) invoke DrawBoxBorder, skill3d_zone_start, 106, skill3d_zone_width, 24, 00155020h, 003CFF3Ch, 1 ; Great Zone (Gold) invoke DrawBoxBorder, skill3d_great_start, 106, skill3d_great_width, 24, 00FFD700h, 00FFFF00h, 1 ; Pointer / Needle at skill3d_needle mov eax, skill3d_needle dec eax invoke DrawBox, eax, 98, 3, 40, 00FFFFFFh mov eax, skill3d_needle sub eax, 2 invoke DrawBox, eax, 96, 5, 2, 00FF3030h invoke DrawBox, eax, 138, 5, 2, 00FF3030h ; Center prompts / outcome cmp skill3d_state, 0 jne @F invoke DrawString8x8, 52, 150, OFFSET textSkillReadyMsg, 00FFD700h invoke DrawString8x8, 76, 166, OFFSET textSkillPrompt, 00D0D8E0h jmp skill_render_keys @@: cmp skill3d_state, 1 jne @F invoke DrawString8x8, 76, 150, OFFSET textSkillPrompt, 00FFFF00h jmp skill_render_keys @@: cmp skill3d_state, 2 jne @F cmp skill3d_last_result, 2 jne skill_normal_hit_text invoke DrawString8x8, 36, 150, OFFSET textSkillGreatMsg, 00FFFF00h jmp skill_render_keys skill_normal_hit_text: invoke DrawString8x8, 64, 150, OFFSET textSkillHitMsg, 003CFF3Ch jmp skill_render_keys @@: cmp skill3d_state, 3 jne @F invoke DrawString8x8, 88, 150, OFFSET textSkillMissMsg, 00FF6464h jmp skill_render_keys @@: cmp skill3d_state, 4 jne @F invoke DrawString8x8, 48, 150, OFFSET textSkillEscape, 003CFF3Ch invoke FormatNumber, skill3d_win_amount, OFFSET hudNumBuffer invoke DrawString8x8, 240, 150, OFFSET hudNumBuffer, 003CFF3Ch invoke DrawString8x8, 64, 166, OFFSET textSkullsAgain, 00FFD700h jmp skill_render_keys @@: invoke DrawString8x8, 44, 150, OFFSET textSkillLost, 00FF6464h invoke DrawString8x8, 64, 166, OFFSET textSkullsAgain, 00FFD700h skill_render_keys: mov kx, 16 invoke DrawKeycap3D, kx, 192, OFFSET textSkillKeySpace, 1 add kx, eax invoke DrawKeycap3D, kx, 192, OFFSET textSkillKeyBet, 0 add kx, eax invoke DrawKeycap3D, kx, 192, OFFSET textKeyEsc, 0 ret RenderSkillGame ENDP """ raw_content = raw_content[:pos_games_start] + new_games_code.encode('cp1251') + raw_content[pos_player_input:] print("[OK] Replaced procedural drawing and games code") # 6. Update Trigger3DInteraction for INTERACT_SKILL_CHECK old_skill_trigger = b"""check_target_skill: cmp eax, INTERACT_SKILL_CHECK jne check_target_buckshot invoke LaunchClassicGame, OFFSET GameSkillCheck, 11, OFFSET szTitleSkillCheck ret""" new_skill_trigger = b"""check_target_skill: cmp eax, INTERACT_SKILL_CHECK jne check_target_buckshot call InitSkillGame mov engineMode, MODE_SKILL ret""" if old_skill_trigger in raw_content: raw_content = raw_content.replace(old_skill_trigger, new_skill_trigger) print("[OK] Updated Trigger3DInteraction for INTERACT_SKILL_CHECK") else: print("[WARN] old_skill_trigger pattern not found verbatim") # 7. Update leave_table: for MODE_SKILL old_leave = b""" cmp skulls3d_state, 1 je engine_tick cmp skulls3d_state, 2 je engine_tick mov engineMode, MODE_WALK""" new_leave = b""" cmp skulls3d_state, 1 je engine_tick cmp skulls3d_state, 2 je engine_tick cmp engineMode, MODE_SKILL jne @F cmp skill3d_state, 1 je engine_tick @@: mov engineMode, MODE_WALK""" if old_leave in raw_content: raw_content = raw_content.replace(old_leave, new_leave) print("[OK] Updated leave_table: for MODE_SKILL") else: print("[WARN] old_leave pattern not found verbatim") # 8. Update engine_loop dispatch for MODE_SKILL old_dispatch = b"""check_skulls_mode: cmp engineMode, MODE_SKULLS jne present_frame call HandleSkullsInput call RenderSkullsGame jmp present_frame""" new_dispatch = b"""check_skulls_mode: cmp engineMode, MODE_SKULLS jne check_skill_mode call HandleSkullsInput call RenderSkullsGame jmp present_frame check_skill_mode: cmp engineMode, MODE_SKILL jne present_frame call HandleSkillInput call RenderSkillGame jmp present_frame""" if old_dispatch in raw_content: raw_content = raw_content.replace(old_dispatch, new_dispatch) print("[OK] Updated engine_loop dispatch for MODE_SKILL") else: print("[WARN] old_dispatch pattern not found verbatim") # 9. Global replacement of reversed cyan color constants to proper 00RRGGBBh color_replacements = [ (b'0000FFFFh', b'00FFFF00h'), # Cyan -> Pure Yellow (b'0000D7FFh', b'00FFD700h'), # Sky Blue -> Pure Gold (b'0000A0D0h', b'00D0A000h'), # Amber Gold (b'0000E0FFh', b'00FFE000h'), # Bright Amber (b'00007A9Ah', b'009A7A00h'), # Bronze / Dark Gold (b'000080A0h', b'00A08000h'), (b'0000B0D0h', b'00D0B000h'), (b'0000B0E0h', b'00E0B000h'), (b'000000FFh', b'00FF2020h'), # Pure Blue -> Bright Ruby Red (b'008080FFh', b'00FF6464h'), # Light Periwinkle -> Soft Coral Red (b'001515B8h', b'00B81515h'), # Blue chip -> Red Clay Casino Chip (b'001515C8h', b'00C81515h'), # Blue pips -> Ruby Red Dice Pips ] for old_c, new_c in color_replacements: count = raw_content.count(old_c) if count > 0: raw_content = raw_content.replace(old_c, new_c) print(f"[OK] Replaced {old_c.decode('ascii')} -> {new_c.decode('ascii')} ({count} occurrences)") # Write back to casino3d.inc with open(CASINO_INC, 'wb') as f: f.write(raw_content) print(f"[SUCCESS] casino3d.inc successfully patched! ({len(raw_content)} bytes)")