jonathanpeppers/dotnes/nes-decompile

Claude Code and agent skill by jonathanpeppers/dotnes

Trust tier 2
  • community
LLM review pending
Source check pending

Checking that the SKILL.md file is still in the repository.

Decompile NES ROM files (.nes) into C# projects that can be rebuilt with dotnes. Use this skill whenever the user wants to decompile a ROM, reverse-engineer a .nes file, convert a ROM to C#, extract code from a NES ROM, create a project from an existing ROM, or do a round-trip test (transpile → decompile → retranspile). Also use when the user says things like "decompile this ROM", "turn this .nes into C#", "extract the code", "what does this ROM do", "reverse engineer", or "round-trip". This is the high-level decompilation tool — for low-level 6502 disassembly, use nes-rom-debug instead.

Install

npx vskill@latest install jonathanpeppers/dotnes/nes-decompile

SKILL.md

NES ROM Decompiler

Decompile .nes ROM files into complete C# projects that can be rebuilt through dotnes.

Decompiler Tool

The decompiler lives at src/dotnes.decompiler/ and is a .NET CLI tool.

Running the Decompiler
bash
dotnet run --project src/dotnes.decompiler -- <input.nes> [output-directory]
  • `<input.nes>` — Path to the NES ROM file (required)
  • `[output-directory]` — Where to write the C# project (optional; defaults to the ROM filename without extension)

Examples:

bash
# Decompile a sample ROM (build it first if needed)
cd samples/hello && dotnet build && cd ../..
dotnet run --project src/dotnes.decompiler -- samples/hello/bin/Debug/net10.0/hello.nes hello-decompiled
# Decompile any .nes ROM
dotnet run --project src/dotnes.decompiler -- path/to/game.nes game-decompiled
# Decompile with default output directory (uses ROM filename)
dotnet run --project src/dotnes.decompiler -- myrom.nes
Output Files

The decompiler generates a complete, buildable C# project:

FileDescription
Program.csDecompiled C# source with recovered NESLib API calls
{name}.csprojMSBuild project with NES configuration from ROM metadata
chr_generic.sCHR ROM data as ca65 assembly (only if ROM has CHR banks)
What Gets Recovered

The decompiler recognizes these NESLib API calls:

CategoryFunctions
Palettepal_col(palette, color)
VRAMvram_adr(NTADR_A(x, y)), vram_write("string")
PPU controlppu_on_all(), ppu_on_bg(), ppu_on_spr(), ppu_off()
Sprites/OAMoam_clear(), oam_size(), oam_hide_rest()
CHR bankingbank_spr(), bank_bg()
Inputpad_poll(0)
Timingdelay(frames), waitvsync()
Randomrand8(), set_rand()

String literals in vram_write() are recovered from ROM data when the bytes are printable ASCII. VRAM addresses passed to vram_adr() are decompiled back to NTADR_A(x, y) macro form when they match the nametable pattern 0x2000 + y*32 + x.

