Skip to content

Repository files navigation

A note on this project: I'm building this to get my hands dirty with agentic AI and see what it can actually do for coding. This is a non-commercial, educational project by hiitsgabe.

I know there's a lot of "AI slop" being sold to gamers right now, and I want to be clear: this isn't that. This is my personal sandbox for testing the limits of AI agents while creating something useful. It is experimental and a bit unstable, but it's a genuine effort to create something cool and helpful while I improve my skills w/ AI.

I will never ask you to donate money to this project, or for me, because of this. The only thing I ask is that if you find a bug, you use the issues here on GitHub to report it so I can make it better for everyone. You can also use issues to give ideas. Pull requests are welcomed, help me build this! :)

🎮 Console Utilities



Screenshot

⚠️ Disclaimer: This application does not endorse any form of piracy. Only download games you legally own.

A PyGame-based utility suite for handheld gaming consoles, with a retro CRT-themed interface designed for D-pad and controller navigation. Browse, download, organize, and manage game files from configurable sources. Supports HTML directory listings, JSON APIs, and Internet Archive. Runs on Batocera/Knulli handhelds, macOS, Windows, Linux, and Android.


✨ Features

📥 Download Management

  • Batch Downloads — Select multiple games and download them in a queue with real-time progress, speed, and ETA
  • Resume Capability — Interrupted downloads can be resumed right where they left off
  • Automatic Extraction — ZIP and RAR files are extracted and organized into the correct system folder
  • NSZ Decompression — Built-in NSZ to NSP conversion for Nintendo Switch files

🔍 Browsing & Navigation

  • Multiple View Modes — List view and grid layout with box art thumbnails
  • Search — Filter games by name within any system
  • Region Filtering — USA-only filter with configurable regex per system
  • Installed Detection — Optionally hide games already downloaded

⚽🏒⚾ Sports ROM Patcher

  • Live Roster Updates — Fetch current or historical season rosters from public sports APIs (ESPN, NHL API, API-Football) and patch them into your legally owned game ROMs
  • Multi-Platform Support — Patchers for retro soccer, baseball, and hockey titles across PS1, SNES, Genesis, and PSP
  • Step-by-Step Workflow — Guided process: select season → fetch rosters → preview teams → pick your ROM → patch
  • Roster Preview — View fetched teams and players before committing changes
  • Player Attributes — Maps real-world stats (goals, assists, speed, etc.) to in-game attribute scales
  • Team Customization — Update team names, kit/jersey colors, and flag designs where supported
  • Historical Seasons — Access roster data from past seasons via public APIs (availability varies by provider)
  • Non-Destructive — Saves patched output to a new file, leaving your original ROM untouched

📖 See the Sports ROM Patcher Guide for detailed usage instructions.

🛠️ Utilities

  • 🎮 Steam Shortcut Creator — Search Steam games and create .steam shortcut files for ES-DE frontends on Android — browse with banner images, pick a folder, and generate the shortcut
  • 🔗 Direct URL Download — Download a file from any URL
  • 📚 Internet Archive Integration — Download individual files or add entire IA collections as systems
  • 🖼️ Image Scraping — Scrape game artwork from multiple providers (Libretro, ScreenScraper, TheGamesDB, RAWG, IGDB) with batch mode support
  • 🔄 File Deduplication — Detect and remove duplicate files (safe and fuzzy matching)
  • ✏️ Filename Cleanup — Batch rename files to clean formats
  • 👻 Ghost File Cleaner — Find and remove orphaned split archives
  • 📂 ZIP/RAR Extraction — Extract archives from the file browser

🔄 Syncthing Save Sync

  • Cross-Device Save Sync — Synchronize game saves between your computer and Knulli/Batocera consoles or Android devices using Syncthing
  • Hub-and-Spoke Architecture — Computer acts as the hub, with multiple consoles and Android devices as spokes
  • Per-System Folders — Auto-configures shared folders for 22+ gaming systems (PSX, SNES, N64, GBA, NDS, PSP, and more)
  • Custom Save Support — Add custom save folders with selective file syncing and .stignore whitelisting
  • Versioning — Built-in 5-file rollback support for save safety
  • Auto-Detection — Discovers Syncthing API key from the local config automatically

Note: This is not Syncthing itself — it's a helper that configures an existing Syncthing installation through its REST API. See the Syncthing Save Sync Guide for setup instructions.

⚙️ System Management

  • Add Custom Systems — Discover systems from directory listings or manually configure new sources
  • Per-System Settings — Custom ROM folders, hide/show systems
  • Multiple Server Formats — HTML directory listings, JSON APIs, Internet Archive metadata API
  • Authentication — Bearer tokens, cookies, and IA S3 credentials

