How ScriptPointer and ScriptPatch Enable Runtime Script Modification in YimMenuV2

YimMenuV2 exposes two complementary Lua objects—ScriptPointer for dynamic address resolution and ScriptPatch for live byte manipulation—that together enable runtime script modification without restarting GTA V.

YimMenuV2 provides developers with powerful tools to inspect and alter GTA V's native script behavior while the game executes. Through the ScriptPointer and ScriptPatch classes exposed to the Lua environment, the menu enables runtime script modification by allowing scripts to locate memory addresses via pattern matching and apply hot-patches to alter game logic on the fly.

Understanding the Core Components

ScriptPointer: Dynamic Memory Address Resolution

ScriptPointer serves as the address resolution layer for runtime script modification. According to the source code in YimMenu/YimMenuV2, this class encapsulates a resolved memory pointer and provides arithmetic operations to navigate script structures.

The implementation resides in src/game/scripting/libraries/ScriptPointer.cpp, where ScriptPointerBinding::New constructs pointers from name-pattern pairs or explicit addresses. The underlying C++ class—defined in src/game/gta/ScriptPointer.hpp—stores the resolved address and exposes methods including Add, Sub, Rip, and Scan.

When registered with Lua, ScriptPointer creates a metatable exposing methods such as:

  • add and sub – Offset arithmetic for pointer adjustment
  • rip – Resolution of relative addresses (RIP-relative addressing)
  • scan – Lookup of script programs via Scripts::FindScriptProgram using hash identifiers
  • get_address and get_name – Introspection utilities

The Scan method specifically enables cross-script references by locating a script program through its hash and returning a new pointer to that script's code block, facilitating dynamic script-to-script interaction.

ScriptPatch: Byte-Level Code Modification

While ScriptPointer locates targets, ScriptPatch executes the actual runtime script modification through byte-level patching. Implemented in src/game/scripting/libraries/ScriptPatch.cpp, this class manages writable overlays that replace original game bytes with custom instructions.

The ScriptPatch constructor accepts a name, pattern, and replacement byte buffer, using the same signature-matching logic as ScriptPointer to resolve target addresses. The binding registers a "ScriptPatch" metatable with Lua, providing three core operations:

  • apply – Writes replacement bytes to the resolved address using core/memory/BytePatches.cpp utilities
  • remove – Restores original bytes from internal backup
  • toggle – Switches between patched and original states
  • is_applied – Query method for patch state verification

This architecture decouples address resolution from modification, allowing patches to be maintained separately from the pointers that locate them.

How ScriptPointer Locates Script Targets

The address resolution pipeline begins with pattern matching against GTA V's script bytecode. In src/game/scripting/libraries/ScriptPointer.cpp, the binding layer parses constructor arguments including:

  1. A human-readable name for debugging
  2. A SimplePattern byte sequence with wildcards
  3. Optional offset parameters for pointer adjustment

Once constructed, the ScriptPointer object can traverse script memory using arithmetic methods. For example, calling Sub adjusts the pointer backward by specified offsets, while Rip handles x64 RIP-relative addressing calculations common in native game code.

The Scan functionality—leveraging Scripts::FindScriptProgram from src/game/gta/Scripts.hpp—enables scripts to locate other active script programs by hash, returning a new ScriptPointer instance referencing that script's code block. This allows Lua scripts to reference and potentially modify external script resources dynamically.

How ScriptPatch Applies Live Modifications

After resolution, ScriptPatch handles the actual memory manipulation. The class encapsulates both the target address (resolved during construction) and a buffer of replacement bytes. When apply is invoked, the patch writes to game memory using low-level utilities in src/core/memory/BytePatches.cpp.

Key characteristics of the patching system include:

  • Atomic application – Patches are applied as contiguous byte sequences
  • Backup preservation – Original bytes are stored internally to support remove operations
  • State tracking – The is_applied method prevents redundant writes or premature removals