What Is NOT Recovered
  • Original variable names, control flow structures, or algorithm intent
  • User-defined functions (inlined into main)
  • Local variables and complex expressions
  • Non-NESLib subroutine calls (appear as comments)
  • Classes, objects, or BCL usage (NES doesn't support these)

Common Workflows

Decompile a dotnes sample ROM

Build the sample, then decompile its ROM output:

bash
# Build the sample
cd samples/hello && dotnet build && cd ../..
# Decompile the ROM
dotnet run --project src/dotnes.decompiler -- samples/hello/bin/Debug/net10.0/hello.nes hello-decompiled
# Inspect the output
cat hello-decompiled/Program.cs
Round-trip test (transpile → decompile → retranspile)

Verify the decompiler produces code that builds back to an equivalent ROM:

bash
# 1. Build original sample
cd samples/hello && dotnet build && cd ../..
# 2. Decompile the ROM
dotnet run --project src/dotnes.decompiler -- samples/hello/bin/Debug/net10.0/hello.nes hello-roundtrip
# 3. Build the decompiled project
cd hello-roundtrip && dotnet build && cd ..
# 4. Compare the two ROMs
python scripts/compare_rom.py samples/hello/bin/Debug/net10.0/hello.nes hello-roundtrip/bin/Debug/net10.0/hello.nes

If the round-trip produces an identical ROM, the decompiler recovered all observable behavior.

Decompile an external .nes ROM

Any iNES-format ROM can be parsed, but the decompiler only recognizes dotnes/neslib patterns:

bash
dotnet run --project src/dotnes.decompiler -- external-game.nes game-output
cat game-output/Program.cs

For ROMs not built with dotnes, the output will contain fewer recognized API calls and more comments for unrecognized subroutines.

Inspect ROM metadata without full decompilation

Use the decompiler's console output to quickly check ROM properties:

powershell
dotnet run --project src/dotnes.decompiler -- myrom.nes 2>&1 | Select-Object -First 6

This shows PRG/CHR bank counts, mapper number, mirroring mode, and interrupt vectors.

How the Decompiler Works

The decompiler uses a three-phase algorithm:

Phase 1: Build Symbol Table
  • Assembles the known neslib built-in subroutines to determine their addresses
  • Finds main() by scanning the initlib block for the first JSR to an address past the built-ins
  • Pattern-matches final built-ins (pusha, pushax, popa, vram_write, etc.) using byte signatures
Phase 2: Decompile Main
  • Collects all 6502 instructions from main until the infinite loop (JMP to self)
  • Uses look-ahead pattern matching to recognize multi-instruction sequences:
  • LDA #imm / JSR pusha → 8-bit argument push
  • LDA #lo / LDX #hi / JSR pushax → 16-bit pointer push
  • LDX #hi / LDA #lo / JSR <sub> → call with 16-bit register argument
  • LDA #imm / JSR <sub> → call with immediate argument
Phase 3: Generate C#
  • Converts the recognized patterns into NESLib API calls with recovered arguments
  • Reconstructs string literals and NTADR_A macro addresses
  • Wraps everything in the standard dotnes program structure

MSBuild Properties in Generated .csproj

The decompiler reads ROM metadata and sets appropriate MSBuild properties:

PropertyConditionExample
NESMapperMapper ≠ 0<NESMapper>1</NESMapper>
NESPrgBanksPRG banks ≠ 2<NESPrgBanks>4</NESPrgBanks>
NESChrBanksCHR banks ≠ 1<NESChrBanks>2</NESChrBanks>
NESVerticalMirroringMirroring is vertical<NESVerticalMirroring>true</NESVerticalMirroring>

Related Skills

  • nes-rom-debug — Low-level 6502 disassembly and byte-level ROM inspection
  • nes-emu-debug — Run ROMs in MesenCE emulator to verify runtime behavior

Security

  • Security scanPassed, 100 of 100Pattern checks on the skill's files.
  • Model reviewNot runA model review is scheduled for the next rescan.

Quality evaluation

  • Task evaluationNot runNo evaluation yet. Run one in Skill Studio.

Source

Popularity

Repository stars
673
Repository forks
24
7-day trend score
33

Stars and forks are for the whole GitHub repository, not this skill alone. Not refreshed yet.

Works with

Any agent vskill installs to: 56 targets in all. These 39 have a page on this site.

  • Claude Code
  • Cursor
  • GitHub Copilot
  • Windsurf
  • Codex
  • Gemini CLI
  • Cline
  • Amp
  • Roo Code
  • Goose
  • Continue
  • Kilo Code
  • Junie
  • Trae
  • OpenHands
  • Qwen Code
  • AI Agent
  • Tabnine Chat
  • Sourcegraph Cody
  • Amazon Q
  • Firebase Genkit
  • Sweep
  • Devin
  • Phind
  • Mentat
  • Claude Desktop
  • Aider
  • GPT Pilot
  • Plandex
  • bolt.new
  • v0
  • Replit Agent
  • Anse
  • TypingMind
  • BetterChatGPT
  • LibreChat
  • Warp AI
  • Pieces
  • Fig AI
Embed badge
vskill VERIFIED badge
[![vskill VERIFIED](https://verified-skill.com/api/v1/skills/jonathanpeppers/dotnes/nes-decompile/badge)](https://verified-skill.com/skills/jonathanpeppers/dotnes/nes-decompile)

Something wrong with this skill or its page? Tell us.