Inventory a game
Skill
re-inventory. First look at a game's files (Windows PE, or DOS MZ/NE/LE executables) - which binaries hold the game's own code, which engine and middleware it uses, whether it is native, managed, scripted or packed, which data containers and save files exist - and record it in docs/FINDINGS.md. Use at the start of a project, or when a new binary or file type turns up.
Copy this prompt into your coding agent. Replace the part in angle brackets.
In my GameFrame project, use the re-inventory skill for <the task>.
Read the skill first and follow its steps in order.
Report the evidence it asks for, with its label: observed, measured, inferred or unknown.Before any decompiling, make a short map of the game with evidence. It says what to analyse, with which tool, and what to leave alone. A wrong choice here (decompiling a packed binary, or analysing the C++ runtime of a Unity game instead of its C# code) wastes days.
0. Get the files out of their installer
A purchased game often arrives as an installer (GOG's Inno Setup .exe, a Steam depot, an NSIS or InstallShield setup, an .msi, a .dmg or .pkg, GOG's Linux .sh). Never run it: extract it.
scripts/extract-installer.sh --detect "~/Downloads/setup_game.exe" # what it is, which tool
scripts/extract-installer.sh "~/Downloads/setup_game.exe" target/gog
python3 tools/triage/compare_trees.py target/game target/gog # same version?
python3 tools/triage/compare_trees.py target/game /dev/null --hashes > docs/HASHES.txt- A small macOS
.appnamed after the game is often only GOG Galaxy's web installer: no game. - Store releases bundle extras worth reading: DOSBox or ScummVM configs (the CPU speed and sound hardware the publisher tuned the game for), manuals and cheat sheets as PDF, saves.
- When you have two releases, compare them before choosing one. Identical executables mean every address and finding carries over; record the hashes (they are not game material) so every later finding names the exact version it was made on.
1. List the files
find target -maxdepth 3 -type f | sed 's/.*\.//' | sort | uniq -c | sort -rn | head -30 # by extension
find target -maxdepth 3 -type f -size +5M -exec ls -lh {} \; | sort -k5 -h # the big onesGroup them: executables and libraries (.exe .dll .so .dylib), data containers (large files with custom extensions: .pak .pkg .dat .arc .bin .wad .pck .assets), configuration (.ini .cfg .xml .json .lua), saves (often in the user's Documents or AppData, not the game folder).
2. Look at every binary
for b in target/*.exe target/*.dll; do .venv/bin/python tools/pe/peinfo.py "$b"; echo; doneFor each, note: 32- or 64-bit, EXE or DLL, PDB path (a leaked build path names the engine and project), compiler (a Rich header means MSVC), imports, exports, RTTI count (C++ class names are recoverable), engine fingerprints, and packer warnings.
Decide which binaries are the game's own code: usually the EXE and any DLL with a game-like name and many exports or imports between them. Leave out operating-system DLLs, the C/C++ runtime (msvcp140.dll, vcruntime140.dll), and known middleware (FMOD, Wwise, Bink, PhysX, Havok, Steam/GOG SDKs): document what they are and move on.
Engines often ship a runtime DLL that exports C++ class names (?Rand@Random@System@@...). Its exports are free, accurate names: decompile it together with the EXE.
DOS and 16-bit programs
file saying "MS-DOS executable" (or peinfo refusing the file) means a DOS program. Use:
for b in target/*.EXE target/*.exe target/*.OVL; do python3 tools/dos/dosinfo.py "$b"; echo; doneIt names the format (MZ real mode, NE 16-bit protected mode, LE/LX 32-bit extender), gives Ghidra's selector for every NE segment, lists imports and exports, and fingerprints the compiler, extender, packer and sound libraries. Two lines matter most:
debug symbols: Turbo Debugger: the original names of every procedure, global and type are in the file. Runpython3 tools/dos/tdinfo.py BINARY summarynow; see docs/DOS.md section 3. This can save weeks.- A packer (LZEXE, PKLITE, EXEPACK, DIET): unpack before anything else.
Launchers are common: a small MZ that runs the real program (tyrian.exe running file0001.exe). The DOSBox-X file log (scripts/dosbox-run.sh --fileio) shows which program and which data files are opened, in order. Runtime files (RTM.EXE, DPMI16BI.OVL, DOS4GW.EXE) are the compiler's DOS extender, not game code. The whole DOS route is in docs/DOS.md.
3. Choose the route
| What peinfo shows | What it means | Route |
|---|---|---|
| Native x64/x86, MSVC or MinGW, no packer | Ordinary compiled C/C++ | GameFrame: re-ghidra, re-trace, re-emulate |
mscoree.dll / _CorExeMain, or Assembly-CSharp.dll | .NET managed code (XNA, MonoGame, Unity Mono) | Decompile C# with ILSpy or dnSpyEx, or REA inspect_managed_artifact; the game logic is in the managed DLLs |
GameAssembly.dll + global-metadata.dat | Unity IL2CPP: C# compiled to C++ | Recover names with Il2CppDumper (or Cpp2IL), then Ghidra with the generated script |
UE4/UnrealEngine strings, .pak files | Unreal Engine | Most logic is in the EXE plus Blueprint bytecode in .uasset; tools such as FModel and UE4SS read the assets |
lua_pcall, .lua/.luac files | Lua scripting on a native engine | Decompile the scripts (unluac, luadec) for game rules; the native side is the engine |
| GameMaker / RPG Maker / Godot strings | A known engine with its own format | Use the engine's community tools for the data; the native binary is the stock runtime |
dosinfo: MZ or NE, Borland/Microsoft/Watcom runtime | 16-bit DOS or Windows 3.x code | GameFrame's DOS route: dosinfo.py, tdinfo.py, Ghidra, dos_emu, DOSBox-X (docs/DOS.md) |
dosinfo: LE/LX (DOS/4GW, PMODE/W) | 32-bit DOS-extender program | Ghidra with an LE/LX loader extension; run it in DOSBox-X |
A ROM or disc image for a console (.nes, .sfc, .md, .z64, .bin/.cue, .iso) | Console code at fixed addresses, often banked, no OS | The console route: docs/consoles/ (platforms, tools, routes to a port) |
An engine's archives or DLLs (.WAD, .PAK, .GRP, .u, .MPQ, glide2x.dll, Engine.dll) | A known engine or library | Read docs/engines/recognising.md; use the engine's documented formats and released source where it exists |
High-entropy executable section, .vmp0, .themida, UPX | Packed or protected | Stop. Unpack first (UPX: upx -d), or work from a memory dump with the user's agreement; Denuvo and VMProtect are out of scope for static analysis |
For an Android or iOS game, an Electron or browser game, or an archive you cannot identify, use REA's routing (re-rea): it has dedicated tools for each.
4. Data containers
For each large file type:
xxd target/data.pak | head -8 # magic number, header fields, offsets
.venv/bin/python -c "import math,collections,sys;d=open(sys.argv[1],'rb').read(1<<20);c=collections.Counter(d);print(-sum(n/len(d)*math.log2(n/len(d)) for n in c.values()))" target/data.pakEntropy near 8.0 means compressed or encrypted; 4 to 6 means plain structured data. Look for known signatures in the first bytes and inside: PK\x03\x04 (ZIP), \x78\x9c/\x78\xda (zlib), \x28\xb5\x2f\xfd (zstd), \x04\x22\x4d\x18 (LZ4 frame), RIFF, OggS, DDS , \x89PNG. Find the code that opens the file (search its name or extension in the strings), then decode it with re-format.
5. Record
Fill docs/FINDINGS.md (correct any first-look numbers the tools overturn, such as an NE segment with no bytes in the file, which is uninitialised data): the binaries table (file, role, architecture, compiler, notes), the engine and middleware with the evidence for each (the import or string that showed it), the data containers, and the open questions. Add the first lines to docs/CHECKLIST.md.
Also record the hardware the game was written for: the minimum CPU, the video modes, the 3D APIs, the sound devices and the input devices it supports (docs/hardware/). Its setup program and its readme list them.
6. Classify the game
Look at the game itself, not only its files: play it or watch it played. Then place it in the taxonomy (docs/games/README.md): who drives (a stream with controls, software over a simulation, an environment, turns and choices), its time model, where its rules live, what must repeat exactly, and its family. Read the family page and copy its rule set into the project's AGENTS.md, adjusted to the game. Record in docs/FINDINGS.md how exact the interface must be, and why. A mixed game gets one line per mode, and the state that switches between them. Next: re-observe.