🖥️ Interface

  • CRT Theme — Phosphor green retro aesthetic with scanlines, vignette, and bezel effects
  • Controller & Keyboard — Full D-pad/gamepad support with acceleration and touch/mouse input
  • Auto-Updates — Check for and install app updates from within the app

🚀 Installation

💻 Development Setup

# Setup conda environment and install dependencies
make setup

# Run with auto-restart on file changes
make run

# Run without auto-restart (full error logs)
make debug

Or manually:

conda env create -f environment.yml
conda activate console_utilities
pip install -e .[dev]
DEV_MODE=true python src/app.py

🎮 Console Installation (Batocera/Knulli)

  1. Create a downloader folder inside your console's pygame roms directory
  2. Run make bundle to create the distribution package
  3. Copy dist/pygame.zip contents (console_utils.pygame + assets/) to the console folder
  4. Rescan games in EmulationStation
  5. Navigate to the PyGame library and launch Console Utilities

🏗️ Building for Other Platforms

make bundle            # 🎮 PyGame bundle for consoles
make bundle-macos      # 🍎 macOS .app standalone
make bundle-windows    # 🪟 Windows .exe standalone
make build-android     # 🤖 Android APK (Docker-based)

🔧 Configuration

System Sources (bundled_data.json)

Systems are configured via JSON files that define where to find files and how to parse server responses. See the docs for details:

User Settings (config.json)

Runtime settings are auto-generated and stored in config.json:

  • 📁 Directories — Working directory, ROMs directory
  • 🖥️ Display — Box art thumbnails, USA-only filter, skip installed games
  • 📚 Internet Archive — Enable/disable, S3 credentials
  • 🖼️ Scraper — Provider selection (Libretro, ScreenScraper, TheGamesDB, RAWG, IGDB), frontend format (EmulationStation, ES-DE, RetroArch, Pegasus), API credentials
  • 🔐 NSZ — Enable/disable, keys file path
  • 🔄 Syncthing — Enable/disable, role (host/console), device IDs, base path, custom saves

🎯 Controls

System Selection

Input Action
⬆️⬇️ D-pad / Arrow Keys Navigate systems
🅱️ Button / Enter Select system
🅰️ Button / Escape Exit application
SELECT Toggle list/grid view

Game Selection

Input Action
⬆️⬇️ D-pad / Arrow Keys Navigate games
⬅️➡️ D-pad / Page Up/Down Jump by letter
🅱️ Button / Space Toggle game selection
🅰️ Button / Escape Return to systems
START / Enter Begin download
SELECT Toggle view/thumbnails

During Download

Input Action
🅰️ Button / Escape Cancel download
Real-time progress with speed & ETA

📁 Project Structure

console_utilities/
├── src/
│   ├── app.py                          # 🚀 Main application entry point
│   ├── state.py                        # 📊 Centralized state management
│   ├── constants.py                    # 🔢 Global constants and paths
│   ├── config/
│   │   └── settings.py                # ⚙️ User settings persistence
│   ├── services/
│   │   ├── data_loader.py            # 📦 System/game data loading
│   │   ├── download_manager.py       # 📥 Download queue management
│   │   ├── file_listing.py           # 📋 Remote file listing (HTML/JSON/IA)
│   │   ├── image_cache.py            # 🖼️ Thumbnail caching
│   │   ├── installed_checker.py      # ✅ Local file detection
│   │   ├── internet_archive.py       # 📚 Internet Archive API
│   │   ├── scraper_manager.py        # 🔍 Image scraper orchestration
│   │   ├── scraper_providers/        # 🎨 Libretro, ScreenScraper, etc.
│   │   ├── we_patcher/              # ⚽ PS1 soccer ROM patcher
│   │   ├── iss_patcher/             # ⚽ SNES soccer ROM patcher
│   │   ├── kgj_mlb_patcher/         # ⚾ SNES baseball ROM patcher
│   │   ├── nhl94_genesis_patcher/   # 🏒 Genesis hockey ROM patcher
│   │   ├── nhl94_snes_patcher/      # 🏒 SNES hockey ROM patcher
│   │   └── nhl07_psp_patcher/       # 🏒 PSP hockey ISO patcher
│   ├── input/
│   │   ├── controller.py             # 🎮 Controller/gamepad input
│   │   ├── navigation.py             # 🕹️ D-pad navigation with acceleration
│   │   └── touch.py                  # 👆 Touch/mouse input
│   ├── ui/                            # 🎨 UI components (Atomic Design)
│   │   ├── theme.py                  # 🎨 Design tokens and theming
│   │   ├── atoms/                    # 🔵 Basic components
│   │   ├── molecules/                # 🟢 Composite components
│   │   ├── organisms/                # 🟡 Complex sections
│   │   ├── templates/                # 🟠 Page layouts
│   │   └── screens/                  # 🔴 Complete screens and modals
│   ├── utils/                         # 🔧 Logging, formatting, NSZ wrapper
│   └── nsz/                           # 🔐 Embedded NSZ library
├── assets/
│   ├── bundled_data.json             # 📋 System configuration
│   ├── docs/                         # 📖 Platform-specific build docs
│   ├── examples/                     # 📝 Example configuration files
│   ├── fonts/                        # 🔤 VT323 retro font
│   └── images/                       # 🖼️ Logo and screenshots
├── docs/                              # 📖 User documentation
├── workdir/                           # 🗂️ Development runtime data
├── dist/                              # 📦 Built distributions
├── Makefile                           # 🏗️ Build and development commands
├── buildozer.spec                     # 🤖 Android build configuration
├── environment.yml                    # 🐍 Conda environment specification
├── pyproject.toml                     # 📋 Python project configuration
└── README.md

