paavohtl Claude Opus 4.6 (1M context) commited on
Commit
cde9dcb
Β·
1 Parent(s): 94ea94e

docs: update CLAUDE.md for address registry, openwa-derive, and key files

Browse files

Add Address Registry & Pointer Identification section documenting
define_addresses!, #[derive(FieldRegistry)], and the query API.
Update crate architecture to include openwa-derive. Update key files
list with registry.rs, macros.rs, and mem.rs.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

Files changed (1) hide show
  1. CLAUDE.md +49 -2
CLAUDE.md CHANGED
@@ -114,7 +114,8 @@ Key env vars:
114
 
115
  ## Crate Architecture
116
 
117
- - **`openwa-core`** β€” Types, addresses, parsers, ASLR rebasing, and typed WA function wrappers. The source of truth for all reverse-engineered type layouts and known addresses (`address.rs`). Contains `rebase` (ASLR delta), `wa_call` (calling convention helpers), and `wa/` (typed handle wrappers like `DDGameWrapperHandle`, `CWndHandle`).
 
118
  - **`openwa-wormkit`** β€” Unified WormKit cdylib that replaces WA functions with Rust and optionally validates types against live memory. Logs to `OpenWA.log` (hooks) and `OpenWA_validation.log` (validation). Uses MinHook for inline hooking. Validation is enabled via `OPENWA_VALIDATE=1` env var.
119
  - **`openwa-harness`** β€” Offline test harness that loads WA.exe into process memory via `LoadLibraryExA(DONT_RESOLVE_DLL_REFERENCES)` for testing without running the game.
120
  - **`openwa-test-runner`** β€” Headless replay test runner (`openwa-test` binary). Discovers replay tests, runs them concurrently via WA.exe's `/getlog` mode, compares output logs. See "Replay Testing" section.
@@ -173,7 +174,10 @@ Currently dormant β€” no hooks wired up. Activate by adding calls in `game_sessi
173
 
174
  ## Key Files
175
 
176
- - `crates/openwa-core/src/address.rs` β€” All known WA.exe addresses with comments
 
 
 
177
  - `crates/openwa-core/src/wa_call.rs` β€” Helpers for calling WA functions (thiscall, stdcall wrappers)
178
  - `crates/openwa-core/src/rebase.rs` β€” ASLR delta computation
179
  - `crates/openwa-core/src/wa/` β€” Typed WA function wrappers (MFC, frontend, registry, DDGame)
@@ -195,6 +199,49 @@ A Ghidra MCP bridge is configured in `.mcp.json`. When using Ghidra tools:
195
  - `C:\koodia\worms-re\thirdparty\wkJellyWorm\` β€” Extensive RE data: task hierarchy, vtables, enums, weapon structs
196
  - `C:\koodia\worms-re\thirdparty\WormKit\` β€” Modding framework, game state structures
197
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
198
  ## Design Conventions
199
 
200
  - Unknown struct fields as `_unknown_XX` padding arrays
 
114
 
115
  ## Crate Architecture
116
 
117
+ - **`openwa-core`** β€” Types, addresses, parsers, ASLR rebasing, and typed WA function wrappers. The source of truth for all reverse-engineered type layouts and known addresses. Contains `registry` (structured address database + field registries), `rebase` (ASLR delta), `wa_call` (calling convention helpers), and `wa/` (typed handle wrappers like `DDGameWrapperHandle`, `CWndHandle`).
118
+ - **`openwa-derive`** β€” Proc macro crate. Provides `#[derive(FieldRegistry)]` for auto-generating field maps from `#[repr(C)]` structs using `offset_of!()`.
119
  - **`openwa-wormkit`** β€” Unified WormKit cdylib that replaces WA functions with Rust and optionally validates types against live memory. Logs to `OpenWA.log` (hooks) and `OpenWA_validation.log` (validation). Uses MinHook for inline hooking. Validation is enabled via `OPENWA_VALIDATE=1` env var.
120
  - **`openwa-harness`** β€” Offline test harness that loads WA.exe into process memory via `LoadLibraryExA(DONT_RESOLVE_DLL_REFERENCES)` for testing without running the game.
