FreeNativeClover3D PROC invoke FreeAnimPack3D,OFFSET clpCabinet3D invoke FreeAnimPack3D,OFFSET clpSymbols3D ret FreeNativeClover3D ENDP InitNativeClover3D PROC invoke LoadAnimPack3D,OFFSET clpCabinet3D,OFFSET clpCabinetPath3D test eax,eax jz clp_init_fail cmp clpCabinet3D.imageWidth,640 jne clp_init_fail cmp clpCabinet3D.height,480 jne clp_init_fail cmp clpCabinet3D.frames,1 jne clp_init_fail invoke LoadAnimPack3D,OFFSET clpSymbols3D,OFFSET clpSymbolsPath3D test eax,eax jz clp_init_fail cmp clpSymbols3D.imageWidth,CLP_CELL jne clp_init_fail cmp clpSymbols3D.height,CLP_CELL jne clp_init_fail cmp clpSymbols3D.frames,7 jne clp_init_fail mov clpState3D,SLOT_READY mov clpTimer3D,0 mov clpStake3D,0 mov clpGross3D,0 mov clpTotal3D,0 mov clpCount3D,0 mov clpWinMask3D,0 mov clpSelected3D,0 mov clpPaytable3D,0 mov clpLeave3D,0 mov clpError3D,0 mov clpBet3D,50 mov clpBetIndex3D,1 mov paused3D,0 mov cardExitActive3D,0 call ClearKeys3D mov eax,1 ret clp_init_fail: call FreeNativeClover3D xor eax,eax ret InitNativeClover3D ENDP ; Tape contents and final board are frozen at the single stake debit. StartNativeClover3D PROC uses ebx esi edi cmp clpState3D,SLOT_SPIN je clp_start_done cmp clpPaytable3D,0 jne clp_start_done cmp clpCabinet3D.pixels,0 je clp_start_done cmp clpSymbols3D.pixels,0 je clp_start_done mov eax,clpBet3D test eax,eax jz clp_start_done cmp eax,10000 ja clp_start_done cmp eax,bankroll ja clp_start_money sub bankroll,eax mov clpStake3D,eax mov clpState3D,SLOT_SPIN mov clpTimer3D,0 mov clpGross3D,0 mov clpCount3D,0 mov clpTotal3D,0 mov clpWinMask3D,0 mov clpSelected3D,0 mov clpLeave3D,0 mov clpError3D,0 xor esi,esi clp_start_column: mov ebx,esi shl ebx,8 xor edi,edi clp_start_tape: invoke RandomRange3D,7 mov clpTape3D[ebx+edi*4],eax inc edi cmp edi,64 jb clp_start_tape xor edi,edi clp_start_rows: mov ecx,edi imul ecx,5 add ecx,esi mov eax,clpGrid3D[ecx*4] mov clpTape3D[ebx+edi*4],eax invoke RandomRange3D,7 mov clpGrid3D[ecx*4],eax mov edx,clpSteps3D[esi*4] add edx,edi mov clpTape3D[ebx+edx*4],eax inc edi cmp edi,3 jb clp_start_rows inc esi cmp esi,5 jb clp_start_column call SaveProgress3D invoke PlayCasinoSound3D,OFFSET soundSlotSpin,0,1 clp_start_done: ret clp_start_money: mov clpError3D,1 ret StartNativeClover3D ENDP ; Reuse the original pure assembly evaluator, never the console game or payer. CloverEvaluate3D PROC uses ebx esi edi mov clpTotal3D,0 mov clpCount3D,0 mov clpWinMask3D,0 mov clpJackpot3D,0 xor esi,esi clp_eval_validate: cmp clpGrid3D[esi*4],6 ja clp_eval_done inc esi cmp esi,15 jb clp_eval_validate lea esi,clpGrid3D lea edi,slotGrid mov ecx,15 rep movsd call EvaluateSlotCombos mov eax,slotBestMultiplier mov clpTotal3D,eax mov eax,slotWinMask mov clpWinMask3D,eax mov eax,slotJackpotHit mov clpJackpot3D,eax mov eax,slotComboCount mov clpCount3D,eax lea esi,slotComboNames lea edi,clpNames3D mov ecx,eax rep movsd lea esi,slotComboMults lea edi,clpMults3D mov ecx,clpCount3D rep movsd lea esi,slotComboMasks lea edi,clpMasks3D mov ecx,clpCount3D rep movsd clp_eval_done: xor eax,eax ret CloverEvaluate3D ENDP SettleNativeClover3D PROC cmp clpState3D,SLOT_SPIN jne clp_settle_done call CloverEvaluate3D mov eax,clpTotal3D mul clpStake3D mov ecx,1000000000 sub ecx,bankroll cmp eax,ecx jbe @F mov eax,ecx @@: mov clpGross3D,eax add bankroll,eax mov clpState3D,SLOT_RESULT mov clpTimer3D,3400 xor eax,eax mov ecx,clpGross3D cmp ecx,clpStake3D seta al invoke NpcRecordRound3D,4,eax call SaveProgress3D mov eax,clpGross3D cmp eax,clpStake3D jb clp_settle_loss jne @F invoke PlayCasinoSound3D,0,0,0 jmp clp_settle_leave @@: invoke PlayCasinoSound3D,OFFSET soundRoundWin,0,1 invoke TriggerCharmWinBonus, clpGross3D jmp clp_settle_leave clp_settle_loss: invoke TriggerCharmLossProtection, clpStake3D test eax, eax jnz clp_settle_leave invoke PlayCasinoSound3D,OFFSET soundRoundLose,0,1 clp_settle_leave: cmp clpLeave3D,0 je clp_settle_done call CloverEscape3D clp_settle_done: ret SettleNativeClover3D ENDP CloverEscape3D PROC mov paused3D,0 cmp clpPaytable3D,0 je @F mov clpPaytable3D,0 call ClearKeys3D ret @@: cmp clpState3D,SLOT_SPIN jne clp_escape_hall mov clpLeave3D,1 call ClearKeys3D ret clp_escape_hall: mov clpLeave3D,0 mov engineMode,MODE_WALK call ClearKeys3D invoke PlayCasinoSound3D,0,0,0 ret CloverEscape3D ENDP CloverReelPosition3D PROC uses ebx index:DWORD mov ebx,index xor eax,eax cmp ebx,4 ja clp_pos_done cmp clpState3D,SLOT_SPIN jne clp_pos_end mov eax,clpTimer3D cmp eax,clpDurations3D[ebx*4] jae clp_pos_end shl eax,10 xor edx,edx div clpDurations3D[ebx*4] mov ecx,2048 sub ecx,eax imul eax,ecx mov ecx,clpSteps3D[ebx*4] imul ecx,CLP_CELL mul ecx shrd eax,edx,20 ret clp_pos_end: mov eax,clpSteps3D[ebx*4] imul eax,CLP_CELL clp_pos_done: ret CloverReelPosition3D ENDP HandleNativeClover3D PROC uses ebx cmp mouseClick3D,0 je clp_handle_tick mov mouseClick3D,0 mov eax,mouseY3D cmp eax,3 jb clp_handle_tick cmp eax,17 jae clp_handle_mouse_controls cmp mouseX3D,252 jb clp_handle_tick cmp mouseX3D,312 jae clp_handle_tick call CloverEscape3D cmp clpState3D,SLOT_SPIN je clp_handle_tick ret clp_handle_mouse_controls: cmp clpState3D,SLOT_SPIN je clp_handle_tick cmp clpPaytable3D,0 je @F cmp eax,202 jb clp_handle_tick cmp eax,220 jae clp_handle_tick cmp mouseX3D,112 jb clp_handle_tick cmp mouseX3D,208 jae clp_handle_tick mov clpPaytable3D,0 ret @@: cmp eax,170 jb clp_handle_tick cmp eax,185 jae clp_handle_mouse_footer cmp mouseX3D,232 jb clp_handle_tick cmp mouseX3D,250 jb clp_handle_previous cmp mouseX3D,292 jb clp_handle_tick cmp mouseX3D,310 jb clp_handle_next jmp clp_handle_tick clp_handle_mouse_footer: cmp eax,222 jb clp_handle_tick cmp eax,238 jae clp_handle_tick mov eax,mouseX3D cmp eax,11 jb clp_handle_tick cmp eax,29 jb clp_handle_down cmp eax,35 jb clp_handle_tick cmp eax,53 jb clp_handle_up cmp eax,120 jb clp_handle_tick cmp eax,190 jb clp_handle_start cmp eax,202 jb clp_handle_tick cmp eax,272 jb clp_handle_paytable clp_handle_tick: cmp clpState3D,SLOT_SPIN jne clp_handle_keys mov eax,deltaTime3D cmp eax,250 jbe @F mov eax,250 @@: add clpTimer3D,eax cmp clpTimer3D,3400 jb clp_handle_done call SettleNativeClover3D ret clp_handle_keys: invoke Pressed3D,50h test eax,eax jnz clp_handle_paytable cmp clpPaytable3D,0 je clp_handle_game_keys invoke Pressed3D,20h test eax,eax jnz clp_handle_paytable invoke Pressed3D,0Dh test eax,eax jnz clp_handle_paytable ret clp_handle_game_keys: invoke Pressed3D,25h test eax,eax jnz clp_handle_previous invoke Pressed3D,27h test eax,eax jnz clp_handle_next invoke Pressed3D,57h test eax,eax jnz clp_handle_up invoke Pressed3D,26h test eax,eax jnz clp_handle_up invoke Pressed3D,53h test eax,eax jnz clp_handle_down invoke Pressed3D,28h test eax,eax jnz clp_handle_down invoke Pressed3D,20h test eax,eax jnz clp_handle_start invoke Pressed3D,0Dh test eax,eax jz clp_handle_done clp_handle_start: call StartNativeClover3D ret clp_handle_paytable: xor clpPaytable3D,1 ret clp_handle_previous: cmp clpCount3D,0 je clp_handle_done cmp clpSelected3D,0 jne @F mov eax,clpCount3D mov clpSelected3D,eax @@: dec clpSelected3D ret clp_handle_next: cmp clpCount3D,0 je clp_handle_done inc clpSelected3D mov eax,clpSelected3D cmp eax,clpCount3D jb clp_handle_done mov clpSelected3D,0 ret clp_handle_up: cmp clpBetIndex3D,6 jae clp_handle_done inc clpBetIndex3D jmp clp_handle_bet clp_handle_down: cmp clpBetIndex3D,0 je clp_handle_done dec clpBetIndex3D clp_handle_bet: mov ecx,clpBetIndex3D mov eax,slotBetValues3D[ecx*4] mov clpBet3D,eax mov clpError3D,0 clp_handle_done: ret HandleNativeClover3D ENDP DrawCloverSymbol3D PROC uses ebx esi edi symbol:DWORD,x:DWORD,y:DWORD local row:DWORD,lastRow:DWORD,source:DWORD cmp symbol,6 ja clp_symbol_done mov eax,clpSymbols3D.pixels test eax,eax jz clp_symbol_done mov ecx,symbol imul ecx,CLP_CELL*CLP_CELL*4 add eax,ecx mov source,eax mov eax,y cmp eax,CLP_TOP jge @F mov eax,CLP_TOP @@: mov row,eax mov eax,y add eax,CLP_CELL cmp eax,CLP_BOTTOM jle @F mov eax,CLP_BOTTOM @@: mov lastRow,eax clp_symbol_row: mov eax,row cmp eax,lastRow jge clp_symbol_done mov ecx,eax sub ecx,y imul ecx,CLP_CELL*4 mov esi,source add esi,ecx imul eax,640*4 mov ecx,x lea edi,screenBuffer[eax+ecx*4] mov ecx,CLP_CELL clp_symbol_column: lodsd test eax,0FF000000h jz @F and eax,00FFFFFFh mov [edi],eax @@: add edi,4 dec ecx jnz clp_symbol_column inc row jmp clp_symbol_row clp_symbol_done: ret DrawCloverSymbol3D ENDP DrawCloverReel3D PROC uses ebx esi edi index:DWORD local symbolY:DWORD,baseStop:DWORD,columnX:DWORD mov ebx,index mov eax,clpColumns3D[ebx*4] mov columnX,eax cmp clpState3D,SLOT_SPIN jne clp_reel_static invoke CloverReelPosition3D,ebx xor edx,edx mov ecx,CLP_CELL div ecx mov baseStop,eax mov eax,CLP_TOP sub eax,edx mov symbolY,eax shl ebx,8 xor esi,esi clp_reel_tape: mov ecx,baseStop add ecx,esi mov eax,clpTape3D[ebx+ecx*4] invoke DrawCloverSymbol3D,eax,columnX,symbolY add symbolY,CLP_CELL inc esi cmp esi,4 jb clp_reel_tape ret clp_reel_static: mov symbolY,CLP_TOP xor esi,esi clp_reel_rows: mov ecx,esi imul ecx,5 add ecx,ebx mov eax,clpGrid3D[ecx*4] invoke DrawCloverSymbol3D,eax,columnX,symbolY add symbolY,CLP_CELL inc esi cmp esi,3 jb clp_reel_rows ret DrawCloverReel3D ENDP CloverComboText3D PROC index:DWORD mov ecx,index cmp ecx,clpCount3D jae clp_combo_none mov edx,clpNames3D[ecx*4] xor ecx,ecx clp_combo_lookup: cmp edx,clpLegacyNames3D[ecx*4] je clp_combo_found inc ecx cmp ecx,11 jb clp_combo_lookup clp_combo_none: mov eax,OFFSET clpNoCombo3D ret clp_combo_found: mov eax,clpShapeNames3D[ecx*4] ret CloverComboText3D ENDP RenderNativeClover3D PROC uses ebx esi edi local cellX:DWORD,cellY:DWORD,selectedMask:DWORD mov esi,clpCabinet3D.pixels test esi,esi jz clp_render_done lea edi,screenBuffer mov ecx,SCREEN_SIZE rep movsd xor esi,esi clp_render_reels: mov ebx,clpColumns3D[esi*4] shr ebx,1 invoke DrawBoxBorder,ebx,63,28,84,000D1816h,00405A46h,1 invoke DrawCloverReel3D,esi inc esi cmp esi,5 jb clp_render_reels cmp clpState3D,SLOT_RESULT jne clp_render_header mov ecx,clpSelected3D cmp ecx,clpCount3D jae clp_render_header mov eax,clpMasks3D[ecx*4] mov selectedMask,eax xor esi,esi clp_render_highlight: mov eax,1 mov ecx,esi shl eax,cl test selectedMask,eax jz clp_render_next_cell mov eax,esi xor edx,edx mov ecx,5 div ecx imul eax,28 add eax,63 mov cellY,eax mov ebx,clpColumns3D[edx*4] shr ebx,1 mov cellX,ebx ; Border strips do not paint over the transparent symbol interior. invoke DrawBox,ebx,cellY,28,1,00E9CE71h mov eax,cellY add eax,27 invoke DrawBox,ebx,eax,28,1,00E9CE71h invoke DrawBox,ebx,cellY,1,28,00E9CE71h add ebx,27 invoke DrawBox,ebx,cellY,1,28,00E9CE71h clp_render_next_cell: inc esi cmp esi,15 jb clp_render_highlight clp_render_header: invoke DrawBox,0,0,320,19,00151D20h invoke DrawString8x8,8,6,OFFSET clpTitle3D,00E8D7ADh invoke DrawString8x8,108,6,OFFSET textBank3D,00A8DDB9h invoke FormatNumber,bankroll,OFFSET hudNumBuffer invoke DrawString8x8,157,6,OFFSET hudNumBuffer,00F4F3E8h invoke DrawBoxBorder,252,3,60,14,002C3637h,00687672h,1 invoke DrawString8x8,258,6,OFFSET cardExitButton3D,00E9D8B0h invoke DrawBox,63,160,194,26,00151D20h mov ebx,OFFSET slotReadyText3D cmp clpState3D,SLOT_SPIN jne @F mov ebx,OFFSET slotRollingText3D @@: cmp clpState3D,SLOT_RESULT jne @F mov ebx,OFFSET clpNoCombo3D cmp clpCount3D,0 je @F mov ebx,OFFSET clpTotalText3D @@: cmp clpError3D,0 je @F mov ebx,OFFSET slotNoMoney3D @@: cmp clpLeave3D,0 je @F mov ebx,OFFSET slotExitText3D @@: invoke DrawString8x8,72,163,ebx,00E8D7ADh cmp clpState3D,SLOT_RESULT jne clp_render_footer cmp clpCount3D,0 je clp_render_footer invoke DrawString8x8,208,163,OFFSET strMultiplier3D,00A8DDB9h invoke FormatNumber,clpTotal3D,OFFSET hudNumBuffer invoke DrawString8x8,216,163,OFFSET hudNumBuffer,00A8DDB9h invoke CloverComboText3D,clpSelected3D invoke DrawString8x8,72,175,eax,00F4F3E8h mov ecx,clpSelected3D invoke FormatNumber,clpMults3D[ecx*4],OFFSET hudNumBuffer invoke DrawString8x8,208,175,OFFSET strMultiplier3D,00E9CE71h invoke DrawString8x8,216,175,OFFSET hudNumBuffer,00E9CE71h invoke DrawBoxBorder,232,170,18,15,0025372Ch,00E9CE71h,1 invoke DrawBoxBorder,292,170,18,15,0025372Ch,00E9CE71h,1 invoke DrawString8x8,237,174,OFFSET clpLeft3D,00E9CE71h invoke DrawString8x8,297,174,OFFSET clpRight3D,00E9CE71h mov eax,clpSelected3D inc eax invoke FormatNumber,eax,OFFSET hudNumBuffer invoke DrawString8x8,252,174,OFFSET hudNumBuffer,00F4F3E8h invoke DrawString8x8,268,174,OFFSET clpSlash3D,00F4F3E8h invoke FormatNumber,clpCount3D,OFFSET hudNumBuffer invoke DrawString8x8,276,174,OFFSET hudNumBuffer,00F4F3E8h clp_render_footer: invoke DrawBox,0,198,320,42,00151D20h invoke DrawString8x8,11,201,OFFSET slotBetText3D,00E8D7ADh invoke FormatNumber,clpBet3D,OFFSET hudNumBuffer invoke DrawString8x8,75,201,OFFSET hudNumBuffer,00F4F3E8h cmp clpState3D,SLOT_RESULT jne @F invoke DrawSlotTotals3D,clpGross3D,clpStake3D,120 @@: mov ebx,1 cmp clpState3D,SLOT_SPIN jne @F xor ebx,ebx @@: invoke DrawBoxBorder,11,222,18,16,0025372Ch,00EEE5CDh,1 invoke DrawBoxBorder,35,222,18,16,0025372Ch,00EEE5CDh,1 invoke DrawString8x8,16,226,OFFSET tableMinusText3D,00EEE5CDh invoke DrawString8x8,40,226,OFFSET tablePlusText3D,00EEE5CDh invoke DrawTableButton3D,120,OFFSET slotSpinText3D,ebx invoke DrawTableButton3D,202,OFFSET slotPayText3D,ebx cmp clpPaytable3D,0 je clp_render_done invoke DrawBoxBorder,18,22,284,200,00151D20h,00D1B16Eh,1 invoke DrawString8x8,76,29,OFFSET slotPayTitle3D,00E8D7ADh invoke DrawString8x8,28,44,OFFSET clpSymbolsText3D,00A8DDB9h invoke DrawString8x8,164,44,OFFSET clpShapesText3D,00A8DDB9h xor esi,esi clp_render_pay_row: mov edi,esi imul edi,11 add edi,58 mov eax,clpShapeNames3D[esi*4] invoke DrawString8x8,156,edi,eax,00F4F3E8h invoke FormatNumber,clpShapeFactors3D[esi*4],OFFSET hudNumBuffer invoke DrawString8x8,280,edi,OFFSET hudNumBuffer,00E8D7ADh cmp esi,7 jae clp_render_pay_next mov eax,clpSymbolNames3D[esi*4] invoke DrawString8x8,28,edi,eax,00F4F3E8h invoke FormatNumber,slotSymbolValues[esi*4],OFFSET hudNumBuffer invoke DrawString8x8,132,edi,OFFSET hudNumBuffer,00E8D7ADh clp_render_pay_next: inc esi cmp esi,11 jb clp_render_pay_row invoke DrawString8x8,28,181,OFFSET clpOverlapText3D,00A8DDB9h invoke DrawString8x8,28,193,OFFSET slotPayNote3D,00A8DDB9h invoke DrawBoxBorder,112,204,96,15,003B6C59h,00E9D8B0h,1 invoke DrawString8x8,128,207,OFFSET slotCloseText3D,00E9D8B0h clp_render_done: ret RenderNativeClover3D ENDP