Skip to content

retznutz/retropac

Repository files navigation

RetroPac Logo

Ultimarc LED Controllers for RetroPie

This program controls LED lighting on Ultimarc LED controllers. The software consists of a C playback engine that communicates via USB to the PAC controller, a C based RGBCommander config file format converter, a small C webserver that serves up the RetroPac animation editor that's written in Nuxt (Vue).

Technically this can run on other Raspberry Pi based game systems, making and installing are all the same. You just need to have similar scripts that run when you start up a rom, end a rom and start up Emulation Station or other emulation software and pass certain info.

Supported Devices

Device LED Channels RGB LEDs Intensity Control Hardware Features
I-PAC Ultimate I/O 96 32 256 levels ✓ Fade
PacLED64 64 21 256 levels ✓ Fade, Flash, Scripting
NanoLED 60 20 256 levels ✓ Fade, Flash, Scripting
PacDrive 16 5 On/Off only -
U-HID 16 5 On/Off only -
USB Button 3 (RGB) 1 256 levels -

RetroPac Demo Video
▶️Watch Video

Features

  • Automatically lights up arcade buttons based on game controls
  • LED animations for attract mode (rainbow, breathing, chase, sparkle, color cycle)
  • Custom animations - Create your own animation sequences in JSON
  • Multiple controller support - Control multiple Ultimarc controllers simultaneously
  • Multi-device support - Works with I-PAC Ultimate, PacLED64, NanoLED, PacDrive, U-HID, and USB Button
  • JSON-based configuration for emulators, ROMs, and button mappings
  • Self-managing daemon mode (auto-kills previous instance)
  • Integrates with RetroPie's runcommand scripts

Requirements

  • Raspberry Pi (tested on Raspberry Pi 3/4)
  • RetroPie
  • Ultimarc LED controller (I-PAC Ultimate I/O, PacLED64, NanoLED, PacDrive, U-HID, or USB Button)
  • libjson-c library for JSON parsing
  • libusb-1.0 for USB communication
  • libxml2 (optional, for RGBcommander config converter)

Installation

Quick Install (Recommended)

The easiest way to install RetroPac is using the install script:

chmod +x install.sh
./install.sh

This will:

  • Install all required system dependencies
  • Install Node.js (if not present)
  • Build retropac, anim-server, and the web interface
  • Install to /usr/local/bin/retropac
  • Create config at /etc/retropac/config.json

Install script options:

  • --no-web - Skip building the web animation editor
  • --no-server - Skip building the anim-server
  • --no-install - Build only, don't install to system

Manual Installation

If you prefer to install manually:

Install Dependencies

sudo apt-get update
sudo apt-get install -y build-essential libjson-c-dev libusb-1.0-0-dev libmicrohttpd-dev

# Optional: for RGBcommander config converter
sudo apt-get install -y libxml2-dev

Build

make
make server

Build Web Interface

cd web
npm install
npm run generate
cd ..

Install

sudo make install

This will install the binary to /usr/local/bin/retropac and config to /etc/retropac/.

Build RGBcommander Converter (Optional)

If you have an existing RGBcommander configuration (rgbcmdd.xml), you can convert it to RetroPac format:

make converter
./bin/rgbcmd2retropac rgbcmdd.xml config.json

Specify a target controller for the converted ROM configs:

./bin/rgbcmd2retropac rgbcmdd.xml config.json --controller ipac-ultimate

Migrate Existing Config to Per-Controller Format

If you have an existing config.json with the old flat ROM format (button colors directly under ROM), you can migrate it to the new per-controller format:

# Migrate using the first controller in your config
./bin/rgbcmd2retropac --migrate config.json

# Migrate and assign ROM configs to a specific controller
./bin/rgbcmd2retropac --migrate config.json --controller pac64

This will convert ROM entries from:

"sf2": {
  "P1_BUTTON1": "#FF0000"
}

To the new per-controller format:

"sf2": {
  "controllers": {
    "ipac-ultimate": {
      "P1_BUTTON1": "#FF0000"
    }
  }
}

