BINX FORGEALL YOU NEED IS AN IDEA.Support BINX ↗
PRACTICAL CODE GUIDE · REVIEWED 10 OCTOBER 2026

Game Reverse Engineering for Beginners: Code, Tools and a Practice Lab

Learn game reverse-engineering methods with an original scoring program, worked code, Ghidra guides and public examples from other developers.

Reverse engineering means working from observable behavior and compiled structure to a tested explanation. For game development, that can help you understand scoring, save formats or a state transition. This guide uses an original tiny scoring program throughout. You need basic functions and a terminal; Linux x86_64 is the tested command path.

Examples from other developers

These are public training and analysis projects. Their code and walkthroughs stay at the authors' original sites.

Public projectWhat they madeHow the method works
Wrongbaud's Hackaday-U exercisesFour sessions of purpose-built x86_64 ELF challenges, slides and example materials.Identify a program, inspect functions and control flow in Ghidra, annotate a hypothesis, then test it. Author's session explanation ↗
Capstone team's Python sampleA short script that turns a supplied byte sequence into addresses, instruction names and operands.Choose the correct CPU/mode, pass the bytes to Cs.disasm, inspect the returned instructions. This is disassembly; game rules still need reconstruction.
Compiler ExplorerA source/assembly comparison tool with small arithmetic examples and optimization controls.Change one expression or compiler flag, then compare generated instructions. Use your original function to learn why multiply/add logic may appear as shifts or address arithmetic.

For a complete beginner path, the official Ghidra student guide covers project creation, importing, analysis and navigation. Linked author projects are source-reviewed learning references; we have not run their exercises or certified their installation here.

How the method applies to games

Game questionWhat to inspectHow to check your explanation
Scoring and combo rulesInput values, threshold branches, arithmetic and return value.Change one token, chain or miss; test the cap and zero floor. The worked lab below covers this.
Movement and collisionYour own update loop, time step, input vector and collision boundary.Measure distance over the same simulated interval, diagonals and four wall contacts; compare the existing controller first.
Game-state transitionsState values, callers and conditions for start, pause, win, lose and restart.Draw the transition table and run the same sequence twice; distinguish display text from the underlying state.
Save and level formatsYour permitted versioned fixtures, field types, lengths and byte order.Change one field, compare bytes, then validate a fresh roundtrip and malformed lengths in a copy.

These are investigation paths for your permitted game project. The executed lab here covers scoring and native binary inspection; it does not certify movement, saves or a full engine importer.

Original worked example: investigate a score

Download complete original practice code

score_lab.c · recovered.py · check.py · observations.json · README.md · LICENSE.txt

Extract the whole reverse-lab folder. Keep its MIT notice. This is an author-made exercise; the reference source is included, so you can check your answer. If you want a challenge, record your observations before opening score_lab.c.

python3 check.py

Requires Python3, a C compiler and GNU binutils. The helper compiles only the supplied original source in temporary folders, inspects actual native artifacts and removes the temporary binaries. Tested GCC13.3.0 and binutils2.42 on Linux x86_64. You should see "result": "passed",444 behavior comparisons and24 invalid-input checks.

Tokens, chain, missesActual outputWhat to investigate
0, 0, 00How much is one token worth?
1, 0, 07How much is one token worth?
2, 0, 014How much is one token worth?
3, 0, 021How much is one token worth?
2, 2, 014Where does the chain bonus start?
2, 3, 064Where does the chain bonus start?
2, 4, 064Where does the chain bonus start?
2, 3, 456How much does each miss subtract?
99, 3, 0743Does the token count cap?
100, 3, 0743Does the token count cap?

