# Architecture of the Pointers System for Game Memory Offsets in YimMenuV2

> Discover the YimMenuV2 Pointers system architecture. Learn how this three-layer design dynamically resolves and caches GTA V memory offsets at runtime for efficient game modding.

- Repository: [YimMenu/YimMenuV2](https://github.com/YimMenu/YimMenuV2)
- Tags: architecture
- Published: 2026-07-17

---

**The Pointers subsystem in YimMenuV2 employs a three-layer architecture—combining compile-time pattern scanning, strongly-typed pointer storage, and a global singleton interface—to dynamically resolve and cache critical GTA V memory offsets at runtime.**

The Pointers system serves as the central nervous system of YimMenuV2, eliminating the fragility of static offset tables by scanning the running process on every launch. According to the YimMenuV2 source code, this architecture enables the menu to survive game updates that shift memory layouts while providing type-safe access to functions, data structures, and hook points across the codebase.

## Overview of the Three-Layer Architecture

The implementation organizes memory resolution into distinct responsibilities, from raw byte matching to high-level typed access.

### Layer 1: Pattern Scanning and Resolution

The foundation relies on the `PatternScanner` class defined in [`src/core/memory/PatternScanner.hpp`](https://github.com/YimMenu/YimMenuV2/blob/main/src/core/memory/PatternScanner.hpp). This engine performs runtime signature matching against loaded modules such as `GTA5_Enhanced.exe` and `socialclub.dll`.

Patterns are declared as compile-time literals using the `Pattern<>` template. For example:

```cpp
constexpr auto swapChainPtrn = Pattern<"72 C7 EB 02 31 C0 8B 0D">("IDXGISwapChain");

```

The scanner walks the target module's memory range, identifies these byte sequences, and hands the match to a `PointerCalculator` (from [`src/core/memory/PointerCalculator.hpp`](https://github.com/YimMenu/YimMenuV2/blob/main/src/core/memory/PointerCalculator.hpp)). This helper performs RIP-relative arithmetic via methods like `Add()`, `Sub()`, and `Rip()` to convert raw matches into absolute addresses.

### Layer 2: Typed Pointer Repository

Once resolved, addresses populate the `PointerData` struct declared in [`src/game/pointers/Pointers.hpp`](https://github.com/YimMenu/YimMenuV2/blob/main/src/game/pointers/Pointers.hpp). This struct declares strongly-typed members such as:

- `ID3D12CommandQueue** CommandQueue`
- `rage::atArray<rage::scrThread*>* ScriptThreads`
- `Functions::GetNetObjectById GetNetObjectById`

The `Pointers` class inherits from `PointerData` and implements `Init()` for the main executable and `LateInit()` for auxiliary modules. This two-phase approach ensures dependencies like `socialclub.dll` are fully loaded before their offsets are resolved.

### Layer 3: Public Singleton Interface

The system exposes a global instance via `inline YimMenu::Pointers Pointers;` defined in the header. After initialization returns `true`, code throughout the menu accesses resolved offsets directly:

```cpp
if (YimMenu::Pointers.QueuePacket)
{
    YimMenu::Pointers.QueuePacket(
        connectionMgr,
        0x2A,
        data, sizeof(data),
        0, nullptr);
}

```

## Initialization Flow: From Module to Memory Address

Understanding the exact sequence of resolution clarifies how the system maintains reliability across game versions.

### Module Discovery and Scanner Setup

Initialization begins in `Pointers::Init()` within [`src/game/pointers/Pointers.cpp`](https://github.com/YimMenu/YimMenuV2/blob/main/src/game/pointers/Pointers.cpp). The method first obtains a module handle through `ModuleMgr.Get("GTA5_Enhanced.exe"_J)`, then constructs a `PatternScanner` instance wrapping the module's memory range.

### Pattern Registration and Callbacks

For each required offset, the code registers a pattern-callback pair:

```cpp
scanner.Add(swapChainPtrn, [](PointerCalculator ptr) {
    Pointers.SwapChain = ptr.Add(3).Rip().As<IDXGISwapChain**>();
});

```

The lambda receives a `PointerCalculator` positioned at the pattern match, performs offset arithmetic, and stores the result in the appropriate `PointerData` member using `.As<T>()` for type safety.

### RIP-Relative Address Calculation

Modern compilers heavily utilize RIP-relative addressing for position-independent code. The `PointerCalculator` abstracts this complexity:

- `Add(n)` advances the pointer by *n* bytes
- `Sub(n)` retreats the pointer by *n* bytes  
- `Rip()` reads the 32-bit displacement at the current position and calculates the absolute target address

This arithmetic is essential for resolving pointers in `.text` sections where absolute addresses are encoded as relative offsets.

### Late Initialization for Auxiliary Modules

Certain features depend on `socialclub.dll`, which loads asynchronously. The `LateInit()` method handles this through:

```cpp
bool Pointers::LateInit()
{
    if (IsSocialClubNeverGoingToLoad())
        return false;
    
    auto socialClub = ModuleMgr.Get("socialclub.dll"_J);
    PatternScanner scanner(socialClub);
    // ... pattern registration for Social Club offsets
    return scanner.Scan();
}

```

This separation prevents race conditions while ensuring network-related pointers are available when needed.

## Byte-Patch Integration and Runtime Modifications

The architecture extends beyond read-only pointers to support runtime code modification. Within the same registration lambdas, the system creates `BytePatch` objects (from [`src/core/memory/BytePatches.hpp`](https://github.com/YimMenu/YimMenuV2/blob/main/src/core/memory/BytePatches.hpp)) when a pattern identifies a region requiring modification.

Examples include `SpectatePatch` and `ModelSpawnBypass`. These patches are stored as members in `PointerData`, allowing other modules to enable or disable them via methods like `Apply()` and `Restore()` without re-scanning memory.

## Practical Usage Examples

The repository demonstrates several access patterns across subsystems:

**Reading game state:**

```cpp
auto width  = *YimMenu::Pointers.ScreenResX;
auto height = *YimMenu::Pointers.ScreenResY;

```

**Accessing entity pools:**

```cpp
auto pedPool = YimMenu::Pointers.PedPool;
for (int i = 0; i < pedPool->m_Size; i++)
{
    auto ped = pedPool->GetAt(i);
    // process ped
}

```

**Network function invocation:**

```cpp
YimMenu::Pointers.JoinSessionByInfo(
    sessionInfo,
    1, 0, 0, 0, 0, 0, 0);

```

## Summary

- **Dynamic Resolution:** The `PatternScanner` eliminates hardcoded offsets by matching byte signatures at runtime against `GTA5_Enhanced.exe` and `socialclub.dll`.
- **Type Safety:** The `PointerData` struct stores resolved addresses as strongly-typed pointers and function pointers, eliminating dangerous casts throughout the codebase.
- **Two-Phase Init:** `Init()` handles the main executable immediately, while `LateInit()` waits for Social Club dependencies, preventing initialization races.
- **Global Access:** The `YimMenu::Pointers` singleton provides zero-overhead access to game memory after successful initialization.
- **Integrated Patching:** `BytePatch` objects stored alongside pointers enable runtime code modification without separate memory management.

## Frequently Asked Questions

### How does YimMenuV2 handle game updates that change memory offsets?

The menu uses signature scanning rather than static offset tables. When Rockstar updates GTA V, the byte patterns around critical functions typically remain stable even if absolute addresses shift. The `PatternScanner` locates these signatures dynamically on every launch, allowing the menu to function without manual offset updates for minor patches.

### What is the difference between Init() and LateInit() in the Pointers system?

`Init()` resolves pointers within the main game executable immediately upon injection, providing access to core engine functions and rendering interfaces. `LateInit()` executes subsequently to scan `socialclub.dll`, which loads asynchronously during the initial connection phase. This separation ensures network-related pointers like `NetworkSession` are valid when the player actually connects to Rockstar's servers.

### Why does the Pointers system use RIP-relative addressing?

RIP-relative addressing is the standard for x64 position-independent code. Game executables encode jump targets and data references as 32-bit offsets from the instruction pointer rather than 64-bit absolute addresses. The `PointerCalculator`'s `Rip()` method decodes these displacements to calculate the true virtual address, which is necessary for resolving pointers in the `.text` section where the game's logic resides.

### How are function pointers type-safely stored and called?

The `PointerData` struct declares function pointer members using typed aliases from the `Functions` namespace (e.g., `Functions::QueuePacket`). During scanning, the `.As<T>()` template method casts the resolved `void*` to the specific function pointer type. This allows direct invocation with compiler-enforced parameter checking, preventing calling convention mismatches that would occur with raw address casts.