# How YimMenuV2's Pattern Scanning System Locates Functions in GTA5_Enhanced.exe

> Discover how YimMenuV2's advanced pattern scanning system finds functions in GTA5_Enhanced.exe using modular scanners, async parallel scanning, and persistent caching for efficient runtime analysis.

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

---

**YimMenuV2 uses a modular pattern scanner with IDA-style signatures, asynchronous parallel scanning, and persistent caching to locate functions and data structures in GTASEnhanced.exe at runtime.**

YimMenuV2 implements a sophisticated memory pattern scanning system to dynamically resolve function addresses inside **GTASEnhanced.exe** without relying on static offsets. This architecture enables the menu to survive game updates by searching for unique byte sequences rather than hardcoded addresses. The scanner operates through a pipeline of module abstraction, signature parsing, and cached memory traversal.

## Core Architecture of the Pattern Scanner

The pattern scanning system in YimMenuV2 is built on three foundational components that work together to map the game's memory space.

### Module Abstraction

Every scan targets a specific **Module** object that wraps a loaded PE image. The `Module` class defined in [`src/core/memory/Module.hpp`](https://github.com/YimMenu/YimMenuV2/blob/main/src/core/memory/Module.hpp) (lines 21-95) exposes critical memory boundaries through methods like `Base()`, `Size()`, and `End()`. When scanning **GTASEnhanced.exe**, the scanner typically receives the main executable module retrieved via `ModuleMgr.GetModule("GTASEnhanced.exe")`, establishing the searchable address range from the module's base address to its end address.

### Pattern Definition and Parsing

Patterns use **IDA-style signatures** such as `"48 89 ?? ?? 8B ??"` where hexadecimal bytes represent exact matches and `??` acts as wildcards. The `SimplePattern` class in [`src/core/memory/Pattern.cpp`](https://github.com/YimMenu/YimMenuV2/blob/main/src/core/memory/Pattern.cpp) (lines 35-59) parses these strings into a byte vector where concrete values occupy specific positions and wildcards become `std::nullopt`. This representation allows the scanner to perform flexible matching against the raw memory of **GTASEnhanced.exe** while maintaining the exact byte relationships found in the game's compiled code.

## The Scanning Process

The `PatternScanner` class orchestrates the search operation through a multi-stage pipeline that prioritizes performance and reliability.

### Asynchronous Orchestration

The scanner maintains an internal list of `(IPattern*, PatternFunc)` pairs representing signatures and their associated callback functions. According to the implementation in [`src/core/memory/PatternScanner.cpp`](https://github.com/YimMenu/YimMenuV2/blob/main/src/core/memory/PatternScanner.cpp) (lines 17-46), the `Scan()` method iterates over these pairs and launches each search as a separate `std::async` task, enabling parallel execution across multiple CPU cores. However, if the process is detected as *manual-mapped*, the scanner automatically falls back to sequential execution to prevent race conditions in modified memory environments.

### Cache-First Resolution

Before performing expensive memory traversals, the scanner consults `PatternCache` to check for previously resolved offsets. As implemented in [`src/core/memory/PatternScanner.cpp`](https://github.com/YimMenu/YimMenuV2/blob/main/src/core/memory/PatternScanner.cpp) (lines 54-62), the cache hashes the pattern signature combined with the module size to generate a unique key. If a cached offset exists, the scanner immediately invokes the callback with the stored address, eliminating redundant scanning. Upon successful discovery of a new pattern, the system writes the offset back to the cache (lines 86-90) for subsequent runs, significantly improving initialization times after the first execution.

### Byte-by-Byte Matching

When the cache misses, `ScanInternal` performs a linear scan through the module's memory range from `Base()` to `End()`. The algorithm verifies that sufficient bytes remain within the module boundaries, then compares each signature byte against memory, treating `std::nullopt` entries as wildcards that match any value. Upon finding a complete match in [`src/core/memory/PatternScanner.cpp`](https://github.com/YimMenu/YimMenuV2/blob/main/src/core/memory/PatternScanner.cpp) (lines 65-92), the scanner logs the resolved address, executes the stored callback function with the matched pointer, updates the persistent cache, and terminates the search for that specific pattern.

## Integration with GTA5_Enhanced.exe

The pattern scanner serves as the backbone for YimMenuV2's runtime function resolution throughout the codebase.

In [`src/game/pointers/Pointers.cpp`](https://github.com/YimMenu/YimMenuV2/blob/main/src/game/pointers/Pointers.cpp) (lines 5-30), the scanner resolves critical GTA 5 native functions required for the menu's core functionality. The system also exposes these capabilities to Lua scripting through [`src/core/scripting/libraries/Memory.cpp`](https://github.com/YimMenu/YimMenuV2/blob/main/src/core/scripting/libraries/Memory.cpp) (lines 3-70), allowing custom scripts to perform their own signature scans.

```cpp
// Locating NETWORK_GET_NETWORK_ID_FROM_PLAYER in GTASEnhanced.exe
auto gta5 = ModuleMgr.GetModule("GTASEnhanced.exe");
PatternScanner scanner(gta5);

scanner.AddPattern(
    new SimplePattern("48 89 ?? ?? 8B ?? ?? ?? ?? ?? 48 8B ??"),
    [](std::uintptr_t addr) {
        g_NetworkGetNetworkIdFromPlayer = reinterpret_cast<decltype(g_NetworkGetNetworkIdFromPlayer)>(addr);
        LOG(INFO) << "Resolved NETWORK_GET_NETWORK_ID_FROM_PLAYER at " << HEX(addr);
    }
);

scanner.Scan();  // Executes async scan (sequential if manual-mapped)

```

```lua
-- Lua exposure via Memory library
function memory.scanPattern(sig, callback)
    local scanner = PatternScanner(gta5)  -- gta5 = GTASEnhanced.exe module
    scanner:AddPattern(SimplePattern(sig), function(addr)
        callback(addr)
    end)
    scanner:Scan()
end

```

## Summary

- **YimMenuV2** locates functions in **GTASEnhanced.exe** using a `PatternScanner` that operates on `Module` objects representing loaded PE images.
- Signatures follow **IDA-style** syntax with wildcards, parsed by `SimplePattern` in [`src/core/memory/Pattern.cpp`](https://github.com/YimMenu/YimMenuV2/blob/main/src/core/memory/Pattern.cpp) into searchable byte vectors.
- The scanner uses **asynchronous parallel execution** via `std::async` for performance, falling back to sequential mode for manual-mapped processes.
- A **persistent cache** stores resolved offsets hashed against module sizes, eliminating redundant scans across application restarts.
- The system is integrated throughout the codebase, from native function resolution in [`Pointers.cpp`](https://github.com/YimMenu/YimMenuV2/blob/main/Pointers.cpp) to Lua scripting interfaces in [`Memory.cpp`](https://github.com/YimMenu/YimMenuV2/blob/main/Memory.cpp).

## Frequently Asked Questions

### What signature format does YimMenuV2 use for pattern scanning?

YimMenuV2 uses **IDA-style signatures** consisting of hexadecimal byte pairs separated by spaces, where `??` represents wildcard bytes that match any value. The `SimplePattern` class in [`src/core/memory/Pattern.cpp`](https://github.com/YimMenu/YimMenuV2/blob/main/src/core/memory/Pattern.cpp) (lines 35-59) parses these strings into byte vectors where wildcards become `std::nullopt`, allowing flexible matching against **GTASEnhanced.exe** memory.

### How does the scanner handle multiple patterns efficiently?

The `PatternScanner` class launches each pattern search as an independent `std::async` task, enabling parallel execution across CPU cores as seen in [`src/core/memory/PatternScanner.cpp`](https://github.com/YimMenu/YimMenuV2/blob/main/src/core/memory/PatternScanner.cpp) (lines 17-46). This asynchronous approach significantly reduces initialization time when resolving numerous functions in **GTASEnhanced.exe**, except when running in manual-mapped mode where sequential execution prevents memory corruption.

### Does YimMenuV2 cache pattern scan results between sessions?

Yes. The scanner implements a **persistent cache** that stores resolved offsets hashed with the module size, as implemented in [`src/core/memory/PatternScanner.cpp`](https://github.com/YimMenu/YimMenuV2/blob/main/src/core/memory/PatternScanner.cpp) (lines 54-62 and 86-90). On subsequent runs, the scanner checks this cache before performing memory traversals, immediately returning cached addresses for known patterns to minimize startup latency.

### Which source files contain the core pattern scanning implementation?

The primary implementation resides in [`src/core/memory/PatternScanner.cpp`](https://github.com/YimMenu/YimMenuV2/blob/main/src/core/memory/PatternScanner.cpp) for the scanning engine and cache integration, [`src/core/memory/Pattern.cpp`](https://github.com/YimMenu/YimMenuV2/blob/main/src/core/memory/Pattern.cpp) for signature parsing, and [`src/core/memory/Module.hpp`](https://github.com/YimMenu/YimMenuV2/blob/main/src/core/memory/Module.hpp) for PE module abstraction. Usage examples appear in [`src/game/pointers/Pointers.cpp`](https://github.com/YimMenu/YimMenuV2/blob/main/src/game/pointers/Pointers.cpp) for GTA 5 native resolution and [`src/core/scripting/libraries/Memory.cpp`](https://github.com/YimMenu/YimMenuV2/blob/main/src/core/scripting/libraries/Memory.cpp) for Lua exposure.