Configuration

JSON Config File

The default configuration file is located at /etc/retropac/config.json. You can specify a custom location with the --config option:

retropac --config /path/to/config.json mame sf2.zip

Example configuration:

{
  "animations_dir": "/home/pi/retropac/animations",
  "ipac_controllers": [
    {
      "device": "ipac-ultimate",
      "vendor_id": "0xd209",
      "product_id": "0x0410",
      "pin_mappings": {
        "P1_BUTTON1": { "r_pin": 1, "g_pin": 2, "b_pin": 3 },
        "P1_BUTTON2": { "r_pin": 4, "g_pin": 5, "b_pin": 6 }
      },
      "default": {
        "P1_COIN": "#FFFF00",
        "P1_START": "#FF0000",
        "P1_BUTTON1": "#FFFF00",
        "P1_BUTTON2": "#0000FF"
      },
      "button_labels": {
        "P1_BUTTON1": "Punch",
        "P1_BUTTON2": "Kick"
      }
    }
  ],
  "emulators": {
    "mame": {
      "roms": {
        "sf2": {
          "controllers": {
            "ipac-ultimate": {
              "P1_COIN": "#FFFF00",
              "P1_START": "#FF0000",
              "P1_BUTTON1": "#00FF00",
              "P1_BUTTON2": "#00FF00",
              "P1_BUTTON3": "#00FF00",
              "P1_BUTTON4": "#00FF00",
              "P1_BUTTON5": "#00FF00",
              "P1_BUTTON6": "#00FF00"
            }
          }
        },
        "default": {
          "P1_COIN": "#FFFF00",
          "P1_START": "#FF0000"
        }
      }
    }
  }
}

Per-Controller ROM Configuration

ROM LED configurations are organized by controller, allowing discrete control over which controller receives which colors:

"sf2": {
  "controllers": {
    "ipac-ultimate": {
      "P1_BUTTON1": "#00FF00",
      "P1_BUTTON2": "#00FF00"
    },
    "pac64": {
      "P1_COIN": "#FFFF00"
    }
  }
}

This prevents unwanted LED activation when different controllers use the same button names for different purposes (e.g., P1_BUTTON1 on your main controller vs cabinet LEDs on a secondary controller).

Backwards Compatibility: The old flat format is still supported but deprecated:

"sf2": {
  "P1_BUTTON1": "#00FF00"
}

Legacy configs will broadcast button colors to all controllers. Use the migration tool to convert to the new format.

Button Labels

The optional button_labels section within each controller lets you define friendly names for buttons. These labels are displayed in the web UI for easier identification:

{
  "ipac_controllers": [
    {
      "device": "ipac-ultimate",
      "vendor_id": "0xd209",
      "product_id": "0x0410",
      "pin_mappings": { ... },
      "default": { ... },
      "button_labels": {
        "P1_COIN": "Coin",
        "P1_START": "Start",
        "P1_BUTTON1": "Light Punch",
        "P1_BUTTON2": "Medium Punch",
        "P1_BUTTON3": "Heavy Punch",
        "P1_BUTTON4": "Light Kick",
        "P1_BUTTON5": "Medium Kick",
        "P1_BUTTON6": "Heavy Kick"
      }
    }
  ]
}

Labels appear in:

  • Pin mapping cards (below the technical button name)
  • Button tooltips in the arcade panel
  • Selected button displays

Multi-Controller Button Mapping

When using multiple controllers, each controller is identified by its device name and can have unique pin mappings:

  • Each controller defines which buttons it controls via pin_mappings
  • ROM configs specify which controller(s) should receive button colors
  • This allows precise control over which LEDs light up on which device

Example with two controllers:

