docs: update CLAUDE.md for address registry, openwa-derive, and key files
Browse filesAdd 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>
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
|
|
|
|
| 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` β
|
|
|
|
|
|
|
|
|
|
| 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
|