.data bpMassTestPath db 'build\hall-expansion\bowling-mass-samples.bin',0 bpMassTest4Path db 'build\hall-expansion\bowling-weight-4.bmp',0 bpMassTest7Path db 'build\hall-expansion\bowling-weight-7.bmp',0 bpMassTestLockedPath db 'build\hall-expansion\bowling-weight-locked.bmp',0 bpMassTestRackPath db 'build\hall-expansion\bowling-weight-rack.bmp',0 bpMassTestRedPath db 'build\hall-expansion\bowling-weight-5.bmp',0 bpMassTestRackPairPath db 'build\hall-expansion\bowling-weight-rack-pair.bmp',0 bpMassTestPowers dd 0,50,100 bpMassShotsPath db 'build\hall-expansion\bowling-mass-shots.bin',0 bpMassShots dd 84*3 dup(0) ; kg, power, launch m/s Q16, inverse mass Q16, incoming vy, outgoing ball/pin vy, locked kg. bpMassTestSamples dd 12*8 dup(0) .code BowlingWeightNativeTests PROC uses ebx esi edi local bank:DWORD,rng:DWORD,kg:DWORD,power:DWORD,handle:DWORD,count:DWORD,inverse:DWORD local aim:DWORD mov expansionStage,183 call InitBowling3D mov hallLevel3D,HALL_BOWLING invoke BeginBowlingPlay3D,1 mov eax,bankroll mov bank,eax mov eax,bwRng3D mov rng,eax mov deltaTime3D,0 mov viewWidth3D,640 mov viewHeight3D,480 mov viewLeft3D,0 mov viewTop3D,0 cmp bpState3D,BP_SELECT_BALL jne bp_mass_test_fail call RenderBowlingPlay3D invoke ExpansionSnapshot,OFFSET bpMassTestRackPath invoke BowlingTintBallPixel3D,55203CC0h,4 cmp eax,5520C03Ch jne bp_mass_test_fail invoke BowlingTintBallPixel3D,55203CC0h,5 cmp eax,55C01E20h jne bp_mass_test_fail invoke BowlingTintBallPixel3D,55203CC0h,7 cmp eax,55C07E20h jne bp_mass_test_fail xor esi,esi bp_mass_test_material: lea eax,[esi+4] invoke BowlingBallMaterial3D,eax invoke ResolveCitySurface3D,eax test eax,eax jz bp_mass_test_fail cmp ecx,64 jne bp_mass_test_fail cmp edx,64 jne bp_mass_test_fail cmp esi,3 jae @F mov eax,bpRackHitX3D[esi*4+4] sub eax,bpRackHitX3D[esi*4] cmp eax,36 jl bp_mass_test_fail @@: inc esi cmp esi,4 jb bp_mass_test_material ; A click away from the actual rack never selects a ball or starts a throw. invoke WindowEvents3D,0,201h,1,00780014h call HandleBowlingPlay3D cmp bpState3D,BP_SELECT_BALL jne bp_mass_test_fail mov eax,bpRackHitY3D shl eax,17 mov edx,bpRackHitX3D shl edx,1 or eax,edx invoke WindowEvents3D,0,201h,1,eax call HandleBowlingPlay3D cmp bpWeightKg3D,4 jne bp_mass_test_fail cmp bpState3D,BP_DIRECTION jne bp_mass_test_fail call RenderBowlingPlay3D invoke ExpansionSnapshot,OFFSET bpMassTest4Path invoke WindowEvents3D,0,100h,34h,0 call HandleBowlingPlay3D cmp bpWeightKg3D,7 jne bp_mass_test_fail cmp bpState3D,BP_DIRECTION jne bp_mass_test_fail call HandleBowlingPlay3D cmp bpState3D,BP_DIRECTION jne bp_mass_test_fail call RenderBowlingPlay3D invoke ExpansionSnapshot,OFFSET bpMassTest7Path ; The weight label opens the in-world rack; labels and spheres share picking. invoke WindowEvents3D,0,201h,1,003C0018h call HandleBowlingPlay3D cmp bpState3D,BP_SELECT_BALL jne bp_mass_test_fail call RenderBowlingPlay3D mov eax,bpRackHitY3D[4] add eax,bpRackHitRadius3D[4] add eax,9 shl eax,17 mov edx,bpRackHitX3D[4] shl edx,1 or eax,edx invoke WindowEvents3D,0,201h,1,eax call HandleBowlingPlay3D cmp bpWeightKg3D,5 jne bp_mass_test_fail cmp bpState3D,BP_DIRECTION jne bp_mass_test_fail call RenderBowlingPlay3D invoke ExpansionSnapshot,OFFSET bpMassTestRedPath ; Test the source/scratch pixels directly: transparent hand borders can reveal ; different rack balls behind them and are not a valid skin screenshot mask. mov esi,bpHandArt3D.pixels lea edi,bpTintedHandPixels3D mov ebx,256*256 xor ecx,ecx bp_mass_test_hand_pixel: mov eax,[esi] mov edx,[edi] xor edx,eax test edx,0FF000000h jnz bp_mass_test_fail test edx,edx jz bp_mass_test_hand_next inc ecx mov edx,eax shr edx,16 and edx,255 and eax,255 cmp edx,eax jae bp_mass_test_fail bp_mass_test_hand_next: add esi,4 add edi,4 dec ebx jnz bp_mass_test_hand_pixel cmp ecx,500 jb bp_mass_test_fail mov eax,bankroll cmp eax,bank jne bp_mass_test_fail mov eax,bwRng3D cmp eax,rng jne bp_mass_test_fail mov expansionStage,184 mov kg,4 mov power,0 xor edi,edi bp_mass_sample: call ResetBowlingPlay3D mov eax,kg mov bpWeightKg3D,eax mov bpMassTestSamples[edi],eax mov eax,power mov eax,bpMassTestPowers[eax*4] mov bpLockedPower3D,eax mov bpMassTestSamples[edi+4],eax mov bpLockedAim3D,FP_1/2 call BowlingPlayLaunch3D cmp bpBallVX3D,0 jne bp_mass_test_fail mov eax,bpLaunchSpeed3D mov bpMassTestSamples[edi+8],eax mov eax,bpInvMass3D[40] mov bpMassTestSamples[edi+12],eax mov eax,bpBallVY3D mov bpMassTestSamples[edi+16],eax mov bpPinVY3D[40],eax mov bpPinVX3D[40],0 mov bpPinX3D[40],0 mov bpPinY3D[40],FP_1*42/10 mov bpPinX3D,0 mov bpPinY3D,4*FP_1 invoke BowlingPlayContact3D,0,10 mov eax,bpPinVY3D[40] mov bpMassTestSamples[edi+20],eax mov eax,bpPinVY3D mov bpMassTestSamples[edi+24],eax mov eax,bpShotWeightKg3D mov bpMassTestSamples[edi+28],eax add edi,32 inc power cmp power,3 jb bp_mass_sample mov power,0 inc kg cmp kg,7 jbe bp_mass_sample invoke CreateFileA,OFFSET bpMassTestPath,40000000h,0,0,2,80h,0 mov handle,eax invoke WriteFile,handle,OFFSET bpMassTestSamples,SIZEOF bpMassTestSamples,ADDR count,0 invoke CloseHandle,handle ; Exercise complete high-power rolls across all selectable masses. mov kg,4 mov aim,0 xor edi,edi bp_mass_shot: call ResetBowlingPlay3D mov eax,kg mov bpWeightKg3D,eax mov bpMassShots[edi],eax mov eax,aim mov eax,bpFeelSampleAim[eax*4] mov bpLockedAim3D,eax mov bpMassShots[edi+4],eax mov bpLockedPower3D,100 call BowlingPlayLaunch3D mov esi,900 bp_mass_shot_tick: call BowlingPlayStep3D xor ebx,ebx bp_mass_shot_bounds: mov eax,bpPinX3D[ebx*4] cmp eax,-FP_1 jl bp_mass_test_fail cmp eax,FP_1 jg bp_mass_test_fail mov eax,bpPinY3D[ebx*4] cmp eax,3*FP_1 jl bp_mass_test_fail cmp eax,FP_1*55/10 jg bp_mass_test_fail inc ebx cmp ebx,10 jb bp_mass_shot_bounds dec esi jnz bp_mass_shot_tick call BowlingPlayReady3D cmp eax,1 jne bp_mass_test_fail mov eax,bpHitMask3D mov bpMassShots[edi+8],eax add edi,12 inc aim cmp aim,21 jb bp_mass_shot mov aim,0 inc kg cmp kg,7 jbe bp_mass_shot invoke CreateFileA,OFFSET bpMassShotsPath,40000000h,0,0,2,80h,0 mov handle,eax invoke WriteFile,handle,OFFSET bpMassShots,SIZEOF bpMassShots,ADDR count,0 invoke CloseHandle,handle mov expansionStage,185 call ResetBowlingPlay3D mov bpWeightKg3D,7 mov bpLockedAim3D,0 mov bpLockedPower3D,70 call BowlingPlayLaunch3D mov eax,bpInvMass3D[40] mov inverse,eax mov bpWeightKg3D,4 mov pressedKeys3D[31h],1 call HandleBowlingPlay3D cmp bpShotWeightKg3D,7 jne bp_mass_test_fail mov eax,bpInvMass3D[40] cmp eax,inverse jne bp_mass_test_fail cmp bpState3D,BP_RELEASE jne bp_mass_test_fail call RenderBowlingPlay3D invoke ExpansionSnapshot,OFFSET bpMassTestLockedPath mov bwTurn3D[4],1 mov bpWeightKg3D,7 call BowlingPlayLaunch3D cmp bpShotWeightKg3D,6 jne bp_mass_test_fail cmp bpWeightKg3D,7 jne bp_mass_test_fail call LeaveBowlingPlay3D invoke BeginBowlingPlay3D,2 call RenderBowlingPlay3D invoke ExpansionSnapshot,OFFSET bpMassTestRackPairPath mov eax,bpRackHitY3D[12] shl eax,17 mov edx,bpRackHitX3D[12] shl edx,1 or eax,edx invoke WindowEvents3D,0,201h,1,eax call HandleBowlingPlay3D cmp bpWeightKg3D,7 jne bp_mass_test_fail cmp bpState3D,BP_DIRECTION jne bp_mass_test_fail call LeaveBowlingPlay3D invoke BowlingCanWalk3D,FP_1*45/10,FP_1*257/10 test eax,eax jnz bp_mass_test_fail ret bp_mass_test_fail: invoke ExitProcess,expansionStage ret BowlingWeightNativeTests ENDP