{
  "ipac_controllers": [
    {
      "device": "ipac-ultimate",
      "pin_mappings": {
        "P1_BUTTON1": { "r_pin": 1, "g_pin": 2, "b_pin": 3 },
        "P1_BUTTON2": { "r_pin": 4, "g_pin": 5, "b_pin": 6 }
      }
    },
    {
      "device": "pac64",
      "pin_mappings": {
        "P1_COIN": { "r_pin": 1, "g_pin": 2, "b_pin": 3 },
        "P2_COIN": { "r_pin": 4, "g_pin": 5, "b_pin": 6 }
      }
    }
  ],
  "emulators": {
    "mame": {
      "roms": {
        "sf2": {
          "controllers": {
            "ipac-ultimate": {
              "P1_BUTTON1": "#00FF00",
              "P1_BUTTON2": "#0000FF"
            },
            "pac64": {
              "P1_COIN": "#FFFF00"
            }
          }
        }
      }
    }
  }
}

In this example, loading Street Fighter 2 will:

  • Set P1_BUTTON1 green and P1_BUTTON2 blue on the ipac-ultimate controller
  • Set P1_COIN yellow on the pac64 controller

Note: If you rename a controller's device field in the web UI, all ROM references to that device are automatically updated.

Important: The animations_dir setting should use an absolute path when running retropac from RetroPie scripts. Relative paths won't work because the working directory varies depending on how retropac is launched.

RetroPie Integration

USB Permissions

To allow non-root users to access the PAC controller, create a udev rule:

sudo nano /etc/udev/rules.d/99-ipac.rules

Add the following content:

# Ultimarc PAC controllers (Ultimate I/O shown)
SUBSYSTEM=="usb", ATTRS{idVendor}=="d209", MODE="0666"
SUBSYSTEM=="usb_device", ATTRS{idVendor}=="d209", MODE="0666"

Note: Replace d209 with your actual vendor ID if different. Run lsusb | grep -i ultimarc to find your device's vendor ID.

Reload udev rules and unplug/replug the controller:

sudo udevadm control --reload-rules
sudo udevadm trigger

Runcommand Scripts

Add to /opt/retropie/configs/all/runcommand-onstart.sh:

#!/bin/bash
# When a game starts, set static LEDs (auto-kills any running animation)
/usr/local/bin/retropac --quiet "$1" "$3"

Add to /opt/retropie/configs/all/runcommand-onend.sh:

#!/bin/bash
# When returning to EmulationStation, start attract mode animation
/usr/local/bin/retropac --custom pulse_red --daemon default default default

Make both scripts executable:

chmod +x /opt/retropie/configs/all/runcommand-onstart.sh
chmod +x /opt/retropie/configs/all/runcommand-onend.sh

EmulationStation Startup Animation

To start the attract mode animation when EmulationStation first launches (on boot), edit the autostart script:

nano /opt/retropie/configs/all/autostart.sh

Add the retropac command before the emulationstation line:

/usr/local/bin/retropac --custom pulse_red --daemon default default default &
emulationstation