This mechanism enables hot-patching of native functions or script blocks, allowing immediate behavioral changes without process restarts or file modifications.

Practical Implementation Workflow

Combining these components enables sophisticated runtime script modification workflows:

  1. Locate – Create a ScriptPointer using signature patterns to find the target native function or script block
  2. Adjust – Use arithmetic methods (add, sub) or rip to navigate to the exact injection point
  3. Reference – Optionally scan to locate related script programs by hash
  4. Patch – Instantiate a ScriptPatch at the resolved address with replacement bytes
  5. Modify – Call apply to write changes, remove to restore, or toggle to switch states

The Lua binding allows dynamic interaction, enabling conditional patching based on game state queries.

Code Examples

Creating a pointer and scanning for a script program:

local ptr = ScriptPointer("myScript", "48 89 ?? ?? ?? 48 8B ??", 0)
local scriptPtr = ptr:scan("SCRIPT_HASH")   -- resolves the script block
print("Address:", scriptPtr:get_address())

Applying a byte patch to disable a function:

-- Replace function prologue with NOPs (0x90)
local patch = ScriptPatch("nopFunc", "40 53 48 83 EC 20", "\x90\x90\x90\x90\x90")
patch:apply()      -- writes the NOP sled to memory
-- Later restoration...
patch:remove()     -- restores original 5 bytes

Summary

  • ScriptPointer (src/game/scripting/libraries/ScriptPointer.cpp) provides dynamic address resolution via pattern matching, arithmetic operations, and cross-script scanning through Scripts::FindScriptProgram
  • ScriptPatch (src/game/scripting/libraries/ScriptPatch.cpp) enables live byte modification with apply, remove, and toggle methods backed by core/memory/BytePatches.cpp
  • Together, these classes allow Lua scripts to locate arbitrary game addresses and modify them at runtime without restarting GTA V
  • The architecture separates concerns: ScriptPointer handles "where," while ScriptPatch handles "what to change"

Frequently Asked Questions

How does ScriptPointer handle pattern matching for address resolution?

ScriptPointer uses the SimplePattern class to match byte sequences against GTA V's script memory. The constructor in ScriptPointerBinding::New accepts a pattern string with wildcard characters (typically ?? for unknown bytes) and an optional offset. When matched, the base address is calculated and stored in the underlying C++ ScriptPointer class, allowing subsequent arithmetic operations to navigate the resolved memory region.

Can ScriptPatch modifications be detected by GTA V's anti-cheat systems?

ScriptPatch writes directly to process memory using the byte-patch utilities in src/core/memory/BytePatches.cpp. While the patches modify executable script regions, YimMenuV2 implements these changes at the memory level below standard script verification layers. However, the persistence and detectability depend on the specific bytes modified and Rockstar's current anti-cheat heuristics, which are subject to change with game updates.

What is the difference between the rip and scan methods in ScriptPointer?

The rip method performs RIP-relative address calculation—common in x64 architecture where addresses are encoded as offsets from the instruction pointer—effectively dereferencing relative pointers within the current script context. Conversely, scan searches the global script table via Scripts::FindScriptProgram to locate entirely different script programs by their hash, returning a pointer to that external script's code block rather than adjusting the current pointer.

How do I safely remove a ScriptPatch to restore original game behavior?

Call the remove method on your ScriptPatch instance. The class maintains an internal backup of the original bytes captured during construction in src/game/scripting/libraries/ScriptPatch.cpp. When remove is invoked, it writes these backed-up bytes back to the target address using the same memory utilities in src/core/memory/BytePatches.cpp, effectively restoring the original instructions without requiring a game restart.

Have a question about this repo?

These articles cover the highlights, but your codebase questions are specific. Give your agent direct access to the source. Share this with your agent to get started:

Share the following with your agent to get started:
curl -s "https://instagit.com/install.md"

Works with
Claude Codex Cursor VS Code OpenClaw Any MCP Client

Maintain an open-source project? Get it listed too →