121
  - **`openwa-test-runner`** β€” Headless replay test runner (`openwa-test` binary). Discovers replay tests, runs them concurrently via WA.exe's `/getlog` mode, compares output logs. See "Replay Testing" section.
 
174
 
175
  ## Key Files
176
 
177
+ - `crates/openwa-core/src/address.rs` β€” Known WA.exe addresses (segment boundaries + re-exports from home modules)
178
+ - `crates/openwa-core/src/registry.rs` β€” Structured address registry, field registries, live object tracker, query API
179
+ - `crates/openwa-core/src/macros.rs` β€” `define_addresses!` macro and `vcall!` macro
180
+ - `crates/openwa-core/src/mem.rs` β€” Pointer classification and `identify_pointer()` for debug tools
181
  - `crates/openwa-core/src/wa_call.rs` β€” Helpers for calling WA functions (thiscall, stdcall wrappers)
182
  - `crates/openwa-core/src/rebase.rs` β€” ASLR delta computation
183
  - `crates/openwa-core/src/wa/` β€” Typed WA function wrappers (MFC, frontend, registry, DDGame)
 
199
  - `C:\koodia\worms-re\thirdparty\wkJellyWorm\` β€” Extensive RE data: task hierarchy, vtables, enums, weapon structs
200
  - `C:\koodia\worms-re\thirdparty\WormKit\` β€” Modding framework, game state structures
201
 
202
+ ## Address Registry & Pointer Identification
203
+
204
+ The `registry` module in `openwa-core` provides a structured, queryable database of known addresses. Three systems work together:
205
+
206
+ ### `define_addresses!` macro
207
+
208
+ Defines known WA.exe addresses with metadata (kind, calling convention, class name). Generates both `pub const` values and `inventory`-collected `AddrEntry` items for runtime queries. Supports class blocks and standalone entries:
209
+
210
+ ```rust
211
+ crate::define_addresses! {
212
+ class "CTaskWorm" {
213
+ vtable CTASK_WORM_VTABLE = 0x0066_44C8;
214
+ ctor CTASK_WORM_CONSTRUCTOR = 0x0050_BFB0;
215
+ }
216
+ fn/Fastcall ADVANCE_GAME_RNG = 0x0053_F320;
217
+ global G_GAME_SESSION = 0x007A_0884;
218
+ }
219
+ ```
220
+
221
+ **Distributed definitions**: Each module defines its own addresses via `define_addresses!`. `address.rs` re-exports them into `mod va` for backward compatibility (`va::CTASK_WORM_VTABLE` still works). When adding new addresses, place the `define_addresses!` block in the home module, then add a `pub use` re-export in `address.rs`.
222
+
223
+ ### `#[derive(FieldRegistry)]`
224
+
225
+ Auto-generates a field map for `#[repr(C)]` structs using `offset_of!()`. Fields prefixed `_unknown`/`_pad` are skipped. Applied to all key structs (DDGame, CTask, CTaskWorm, etc.). Enables runtime offset β†’ field name lookups.
226
+
227
+ ```rust
228
+ #[derive(FieldRegistry)]
229
+ #[repr(C)]
230
+ pub struct CTask { ... }
231
+ // Generates: CTask::field_registry() -> &'static StructFields
232
+ // Also registers in global inventory for struct_fields_for("CTask")
233
+ ```
234
+
235
+ ### Query API (`registry::*`)
236
+
237
+ - `lookup_va(ghidra_va)` β€” find address entry by VA (exact or nearest-below)
238
+ - `vtable_class_name(ghidra_vtable)` β€” vtable address β†’ class name
239
+ - `format_va(ghidra_va)` β€” human-readable name string
240
+ - `struct_fields_for("DDGame")` / `struct_fields_for_vtable(va)` β€” get field map
241
+ - `field_at_inherited("CTaskWorm", offset)` β€” inheritance-aware field lookup (walks CTaskWorm β†’ CGameTask β†’ CTask)
242
+ - `identify_pointer(value, delta)` β†’ `PointerIdentity` β€” full pointer identification (static addresses, live objects, vtable-based object detection)
243
+ - `register_live_object()` / `identify_live_pointer()` β€” track heap objects for field-level pointer resolution
244
+
245
  ## Design Conventions
246
 
247
  - Unknown struct fields as `_unknown_XX` padding arrays