CTaskCloud.pos_y was never a position — it's a per-frame animation phase
counter passed as the palette arg to blit_sprite. Rename to anim_phase
(and vel_y to phase_speed) to match actual semantics. Migrate the cloud
producer from DrawSpriteCmd to RenderMessage::Sprite as the first typed
render queue user.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
refactor: rename openwa-wormkit crate to openwa-dll, output openwa.dll
The project hasn't been a WormKit DLL for a long time — it requires a
custom launcher. Rename the crate to openwa-dll with output openwa.dll
to match the rest of the naming convention (openwa-core, openwa-launcher).
Updates all references across Cargo.toml, Rust sources, PowerShell scripts,
CLAUDE.md, skill files, and docs. Replaces stale "wormkit hook/shim"
comments with accurate descriptions. Three remaining "WormKit" references
are legitimate (refer to the actual WA modding framework).
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
The old input.rs was a grab-bag of unrelated concerns. Split into:
- frame_hook.rs: TurnManager_ProcessFrame hook, debug_sync, watchpoint
arming. Always installed (including baseline/trace-desync mode).
- replay_test.rs: Fast-forward + gameplay milestone tracking. Only for
headful replay testing — headless runs at max CPU speed already.
- debug_utils.rs: dump_region memory inspection (used by validation).
Moved get_ddgame()/get_wrapper() to openwa-core::engine::game_session
as shared #[cfg(x86)] accessors, eliminating duplicates in wormkit
and debugui.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
The raw fields grid now has a "Points to" column that uses
identify_pointer() to annotate each DWORD value:
- Static addresses: "→ CTASK_WORM_VTABLE"
- Heap objects with known vtable: "→ DSSound*"
- Fields inside tracked live objects: "→ DDGame.sound"
Pointer labels shown in light blue for visual distinction.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
feat: replace hardcoded debug UI field labels with registry lookups
Remove CGAMETASK_FIELD_LABELS and all per-entity extra_labels arrays
from the debug UI inspector. Field names are now resolved via
registry::field_at_inherited() which walks the CTask inheritance chain
(entity → CGameTask → CTask).
Add #[derive(FieldRegistry)] to CGameTask and CTaskMissile. Add
field_at_inherited() helper for inheritance-aware offset → name lookup.
Entity types without Rust struct definitions (CTaskMine, CTaskOilDrum,
CTaskCrate) will show base class fields only until their structs are
defined — but any new struct fields are automatically picked up.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
feat: add structured address registry with runtime pointer identification
Replace flat pub const address definitions with define_addresses! macro
that generates both compile-time constants and a global queryable registry
via the inventory crate. ~200 addresses now have structured metadata
(kind, calling convention, class name).
Key additions:
- registry.rs: AddrEntry types, sorted lookup table, query API
(lookup_va, vtable_class_name, format_va, detect_pointer)
- define_addresses! macro: class blocks group vtable+ctor+vmethods,
standalone entries for functions/globals/data
- detect_pointer() in mem.rs: identifies static addresses by name,
heap objects by vtable class name
- classify_pointer() detail strings now include registry names
Eliminates three duplicated vtable→name mappings in snapshot.rs,
debugui/app.rs, and validation/mod.rs. All 488 existing va::* call
sites compile unchanged.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
feat: add Cheats menu to debug UI with "Unlock all weapons"
Add a menu bar to the debug UI toolbar with a Cheats dropdown.
"Unlock all weapons" sets ammo to -1 (unlimited) and delays to 0
for all 6 alliances across all 71 weapons, using the new typed
WeaponSlots/TeamWeaponSlots structs.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Reduce from 4 to 2 DDGameWrapper__LoadingProgressTick calls, matching
the original constructor. Tick counter +0x04D8 now matches exactly
(0x334). All DDGameWrapper fields match the original.
Remaining headless checksum mismatch is likely due to headless display
handling differences (our headless display is non-null vs original's
NULL display parameter).
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
feat: add CTaskCrate struct, raw field debug UI, new task fields
Runtime analysis of CTask__AppendChild (0x4fdc70) and CTask__UnlinkChild
(0x4fdce0) reveals the true semantics of the children sub-struct:
+0x08 children_capacity — starts 0x10, doubles on overflow
+0x0C children_dirty — flag set to 1 when any child is unlinked
+0x10 children_watermark — insertion counter, never decremented on remove
+0x14 children_data — sparse pointer array; dead slots are nulled
The append-only watermark means CTaskFilter's "(N children)" label was
rising unboundedly as sea bubbles spawned. Fixed by computing live count
from non-null slots rather than reading children_watermark directly.
Also adds dump_ctask_children() to validation (F8 hotkey) for live
verification of these fields. Ghidra functions renamed accordingly.
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
feat: update debug UI with TurnGameCtx and CTaskTeam new fields
- CTaskTeam (0x460 bytes, vtable 0x669EE4, class_type=10): per-team entity
with team_index (+0x38), _item_slots[100] (+0x88), worm_count (+0x218)
- Size confirmed from malloc(0x460) in FUN_005528c0 (the factory function)
- Secondary interface vtable at +0x30 (Ghidra 0x669F00)
- Registered in SharedData with type code 0x15 (team_index as key)
- Rename CTaskTurnGame._ctaskteam → _game_ctx with detailed comment
explaining it's the intermediate game-context base (class_type=5, vtable
0x669C44), NOT the per-team CTaskTeam — different class, different size
- Add CTaskTeam offset_of! checks in validation (team_index, worm_count)
- Add CTaskTeam inspector section in debug UI (team_index, worm_count)
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
feat: add CTaskFire and CTaskTurnGame structs with runtime validation
- CTaskFire (0xD8 bytes, class_type=0x18): spawn coords, timer, burn_rate,
spread_counter, lifetime, slot_index fields
- CTaskTurnGame (0x2E0 bytes): 15 named fields covering timers (turn_timer
+0x18C, idle_timer +0x184, retreat_timer +0x178), team tracking
(current_team, current_worm, arena_team, arena_worm), and frame counters
(active_worm_frames, retreat_frames, _timer_scale); all offsets runtime-
validated via offset_of! checks (15 PASS)
- dump_turngame(): finds TurnGame via vtable scan + SharedDataTable, dumps
known fields and full 0x2E0-byte raw region via dump_region
- dump_region refactored from DDGame-specific to generic *const u8 base
- replay-test.ps1: fix launcher invocation (pass $waExe explicitly so
replay file is forwarded as a WA.exe arg, not misinterpreted as exe path)
- Debug UI inspector sections for CTaskFire and CTaskTurnGame
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
feat: add CTaskFire struct and debug inspector support
- Add CTASK_MISSILE_VTABLE (0x664438) to address.rs
- Add CTaskMissile to KNOWN_VTABLES in debug UI census
- Remove shared_data/owns_data/ddgame from CTask base inspector (same for every entity)
- Ghidra: label CTaskMissile__vtable and rename 6 overridden methods
(Init, Free, HandleMessage, PhysicsUpdate_Maybe, vt12, vt18_GetField130)
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
feat(debugui): task tree entity census, transient filtering, scrollable inspector
- Replace SharedDataTable-based census with full DFS from CTaskTurnGame root,
so parent-hierarchy entities (CTaskTurnGame etc.) are included and the
liveness check no longer wrongly prunes them
- Filter transient entities (CTaskSeaBubble) from census by default; toolbar
checkbox toggles visibility and shows hidden count in the entity label
- Wrap inspector body in a ScrollArea so long entity trees are fully reachable
- Make census ScrollArea fill panel width (auto_shrink disabled, num_columns=3)
- Add CTASK_SEA_BUBBLE_VTABLE (0x669E88) to address.rs
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
fix(debugui): clear stale entity selection when entity is destroyed
Build a live-entity snapshot once per frame and prune selected_entity and
nav_history before rendering, preventing UAF crashes when the inspected
entity is freed (match ended, worm died, etc.).
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
feat: add egui debug UI window with entity census, inspector, and log panel
Spawns a floating egui/eframe window in the same process as WA.exe (DLL
injection) when OPENWA_DEBUG_UI=1. Shows a live entity census from the
SharedData hash table, a struct inspector with navigation history, and a
scrollable log stream.
- New crate: openwa-debugui (egui 0.28 + glow backend, winit any-thread)
- Entity type names resolved via vtable map with ClassType fallback
- Children tree reads sparse slot array (children_size = high-watermark)
- Add CTASK_MINE/OILDRUM/CLOUD_VTABLE constants to address.rs (derived
from runtime vtables: delta 0x6C0000)
- debug-ui feature gate in openwa-wormkit; deploy-debug.ps1 / start-debug.ps1
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>