Overview
Native game functions are represented by partial methods with attributes that tell the source generator how to create wrappers. The library uses function pointers for all native calls, providing minimal managed↔unmanaged overhead.Function Types
There are three main types of native functions:- MemberFunction - Non-virtual member functions (including static functions)
- VirtualFunction - Virtual member functions (called via vtable)
- StaticAddress - Static singleton instances and global pointers
MemberFunction
Basic Usage
For non-virtual member functions and static functions:Static Functions
Mark the method asstatic if it’s a static function:
How It Works
The generator creates a wrapper that:- Resolves the function address from the signature
- Checks if the address is valid
- Calls the function via function pointer
- Passes the struct pointer as
thisfor member functions
Example: Instance Member Function
Example: Static Member Function
VirtualFunction
Basic Usage
For virtual member functions (called through vtable):How It Works
The generator:- Creates a VirtualTable struct with function pointers at specific offsets
- Adds a
VirtualTablepointer field at offset 0x0 - Creates a wrapper that calls through the vtable
Finding Virtual Function Index
Method 1: Count from IDA/Ghidra
- Locate the vtable in IDA/Ghidra
- Count the position of your function (starting from 0)
- Use that as the index
Method 2: Calculate from Offset
If you know the vtable offset:0x270 = index 78 (0x270 ÷ 8 = 78)
Examples
StaticAddress
Basic Usage
For returning static object locations (usually singletons):- signature: Pattern to find the reference
- offset: Byte offset to the address within the signature
- isPointer: Whether the address points to a pointer (
**) or instance (*)
isPointer Parameter
When isPointer: true
The static address is a pointer to a pointer (common for heap-allocated singletons):
When isPointer: false
The static address is a direct instance (allocated in the binary):
Finding the Offset
The offset is where the address bytes are in your signature:48 8B 0D ?? ?? ?? ??=mov rcx, [rip + offset]- The 4
??bytes (offset 3-6) are the RIP-relative address - Use offset
3
Examples
Function Signatures
All signatures must follow these rules:- Use
??for wildcard bytes (two characters per byte) - Include 2 hex characters per byte (e.g.,
0FnotF) - Make signatures unique enough to find the function
- Make signatures stable across patches
Good Signature Patterns
Bad Signature Patterns
String Parameters
The Problem
C#string cannot be used with DisableRuntimeMarshalling. Use byte* for C-style strings:
String Overloads
Add[GenerateStringOverloads] to generate convenient overloads:
Usage Examples
CStringPointer
For returned C strings, useCStringPointer:
string - it makes assumptions about memory lifetime.
Return Types
Allowed Return Types
- Primitive types:
void,bool,byte,int,float, etc. - Enums
- Pointers:
SomeStruct* - Struct values:
SomeStruct(if small) CStringPointerfor C strings
Not Allowed
string- useCStringPointerorbyte*- Managed types
- Generic types
Method Modifiers
Required: partial
All function methods must bepartial:
Optional: static
Use for static functions:Complete Examples
GameObject.cs
Character.cs
AtkUnitBase.cs
Framework.cs (Singleton)
Testing Functions
After adding functions:- Build the project to verify syntax
- Check generated code for correctness
- Test in-game using ResolverTester or a Dalamud plugin
- Verify signatures resolve correctly
- Call the function and verify behavior
Common Mistakes
- Forgetting
partialkeyword - Using
stringinstead ofbyte*orCStringPointer - Wrong virtual function index
- Incorrect signature offset for StaticAddress
- Missing
statickeyword for static functions - Wrong
isPointervalue for StaticAddress - Signature too short or unstable
Next Steps
- Signatures Guide - Learn how to create robust signatures
- Testing Guide - Test your function definitions
- Contributing Guide - Submit your changes