Skip to content

Parity audit — 2026-06-12

Six parallel subsystem audits comparing the Ghidra decompile (analysis/ghidra/raw/crimsonland.exe_decompiled.c, line refs below) against the Python port. Known/intentional divergences documented in docs/rewrite/original-bugs.md or gated behind --preserve-bugs were excluded; everything listed here appears to be an undocumented divergence. Items are suspected until validated against a Frida capture.

Subsystems covered: weapons, perks, creatures, bonuses/player, projectiles/collision/RNG, modes/quests. Each section ends with what was verified clean, so coverage is close to exhaustive for these subsystems rather than a sample.

This file doubled as the remaining-work tracker: each fixed finding was removed in the same commit as its fix. All findings are now resolved - the sections below record what the audit verified as already matching native. Replay fixtures recorded before this series need re-recording (the fixes change the deterministic RNG stream), and the python and zig runtimes produce byte-identical verify payloads on kill-bearing replays (scripts/gen_kill_replay.py).


Verified clean

  • RNG core: CrtRand exactly matches the CRT LCG @ 0x461746 (multiplier 0x343fd, increment 0x269ec3, >> 16 & 0x7fff); seeding/masking/advance correct.
  • Weapon table (weapon_table_init @ 0x4519b0 vs weapons.py): clip/cooldown/ reload/spread/flags/ammo-class/travel/damage cross-checked across the full roster, including icon quirks and misspelled names behind preserve_bugs.
  • Per-weapon fire recipes: pellet counts, jitter/speed RNG masks and call order, Multi-Plasma fan, casing draws, aim-jitter draws, SFX variant draw, muzzle-sprite ordering and alpha tables, cooldown/spread/ammo bookkeeping, reload paths (fastloader/anxious/stationary/angry).
  • Projectile pipeline: projectile_spawn (fire-bullets override incl. double shots-fired quirk), 3-substep movement with f32 spill placement, damage formula ((100/max(50,d))*scale*30+10)*0.95, pierce pool bookkeeping, ion AoE constants, shock-chain hop rules, secondary constants (accel caps, detonation scales, damage formulas, decal/shard counts), frame update order (perks → effects → creatures → projectiles → player → modes → bonus timers).
  • Perks: choice generation (7-slot fill, Monster Vision force, Death Clock block-list sentinel, rarity gates, attempt escapes), perk_can_offer prereqs/flags, apply effects for ~30 perks (magnitudes, RNG order), player-damage perk chain, creature-damage multipliers.
  • Creatures: survival_spawn_creature type tiers/rare rolls/stat formulas, AI modes 0–8 target math, turn rates, anim multipliers, plague spread/tick, contact-damage flow, ranged-fire gates, death staging and handle_death ordering, radius-damage margin, spawn-slot timer semantics.
  • Bonuses: drop-selection buckets (roll%162 mapping, fallbacks, suppression rules), effect magnitudes/durations × Bonus Economist, nuke/freeze recipes, pickup/decay rules, try_spawn_on_kill (documented bugs gated), Telekinetic.
  • Modes: survival wave pacing/milestones/weapon handouts, rush spawn cadence and stats, quest timeline interpreter, hardcore spawn-table adjustment, quest results reveal cadence, typo pacing, level-up thresholds.
  • Player: movement/aim constants, XP curve, player damage chain incl. documented co-op bugs.

Follow-up

Validate the full series against a fresh Frida capture of the original binary when convenient; the unit tests pin the decompile-derived behavior, but a capture run is the ground-truth check.