*/
Back to Blogs

Building Cheat-Menu: A Mod Menu for GTA III, Vice City & San Andreas

A deep dive into building a cross-game mod menu using C++ and ImGui, covering memory management, game hooking, and rendering.

C++
ImGui
Game Modding

Introduction

For over four years, I worked on Cheat-Menu, a mod menu supporting Grand Theft Auto III, Vice City, and San Andreas. This project taught me more about systems programming, memory management, and real-time rendering than any coursework ever could.

The Architecture

The menu is built as an ASI plugin — a DLL that gets loaded by the game engine at startup. The core architecture follows a modular pattern:

code
class CheatMenu {
private:
    std::unordered_map<std::string, Category*> categories;

public:
    void Initialize() {
        RegisterCategory("Player", new PlayerCategory());
        RegisterCategory("Vehicle", new VehicleCategory());
        RegisterCategory("World", new WorldCategory());
    }

    void Render() {
        ImGui::Begin("Cheat Menu");
        for (auto& [name, category] : categories) {
            if (ImGui::TreeNode(name.c_str())) {
                category->Render();
                ImGui::TreePop();
            }
        }
        ImGui::End();
    }
};

Each category is self-contained, managing its own state and rendering logic. This made it easy to add new features without touching the core system.

Memory Hooking

The most challenging aspect was hooking into game functions without causing crashes. I used a detour-based approach:

  1. Find the target function — scan memory for known byte patterns
  2. Save the original bytes — so we can restore them later
  3. Write a jump — redirect execution to our handler
  4. Call the original — when we want default behavior

The pattern scanning approach works across different game versions since the actual addresses change between patches:

code
uintptr_t FindPattern(const char* module, const char* pattern) {
    auto* base = GetModuleHandleA(module);
    // Scan through memory looking for the byte pattern
    // ...
    return address;
}

Lessons Learned

  • Memory safety is paramount — one wrong pointer dereference crashes the game
  • ImGui is incredibly powerful — it made UI development straightforward
  • Backwards compatibility matters — supporting three game engines simultaneously required careful abstraction
  • Community feedback drives development — user-reported bugs helped me find edge cases I never would have discovered alone
GitHub
LinkedIn
youtube