PortForge is a desktop application designed to manage game ports by facilitating the downloading, building, and installation of games, including those requiring compilation from source. It also organizes ROM libraries, ensuring dependent games can automatically access original ROM files.
Key Features:
Compiling Support: Handles ports that need compilation from source.
ROM Organization: Maintains a structured library for easy access to original ROMs.
One-Click Installation: Streamlines the process of downloading, building, and launching games with a single action.
Playtime Tracking: Records session lengths and cumulative playtime for user convenience.
Cross-Platform Compatibility: Supports Windows, macOS, and Linux operating systems.
Install Variants: Allows users to select options like ROM region or texture packs before installation.
Audience & Benefit:
Ideal for game enthusiasts, retro gamers, and modders, PortForge simplifies the management of ports and mods. It automates tedious tasks and ensures a well-organized ROM library, enhancing the user experience by reducing manual intervention.
README
PortForge
A desktop application for managing and launching game ports. PortForge handles downloading, building, and installing ports — including those that require compilation from source — and keeps your ROM library organized so games that depend on original ROM files can find them automatically.
This program is still at a very early stage. There are going to be bugs, I honestly have no idea to what degree it will work on Windows or Mac, and while I will try to avoid it, future updates may require manual moving of user data files.
On MediaItems
MediaItem is a filesystem-native open standard for cataloguing, archiving, and interacting with any form of media of my own invention. Documentation covering the standard will be released "soon™".
Roadmap
Make a Flatpak build for Linux
Add support for per-game executable arguments
Add support for editing per-game executable arguments from the PortForge UI
Add support for managing different versions of games
Add support for managing mods without reinstalling
Add support for building games for mobile platforms like Android and Nintendo Switch
Expand documentation to include how to dump ROMs
Expand ROM management functionality
Build complete ROM database based on No-Intro and Redump
Add support for playing Rom files via emulators
Add support for getting older PC games to run
Add support for dumping disc-based games with redumper
Features
Library view — browse available game ports with cover art and banner images
One-click install — download, extract, build, and launch from a single button
Build system — supports ports that must be compiled from source (e.g. SM64 ports), with per-platform build specs, multi-variant installs, and user-configurable args
ROM management — import ROMs by drag-and-drop; PortForge matches files by checksum and stores them in a central library; the library is indexed in SQLite for fast lookups without re-scanning on every page open
Install variants — choose ROM region, texture pack, or other options before installing; options requiring a missing ROM are shown as unavailable
Library updates — when the MediaItems library is synced, installed games are compared against the new version; an Update button appears on the game page when the library has changed
Play time tracking — session length is recorded and added to a time counter
Uninstall — remove installed files via the UI, with optional custom uninstall steps per game
Wails CLI v2: go install github.com/wailsapp/wails/v2/cmd/wails@latest
Getting started
Development
wails dev
Starts a Vite dev server with hot reload for the frontend. The app is also accessible in a browser at http://localhost:34115.
In dev mode the app reads the MediaItems catalog from the mediaitems/ folder at the project root instead of the OS config directory.
Production build
wails build
Produces a self-contained binary in build/bin/.
First-run setup
On first launch PortForge asks for one folder:
Folder
Purpose
User data folder
Writable. PortForge stores your ROM files, installed games, and save state here.
The MediaItems library is managed automatically by PortForge and stored in the OS configuration directory.
MediaItems library
The library is a folder tree of MediaItems — JSON files that describe games, ROMs, and platforms. PortForge reads this folder in the OS configuration directory and syncs it to the index on demand; it is never directly user-editable.
mediaitems/
├── VideoGameVersion/
│ └── Super Mario 64 Render96 · 2020/
│ ├── .mediaitem.json ← game metadata, download URL, ROM dependencies
│ ├── .install.json ← build spec (optional)
│ └── .artwork/
│ ├── cover.jpg
│ └── banner.jpg
└── VideoGameRom/
└── Super Mario 64 (USA)/
└── .mediaitem.json ← ROM title, platform, expected checksums
A SQLite index (library.db in the config directory) caches the listing fields from these JSON files and the presence of user ROM files so lookups are fast without re-parsing files on every page open. The index is rebuilt automatically after each sync, and can be refreshed manually at any time via Refresh index on the Settings page.
User library
When a game is installed or a ROM is imported, PortForge copies the relevant MediaItem folder from the library into the user data directory under library/. This snapshot is used to detect when the catalog has been updated since you last installed: if the catalog version of a MediaItem differs from your local copy after a sync, an Update button appears on the game's detail page.
ROM library
ROMs are stored in the user data folder and identified by MD5 checksum rather than filename. To add ROMs, drag and drop the files onto any PortForge window. PortForge matches each file against the known ROMs in the library and offers to copy or move it into place.
Build system
All games come with a .install.json file alongside their .mediaitem.json. The spec defines dependencies, user-configurable args, and an ordered list of install steps.
See docs/build-system.md for the full reference, including all step types (fetch, extract, run, copy, move, defineExecutable, and more), arg configuration, conditional steps, and a complete worked example.