Skip to content
forked from encounter/objdiff

Same local diffing tool as Objdiff, has an extra feature to export scratches more easily

License

Notifications You must be signed in to change notification settings

Grien25/objdiff

 
 

Repository files navigation

objdiff Build Status

A local diffing tool for decompilation projects. Inspired by decomp.me and asm-differ.

Features:

  • Compare entire object files: functions and data
  • Built-in C++ symbol demangling (GCC, MSVC, CodeWarrior, Itanium)
  • Automatic rebuild on source file changes
  • Project integration via configuration file
  • Search and filter objects with quick switching
  • Click-to-highlight values and registers
  • Detailed progress reporting (powers decomp.dev)
  • WebAssembly API, web interface and Visual Studio Code extension (WIP)

Supports:

  • ARM (GBA, DS, 3DS)
  • ARM64 (Switch)
  • MIPS (N64, PS1, PS2, PSP)
  • PowerPC (GameCube, Wii, PS3, Xbox 360)
  • SuperH (Saturn, Dreamcast)
  • x86, x86_64 (PC)

See Usage for more information.

Downloads

To build from source, see Building.

GUI

For Linux and macOS, run chmod +x objdiff-* to make the binary executable.

CLI

CLI binaries are available on the releases page.

Screenshots

Symbol Screenshot Diff Screenshot

Usage

objdiff compares two relocatable object files (.o). Here's how it works:

  1. Create an objdiff.json configuration file in your project root (or generate it with your build script).
    This file lists all objects in the project with their target ("expected") and base ("current") paths.

  2. Load the project in objdiff.

  3. Select an object from the sidebar to begin diffing.

  4. objdiff automatically:

    • Executes the build system to compile the base object (from current source code)
    • Compares the two objects and displays the differences
    • Watches for source file changes and rebuilds when detected

The configuration file allows complete flexibility in project structure - your build directories can have any layout as long as the paths are specified correctly.

See Configuration for setup details.

Configuration

Projects can add an objdiff.json file to configure the tool automatically. The configuration file must be located in the root project directory.

If your project has a generator script (e.g. configure.py), it's highly recommended to generate the objdiff configuration file as well. You can then add objdiff.json to your .gitignore to prevent it from being committed.

{
  "$schema": "https://raw.githubusercontent.com/encounter/objdiff/main/config.schema.json",
  "custom_make": "ninja",
  "custom_args": [
    "-d",
    "keeprsp"
  ],
  "build_target": false,
  "build_base": true,
  "watch_patterns": [
    "*.c",
    "*.cc",
    "*.cp",
    "*.cpp",
    "*.cxx",
    "*.c++",
    "*.h",
    "*.hh",
    "*.hp",
    "*.hpp",
    "*.hxx",
    "*.h++",
    "*.pch",
    "*.pch++",
    "*.inc",
    "*.s",
    "*.S",
    "*.asm",
    "*.py",
    "*.yml",
    "*.txt",
    "*.json"
  ],
  "ignore_patterns": [
    "build/**/*"
  ],
  "units": [
    {
      "name": "main/MetroTRK/mslsupp",
      "target_path": "build/asm/MetroTRK/mslsupp.o",
      "base_path": "build/src/MetroTRK/mslsupp.o",
      "metadata": {}
    }
  ]
}

Schema

Note

View config.schema.json for all available options. Below is a summary of the most important options.

Build Configuration

custom_make (optional, default: "make")
If the project uses a different build system (e.g. ninja), specify it here. The build command will be [custom_make] [custom_args] path/to/object.o.

custom_args (optional)
Additional arguments to pass to the build command prior to the object path.

build_target (default: false)
If true, objdiff will build the target objects before diffing (e.g. make path/to/target.o). Useful if target objects are not built by default or can change based on project configuration. Requires proper build system configuration.

build_base (default: true)
If true, objdiff will build the base objects before diffing (e.g. make path/to/base.o). It's unlikely you'll want to disable this unless using an external tool to rebuild the base object.

