Overview
Without debug symbols or RTTI, struct layouts must be reconstructed by:- Static analysis - Memory access patterns in decompiled code
- Runtime capture - Field values at known offsets via Frida
- Cross-validation - Confirming struct boundaries and field types
Pool Detection
Crimsonland uses fixed-size pools for game entities. Identify them by looking for:Consistent Stride Patterns
- Pool base:
0x004926b8 - Entry size:
0x40bytes - Field offset:
0x08
Loop Boundaries
0x60 entries × 0x40 bytes = 0x1800 bytes total
Known Pools
Projectile Pool
Projectile Pool
Base:
Entry size:
Count:
Total:
0x004926b8Entry size:
0x40 bytesCount:
0x60 entriesTotal:
0x1800 bytesPlayer Pool
Player Pool
Base:
Entry size:
Count: 4 players (max)
Note: Some fields live at negative offsets before
0x004908d4 (player_health table)Entry size:
0x360 bytesCount: 4 players (max)
Note: Some fields live at negative offsets before
player_healthCreature Pool
Creature Pool
Base:
Entry size:
Count:
0x0048d0a8Entry size:
0x98 bytesCount:
0x180 entriesField Identification
1. Track All Accesses
Find every read/write to a pool:- Offset from base
- Operation (read/write)
- Data type (byte, int, float)
- Context (function, purpose)
2. Group by Offset
3. Infer Field Names
Based on usage:- Decremented over time → timer, countdown, lifetime
- Compared to zero → flag, state check, death condition
- Updated with
+=→ position, velocity, accumulator - Set once on spawn → type ID, owner, configuration
4. Validate with Runtime
Capture actual field values:Structure-of-Arrays vs Array-of-Structs
Array-of-Structs (AoS)
All fields for one entry are contiguous:Structure-of-Arrays (SoA)
Each field is a separate array:Example: FX Queue (SoA)
0x80 * sizeof(float) = 0x200
Special Cases
Negative Offsets
Some structs have fields before the “base” address:Embedded Sub-Structs
Union Fields
Same offset used for different purposes:Cross-Validation Techniques
1. Size Calculation
Count known fields and check against stride:2. Boundary Checks
Confirm struct doesn’t overlap next pool:3. Runtime Dumps
Capture full entry as hex:Documentation Format
Use consistent struct documentation:Automated Tools
Ghidra Scripts
ExportDataMap.java - Extract struct definitions to JSON:Frida Helpers
Pool dumper (scripts/frida/dump_pool.js):
Example: Recovering Weapon Table
Let’s walk through recovering the weapon data table.Step 1: Find References
Search for weapon-related functions:0x004d7a00, stride 0x48 (72 bytes).
Step 2: Track Field Usage
Step 3: Runtime Capture
Step 4: Document
Related Pages
Game State
Global game state structures
Entity Pools
Creature, projectile, and effect pools
Frida Capture
Runtime validation of struct layouts