Files
ReSkate/Engine/Game/Build/20260929/physics_wake.h
T
AyeZeeBB 7dabd99a40 Crashes: the Trainer no longer writes into freed memory, throwdown models go before a level unload, and a gone texture draws nothing instead of crashing
From the first 6k Sentry reports of 55a7342 (2026-10-24), whose top sites were all new since 2.1.1:

- Trainer: scale_underflip_bands wrote the underflip rate bands' MinScale and MaxScale every tick on
  every copy it had ever found, checking only that the address was readable. A level's copies go back
  to the game's heap with it, so 1.0 and 0.6 landed in the upper half of whatever the game made there
  next (Skate.exe+0x157f930, +0x12a1549, +0x10084de, +0x11ef49e, +0x3db81ea, +0x12c21ca: about a
  third of the crashes, every dump with a pointer whose high dword is one of those floats). A copy is
  now written only while it still is that band and holds the game's band or the last one written;
  any other is forgotten.
- Throwdowns: models the page released were destroyed 3 s later by the menu tick, which does not run
  while a level loads, so the game's own flush of the unloaded level's types destroyed them after
  their assets were freed (Skate.exe+0x3dc5eaa, 18%). Before a level unload they are destroyed at
  once, as the native menu's own are.
- Textures: the guard's "default for the id" is the entry itself, so for a dead entry resolve gave a
  null texture, and the texture view cache asked it for its key (Skate.exe+0x3e6ddc1, 17%, every
  report with TheVlixOne-Nike_Pack). A stub at the cache insert hands back the empty view the cache
  already built when the texture is null; the guard is on only when that patch applies.
- Physics: the wake guard widens every pass because ReSkate raises the owner pool to 160000; its log
  line now says so once instead of claiming a prevented crash thousands of times a session.

Built; not yet checked in the game.
2026-10-24 17:19:32 -05:00

32 lines
2.2 KiB
C++

#pragma once
#include "Engine/Game/Build/fingerprint.h"
#include <cstdint>
// The physics entity system's wake pass (Extension/World/physics_wake_guard.cpp).
//
// wake(system), a per-frame callback of the Physics entity system (its vtable at 0x64c6ff8,
// called from the entity world's update at 0x3cd6055), collects the bodies changed this step
// (0x269c270 on the world at system + 0x20), finds each one's physics owner (0x25d5f90, by the
// state's body-to-owner list at + 0xb30) and calls each owner once (owner + 0x18 -> vtbl + 0xf0).
// It keeps "once" in a bitset on the heap with a bit for each of `owner_limit` owners
// (system + 0xf8, a Physics setting: 20000), and sets the bit of an owner's index (0x3d2f846)
// without checking it against that. An index is good while it is below the world's owner
// count (its generation list, world + 0x810 .. + 0x818, four bytes each; 0x25d7d90), and the
// owner pool hands indices out first in, first out, so after a long session in which many
// bodies come and go (multiplayer's remote skaters, made and removed as players cross the
// build radius) indices pass 20000. The bit then lands in the next heap block's header, and a
// later free crashes in the allocator (Skate.exe+0x3d99e2f, +0x3d9ee43, +0x3d9ee47; indices
// 20199, 20203 and 20215 in three dumps, the next block's size off by exactly that bit;
// 2026-10-21).
// The owner count is past 20000 in every session because ReSkate raises the owner pool to 160000
// (Extension/World/physics_world_size.cpp) and the generation list is sized to the pool; the setting
// is written only by the system's init (0x3d2fe20) and read only by the wake pass (2026-10-24).
namespace dingosdk::game::build::v20260929::physics_wake {
inline constexpr Fingerprint wake{0x3d2f780, {
0x48,0x89,0x5c,0x24,0x08,0x48,0x89,0x7c,0x24,0x10,0x55,0x48,0x8d,0x6c,0x24,0xa9,
0x48,0x81,0xec,0xa0,0x00,0x00,0x00,0x48,0x8b,0xd9,0x48,0x8d,0x55,0x0f,0x48,0x8b}};
inline constexpr std::ptrdiff_t world_offset = 0x20; // system + 0x20: the world
inline constexpr std::ptrdiff_t owner_limit_offset = 0xf8; // system + 0xf8: u32, the bitset's size in owners
inline constexpr std::ptrdiff_t owner_generations_begin = 0x810, owner_generations_end = 0x818; // world: u32 each
}