File Watching

watch_patterns (optional, default: listed above)
A list of glob patterns to watch for changes (supported syntax). When these files change, objdiff automatically rebuilds and re-compares objects.

ignore_patterns (optional, default: listed above)
A list of glob patterns to explicitly ignore when watching for changes (supported syntax).

Units (Objects)

units (optional)
If specified, objdiff displays a list of objects in the sidebar for easy navigation. Each unit contains:

  • name (optional) - The display name in the UI. Defaults to the object's path.
  • target_path (optional) - Path to the "target" or "expected" object (the intended result).
  • base_path (optional) - Path to the "base" or "current" object (built from current source code). Omit if there is no source object yet.
  • metadata.auto_generated (optional) - Hides the object from the sidebar but includes it in progress reports.
  • metadata.complete (optional) - Marks the object as "complete" (linked) when true or "incomplete" when false.

Building

Install Rust via rustup.

git clone https://github.com/encounter/objdiff.git
cd objdiff
cargo run --release

Or install directly with cargo:

cargo install --locked --git https://github.com/encounter/objdiff.git objdiff-gui objdiff-cli

Binaries will be installed to ~/.cargo/bin as objdiff and objdiff-cli.

Local Scratch Creation

objdiff now supports creating local scratches that save all the necessary files to your local filesystem instead of uploading to decomp.me. This is useful mainly for creating sets and piles of code.

Configuration

Add the local_scratch_dir field to your objdiff.json configuration (optional):

{
  "local_scratch_dir": "scratches",
  "units": [
    {
      "name": "my_function",
      "target_path": "build/target/my_function.o",
      "base_path": "build/src/my_function.o",
      "scratch": {
        "platform": "n64",
        "compiler": "gcc2.7.2kmc",
        "c_flags": "-O2 -g2",
        "ctx_path": "ctx.c"
      }
    }
  ]
}

Default Directory (used when local_scratch_dir is not specified):

  • All platforms: ~/Documents/scratches

Generated Files

When creating a local scratch, objdiff generates the following files in a timestamped folder:

  • ctx.c - Context/header files
  • code.c - Source code
  • metadata.json - Compiler settings
  • target.o - The target assembly
  • current.o - The current assembly if available

Example Directory Structure

scratches/
├── Func1/
│   ├── ctx.c
│   ├── code.c
│   ├── metadata.json
│   ├── target.o
│   └── current.o
└── Func2/
    ├── ctx.c
    ├── code.c
    ├── metadata.json
    ├── target.o
    └── current.o

Usage

Local scratch creation is now available through the GUI with a dedicated "💾 Local" button beside the existing "📲 decomp.me" button.

GUI Usage

  1. Configure your project (optional): Add local_scratch_dir to your objdiff.json configuration
  2. Select a function: Navigate to any function in the diff view
  3. Click the Local button: Use the "💾 Local" button to create a local scratch
  4. Access your files: Find the generated files in your configured directory or the default location

Requirements

  • Function must have proper scratch configuration (platform, compiler, etc.)
  • Target object file must be available
  • A valid home directory must be accessible (for automatic default path detection)

The local scratch files can then be used with any decompilation toolchain or kept as backups.

Contributing

Install pre-commit to run linting and formatting automatically:

rustup toolchain install nightly  # Required for cargo fmt/clippy
cargo install --locked cargo-deny # https://github.com/EmbarkStudios/cargo-deny
uv tool install pre-commit        # https://docs.astral.sh/uv, or use pipx or pip
pre-commit install

License

Licensed under either of

at your option.

Contribution

Unless you explicitly state otherwise, any contribution intentionally submitted for inclusion in the work by you, as defined in the Apache-2.0 license, shall be dual licensed as above, without any additional terms or conditions.

About

Same local diffing tool as Objdiff, has an extra feature to export scratches more easily

Resources

License

Stars

Watchers

Forks

Packages

No packages published

Languages

  • Rust 99.9%
  • TypeScript 0.1%