📦 Dependencies

  • 🐍 Python 3.11+
  • 🎮 pygame >= 2.0.0
  • 🌐 requests >= 2.25.0
  • 📦 rarfile (bundled for console)
  • 👀 watchdog (development only)
  • 🖤 black, flake8 (development only)

🖥️ Compatibility

Platform Details
🎮 Console Knulli RG35xxSP and other Batocera-based handhelds
💻 Desktop macOS (.app), Windows (.exe), Linux
📱 Mobile Android (APK via Buildozer)
🖥️ Display 800x600 resolution, optimized for small screens

📖 Documentation


⚖️ Legal Notice and Disclaimer

⚠️ IMPORTANT LEGAL DISCLAIMER:

  • No ROM Data Storage — This system does not host, store, or distribute any ROM files, game data, or copyrighted content. It is purely a download management and ROM patching tool.

  • No Game Copies — This application contains no copies of games, ROMs, ISOs, or any copyrighted gaming content whatsoever.

  • ROM Patching — Original Copies Only — The sports ROM patcher feature requires users to provide their own legally obtained ROM or ISO files dumped from original game media they own. This project does not provide, link to, or facilitate the acquisition of any game files. Any ROM or ISO used with the patcher must come from an original copy of the game that you legally own.

  • No Affiliation — This project is not affiliated with, endorsed by, or associated with any game publishers, developers, sports leagues, or rights holders.

  • Example Configuration — Any included configuration files serve as examples only. They demonstrate how the system works but do not endorse or recommend any specific download sources.

  • Legal Responsibility — Users are solely responsible for:

    • Ensuring they have legal rights to download any content
    • Providing only legally owned ROM/ISO files for patching
    • Complying with copyright laws in their jurisdiction
    • Verifying the legality of any download sources they configure
    • Understanding that downloading copyrighted content without permission may be illegal
  • Third-Party Sources — Any websites or download sources referenced in configuration examples are third-party services. Users should research and evaluate the legal status of such sources independently.

  • Legal Use Only — This tool is intended exclusively for downloading legally owned content, homebrew games, or content explicitly permitted for distribution. The ROM patching features are intended solely for personal use with games you legally own.

  • No Liability — The developers and contributors of this project assume no responsibility or liability for any misuse of this software. Users bear full responsibility for how they use this tool and must ensure compliance with all applicable laws.

By using this software, you acknowledge that you understand these legal responsibilities and agree to use it only for lawful purposes.


🙏 Credits & Acknowledgments

This project incorporates the following open source libraries and projects:

  • NSZ Library — NSZ compression/decompression functionality provided by nicoboss/nsz — A compression/decompression tool with fast compression and decompression for various file formats.
  • Syncthing — Save synchronization powered by Syncthing — An open-source continuous file synchronization program.

🐛 Troubleshooting

Error Logging

  • Check error.log in the application directory for detailed error information
  • On Batocera systems: /userdata/roms/pygame/downloader/error.log
  • Development: py_downloads/error.log in the project root

Common Issues

Problem Solution
🚫 No games showing Verify your system configuration and network connectivity
❌ Download failures Check available disk space and directory permissions
🖥️ Display issues Ensure pygame dependencies are properly installed
🖼️ Thumbnails not loading Check that the boxarts URL is correct and accessible

Development

make format    # 🖤 Format code with black
make lint      # 🔍 Lint code with flake8
make test      # 🧪 Run tests with pytest
make clean     # 🧹 Clean build artifacts

📜 License

This project is licensed under CC BY-NC 4.0. You're free to share, adapt, and build upon it for non-commercial purposes, with attribution. See the LICENSE file for details.


🤝 Contributing

Pull requests are welcome — from humans and AI agents alike! 🤖 For major changes, please open an issue first to discuss proposed modifications.

About

Python App to Manage Retro Gaming Consoles

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Contributors

Languages