Important: The & at the end runs retropac in the background so EmulationStation continues to start. Without it, EmulationStation would wait for retropac to exit (which it won't in daemon mode).

Usage

retropac [options] <emulator> <rom_path> [mode]

Command Line Options

Option Description
--animate <type> Run built-in animation (see Animation Types below)
--custom <name> Run custom animation by filename (without .json)
--speed <ms> Animation speed in milliseconds (default: 50)
--color <hex> Base color for animations (e.g., #FF0000)
--set-button <name> <color> Set a single button LED (e.g., --set-button P1_BUTTON1 #FFFFFF)
--daemon Run as background daemon
--quiet Suppress all console output
--config <path> Custom config file path (default: /etc/retropac/config.json)
--help Show help message

Animation Types (Built-in)

Type Description
rainbow Rotating rainbow colors across all buttons
breathing Smooth fade in/out pulse effect
chase Running light with trailing fade
sparkle Random sparkle effect
color_cycle Cycle through a list of colors

Examples

Basic Usage

Run with a specific game (sets LEDs based on emulator/ROM config):

retropac mame /home/pi/RetroPie/roms/mame/sf2.zip

Use default button configuration (EmulationStation menu):

retropac default default default

Built-in Animations

Run rainbow animation as daemon (background):

retropac --animate rainbow --daemon default default default

Run breathing animation with red color at 30ms speed:

retropac --animate breathing --color '#FF0000' --speed 30 default default default

Run chase animation in foreground (Ctrl+C to stop):

retropac --animate chase --color '#00FF00' default default default

Run sparkle animation with blue:

retropac --animate sparkle --color '#0000FF' --daemon default default default

Single Button Control

Set a single button LED to white (useful for testing pin mappings):

retropac --set-button P1_BUTTON1 '#FFFFFF'

Turn off a single button LED:

retropac --set-button P1_BUTTON1 '#000000'

Set button to red in quiet mode (no output):

retropac --quiet --set-button P1_START '#FF0000'

Note: The --set-button option doesn't require emulator/ROM arguments. It directly controls a single LED using the pin mappings from config.json.

Custom Animations

Run a custom animation by filename:

retropac --custom rainbow_wave default default default

Run custom animation as daemon:

retropac --custom rainbow_wave --daemon default default default

Run the idle animation configured in config.json:

retropac --custom idle --daemon default default default

RetroPie Integration Examples

When a game starts (in runcommand-onstart.sh):

#!/bin/bash
# Set static LEDs for the game (auto-kills any running animation)
/usr/local/bin/retropac "$1" "$3"

When a game ends (in runcommand-onend.sh):

#!/bin/bash
# Start attract mode with custom animation
/usr/local/bin/retropac --custom idle --daemon default default default

# Or use a built-in animation
# /usr/local/bin/retropac --animate rainbow --daemon default default default

Self-Managing Daemon

RetroPac automatically manages its daemon process:

  • Each invocation kills any existing retropac daemon
  • PID is stored in /tmp/retropac.pid
  • No need for manual pkill in shell scripts

Supported Buttons

  • P1_COIN, P2_COIN, P3_COIN, P4_COIN
  • P1_START, P2_START, P3_START, P4_START
  • P1_BUTTON1-6, P2_BUTTON1-6, P3_BUTTON1-6, P4_BUTTON1-6
  • P1_JOYSTICK, P2_JOYSTICK, P3_JOYSTICK, P4_JOYSTICK
  • P1_TRACKBALL, P2_TRACKBALL, P3_TRACKBALL, P4_TRACKBALL

Custom Animations

RetroPac supports custom animations defined in JSON files. See docs/ANIMATIONS.md for the complete format specification.

Quick Setup

  1. Create an animations directory alongside your config.json
  2. Add animation JSON files (e.g., rainbow_wave.json)
  3. Configure the idle animation in config.json:
{
  "animations_dir": "animations",
  "idle_animation": "rainbow_wave",
  "ipac_controllers": [...],
  "default": {...},
  "emulators": {...}
}

Animation File Format

{
  "name": "Rainbow Wave",
  "speed": 50,
  "loop": true,
  "frames": [
    {
      "buttons": [
        {"button": "P1_BUTTON1", "color": "#FF0000"},
        {"button": "P1_BUTTON2", "color": "#FF7F00"}
      ],
      "fade": true,
      "fade_speed_ms": 200
    }
  ]
}
Field Description
name Display name for the animation
speed Base timing interval in milliseconds
loop Whether animation repeats (true/false)
frames Array of frame objects

Frame Fields

Field Description
buttons Array of button-color pairs to set in this frame
fade Whether to fade to the colors
fade_speed_ms Fade duration in milliseconds

Button-Color Pair Fields

Field Description
button Button identifier (e.g., "P1_BUTTON1")
color Target color in hex format
controller (Optional) Controller index (0-based) to target. Omit to apply to all controllers.

Project Structure

retropac/
├── src/                    # Source files
│   ├── main.c              # Main program entry
│   ├── config.c            # JSON configuration parsing
│   ├── ipac.c              # PAC USB communication
│   └── animation.c         # LED animation engine
├── include/                # Header files
│   └── retropac.h
├── animations/             # Custom animation files
│   ├── rainbow_wave.json
│   ├── pulse_red.json
│   └── startup_sequence.json
├── web/                    # Animation Editor web app
│   ├── app.vue             # Main Vue component
│   ├── components/         # Vue components
│   └── composables/        # API composables
├── docs/                   # Documentation
│   └── ANIMATIONS.md       # Custom animation format docs
├── tools/                  # Utility tools
│   ├── rgbcmd2retropac.c   # RGBcommander converter
│   └── anim-server.c       # Animation Editor HTTP server
├── config.example.json     # Example configuration
├── Makefile
└── README.md

Animation Editor

RetroPac includes a visual web-based animation editor for creating and editing custom animation files.

For complete setup instructions, see docs/EDITOR_SETUP.md.

Quick Start

# Install dependencies
sudo apt install libmicrohttpd-dev libjson-c-dev
curl -fsSL https://deb.nodesource.com/setup_20.x | sudo -E bash -
sudo apt install nodejs

# Build server and web app
make server
cd web && npm install && npm run generate && cd ..

# Run the server
./bin/anim-server

Then open a browser on another computer and navigate to:

http://<your-raspberry-pi-ip>:8080

Animation Editor Features

  • Visual arcade panel layout - Click buttons to select them
  • Color picker - Choose colors for selected buttons
  • Frame timeline - Add, remove, and reorder animation frames
  • Drag-and-drop reordering - Rearrange frames by dragging them in the timeline
  • Live preview - Play animations with real-time frame highlighting
  • Frame settings - Configure fade, fade speed, and delay per frame
  • Animation settings - Set name, speed, and loop options
  • Save/Load - Animations are saved directly to the animations directory
  • Full-width responsive layout - Works on any screen size

Config Editor

The web application also includes a Config Editor for managing your RetroPac configuration file (config.json) directly from the browser.

Accessing the Config Editor

Navigate to the Config tab in the web interface, or go directly to:

http://<your-raspberry-pi-ip>:8080/config

Config Editor Features

iPAC Controller Management

  • Add/Remove Controllers - Manage multiple PAC controllers
  • Editable Device Settings - Modify device name, vendor ID, and product ID
  • Pin Mappings - Configure RGB pin numbers for each button
  • Test Button - Click the 💡 icon to light up a button on the hardware (verifies correct pin mapping)
  • Friendly Labels - Custom button labels are displayed below the technical name
  • Add Button Dropdown - Select from available button names (filters out already-used buttons)

Button Labels

  • Custom Names - Define friendly names for buttons (e.g., "Punch", "Kick", "Jump")
  • Display Everywhere - Labels appear in pin mappings, tooltips, and selected button displays
  • Per-Button Configuration - Set labels for any or all of the 86 supported buttons

Default Button Colors

  • Visual Color Picker - Set default LED colors for each button
  • Add/Remove Buttons - Configure which buttons have default colors
  • Button Name on Top - Clear card layout with color picker below

Emulators & ROMs

  • Emulator Management - Add, remove, and configure emulators
  • ROM Configuration - Set per-ROM button colors
  • Duplicate ROM - Quickly copy a ROM configuration as a starting point
  • Alphabetical Sorting - Emulators and ROMs are sorted for easy navigation
  • Expandable Sections - Collapse/expand ROMs to manage large configurations

General Features

  • Auto-Save Detection - Unsaved changes are tracked with a visual indicator
  • Backup Function - Create timestamped backups (config-bak-yyyyMMddHHmmss.json)
  • Toast Notifications - Feedback for save, backup, and error states
  • Responsive Design - Works on desktop and tablet screens

API Endpoints

The server provides the following REST API endpoints for configuration:

Method Endpoint Description
GET /api/config Get the full configuration
PUT /api/config Save the full configuration
POST /api/config/backup Create a backup of config.json
GET /api/buttons Get list of valid button names
GET /api/version Get server version info

License

MIT License

About

Ultimarc I-PAC Ultimate and PacLED64 LED Controller for Retropie

Resources

Stars

Watchers

Forks

Sponsor this project

 

Packages