Releases: Rawframe-Project/maul2d
Release list
v1.10: the host integration release
The host integration release, a full audit of the embedding
contract answered:
- The engine opens no threads: parallelism rides the host's task
executor (the same enqueue/finish contract as Box2D v3 and
Maul3D), and the Threads::Threads dependency is gone. - The host owns diagnostics: a contextful assert handler sees
every internal failure first, and the CPU-backend guard that
was the one release-abort now refuses with a null id. - Refusals carry typed reasons (m2Result / m2LastResult).
- Worlds weigh themselves (m2World_MemoryBytes).
- The threading contract is written into the header and raced in
CI: distinct worlds on distinct threads, bit-identical to
serial. - The API census counts itself: 277 frozen 1.x functions,
regenerated and asserted by CI.
Worker-count invariance, the golden hash, and every determinism
gate held to the bit throughout.
v1.9.0
Maul2D 1.9.0: the hardened release
This release caps a full hardening pass over the engine. The contract is unchanged and unbroken: the same inputs produce the same bits on every platform, snapshots restore exactly, and the command journal replays onto identical bits. Sixteen gated hash lines are checked across ten platform cells (x64 AVX2, arm64 NEON, portable scalar, WebAssembly) on every commit.
What landed
- WebAssembly and a browser testbed. The engine compiles to wasm32 bit-identically to native, and the interactive testbed runs in the browser at the project's GitHub Pages.
- Destruction and fluids.
m2World_ShatterBodybreaks a body into pieces carrying the parent's velocity field, journaled as one op. Particle-free buoyancy volumes give drag and lift without a fluid. Particles gained lifetime and userData. - Determinism tooling. Per-subsystem hashes (
m2World_HashParts) bisect a divergence; a validate build mode with misuse and overflow counters; a fuzzer deepened with a regression bank and a weekly deep sweep; a coverage audit that brought the debug-draw path to a dedicated suite. - Solver stability. An over-constrained scene can no longer pump velocity to infinity: linear and angular speed are capped the way the reference does, which also surfaced and fixed a latent journal-replay divergence in the belt-wake path.
- Portability.
m2GetSimdBackendandm2CpuSupportsBackendreport the compiled SIMD backend and whether this CPU can run it; an AVX2 build on a CPU without AVX2 now aborts with a clear message instead of trapping. Prebuilt packages ship a portable scalar variant for each x64 platform, bit-identical to AVX2 but running anywhere.
Packages
maul2d-v1.9.0-linux-x64,-windows-x64,-macos-arm64: the dev library (headers, static lib, CMake package, pkg-config). x64 targets AVX2 (Haswell 2013+).maul2d-v1.9.0-linux-x64-portable,-windows-x64-portable: the scalar backend, bit-identical and running on any x64.Maul2D-testbed-v1.9.0-linux-x64,-windows-x64: the playable testbed. The same demo runs in the browser from the project page.
The 1.x API surface stays frozen: signatures, semantics and id layouts do not change until a 2.0; additions arrive in minor releases like this one.
Full Changelog: v1.8.0...v1.9.0
v1.8.0: the settled release
The maturity sprint closes. Since the completion release: red-team round eight (seven attacks on the fluids, machinery, jelly and decompose surface, all held), the fuzzer now fills pools and tears nets under all four promises on every seed and cell, a weekly scheduled CI run of the full matrix plus a 300k-step soak guards against toolchain drift, the 1.x API surface is frozen with its format contract written into the guide, cmake install / find_package / pkg-config all hand consumers the same bits (verified end to end), tag pushes attach prebuilt static libraries for Linux, Windows and macOS (this release is the first to carry them, built by the new pipeline), the testbed's goo scene shows the whole particle palette in color, samples/minimal takes a newcomer from install to a hash-verified rollback in ten minutes, and particles answer region queries under the standard enumeration contract. Wire v30, snapshot v31, 16 gated determinism lines across 9 CI cells and 3 instruction sets.
v1.6.0: the water release
Deterministic particle fluids join the contract: an opt-in per-world pool (fixed capacity, physics pinned at creation) with slot-stable storage, a canonical neighbor grid, a LiquidFun-lineage relaxation solver (pressure, damping, optional viscosity), two-way rigid coupling (light things float, dense things sink), anti-tunneling projection, one-way platform and sensor laws, and wake-on-touch. Everything lives inside the same snapshot, journal and hash discipline as the rigid world: 16 gated determinism lines across 9 CI cells and 3 instruction sets, with the API fuzzer driving water through all four promises on every seed. The testbed gains a faucet-and-basin scene whose pour rewinds bit for bit; the guide gains the Water chapter. Wire v25, snapshot v28. The reference lineage is credited in THIRD_PARTY.md.
Maul2D v1.5.0
Maul2D 1.5.0: the second basket
- Leftover parity basket: body/shape/chain/joint world accessors,
AABB readers, point and frame helpers, per-shape queries, manual
sleep, runtime bullet/density/user data (joints included), drift
readers, kinematic follow via SetTargetTransform. - Richer distance joint: hard length ranges built on stiff stops
that beat soft ropes, runtime SetLength/SetLengthRange, and
journaled spring retuning across joint types (mouse drag spring
included). - All-hits queries: CastRayAll and swept circle/capsule/polygon
variants, ascending fractions, truthful totals, closest kept
under capacity pressure. - The character mover kit: CollideMover planes, the SolvePlanes
accumulated-push solver, ClipVector, with CastCapsuleClosest as
the mover cast. Pure and replay-safe. - The interactive testbed (eight scenes, mouse-joint grabbing,
explosions, the rewind ring that plays time backward) and a
Windows cross-build path.
Wire v20, snapshot v24, all under the standing contract: three
instruction sets, one bit law, fifteen gate lines across nine CI
cells, the mirror, and the fuzzer.
Maul2D v1.4.0
Maul2D 1.4.0: the parity release
The feature-parity sprint against Box2D v3.1.1, complete in six
slices:
- Body dynamics: forces and torques with one-step lifetime, linear
and angular damping (Pade form), fixed rotation as a mass
property, sleep control per body and per world. - Queries: convex sweeps (circle, capsule, polygon) and shape
overlaps through one GJK kernel with the one-sided chain law. - Joints: collideConnected on every def, plus the filter, motor and
mouse joints with journaled runtime retargeting. - Integration: body dormancy (Disable/Enable), mass override with a
documented lifetime, m2World_Explode as one deterministic journal
op, frame helpers, per-body joint enumeration, live shape
geometry with type changes, chain material retuning. - Deliberate absences documented in the guide.
Wire v18, snapshot v23. Everything under the standing contract:
bit-identical across AVX2, NEON and scalar backends, 15 gate lines
compared across 9 CI cells, rollback and journal replay proven by
the mirror test and the hostile-integrator fuzzer.
Maul2D v1.3.0
Maul2D 1.3.0: the simd release
x64 baseline moves to AVX2+FMA (Haswell 2013+); arm64 is NEON.
src/simd.h: eight-lane vectors with a bit law: every operation is a
single-rounding IEEE op with identical semantics on AVX2, NEON and
the scalar fmaf fallback. min/max are compare+select (SSE and NEON
disagree about NaN and signed zero), fused multiply-add is explicit
and correctly rounded everywhere, implicit contraction stays
forbidden. The contact warm-start and solve kernels are written once
against that API.
The law is a hard gate, not a promise: CI's sanitize cell builds
with -DMAUL2D_SIMD=scalar and its 15 gate hashes join the
cross-platform comparison as a ninth cell; AVX2 cells, NEON cells
and the scalar cell must produce identical bits or the build is red.
They did, on first contact.
Need the old baseline? -DMAUL2D_SIMD=scalar builds a portable
fallback with bit-identical results.
Maul2D v1.2.0
Maul2D 1.2.0: the integrator surface
Everything an engine layer or editor needs to walk, read, and
rebuild a world from a bare world id:
- Enumeration: m2World_GetBodies/GetJoints/GetChains,
m2Body_GetShapes, m2Chain_GetShapes. Ascending slot order,
truthful totals. - Introspection: body type, local center, bullet flag, gravity
scale; shape type, sensor flag, filter, density; joint type and
endpoint bodies. - Geometry readback: exact stored bits for all five shape kinds.
- Joint parameter readback: every def field has a getter, including
break limits.
The surface is provably complete: the mirror test rebuilds a world
from public getters alone and holds hash equality with the original
through 90 steps.
No wire or snapshot changes; every addition is a pure reader, proven
by byte-identical gate hashes across the three slices.
Maul2D v1.1.0
Maul2D 1.1.0
Chains become first-class: m2CreateChain returns m2ChainId (breaking
change vs 1.0.0: the segment count moved to m2Chain_GetSegmentCount),
m2DestroyChain removes a whole run by handle, slots retire with
generation bumps, chains die with their body.
Destroy-path wake law: destroying a body, shape, or chain wakes
whatever was resting on it. Sleepers no longer float on a memory.
Joint reaction getters: m2Joint_GetReactionForce/Torque return the
exact numbers the break pass compares, from one shared computation.
Snapshot v19, journal wire v14 (op 24). Red-team round 7 passed:
rollback resurrects chains bit-exactly, lifecycle journals replay
onto identical hashes, restored reaction readings match to the bit.
Maul2D v1.0.0
Maul2D 1.0.0
Deterministic across eight platform cells, rollback-native,
journal-replayable, red-teamed six times, banded against Box2D v3 in
behavior and now within one and a half times of it in active-scene
speed with portable C. The contract: cross-platform bit determinism,
bit-exact rollback, replayable history. The guide in docs/ is the
ten-minute tour.