How to do it, step by step

  1. STEP 1

    Define one question and preserve the baseline

    Start with files you own or are permitted to analyze. Reuse source, debug symbols, engine tools and existing BINX systems first. Here the question is simply: how do three inputs become a score? Work in a copy and record tool versions and a file hash. Do not start by rewriting your working game.

    cc -std=c11 -Wall -Wextra -g -O0 score_lab.c -o score_lab
    readelf -h score_lab

    Check: the built lab is ELF64/x86_64. Commands and instruction syntax below are for this target; PE, ARM and other platforms need their own tools.

  2. STEP 2

    Change one input, predict, observe

    ./score_lab 2 0 0
    ./score_lab 2 3 0
    ./score_lab 2 3 4

    Check: scores14,64,56. Two tokens give14; chain3 appears to add50; four misses remove8. These are hypotheses from observations. Test chain2/3/4, token99/100 and a large miss count before accepting the rule.

  3. STEP 3

    Find anchors, then inspect instructions

    strings score_lab
    nm score_lab
    objdump -d -M intel --disassemble=award_points score_lab

    Check: the output string is an anchor, the symbol identifies our function and objdump prints its real instructions. Follow argument values, comparison branches, arithmetic and the return. A string by itself does not prove the scoring location. With optimization,7× may use shifts/subtraction and a conditional may become a conditional move.

  4. STEP 4

    Compare a stripped copy and a decompiler hypothesis

    cp score_lab score_stripped
    strip --strip-all score_stripped
    nm score_stripped
    objdump -d -M intel score_stripped

    Check: our award_points label is removed, but code, output string and observed behavior remain. Keep the original intact. In Ghidra create a Non-Shared project, import your built lab, confirm ELF/x86_64, open it and accept analysis. For the named build locate award_points and compare Listing/Decompiler. On the stripped copy follow string references and callers, then trace the arguments and branches. Annotate guesses and rename only after evidence. Interactive Ghidra steps are source-reviewed instructions; they have not been executed in this release.

    Decompiler output is estimated pseudo-C. Comments, original variable names, exact source structure and design intent may be lost. Do not describe a pseudo-C display as recovered original source.

  5. STEP 5

    Write your own model and compare

    Our reconstructed rule caps tokens99, awards7each, adds50 for chain>=3, subtracts2per miss and floors the result0. Compare it with many valid inputs and the reference source. The helper checks111 inputs across O0/O2 and stripped/unstripped native binaries, then rejects malformed/out-of-domain CLI inputs.

    Check: all444 comparisons and24 rejection checks pass. This tests this bounded lab, not every game, compiler or possible input. For a permitted game project, preserve its existing systems and apply the same method to one small mechanic or format.

The code and what it proves

Open the original C reference after your investigation
/* Original Forge practice program. See LICENSE.txt. */
#include <errno.h>
#include <stdio.h>
#include <stdlib.h>

int award_points(int tokens, int chain, int misses) {
    if (tokens > 99) tokens = 99;
    int points = tokens * 7;
    if (chain >= 3) points += 50;
    points -= misses * 2;
    return points < 0 ? 0 : points;
}

static int argument(const char *text, int *value) {
    char *end;
    errno = 0;
    long n = strtol(text, &end, 10);
    if (errno || end == text || *end || n < 0 || n > 999) return 0;
    *value = (int)n;
    return 1;
}

int main(int argc, char **argv) {
    int tokens, chain, misses;
    if (argc != 4 || !argument(argv[1], &tokens) ||
        !argument(argv[2], &chain) || !argument(argv[3], &misses)) {
        fprintf(stderr, "Use: score_lab TOKENS CHAIN MISSES (integers 0..999)\n");
        return 2;
    }
    printf("Forge practice score: %d\n", award_points(tokens, chain, misses));
    return 0;
}

Original reconstructed Python function

"""Original hypothesis reconstructed for this practice program only."""
def award_points(tokens, chain, misses):
    if any(type(n) is not int or not 0 <= n <= 999 for n in (tokens, chain, misses)):
        raise ValueError('Practice input domain: three integers 0..999')
    return max(0, min(tokens, 99) * 7 + (50 if chain >= 3 else 0) - misses * 2)

Inspect the complete native comparison script · Read actual observations and scope · Keep the original permission notice

Behavior can match without reproducing the original source. Keep observed inputs, predicted outputs, compiler/options and open questions together. When you add a new hypothesis, try a case likely to disprove it. For a file-format exercise, build your own versioned fixture and validate bounds/types before interpreting bytes.

Take the method and complete code to your AI

Review before sharing. You can select the text manually.

Review the full original source and learning brief

Actual native compilation/inspection/strip/execution passes. Interactive Ghidra/decompiler, browser/clipboard/device/assistive and other toolchain/target checks remain OPEN. This guide contains no real-game example, extracted game assets or third-party binary. Original lab rights do not extend to linked tools, course materials or other inputs.

Learn at the original sources

Continue with your original map workflow · Understand your own game modules · All Forge guides