From c8452024c48bc28300247ef1991742a5bed36047 Mon Sep 17 00:00:00 2001 From: "prompt.ac/@jeffrey" Date: Sun, 27 Sep 2026 20:34:31 -0700 Subject: [PATCH] Spread unique park items, add kart hills and raise decal resolution --- xbox/live/oskiewar.js | 65 +++++++++++++++---- xbox/live/tests/pool-playground.test.mjs | 32 +++++++-- xbox/macos-native/PoolDecals.swift | 6 +- xbox/macos-native/main.swift | 1 + xbox/native-bios/App.cpp | 2 +- xbox/native-bios/Package.appxmanifest | 2 +- xbox/native-bios/QuickJsEngine.cpp | 1 + .../tests/quickjs_engine_smoke.cpp | 6 +- xbox/runtime/include/ac/decal_surface.hpp | 2 +- 9 files changed, 87 insertions(+), 30 deletions(-) diff --git a/xbox/live/oskiewar.js b/xbox/live/oskiewar.js index 2e16026ef3..1183fca937 100644 --- a/xbox/live/oskiewar.js +++ b/xbox/live/oskiewar.js @@ -102,7 +102,8 @@ if (hostAnalytics) const hostAc = typeof ac === "function" ? ac : null; // Monotonic count of committed revisions to this piece (next revision included). -const buildVersion = 203; +const buildVersion = 204; +const parkDecalResolution=Number(globalThis.decalSurfaceSize)||2048; const floorY = 1800; // Oskiewar now opens as a versus game. An ordinary web visit hosts a room — // the URL becomes the invitation — and until a friend opens it, all you can @@ -1637,6 +1638,7 @@ function parkGroundAt(x,z){ return parkDeckY-Math.max(height,parkHalfPipeHeight(x,z)); } function poolFloorAt(x,z=0){ + if(zbay*w.width+109+radius&&u<(bay+1)*w.width-109-radius; @@ -3269,7 +3272,7 @@ function addDecal(decal) { if(poolDecalsNative===null)clearPoolDecals(); if(poolDecalsNative){ for(const patch of rasterDecalPatches(decal)){ - const args=[...patch.uv,...patch.points.flatMap(p=>[(p.x-gridLeft+parkLotMargin)/(gridWidth+parkLotMargin*2)*2048,(p.z-worldNear+parkLotMargin)/(roomDepth+parkLotMargin*2)*2048])]; + const args=[...patch.uv,...patch.points.flatMap(p=>[(p.x-gridLeft+parkLotMargin)/(gridWidth+parkLotMargin*2)*parkDecalResolution,(p.z-worldNear+parkLotMargin)/(roomDepth+parkLotMargin*2)*parkDecalResolution])]; if(decal.color&&typeof decalTint==='function')decalTint(...args,...decal.color);else decalStamp(...args); } poolDecalCount++; @@ -6524,9 +6527,10 @@ function placeFreeskateBoard(rider = players[0], chosen = null) { board.active = true; board.heldBy = -1; board.releasedBy = -1; - board.x = rider.x + (poolOnly()?-170:(rider.facing || 1)*170); + board.x = poolOnly()?1800:rider.x+(rider.facing || 1)*170; board.y = terrainFloorAt(board.x) - 18; - board.z = rider.z || 0; + board.z = poolOnly()?1800:rider.z || 0; + if(poolOnly())board.y=poolFloorAt(board.x,board.z)-18; board.vx = board.vy = 0; board.rotation = 0; board.flipSpin = 0; @@ -6612,6 +6616,7 @@ function beginFreeskate(now) { parkFreeskateChair(); for (const pickup of [...gunPickups, ...saberPickups, ...grenadePickups]) pickup.active = false; + if(poolOnly()){rider.spawnX=rider.x=parkHalfPipe3D.x;rider.z=parkHalfPipe3D.z;rider.y=poolFloorAt(rider.x,rider.z);} // Clear loose vehicles before placing the course's board or monowheel. for (const item of balls) item.active = false; if (indoorSkate() || halfpipeOnly()) { @@ -9739,6 +9744,16 @@ function updateCameraDoll(dt, now) { const tip=chalkTip(p),target={x:(p.x+tip.x)*.5,y:poolFloorAt(p.x,p.z||0),z:((p.z||0)+tip.z)*.5}; cameraDoll.track({target,position:{x:target.x,y:target.y-1150,z:target.z-180},width:1400,perspective:.65,fov:62,roll:0},dt,4);poolIdleSeconds=poolIdleClose=0;return; } + if(p.goKart){ + const look=450+Math.min(750,speed*.13),distance=1000+Math.min(550,speed*.09); + const target={x:p.x+Math.cos(heading)*look,y:p.y-90,z:(p.z||0)+Math.sin(heading)*look}; + let position={x:p.x-Math.cos(heading)*distance,y:p.y-500,z:(p.z||0)-Math.sin(heading)*distance}; + if(insidePark(p.x,p.z||0))position=clearPoolCamera(position,{x:p.x,y:p.y-50,z:p.z||0}); + for(let i=0;i<16;i++){const t=i/16,x=lerp(position.x,target.x,t),z=lerp(position.z,target.z,t);position.y=Math.min(position.y,(poolFloorAt(x,z)-120-target.y*t)/(1-t));} + cameraDoll.track({target,position,width:2200,perspective:1,fov:68,roll:0},dt,3); + cameraDoll.position.y=Math.min(cameraDoll.position.y,poolFloorAt(cameraDoll.position.x,cameraDoll.position.z)-140); + cameraDoll.dirty=true;poolIdleSeconds=poolIdleClose=0;return; + } if(p.raceLoop){ const loop=p.raceLoop,target={x:loop.x,y:parkDeckY-loop.radius,z:loop.z},position={x:loop.x-900,y:parkDeckY-1500,z:loop.z-2400}; cameraDoll.track({target,position,width:3400,perspective:1,fov:65,roll:0},dt,6);poolIdleSeconds=poolIdleClose=0;return; @@ -20392,6 +20407,22 @@ function drawTerrainBackWall(left, right, far, color) { } function outdoorCircuit(){const radius=80467.2/(Math.PI*2);return {x:gridLeft+gridWidth*.52,z:worldNear-1500-radius,radius};} +function outdoorGroundAt(x,z){ + const t=outdoorCircuit(),a=Math.atan2(x-t.x,z-t.z),distance=Math.hypot(x-t.x,z-t.z); + const ridge=clamp(1-Math.max(0,Math.abs(distance-t.radius)-400)/2200,0,1); + return parkDeckY-(1-Math.cos(a))*260*(1+.35*Math.sin(a*3))*ridge; +} +function boundKartTrack(p,previous){ + if(!p.goKart)return; + const t=outdoorCircuit(),dx=p.x-t.x,dz=(p.z||0)-t.z,r=Math.hypot(dx,dz),a=Math.atan2(dx,dz); + if(Math.abs(a)<.055)return; // entrance from the parking lot + const old=Math.hypot(previous.x-t.x,previous.z-t.z)-t.radius,offset=r-t.radius; + if(Math.abs(old)<=280&&Math.abs(offset)>280&&p.y>outdoorGroundAt(p.x,p.z)-100){ + const target=t.radius+Math.sign(offset)*280,nx=dx/r,nz=dz/r; + p.x=t.x+nx*target;p.z=t.z+nz*target; + const normal=p.vx*nx+(p.vz||0)*nz;p.vx-=normal*nx*1.2;p.vz-=normal*nz*1.2; + } +} const outdoorChunks=new Map(); function drawOutdoorCircuit(){ const rider=players[0],track=outdoorCircuit(),keep=new Set(),chunkSize=3000; @@ -20401,18 +20432,26 @@ function drawOutdoorCircuit(){ for(let ix=gx-2;ix<=gx+2;ix++)for(let iz=gz-2;iz<=gz+2;iz++){ const x=ix*chunkSize,z=iz*chunkSize,end=Math.min(z+chunkSize,worldNear-parkLotMargin); if(end<=z)continue; - draw('ground:'+ix+':'+iz,()=>worldQuad({x,y:parkDeckY+2,z},{x:x+chunkSize,y:parkDeckY+2,z},{x:x+chunkSize,y:parkDeckY+2,z:end},{x,y:parkDeckY+2,z:end},[97,111,92])); + draw('ground:'+ix+':'+iz,()=>{ + const at=(x,z)=>({x,z,y:outdoorGroundAt(x,z)+8}); + for(let xx=x;xx7500)continue; draw('road:'+chunk,()=>{ - const at=(a,r,y=parkDeckY-1)=>({x:track.x+Math.sin(a)*r,y,z:track.z+Math.cos(a)*r}); + const at=(a,r,y=parkDeckY-1)=>{const x=track.x+Math.sin(a)*r,z=track.z+Math.cos(a)*r;return {x,z,y:outdoorGroundAt(x,z)+y-parkDeckY};}; for(let i=chunk*chunkSegments;i<(chunk+1)*chunkSegments;i++){ const a=i/segments*Math.PI*2,b=(i+1)/segments*Math.PI*2,r=track.radius; worldQuad(at(a,r-350),at(b,r-350),at(b,r+350),at(a,r+350),[49,53,60]); for(const side of [-1,1])worldQuad(at(a,r+side*325,parkDeckY-2),at(b,r+side*325,parkDeckY-2),at(b,r+side*350,parkDeckY-2),at(a,r+side*350,parkDeckY-2),i%2?[236,230,207]:[180,64,75]); + if(i>2&&i[(x-bounds.x)/bounds.w*2048,(z-bounds.z)/bounds.h*2048]; + const pix=(x,z)=>[(x-bounds.x)/bounds.w*parkDecalResolution,(z-bounds.z)/bounds.h*parkDecalResolution]; for(let x=gridLeft-parkLotMargin;x0)continue; const n=Math.abs(Math.sin(x*.173+z*.617)),gray=45+Math.round(n*33); @@ -23391,19 +23430,17 @@ function resetParkSupply(now){ chalkPickups.length=0;parkAxes.length=0;for(const p of players){p.chalkColor=null;p.chalkPrevious=null;p.chalkDrawing=false;} if(poolOnly()){ chalkColors.forEach((color,i)=>{const [x,z]=[[900,900],[2300,-1700],[4300,2300],[6000,-2100],[7900,900],[3300,worldNear-900]][i];chalkPickups.push({x,z,y:poolFloorAt(x,z)-12,color,active:true});}); - for(const [x,z,color] of [[5000,2200,[234,105,116]],[3500,worldNear-900,[108,190,235]]])parkKarts.push({x,z,y:poolFloorAt(x,z),poolYaw:0,color,active:true,safeUntil:0}); + for(const [x,z,color] of [[5000,worldNear-1200,[108,190,235]]])parkKarts.push({x,z,y:poolFloorAt(x,z),poolYaw:0,color,active:true,safeUntil:0}); for(let i=gunPickups.length-1;i>=0;i--)if(gunPickups[i].parkScatter)gunPickups.splice(i,1); - for(const [x,z,kind] of [[2400,-1100,'RUBBER SMG'],[4500,1300,'HANDGUN'],[7100,-800,'RUBBER SMG']])gunPickups.push({parkScatter:true,kind,x,z,y:poolFloorAt(x,z)-65,amount:kind==='RUBBER SMG'?90:24,active:true,startsActive:false,respawnAt:Infinity}); - for(const [x,z] of [[3900,-200],[6500,700]])parkAxes.push({x,z,y:poolFloorAt(x,z)-65,active:true}); + for(const [x,z,kind] of [[7100,-1800,'RUBBER SMG'],[4800,1600,'HANDGUN']])gunPickups.push({parkScatter:true,kind,x,z,y:poolFloorAt(x,z)-65,amount:kind==='RUBBER SMG'?90:24,active:true,startsActive:false,respawnAt:Infinity}); + for(const [x,z] of [[6500,700]])parkAxes.push({x,z,y:poolFloorAt(x,z)-65,active:true}); } if(halfpipeOnly()){ for(const p of [...gunPickups,...saberPickups,...grenadePickups])p.active=false; axePickup.active=false;for(const p of players){p.axeHeld=false;p.underPipe=false;} if(poolOnly()){ for(const pickup of gunPickups)if(pickup.parkScatter)pickup.active=true; - const pistol=gunPickups.find(p=>p.kind==='HANDGUN'); - Object.assign(pistol,{active:true,amount:12,x:pool.x+160,z:100,y:poolFloorAt(pool.x+160,100)-65}); - Object.assign(axePickup,{active:true,x:pool.x-170,z:-100,y:poolFloorAt(pool.x-170,-100)-65}); + } bottomGlass.fill(false);turboParticles.length=0; Object.assign(parkSupply,{nextAt:Infinity,drone:null,drop:null,ko:null}); diff --git a/xbox/live/tests/pool-playground.test.mjs b/xbox/live/tests/pool-playground.test.mjs index 8c027a2760..2cbee36099 100644 --- a/xbox/live/tests/pool-playground.test.mjs +++ b/xbox/live/tests/pool-playground.test.mjs @@ -7,7 +7,7 @@ function playground(legacyAudio=false){ let now=1e6;const noop=()=>{},audio=[],drums=[]; const api=new Function('runtime','capabilities','telemetry','gameSignal','drum','wipe','box','line','triangle','write','systemWrite','oscillator','oscillatorStop',`${source} configureWorldMap('skatepark','pool');fightOpponent='freeskate';gameMode='fight'; - return {freeItemArm,assignedItemArm,heldHandItems,emitSignal,outdoorCircuit,drawOutdoorCircuit,outdoorChunks,rasterDecalPatches,updateBoomerboard,inputPads,updateGarments,garmentStates,parkSpeakerLocations,parkKarts,dropParkItem,parkDropName,brokenParkRoof,parkRoofKey,parkBuildingHeight,generateParkProfile,drawParkStereoGeometry,updateSpin,bloodDrops,popCivilianHead,updateFootprints,playDrum,updateParkMusic,clock:()=>runtime().monotonicUs,raceTrack,enterRaceLoop,updateRaceLoop,strikeParkWindow,updateChalk,chalkTip,chalkColors,chalkPickups,decals,stereoGain,parkStereo,seatActionRuns,seatHudReadout,milkAt,swimMilk,parkPools,drawCerealMilk,ragdollBodies,updateRagdolls,ragdollGeometry,OskiewarRagdoll,seatActionText,looseRunnerGeometry,drawLooseRunner,mainNativeCamera,characterLocalCamera,spectatorState,netDrainHostInbox,players,updatePlayer,runnerWorldGeometry,projectRunnerWorldGeometry,cameraDoll, + return {beginFreeskate,monowheel,parkAxes,freeItemArm,assignedItemArm,heldHandItems,emitSignal,outdoorCircuit,drawOutdoorCircuit,outdoorChunks,rasterDecalPatches,updateBoomerboard,inputPads,updateGarments,garmentStates,parkSpeakerLocations,parkKarts,dropParkItem,parkDropName,brokenParkRoof,parkRoofKey,parkBuildingHeight,generateParkProfile,drawParkStereoGeometry,updateSpin,bloodDrops,popCivilianHead,updateFootprints,playDrum,updateParkMusic,clock:()=>runtime().monotonicUs,raceTrack,enterRaceLoop,updateRaceLoop,strikeParkWindow,updateChalk,chalkTip,chalkColors,chalkPickups,decals,stereoGain,parkStereo,seatActionRuns,seatHudReadout,milkAt,swimMilk,parkPools,drawCerealMilk,ragdollBodies,updateRagdolls,ragdollGeometry,OskiewarRagdoll,seatActionText,looseRunnerGeometry,drawLooseRunner,mainNativeCamera,characterLocalCamera,spectatorState,netDrainHostInbox,players,updatePlayer,runnerWorldGeometry,projectRunnerWorldGeometry,cameraDoll, parkHalfPipe3D,parkHalfPipeHeight,parkDeckY,poolFloorAt,poolSlopeAt,gunPickups,axePickup, resetParkSupply,updateParkSupply,updateGunPickups,resetParkKids,updateParkKids,parkKids, bullets,updateBullets,gunPose,drawPoolGeometry,captureQuadMesh,drawRunner, @@ -67,10 +67,10 @@ test('half-pipe has a flat, circular transitions, decks, and open roll-ins match }); test('pistol and axe are collectible in 3D, and pistol shoots along the rider heading',()=>{ const a=playground(),p=a.players[0];a.resetParkSupply(a.now()); - const gun=a.gunPickups.find(g=>g.kind==='HANDGUN');assert.ok(gun.active&&a.axePickup.active); + const gun=a.gunPickups.find(g=>g.active&&g.kind==='HANDGUN'),axe=a.parkAxes[0];assert.ok(gun.active&&axe.active); Object.assign(p,{x:gun.x,z:gun.z+500,y:gun.y+65});a.updateGunPickups(a.now());assert.ok(gun.active,'no pickup across depth'); p.z=gun.z;a.updateGunPickups(a.now());assert.ok(p.gunAmmo>0);assert.equal(gun.active,false); - Object.assign(p,{x:a.axePickup.x,z:a.axePickup.z,y:a.axePickup.y+65});a.updateParkSupply(1/60,a.now());assert.ok(p.axeHeld); + Object.assign(p,{x:axe.x,z:axe.z,y:axe.y+65});a.updateParkSupply(1/60,a.now());assert.ok(p.axeHeld); p.poolYaw=Math.PI/2;const ammo=p.gunAmmo;a.step(['Y']);assert.equal(p.gunAmmo,ammo-1);assert.equal(a.bullets.length,1); const shot=a.bullets[0],z=shot.z;assert.ok(Math.abs(shot.vx)<1e-6&&shot.vz>0); a.updateBullets(1/60,a.now(),false);assert.ok(shot.z>z);assert.equal(shot.previousZ,z); @@ -138,7 +138,7 @@ test('normal jump and forward input can leave the building and land in the lot', Object.assign(p,{x:w.width*.5,z:w.az+300,y:a.parkDeckY,poolYaw:-Math.PI/2,vx:0,vz:-1400,vy:0,grounded:true}); a.step(['A','ArrowUp']);for(let i=0;i<180;i++)a.step(['ArrowUp']); assert.ok(a.brokenParkWindows.size>0,'jump impact breaks a window'); - assert.ok(p.z{ const a=playground(),mesh=a.captureQuadMesh(a.drawPoolGeometry),root=a.buildParkScene(mesh); @@ -499,7 +499,7 @@ test('held punch draws neon chalk through movement and spins, without an attack' assert.equal(p.attackKind,'');a.updateChalk(p,[],a.now());assert.equal(p.chalkDrawing,false);assert.equal(p.chalkPrevious,null); }); test('park scatters SMGs and held fire shoots repeated individual rounds',()=>{ - const a=playground(),p=a.players[0];a.resetParkSupply(a.now());assert.ok(a.gunPickups.filter(g=>g.active&&g.kind==='RUBBER SMG').length>=2); + const a=playground(),p=a.players[0];a.resetParkSupply(a.now());assert.equal(a.gunPickups.filter(g=>g.active&&g.kind==='RUBBER SMG').length,1); p.gunMode='RUBBER SMG';p.gunAmmo=30;for(let i=0;i<60;i++)a.step(['Y']); assert.ok(p.gunAmmo<22);assert.ok(p.gunAmmo>15,`ammo=${p.gunAmmo}, shots=${a.drums.filter(d=>d.name==='smg-shot').length}`);assert.ok(a.drums.some(d=>d.name==='smg-shot')); }); @@ -597,8 +597,8 @@ test('weapons drop with their ammo and cannot be instantly collected again',()=> assert.equal(a.parkDropName(p),'pistol');assert.ok(a.dropParkItem(p,a.now()));assert.equal(p.gunAmmo,0); const gun=a.gunPickups.at(-1);assert.equal(gun.amount,17);assert.ok(gun.safeUntil>a.now());a.updateGunPickups(a.now());assert.equal(p.gunAmmo,0); }); -test('go-karts are spread across gym and lot, mount nearby and dismount with jump',()=>{ - const a=playground(),p=a.players[0];a.resetParkSupply(a.now());assert.equal(a.parkKarts.length,2);const kart=a.parkKarts[0]; +test('single outdoor go-kart mounts nearby and dismounts with jump',()=>{ + const a=playground(),p=a.players[0];a.resetParkSupply(a.now());assert.equal(a.parkKarts.length,1);const kart=a.parkKarts[0]; Object.assign(p,{x:kart.x,y:kart.y,z:kart.z});a.updateParkSupply(1/60,a.now());assert.equal(p.goKart,kart);assert.equal(kart.active,false); a.step(['A']);assert.equal(p.goKart,null);assert.equal(kart.active,true);assert.ok(kart.safeUntil>a.now()); }); @@ -656,3 +656,21 @@ test('drawing directions translate directly regardless of facing and never doubl assert.equal(p.spin,null);assert.ok(p.chalkDrawing); a.step([]);assert.equal(p.chalkDrawing,false); }); + +test('park supply has one weapon of each kind, one kart and a clear half-pipe spawn',()=>{ + const a=playground();a.resetParkSupply(a.now()); + const guns=a.gunPickups.filter(p=>p.active); + assert.equal(guns.filter(p=>p.kind==='HANDGUN').length,1); + assert.equal(guns.filter(p=>p.kind==='RUBBER SMG').length,1); + assert.equal(a.parkAxes.filter(p=>p.active).length,1);assert.equal(a.axePickup.active,false); + assert.equal(a.parkKarts.length,1);assert.equal(new Set(a.chalkPickups.map(p=>p.color.name)).size,a.chalkPickups.length); + for(const p of [...guns,...a.parkAxes,...a.parkKarts,...a.chalkPickups])assert.ok(Math.hypot(p.x-a.parkHalfPipe3D.x,p.z-a.parkHalfPipe3D.z)>650); +}); + +test('outdoor circuit has real elevation and kart barriers preserve tangential travel',()=>{ + const a=playground(),t=a.outdoorCircuit(),p=a.players[0]; + assert.ok(Math.abs(a.poolFloorAt(t.x,t.z-t.radius)-a.poolFloorAt(t.x,t.z+t.radius))>400); + const previous={x:t.x+t.radius+270,z:t.z};Object.assign(p,{goKart:{},x:t.x+t.radius+340,z:t.z,y:a.poolFloorAt(t.x+t.radius,t.z),vx:1500,vz:600}); + a.boundParkBody(p,previous);assert.ok(p.x<=t.x+t.radius+280.001);assert.ok(p.vx<0);assert.equal(p.vz,600); + a.updateCameraDoll(1,a.now());assert.ok(a.cameraDoll.position.yCreateTexture2D(&texture,&pixels,&m_decalTexture)); Check(m_device->CreateShaderResourceView(m_decalTexture.Get(),nullptr,&m_decalView)); m_decalSurface.clean(); - LogTelemetry("AC_NATIVE_DECALS ready=1 atlas=256x256 surface=2048x2048 retained=1 alpha=1"); + LogTelemetry("AC_NATIVE_DECALS ready=1 atlas=256x256 surface=4096x4096 retained=1 alpha=1"); m_frameThemeQuads.reserve(kMaxThemeQuads); LogTelemetry(std::string("AC_NATIVE_THEME ready=") + (m_themeViews[0] && m_themeViews[1] ? "1" : "0") + diff --git a/xbox/native-bios/Package.appxmanifest b/xbox/native-bios/Package.appxmanifest index 9c1ea1b5f0..17be5272bc 100644 --- a/xbox/native-bios/Package.appxmanifest +++ b/xbox/native-bios/Package.appxmanifest @@ -6,7 +6,7 @@ IgnorableNamespaces="uap mp rescap"> + Version="1.0.0.61" /> diff --git a/xbox/native-bios/QuickJsEngine.cpp b/xbox/native-bios/QuickJsEngine.cpp index 0bcfeb86a1..ef9b1bf5e1 100644 --- a/xbox/native-bios/QuickJsEngine.cpp +++ b/xbox/native-bios/QuickJsEngine.cpp @@ -1016,6 +1016,7 @@ class QuickJsPiece final : public JsPiece { JS_SetPropertyStr(context_, global, "meshUpload", JS_NewCFunction(context_, MeshUpload, "meshUpload", 3)); JS_SetPropertyStr(context_, global, "meshDraw", JS_NewCFunction(context_, MeshDraw, "meshDraw", 7)); JS_SetPropertyStr(context_, global, "meshFree", JS_NewCFunction(context_, MeshFree, "meshFree", 1)); + JS_SetPropertyStr(context_, global, "decalSurfaceSize", JS_NewInt32(context_, 4096)); JS_SetPropertyStr(context_, global, "meshTransparency", JS_NewBool(context_, true)); JS_SetPropertyStr(context_, global, "triangle3d", JS_NewCFunction(context_, Triangle3d, "triangle3d", 12)); JS_SetPropertyStr(context_, global, "triangles3d", JS_NewCFunction(context_, Triangles3d, "triangles3d", 2)); diff --git a/xbox/native-bios/tests/quickjs_engine_smoke.cpp b/xbox/native-bios/tests/quickjs_engine_smoke.cpp index e1a24d27aa..04e951252b 100644 --- a/xbox/native-bios/tests/quickjs_engine_smoke.cpp +++ b/xbox/native-bios/tests/quickjs_engine_smoke.cpp @@ -42,13 +42,13 @@ int main() { const auto* allocation=surface.pixels.data(); assert(surface.stamp({0,0,128,128,20,20,44,20,44,44,20,44})); assert(surface.dirty && surface.left==20 && surface.right==44); - unsigned alpha=0;for(unsigned y=20;y<44;y++)for(unsigned x=20;x<44;x++)alpha+=surface.pixels[(y*2048+x)*4+3]; + unsigned alpha=0;for(unsigned y=20;y<44;y++)for(unsigned x=20;x<44;x++)alpha+=surface.pixels[(y*DecalSurface::side+x)*4+3]; assert(alpha>0); const auto before=surface.pixels; for(int i=0;i<10000;i++)assert(surface.stamp({0,0,128,128,100,100,108,100,108,108,100,108})); - assert(surface.pixels.data()==allocation && surface.pixels.size()==2048u*2048u*4u); + assert(surface.pixels.data()==allocation && surface.pixels.size()==DecalSurface::side*DecalSurface::side*4u); for(unsigned y=20;y<44;y++)for(unsigned x=20;x<44;x++)for(int k=0;k<4;k++) - assert(surface.pixels[(y*2048+x)*4+k]==before[(y*2048+x)*4+k]); + assert(surface.pixels[(y*DecalSurface::side+x)*4+k]==before[(y*DecalSurface::side+x)*4+k]); assert(!surface.stamp({250,0,128,128,0,0,10,0,10,10,0,10})); surface.clear();for(auto value:surface.pixels)assert(value==0); } diff --git a/xbox/runtime/include/ac/decal_surface.hpp b/xbox/runtime/include/ac/decal_surface.hpp index 6648939244..cfa880cb3e 100644 --- a/xbox/runtime/include/ac/decal_surface.hpp +++ b/xbox/runtime/include/ac/decal_surface.hpp @@ -6,7 +6,7 @@ namespace ac::xbox { // A fixed raster canvas. Stamps are blended once; no stamp history is retained. class DecalSurface { public: - static constexpr unsigned side = 2048; + static constexpr unsigned side = 4096; std::vector pixels = std::vector(side * side * 4); unsigned left=0, top=0, right=side, bottom=side; bool dirty=true; -- 2.51.2