; Scratch-off state, coating masks, pointer capture and rendering are all MASM. LoadScratchArt3D PROC cmp scrReady3D,1 je scratch_art_ok invoke LoadAnimPack3D,OFFSET scrTicketArt3D,OFFSET scrTicketPath3D invoke LoadAnimPack3D,OFFSET scrTableArt3D,OFFSET scrTablePath3D invoke LoadAnimPack3D,OFFSET scrCoinArt3D,OFFSET scrCoinPath3D invoke LoadAnimPack3D,OFFSET scrFoilArt3D,OFFSET scrFoilPath3D invoke LoadAnimPack3D,OFFSET scrSymbolsArt3D,OFFSET clpSymbolsPath3D invoke LoadAnimPack3D,OFFSET scrCounterArt3D,OFFSET scrCounterPath3D invoke LoadAnimPack3D,OFFSET scrPortraitArt3D,OFFSET scrPortraitPath3D invoke LoadAnimPack3D,OFFSET scrPortraitMap3D,OFFSET scrPortraitMapPath3D invoke LoadAnimPack3D,OFFSET scrPayoutArt3D,OFFSET scrPayoutPath3D invoke ValidateCityPack3D,OFFSET scrPayoutArt3D,96,72,1 invoke ValidateCityPack3D,OFFSET scrTicketArt3D,448,288,4 invoke ValidateCityPack3D,OFFSET scrTableArt3D,640,480,1 invoke ValidateCityPack3D,OFFSET scrCoinArt3D,64,64,4 invoke ValidateCityPack3D,OFFSET scrFoilArt3D,SCR_W,SCR_H,1 invoke ValidateCityPack3D,OFFSET scrSymbolsArt3D,56,56,7 invoke ValidateCityPack3D,OFFSET scrCounterArt3D,224,240,1 invoke ValidateCityPack3D,OFFSET scrPortraitArt3D,540,720,3 invoke ValidateCityPack3D,OFFSET scrPortraitMap3D,540,720,3 cmp scrPortraitArt3D.pixels,0 je scratch_art_fail cmp scrPortraitMap3D.pixels,0 je scratch_art_fail cmp scrTicketArt3D.pixels,0 je scratch_art_fail cmp scrCoinArt3D.pixels,0 je scratch_art_fail cmp scrSymbolsArt3D.pixels,0 je scratch_art_fail cmp scrFoilArt3D.pixels,0 je scratch_art_fail mov scrReady3D,1 scratch_art_ok: mov eax,1 ret scratch_art_fail: call FreeScratchArt3D xor eax,eax ret LoadScratchArt3D ENDP FreeScratchArt3D PROC invoke FreeAnimPack3D,OFFSET scrTicketArt3D invoke FreeAnimPack3D,OFFSET scrTableArt3D invoke FreeAnimPack3D,OFFSET scrCoinArt3D invoke FreeAnimPack3D,OFFSET scrFoilArt3D invoke FreeAnimPack3D,OFFSET scrSymbolsArt3D invoke FreeAnimPack3D,OFFSET scrCounterArt3D invoke FreeAnimPack3D,OFFSET scrPortraitArt3D invoke FreeAnimPack3D,OFFSET scrPortraitMap3D invoke FreeAnimPack3D,OFFSET scrPayoutArt3D mov scrReady3D,0 ret FreeScratchArt3D ENDP ScratchCancelStroke3D PROC mov scrLastValid3D,0 cmp scrHeld3D,0 je scratch_cancel_done mov scrHeld3D,0 invoke ReleaseCapture scratch_cancel_done: ret ScratchCancelStroke3D ENDP BeginScratch3D PROC mov scrCatalog3D,0 call LoadScratchArt3D cmp scrState3D,0 jne @F call ScratchConfigure3D @@: mov engineMode,MODE_SCRATCH mov paused3D,0 mov scrError3D,0 mov scrNewPixels3D,0 mov scrPointerValid3D,0 call ClearKeys3D ret BeginScratch3D ENDP LeaveScratch3D PROC cmp scrCatalog3D,0 je @F mov scrCatalog3D,0 call ClearKeys3D ret @@: call ScratchCancelStroke3D mov scrDealMs3D,0 mov scrPayoutMs3D,0 mov engineMode,MODE_WALK mov paused3D,0 call ClearKeys3D call SaveProgress3D ret LeaveScratch3D ENDP ; One mask format serves rectangular, circular and single-area tickets. ScratchConfigure3D PROC uses ebx esi edi local rowY:DWORD,pointX:DWORD mov scrDealMs3D,0 mov scrPayoutMs3D,0 mov scrDustStep3D,0 mov scrScrapeCooldown3D,0 mov scrNewPixels3D,0 mov scrDustIndex3D,0 lea edi,scrDustLife3D xor eax,eax mov ecx,SCR_DUST_COUNT rep stosd lea edi,scrCounts3D mov ecx,48 rep stosd cmp scrType3D,4 jb @F call ScratchConfigurePortrait3D ret @@: mov scrCellCount3D,9 mov scrCellW3D,SCR_W mov scrCellH3D,SCR_H cmp scrType3D,1 jne @F mov scrCellH3D,34 @@: cmp scrType3D,2 jne @F mov scrCellW3D,44 mov scrCellH3D,44 @@: cmp scrType3D,3 jne @F mov scrCellCount3D,1 mov scrCellW3D,240 mov scrCellH3D,120 @@: lea edi,scrMask3D xor eax,eax mov ecx,9*SCR_MASK_AREA rep stosb lea edi,scrCounts3D mov ecx,48 rep stosd xor ebx,ebx xor esi,esi scratch_config_cell: imul edi,esi,SCR_MASK_AREA add edi,OFFSET scrMask3D mov rowY,0 scratch_config_row: mov pointX,0 scratch_config_pixel: cmp scrType3D,2 jne scratch_config_opaque mov eax,pointX sub eax,21 imul eax,eax mov edx,rowY sub edx,21 imul edx,edx add eax,edx cmp eax,21*21 ja scratch_config_next scratch_config_opaque: mov BYTE PTR [edi],255 cmp esi,0 jne scratch_config_next inc ebx scratch_config_next: inc edi inc pointX mov eax,pointX cmp eax,scrCellW3D jb scratch_config_pixel inc rowY mov eax,rowY cmp eax,scrCellH3D jb scratch_config_row inc esi cmp esi,scrCellCount3D jb scratch_config_cell mov scrCellArea3D,ebx imul eax,ebx,72 xor edx,edx mov ecx,100 div ecx mov scrRevealAt3D,eax ret ScratchConfigure3D ENDP ScratchSelectType3D PROC kind:DWORD cmp scrState3D,1 je scratch_select_done mov eax,kind cmp eax,-1 jne @F mov eax,6 @@: cmp eax,7 jb @F xor eax,eax @@: cmp eax,scrType3D je scratch_select_done mov scrType3D,eax mov scrState3D,0 mov scrOpened3D,0 mov scrGross3D,0 mov scrError3D,0 mov scrZoom3D,0 call ScratchCancelStroke3D call ScratchConfigure3D scratch_select_done: ret ScratchSelectType3D ENDP ; A paid ticket is immutable. Losing tickets never accidentally contain a ; triple; winning tickets contain exactly one triple. Shuffle only at purchase. BuyScratch3D PROC uses ebx esi edi cmp scrState3D,1 je scratch_buy_done cmp scrReady3D,1 jne scratch_buy_done mov ecx,scrPriceIndex3D cmp ecx,2 ja scratch_buy_done mov eax,scrPrices3D[ecx*4] cmp bankroll,eax jb scratch_buy_poor mov scrStake3D,eax sub bankroll,eax mov scrState3D,1 mov scrGross3D,0 mov scrOpened3D,0 mov scrError3D,0 mov scrPrizeSymbol3D,-1 call ScratchConfigure3D cmp scrType3D,4 jb @F call ScratchBuildPortrait3D mov scrZoom3D,1 jmp scratch_buy_save @@: invoke RandomRange3D,1000 cmp eax,600 jb scratch_losing_bag xor esi,esi scratch_pick_prize: cmp eax,scrCutoffs3D[esi*4] jb scratch_prize_picked inc esi jmp scratch_pick_prize scratch_prize_picked: mov scrPrizeSymbol3D,esi mov eax,scrMultipliers3D[esi*4] imul eax,scrStake3D mov scrGross3D,eax mov scrBag3D,esi mov scrBag3D[4],esi mov scrBag3D[8],esi mov edi,3 xor ebx,ebx scratch_win_fill: cmp ebx,esi je @F mov scrBag3D[edi*4],ebx inc edi @@: inc ebx cmp ebx,7 jb scratch_win_fill mov esi,8 jmp scratch_shuffle scratch_losing_bag: xor esi,esi scratch_loss_fill: mov eax,esi shr eax,1 mov scrBag3D[esi*4],eax inc esi cmp esi,14 jb scratch_loss_fill mov esi,13 scratch_shuffle: lea eax,[esi+1] invoke RandomRange3D,eax mov ebx,scrBag3D[esi*4] mov edx,scrBag3D[eax*4] mov scrBag3D[esi*4],edx mov scrBag3D[eax*4],ebx dec esi jnz scratch_shuffle lea esi,scrBag3D lea edi,scrGrid3D mov ecx,9 rep movsd call ScratchBuildVariant3D scratch_buy_save: call ScratchCancelStroke3D call ScratchStartDeal3D call SaveProgress3D scratch_buy_done: ret scratch_buy_poor: mov scrError3D,1 ret BuyScratch3D ENDP ScratchBuildVariant3D PROC uses ebx esi edi local rowStart:DWORD cmp scrType3D,1 je scratch_numbers_build cmp scrType3D,2 jne scratch_variant_done cmp scrPrizeSymbol3D,-1 je scratch_variant_done ; Preserve the shuffled six distinct nonwinning symbols, put the triple ; in exactly one horizontal row. No diagonal or scattered triple pays. xor esi,esi xor edi,edi scratch_row_collect: mov eax,scrGrid3D[esi*4] cmp eax,scrPrizeSymbol3D je @F mov scrBag3D[edi*4],eax inc edi @@: inc esi cmp esi,9 jb scratch_row_collect invoke RandomRange3D,3 imul eax,3 mov rowStart,eax xor esi,esi xor edi,edi scratch_row_place: mov eax,esi sub eax,rowStart cmp eax,3 jb scratch_row_winner mov eax,scrBag3D[edi*4] inc edi jmp scratch_row_store scratch_row_winner: mov eax,scrPrizeSymbol3D scratch_row_store: mov scrGrid3D[esi*4],eax inc esi cmp esi,9 jb scratch_row_place ret scratch_numbers_build: xor esi,esi scratch_number_pool: lea eax,[esi+1] mov scrBag3D[esi*4],eax inc esi cmp esi,30 jb scratch_number_pool mov esi,29 scratch_number_shuffle: lea eax,[esi+1] invoke RandomRange3D,eax mov ebx,scrBag3D[esi*4] mov edx,scrBag3D[eax*4] mov scrBag3D[esi*4],edx mov scrBag3D[eax*4],ebx dec esi jnz scratch_number_shuffle xor esi,esi scratch_number_copy: mov eax,scrBag3D[esi*4] mov scrGrid3D[esi*4],eax invoke RandomRange3D,7 mov eax,scrMultipliers3D[eax*4] imul eax,scrStake3D mov scrCellPrizes3D[esi*4],eax inc esi cmp esi,9 jb scratch_number_copy cmp scrGross3D,0 je scratch_variant_done invoke RandomRange3D,6 lea esi,[eax+3] invoke RandomRange3D,3 mov eax,scrGrid3D[eax*4] mov scrGrid3D[esi*4],eax mov eax,scrGross3D mov scrCellPrizes3D[esi*4],eax scratch_variant_done: ret ScratchBuildVariant3D ENDP FinishScratch3D PROC cmp scrState3D,1 jne scratch_finish_done mov eax,scrCellCount3D cmp scrOpened3D,eax jne scratch_finish_done ; Mark paid before invoking persistence; repeated clicks cannot pay twice. mov scrState3D,2 mov eax,bankroll add eax,scrGross3D cmp eax,1000000000 jbe @F mov eax,1000000000 @@: mov bankroll,eax mov ecx, scrGross3D cmp ecx, scrStake3D ja scratch_charm_win je @F mov eax,scrStake3D sub eax,scrGross3D invoke TriggerCharmLossProtection,eax jmp @F scratch_charm_win: mov eax,scrGross3D sub eax,scrStake3D invoke TriggerCharmWinBonus,eax @@: call ScratchStartPayout3D call SaveProgress3D scratch_finish_done: ret FinishScratch3D ENDP ; A normal application close settles an already-paid ticket, even if the ; player has since returned to another table. No pending prize is discarded. SettleScratchOnQuit3D PROC cmp scrState3D,1 jne scratch_quit_done mov eax,scrCellCount3D mov scrOpened3D,eax call FinishScratch3D scratch_quit_done: ret SettleScratchOnQuit3D ENDP ScratchCellOrigin3D PROC cell:DWORD cmp scrType3D,4 jb @F invoke ScratchPortraitBounds3D,cell ret @@: cmp scrType3D,3 jne @F mov eax,200 mov edx,176 ret @@: mov eax,cell xor edx,edx mov ecx,3 div ecx imul eax,SCR_DY add eax,SCR_Y imul edx,SCR_DX add edx,SCR_X xchg eax,edx cmp scrType3D,1 jne @F add edx,8 @@: cmp scrType3D,2 jne @F add eax,30 @@: ret ScratchCellOrigin3D ENDP ScratchErasePixel3D PROC uses ebx esi edi px:DWORD,py:DWORD cmp scrDealMs3D,0 jne scratch_pixel_done cmp scrState3D,1 jne scratch_pixel_done cmp scrType3D,4 jb @F invoke ScratchErasePortrait3D,px,py ret @@: xor esi,esi scratch_pixel_find: invoke ScratchCellOrigin3D,esi mov ebx,px sub ebx,eax cmp ebx,scrCellW3D jae scratch_pixel_next_cell mov eax,py sub eax,edx cmp eax,scrCellH3D jb scratch_pixel_found scratch_pixel_next_cell: inc esi cmp esi,scrCellCount3D jb scratch_pixel_find ret scratch_pixel_found: cmp scrRevealed3D[esi*4],0 jne scratch_pixel_done imul eax,scrCellW3D mov edx,eax add edx,ebx imul edi,esi,SCR_MASK_AREA add edx,edi cmp scrMask3D[edx],0 je scratch_pixel_done mov scrMask3D[edx],0 inc scrNewPixels3D inc scrCounts3D[esi*4] mov eax,scrRevealAt3D cmp scrCounts3D[esi*4],eax jb scratch_pixel_done mov scrRevealed3D[esi*4],1 mov eax,scrCellArea3D mov scrCounts3D[esi*4],eax add edi,OFFSET scrMask3D mov ecx,SCR_MASK_AREA xor eax,eax rep stosb inc scrOpened3D call FinishScratch3D scratch_pixel_done: ret ScratchErasePixel3D ENDP ; A narrow ellipse matches the scraping rim, rather than a circular eraser. ScratchStamp3D PROC uses ebx esi brushX:DWORD,brushY:DWORD mov esi,-4 scratch_stamp_y: mov ebx,-10 scratch_stamp_x: mov eax,ebx imul eax,eax imul eax,16 mov edx,esi imul edx,edx imul edx,100 add eax,edx cmp eax,1600 ja scratch_stamp_next mov eax,brushX add eax,ebx mov edx,brushY add edx,esi invoke ScratchErasePixel3D,eax,edx scratch_stamp_next: inc ebx cmp ebx,10 jle scratch_stamp_x inc esi cmp esi,4 jle scratch_stamp_y ret ScratchStamp3D ENDP ScratchStroke3D PROC uses ebx esi edi x0:DWORD,y0:DWORD,x1:DWORD,y1:DWORD local deltaX:DWORD,deltaY:DWORD,steps:DWORD,px:DWORD mov eax,x1 sub eax,x0 mov deltaX,eax cdq xor eax,edx sub eax,edx mov ebx,eax mov eax,y1 sub eax,y0 mov deltaY,eax cdq xor eax,edx sub eax,edx cmp eax,ebx jbe @F mov ebx,eax @@: mov eax,ebx xor edx,edx mov ecx,3 div ecx inc eax mov steps,eax xor esi,esi scratch_stroke_step: mov eax,deltaX imul eax,esi cdq idiv steps add eax,x0 mov px,eax mov eax,deltaY imul eax,esi cdq idiv steps add eax,y0 invoke ScratchStamp3D,px,eax inc esi cmp esi,steps jbe scratch_stroke_step ret ScratchStroke3D ENDP ScratchApplyPointer3D PROC cmp scrDealMs3D,0 jne scratch_apply_reset cmp scrCatalog3D,0 jne scratch_apply_reset cmp scrHeld3D,1 jne scratch_apply_reset cmp scrPointerValid3D,1 jne scratch_apply_reset cmp scrState3D,1 jne scratch_apply_reset cmp scrLastValid3D,1 je @F mov eax,scrPointerX3D mov scrLastX3D,eax mov eax,scrPointerY3D mov scrLastY3D,eax @@: invoke ScratchStroke3D,scrLastX3D,scrLastY3D,scrPointerX3D,scrPointerY3D mov eax,scrPointerX3D mov scrLastX3D,eax mov eax,scrPointerY3D mov scrLastY3D,eax mov scrLastValid3D,1 ret scratch_apply_reset: mov scrLastValid3D,0 ret ScratchApplyPointer3D ENDP ; Return 1 only for messages owned by this scene. Other games retain their ; existing logical pointer coordinates and click behaviour unchanged. ScratchMouseEvent3D PROC uses ebx hwnd:DWORD,msg:DWORD,wp:DWORD,lp:DWORD cmp msg,20Ah jne @F cmp scrDealMs3D,0 jne scratch_event_yes cmp scrType3D,4 jb scratch_event_yes movsx eax,WORD PTR wp[2] test eax,eax jz scratch_event_yes setg al movzx eax,al cmp eax,scrZoom3D je scratch_event_yes mov scrZoom3D,eax call ScratchCancelStroke3D jmp scratch_event_yes @@: cmp msg,20h jne @F cmp scrPointerValid3D,1 jne scratch_event_no invoke SetCursor,0 jmp scratch_event_yes @@: cmp msg,215h je scratch_event_lost cmp msg,8 jne @F call ScratchCancelStroke3D mov scrPointerValid3D,0 jmp scratch_event_no @@: cmp msg,202h jne @F call ScratchCancelStroke3D jmp scratch_event_yes @@: cmp msg,200h je scratch_event_position cmp msg,201h je scratch_event_position cmp msg,203h jne scratch_event_no scratch_event_position: mov scrPointerValid3D,0 cmp viewWidth3D,0 je scratch_event_invalid cmp viewHeight3D,0 je scratch_event_invalid movsx eax,WORD PTR lp sub eax,viewLeft3D cmp eax,viewWidth3D jae scratch_event_invalid imul eax,640 xor edx,edx div viewWidth3D mov scrPointerX3D,eax movsx eax,WORD PTR lp[2] sub eax,viewTop3D cmp eax,viewHeight3D jae scratch_event_invalid imul eax,480 xor edx,edx div viewHeight3D mov scrPointerY3D,eax mov scrPointerValid3D,1 cmp msg,200h je scratch_event_move mov scrClick3D,1 mov eax,scrPointerX3D mov scrClickX3D,eax mov eax,scrPointerY3D mov scrClickY3D,eax mov scrHeld3D,1 mov scrLastValid3D,0 invoke SetCapture,hwnd call ScratchApplyPointer3D jmp scratch_event_yes scratch_event_move: test wp,1 jz @F ; Process every event, including a complete quick gesture between ticks. call ScratchApplyPointer3D jmp scratch_event_yes @@: call ScratchCancelStroke3D jmp scratch_event_yes scratch_event_invalid: mov scrLastValid3D,0 jmp scratch_event_yes scratch_event_lost: mov scrHeld3D,0 mov scrLastValid3D,0 scratch_event_yes: mov eax,1 ret scratch_event_no: xor eax,eax ret ScratchMouseEvent3D ENDP HandleScratch3D PROC uses ebx esi call ScratchTickVisuals3D cmp scrCatalog3D,0 je @F call HandleScratchCatalog3D ret @@: cmp scrClick3D,0 je scratch_keys mov scrClick3D,0 cmp scrClickY3D,6 jb scratch_keys cmp scrClickY3D,34 jae scratch_footer_hit cmp scrClickX3D,504 jb scratch_keys cmp scrClickX3D,624 jae scratch_keys call LeaveScratch3D ret scratch_footer_hit: cmp scrClickY3D,46 jb scratch_keys cmp scrClickY3D,76 jae scratch_footer_buttons cmp scrClickX3D,348 jb scratch_keys cmp scrClickX3D,624 jae scratch_keys call ScratchCancelStroke3D mov scrCatalog3D,1 mov scrCatalogLocked3D,0 ret scratch_footer_buttons: cmp scrClickY3D,436 jb scratch_keys cmp scrClickY3D,472 jae scratch_keys cmp scrClickX3D,384 jb scratch_price_hit cmp scrClickX3D,624 jae scratch_keys call BuyScratch3D jmp scratch_keys scratch_price_hit: cmp scrType3D,4 jb @F cmp scrClickX3D,344 jb @F cmp scrClickX3D,376 jae @F call ScratchToggleZoom3D jmp scratch_keys @@: cmp scrState3D,1 je scratch_keys mov eax,scrClickX3D sub eax,16 js scratch_keys xor edx,edx mov ecx,108 div ecx cmp eax,2 ja scratch_keys cmp edx,100 jae scratch_keys mov scrPriceIndex3D,eax mov scrError3D,0 scratch_keys: invoke Pressed3D,5Ah test eax,eax jz @F call ScratchToggleZoom3D @@: invoke Pressed3D,25h test eax,eax jz @F mov eax,scrType3D dec eax invoke ScratchSelectType3D,eax @@: invoke Pressed3D,27h test eax,eax jz @F mov eax,scrType3D inc eax invoke ScratchSelectType3D,eax @@: mov ebx,31h scratch_price_key: invoke Pressed3D,ebx test eax,eax jz @F cmp scrState3D,1 je @F mov eax,ebx sub eax,31h mov scrPriceIndex3D,eax mov scrError3D,0 @@: inc ebx cmp ebx,33h jbe scratch_price_key invoke Pressed3D,20h test eax,eax jz scratch_draw_stroke call BuyScratch3D scratch_draw_stroke: call ScratchApplyPointer3D cmp scrNewPixels3D,0 je scratch_handle_done call ScratchSpawnDust3D mov scrNewPixels3D,0 ret scratch_handle_done: ret HandleScratch3D ENDP ScratchDrawContent3D PROC uses ebx esi edi cell:DWORD,originX:DWORD,originY:DWORD local textX:DWORD,textY:DWORD,ink:DWORD mov esi,cell cmp scrType3D,1 je scratch_content_number cmp scrType3D,3 je scratch_content_instant cmp scrState3D,2 jne @F mov eax,scrGrid3D[esi*4] cmp eax,scrPrizeSymbol3D jne @F mov eax,originX shr eax,1 mov textX,eax mov eax,originY shr eax,1 mov textY,eax mov eax,scrCellW3D shr eax,1 mov edx,scrCellH3D shr edx,1 invoke DrawBoxBorder,textX,textY,eax,edx,00F2EAD0h,00056837h,1 @@: mov ebx,38 cmp scrType3D,2 jne @F mov ebx,30 @@: mov eax,scrCellW3D sub eax,ebx shr eax,1 add eax,originX mov edx,scrCellH3D sub edx,ebx shr edx,1 add edx,originY invoke DrawAnimSprite3D,OFFSET scrSymbolsArt3D,scrGrid3D[esi*4],eax,edx,ebx,ebx ret scratch_content_number: mov ink,00303B32h cmp esi,3 jb scratch_content_num_draw xor edi,edi scratch_content_match: mov eax,scrGrid3D[edi*4] cmp eax,scrGrid3D[esi*4] jne @F mov ink,00056837h @@: inc edi cmp edi,3 jb scratch_content_match scratch_content_num_draw: mov eax,originX add eax,36 shr eax,1 mov textX,eax mov eax,originY add eax,4 shr eax,1 mov textY,eax invoke FormatNumber,scrGrid3D[esi*4],OFFSET hudNumBuffer invoke DrawString8x8,textX,textY,OFFSET hudNumBuffer,ink cmp esi,3 jb scratch_content_done invoke FormatNumber,scrCellPrizes3D[esi*4],OFFSET hudNumBuffer mov eax,originX add eax,32 mov textX,eax mov eax,originY add eax,22 invoke DrawBuckshotText3D,textX,eax,OFFSET hudNumBuffer,ink ret scratch_content_instant: invoke DrawString8x8,128,100,OFFSET scratchAmount3D,00303B32h invoke FormatNumber,scrGross3D,OFFSET hudNumBuffer lea edi,hudNumBuffer xor ecx,ecx scratch_amount_length: cmp BYTE PTR [edi+ecx],0 je @F inc ecx jmp scratch_amount_length @@: imul eax,ecx,4 mov ebx,160 sub ebx,eax invoke DrawString8x8,ebx,124,OFFSET hudNumBuffer,00056837h scratch_content_done: ret ScratchDrawContent3D ENDP RenderScratch3D PROC uses ebx esi edi local cell:DWORD,centerX:DWORD,centerY:DWORD,py:DWORD,px:DWORD,maskAt:DWORD,ink:DWORD cmp scrReady3D,1 jne scratch_render_missing ; The ticket lies on an overhead writing mat, not in front of a dealer. cmp scrTableArt3D.pixels,0 je scratch_render_plain mov esi,scrTableArt3D.pixels lea edi,screenBuffer mov ecx,SCREEN_SIZE rep movsd jmp scratch_render_paper scratch_render_plain: invoke DrawBox,0,0,320,240,001B4839h scratch_render_paper: call ScratchSaveBackdrop3D cmp scrType3D,4 jb @F call RenderScratchPortrait3D jmp scratch_render_hud @@: invoke DrawAnimSprite3D,OFFSET scrTicketArt3D,scrType3D,96,92,448,288 mov eax,scrType3D mov esi,scrNames3D[eax*4] xor ecx,ecx scratch_title_length: cmp BYTE PTR [esi+ecx],0 je @F inc ecx jmp scratch_title_length @@: imul eax,ecx,4 mov ebx,160 sub ebx,eax invoke DrawString8x8,ebx,65,esi,00E5D29Eh cmp scrType3D,1 jne @F invoke DrawBuckshotText3D,144,170,OFFSET scratchLucky3D,00303B32h invoke DrawBuckshotText3D,144,220,OFFSET scratchYours3D,00303B32h @@: mov cell,0 scratch_render_cell: invoke ScratchCellOrigin3D,cell mov centerX,eax mov centerY,edx cmp scrState3D,0 je scratch_render_coating invoke ScratchDrawContent3D,cell,centerX,centerY scratch_render_coating: mov eax,cell imul eax,SCR_MASK_AREA mov maskAt,eax mov py,0 scratch_coating_row: mov eax,py imul eax,scrCellW3D mov esi,eax add esi,maskAt mov eax,centerY add eax,py imul eax,640 add eax,centerX lea edi,screenBuffer[eax*4] mov px,0 scratch_coating_pixel: cmp scrMask3D[esi],0 je scratch_coating_next scratch_coating_opaque: mov eax,py xor edx,edx mov ecx,SCR_H div ecx imul ebx,edx,SCR_W mov eax,px xor edx,edx mov ecx,SCR_W div ecx lea eax,[ebx+edx] mov edx,scrFoilArt3D.pixels mov eax,[edx+eax*4] mov [edi],eax scratch_coating_next: add edi,4 inc esi inc px mov eax,scrCellW3D cmp px,eax jb scratch_coating_pixel inc py mov eax,scrCellH3D cmp py,eax jb scratch_coating_row inc cell mov eax,scrCellCount3D cmp cell,eax jb scratch_render_cell ; Printed odds legend belongs on the paper, not over the scratch surface. cmp scrType3D,1 je scratch_print_rule cmp scrType3D,3 je scratch_print_rule xor esi,esi scratch_legend: imul ebx,esi,43 add ebx,176 invoke DrawAnimSprite3D,OFFSET scrSymbolsArt3D,esi,ebx,338,16,16 add ebx,18 invoke FormatNumber,scrMultipliers3D[esi*4],OFFSET hudNumBuffer invoke DrawBuckshotText3D,ebx,346,OFFSET hudNumBuffer,00303B32h add ebx,16 invoke DrawBuckshotText3D,ebx,346,OFFSET scrTimes3D,00303B32h inc esi cmp esi,7 jb scratch_legend jmp scratch_render_hud scratch_print_rule: mov eax,scrType3D mov ebx,340 cmp eax,1 jne @F mov ebx,328 @@: invoke DrawBuckshotText3D,176,ebx,scrRules3D[eax*4],00303B32h jmp scratch_render_hud scratch_render_missing: invoke DrawBox,0,0,320,240,001B4839h invoke DrawString8x8,104,112,OFFSET scratchMissing3D,00E99383h scratch_render_hud: cmp scrReady3D,1 jne @F call ScratchDrawDelivery3D call ScratchDrawPayout3D cmp scrType3D,4 jb @F call ScratchPortraitInfo3D @@: invoke DrawBox,0,0,320,20,0014191Dh invoke DrawString8x8,12,6,OFFSET scratchTitle3D,00E5D29Eh invoke DrawBoxBorder,252,3,60,14,00252D2Ah,0086754Eh,1 invoke DrawString8x8,266,6,OFFSET coinExitText3D,00E5D29Eh invoke DrawBox,4,23,148,15,0014191Dh invoke DrawString8x8,8,27,OFFSET coinBankText3D,00E5D29Eh invoke FormatNumber,bankroll,OFFSET hudNumBuffer invoke DrawString8x8,56,27,OFFSET hudNumBuffer,00FFFFFFh invoke DrawBoxBorder,174,23,138,15,00252D2Ah,0086754Eh,1 invoke DrawBuckshotText3D,356,50,OFFSET scratchKind3D,00ADB9BCh invoke DrawBuckshotText3D,608,57,OFFSET scrNext3D,00E5D29Eh mov eax,scrType3D invoke DrawBuckshotText3D,356,62,scrNames3D[eax*4],00E5D29Eh invoke DrawBox,0,194,320,46,0014191Dh invoke DrawBuckshotText3D,16,405,OFFSET scratchCost3D,00E5D29Eh mov eax,scrPriceIndex3D mov eax,scrPrices3D[eax*4] cmp scrState3D,0 je @F mov eax,scrStake3D @@: invoke FormatNumber,eax,OFFSET hudNumBuffer invoke DrawString8x8,56,201,OFFSET hudNumBuffer,00FFFFFFh cmp scrError3D,0 je scratch_status invoke DrawString8x8,168,201,OFFSET scratchPoor3D,00E99383h jmp scratch_buttons scratch_status: cmp scrState3D,2 je scratch_result cmp scrState3D,1 jne scratch_rule invoke DrawString8x8,168,201,OFFSET scratchWait3D,00E5D29Eh invoke FormatNumber,scrOpened3D,OFFSET hudNumBuffer invoke DrawString8x8,232,201,OFFSET hudNumBuffer,00FFFFFFh jmp scratch_buttons scratch_rule: mov eax,scrType3D invoke DrawBuckshotText3D,328,405,scrRules3D[eax*4],00ADB9BCh jmp scratch_buttons scratch_result: invoke DrawBuckshotText3D,336,405,OFFSET scratchPayout3D,00ADB9BCh invoke FormatNumber,scrGross3D,OFFSET hudNumBuffer invoke DrawString8x8,212,201,OFFSET hudNumBuffer,0090D5ADh call RenderScratchNet3D scratch_buttons: cmp scrType3D,4 jb @F invoke DrawBoxBorder,172,218,16,18,00252D2Ah,0086754Eh,1 mov eax,OFFSET scrZoomIn3D cmp scrZoom3D,0 je scratch_zoom_label mov eax,OFFSET scrZoomOut3D scratch_zoom_label: invoke DrawString8x8,176,223,eax,00E5D29Eh @@: xor esi,esi scratch_price_button: mov ink,0086754Eh cmp scrState3D,1 je @F cmp esi,scrPriceIndex3D jne @F mov ink,00E5D29Eh @@: imul ebx,esi,54 add ebx,8 invoke DrawBoxBorder,ebx,218,50,18,00252D2Ah,ink,1 add ebx,9 invoke FormatNumber,scrPrices3D[esi*4],OFFSET hudNumBuffer invoke DrawString8x8,ebx,223,OFFSET hudNumBuffer,ink inc esi cmp esi,3 jb scratch_price_button invoke DrawBoxBorder,192,218,120,18,00252D2Ah,0086754Eh,1 mov eax,OFFSET scratchBuy3D cmp scrState3D,2 jne @F mov eax,OFFSET scratchNext3D @@: cmp scrState3D,1 jne @F mov eax,OFFSET scratchActive3D @@: invoke DrawString8x8,224,223,eax,00E5D29Eh cmp scrReady3D,1 jne scratch_render_done cmp scrCatalog3D,0 je @F call RenderScratchCatalog3D jmp scratch_coin_draw @@: call ScratchDrawDust3D scratch_coin_draw: cmp scrPointerValid3D,1 jne scratch_render_done mov eax,scrPointerX3D sub eax,32 mov centerX,eax mov eax,scrPointerY3D sub eax,60 mov centerY,eax xor eax,eax cmp scrHeld3D,1 jne @F mov eax,animationClock3D shr eax,7 and eax,3 @@: invoke DrawAnimSprite3D,OFFSET scrCoinArt3D,eax,centerX,centerY,64,64 scratch_render_done: ret RenderScratch3D ENDP ScratchCanWalk3D PROC px:DWORD,py:DWORD mov eax,px sub eax,scrStation3D.posX cdq xor eax,edx sub eax,edx cmp eax,FP_1*19/20 ja scratch_walk_clear mov eax,py sub eax,scrStation3D.posY cdq xor eax,edx sub eax,edx cmp eax,FP_1*2/5 ja scratch_walk_clear xor eax,eax ret scratch_walk_clear: mov eax,1 ret ScratchCanWalk3D ENDP include src_graphics/scratch_portrait.inc include src_graphics/scratch_ui.inc include src_graphics/scratch_effects.inc