- Billiards: add native Russian Pyramid & American Eight-Ball pool with physics prediction, controls, and regression tests - Scratch Tickets: add dedicated counter, mat presentation, elliptical coin scraping, 4 ticket types, and payout effects - First-Person Dice: add native dice scene, hand anchor frames, throwing animation, and table perspective - City Wake & Weather: add arrival cutscene, alley geometry, weather/rain effects, and lighter/rocker animation - World Dressing: add hall paintings, furniture packs, hall lighting, and scene regression tests - Build & Tooling: update build.bat for modern MSVC toolchain, update launcher hash, and refresh shipping binaries
1211 lines
28 KiB
PHP
1211 lines
28 KiB
PHP
; 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
|
|
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
|