; Presentation state has its own clock and RNG; it never changes ticket odds. ScratchEase3D PROC elapsed:DWORD,duration:DWORD mov eax,elapsed cmp eax,duration jb @F mov eax,256 ret @@: shl eax,8 xor edx,edx div duration mov ecx,eax imul eax,eax shl ecx,1 neg ecx add ecx,768 imul eax,ecx shr eax,16 ret ScratchEase3D ENDP ScratchStartDeal3D PROC mov scrDealMs3D,900 mov scrPayoutMs3D,0 invoke PlayCasinoSound3D,OFFSET scrPaperSound3D,0,1 ret ScratchStartDeal3D ENDP ScratchStartPayout3D PROC mov scrDealMs3D,0 mov scrPayoutMs3D,0 cmp engineMode,MODE_SCRATCH jne @F cmp scrGross3D,0 je @F mov scrPayoutMs3D,1800 invoke PlayCasinoSound3D,OFFSET scrPayoutSound3D,0,1 @@: ret ScratchStartPayout3D ENDP ScratchTickVisuals3D PROC uses ebx esi mov eax,deltaTime3D cmp eax,250 jbe @F mov eax,250 @@: sub scrDealMs3D,eax jns @F mov scrDealMs3D,0 @@: sub scrPayoutMs3D,eax jns @F mov scrPayoutMs3D,0 @@: sub scrScrapeCooldown3D,eax jns @F mov scrScrapeCooldown3D,0 @@: cmp eax,100 jbe @F mov eax,100 @@: add scrDustStep3D,eax scratch_visual_step: cmp scrDustStep3D,8 jb scratch_visual_done sub scrDustStep3D,8 xor esi,esi scratch_visual_particle: cmp scrDustLife3D[esi*4],0 je scratch_visual_next sub scrDustLife3D[esi*4],8 jns @F mov scrDustLife3D[esi*4],0 @@: mov eax,scrDustY3D[esi*4] cmp eax,scrDustFloor3D[esi*4] jge scratch_visual_next mov eax,scrDustVX3D[esi*4] add scrDustX3D[esi*4],eax add scrDustVY3D[esi*4],6 mov eax,scrDustVY3D[esi*4] add scrDustY3D[esi*4],eax mov eax,scrDustFloor3D[esi*4] cmp scrDustY3D[esi*4],eax jl scratch_visual_next mov scrDustY3D[esi*4],eax scratch_visual_next: inc esi cmp esi,SCR_DUST_COUNT jb scratch_visual_particle jmp scratch_visual_step scratch_visual_done: ret ScratchTickVisuals3D ENDP ScratchSpawnDust3D PROC uses ebx esi edi cmp scrState3D,1 jne scratch_spawn_begin cmp scrScrapeCooldown3D,0 jne @F invoke PlayCasinoSound3D,OFFSET scrScrapeSound3D,0,1 mov scrScrapeCooldown3D,150 @@: scratch_spawn_begin: mov edi,3 scratch_spawn_fragment: mov esi,scrDustIndex3D mov eax,scrVisualSeed3D imul eax,1664525 add eax,1013904223 mov scrVisualSeed3D,eax mov ebx,eax and eax,511 add eax,1200 mov scrDustLife3D[esi*4],eax mov eax,scrPointerX3D shl eax,8 mov scrDustX3D[esi*4],eax mov eax,scrPointerY3D shl eax,8 mov scrDustY3D[esi*4],eax mov eax,ebx shr eax,12 and eax,255 sub eax,128 mov scrDustVX3D[esi*4],eax mov eax,ebx shr eax,20 and eax,127 add eax,64 neg eax mov scrDustVY3D[esi*4],eax mov eax,ebx shr eax,8 and eax,31 add eax,scrPointerY3D add eax,20 cmp eax,385 jbe @F mov eax,385 @@: shl eax,8 mov scrDustFloor3D[esi*4],eax inc esi and esi,SCR_DUST_COUNT-1 mov scrDustIndex3D,esi dec edi jnz scratch_spawn_fragment ret ScratchSpawnDust3D ENDP ScratchDrawDust3D PROC uses ebx esi edi xor esi,esi scratch_draw_fragment: cmp scrDustLife3D[esi*4],0 je scratch_draw_fragment_next mov eax,scrDustX3D[esi*4] sar eax,8 cmp eax,638 jae scratch_draw_fragment_next mov edx,scrDustY3D[esi*4] sar edx,8 cmp edx,40 jb scratch_draw_fragment_next cmp edx,386 jae scratch_draw_fragment_next imul edx,640 add edx,eax mov ebx,esi and ebx,3 mov eax,scrDustInk3D[ebx*4] mov screenBuffer[edx*4],eax mov screenBuffer[edx*4+4],eax test esi,1 jz scratch_draw_fragment_next mov screenBuffer[edx*4+640*4],00868D89h scratch_draw_fragment_next: inc esi cmp esi,SCR_DUST_COUNT jb scratch_draw_fragment ret ScratchDrawDust3D ENDP ScratchSaveBackdrop3D PROC uses esi edi cmp scrDealMs3D,350 jbe @F lea esi,screenBuffer[640*40*4] lea edi,scrBackdrop3D[640*40*4] mov ecx,640*348 rep movsd @@: ret ScratchSaveBackdrop3D ENDP ScratchDrawDelivery3D PROC uses ebx esi edi local left:DWORD,top:DWORD,right:DWORD,bottom:DWORD,rowY:DWORD,pointX:DWORD local offsetX:DWORD,offsetY:DWORD,sourceBase:DWORD cmp scrDealMs3D,350 jbe scratch_delivery_done mov eax,900 sub eax,scrDealMs3D invoke ScratchEase3D,eax,550 neg eax add eax,256 imul edx,eax,360 sar edx,8 mov offsetY,edx imul eax,-56 sar eax,8 mov offsetX,eax lea edi,scrPaperLayer3D xor eax,eax mov ecx,640*480 rep stosd mov left,96 mov top,92 mov right,544 mov bottom,380 cmp scrType3D,4 jae scratch_delivery_portrait mov eax,scrType3D imul eax,448*288*4 add eax,scrTicketArt3D.pixels mov sourceBase,eax jmp scratch_delivery_bounds scratch_delivery_portrait: mov eax,scrViewX3D mov left,eax add eax,scrViewW3D mov right,eax mov eax,scrViewY3D mov top,eax add eax,scrViewH3D mov bottom,eax scratch_delivery_bounds: cmp top,40 jge @F mov top,40 @@: cmp bottom,388 jle @F mov bottom,388 @@: mov eax,top mov rowY,eax scratch_delivery_row: mov eax,left mov pointX,eax scratch_delivery_pixel: cmp scrType3D,4 jae scratch_delivery_copy mov eax,rowY sub eax,92 imul eax,448 add eax,pointX sub eax,96 mov edi,sourceBase cmp BYTE PTR [edi+eax*4+3],0 je scratch_delivery_next scratch_delivery_copy: imul ebx,rowY,640 add ebx,pointX mov eax,screenBuffer[ebx*4] or eax,0FF000000h mov scrPaperLayer3D[ebx*4],eax scratch_delivery_next: inc pointX mov eax,pointX cmp eax,right jb scratch_delivery_pixel inc rowY mov eax,rowY cmp eax,bottom jb scratch_delivery_row lea esi,scrBackdrop3D[640*40*4] lea edi,screenBuffer[640*40*4] mov ecx,640*348 rep movsd ; A clipped, paper-shaped contact shadow, never a rectangular overlay. mov eax,top mov rowY,eax scratch_delivery_shadow_row: mov eax,left mov pointX,eax scratch_delivery_shadow_pixel: imul ebx,rowY,640 add ebx,pointX cmp BYTE PTR scrPaperLayer3D[ebx*4+3],0 je scratch_delivery_shadow_next mov eax,pointX add eax,offsetX add eax,4 cmp eax,640 jae scratch_delivery_shadow_next mov edx,rowY add edx,offsetY add edx,6 cmp edx,40 jb scratch_delivery_shadow_next cmp edx,388 jae scratch_delivery_shadow_next imul edx,640 add edx,eax mov eax,screenBuffer[edx*4] mov ecx,eax and ecx,00FCFCFCh shr ecx,2 sub eax,ecx mov screenBuffer[edx*4],eax scratch_delivery_shadow_next: inc pointX mov eax,pointX cmp eax,right jb scratch_delivery_shadow_pixel inc rowY mov eax,rowY cmp eax,bottom jb scratch_delivery_shadow_row invoke DrawAnimSprite3D,OFFSET scrPaperLayerPack3D,0,offsetX,offsetY,640,480 scratch_delivery_done: ret ScratchDrawDelivery3D ENDP ScratchDrawPayout3D PROC uses ebx esi edi local elapsed:DWORD,progress:DWORD,coinX:DWORD,coinY:DWORD cmp scrState3D,2 jne scratch_payout_done cmp scrGross3D,0 je scratch_payout_done mov eax,1800 sub eax,scrPayoutMs3D mov elapsed,eax invoke ScratchEase3D,eax,400 imul eax,96 sar eax,8 sub eax,88 invoke DrawAnimSprite3D,OFFSET scrPayoutArt3D,0,eax,300,88,66 xor esi,esi scratch_payout_coin: imul eax,esi,110 add eax,350 mov edx,elapsed sub edx,eax js scratch_payout_coin_next cmp edx,850 jae scratch_payout_coin_next invoke ScratchEase3D,edx,850 mov progress,eax imul ebx,eax,60 sar ebx,8 add ebx,40 mov edx,256 sub edx,eax imul edx,eax imul edx,80 sar edx,16 add ebx,edx mov coinX,ebx imul eax,260 sar eax,8 neg eax add eax,330 mov coinY,eax mov eax,elapsed shr eax,6 add eax,esi and eax,3 invoke DrawAnimSprite3D,OFFSET scrCoinArt3D,eax,coinX,coinY,20,20 scratch_payout_coin_next: inc esi cmp esi,5 jb scratch_payout_coin scratch_payout_done: ret ScratchDrawPayout3D ENDP