-
Notifications
You must be signed in to change notification settings - Fork 6
Home
The universal controller remapping toolkit for Windows
PadForge turns any controller, keyboard, or mouse into a virtual Xbox, PlayStation, flight stick, wheel, MIDI, or Keyboard+Mouse device that games and applications recognize as real hardware. 1000 Hz polling, interactive 3D visualization, and deep customization for deadzones, sensitivity curves, macros, and force feedback.

Powered by HIDMaestro — one driver, 225+ device profiles.
New in v3: A single user-mode driver, HIDMaestro, replaces ViGEmBus and vJoy with 225+ device profiles spanning Xbox (360, One, Series, Elite, Adaptive), PlayStation (DualShock 3/4, DualSense, DualSense Edge), flight sticks, racing wheels, HOTAS, and generic gamepads. The Extended virtual controller can run any HIDMaestro profile or a fully custom HID descriptor (up to 8 axes, 128 buttons, 4 POV hats). Slot capacity raised to 16 across all types. Sony Report 0x01 passthrough on PlayStation outputs forwards source-device gyro, accelerometer, touchpad, and battery level to the game. The OpenXInput fork (embedded inside the EXE) filters PadForge's own virtuals from its own XInput view so device enumeration stays clean. Touchpad overlay, HM inactivity destroy timeout, bubble-up cascade for mid-stack slot removal, and a "Reset Position" overlay control.
New in v3.1.0: Two new tabs on every PlayStation-class slot with a DualSense assigned — Adaptive Triggers (seven effect modes including Multi-Position Feedback, Slope, Multi-Position Vibration, with a live effect-profile preview that draws the resistance/amplitude shape across the trigger pull) and Lighting (thirteen lightbar modes: static, breathing, rainbow, palette cycle, audio pulse, audio-band three-color modes, and input-reactive variants). Theme-tracking icons on every page so a light/dark switch doesn't leave anything stuck. Localization for all new strings across nine languages (de, es, fr, it, ja, ko, nl, pt-BR, zh-Hans).
Everything you need to download, install, and launch PadForge for the first time.
| Page | Description | |
|---|---|---|
| ⬇ | Installation | Download the portable single-file EXE. System requirements (Windows 10/11 x64). Install optional drivers (HIDMaestro, HidHide, Windows MIDI Services). Auto-elevation and start-at-login. |
| ■ | Dashboard | Start and stop the input engine with a live polling-rate readout. Per-slot virtual controller cards with status, type, device name, and slot number. Add controllers, toggle the DSU motion server, web controller server, and touchpad overlay, and check driver installation status. |
Create virtual controllers, explore them in 3D, and map every button and axis.
| Page | Description | |
|---|---|---|
| ➕ | Controller Slots | Up to 16 virtual controller slots across 5 categories: Xbox, PlayStation, Extended (HIDMaestro: flight sticks, wheels, third-party gamepads, custom HID), MIDI, and Keyboard+Mouse. Enable, disable, delete, and drag-reorder slots. Configure Extended axes, buttons, POVs. Configure MIDI channel, velocity, CC, and notes. Per-type driver requirements. Multi-slot device assignment. |
| ▶ | 3D and 2D Visualization | Rotate, zoom, and pan an interactive 3D controller model with live button highlighting and stick/trigger animation. Toggle to a flat 2D PNG overlay, a procedural Extended schematic (dynamic sticks, triggers, buttons, POVs), or a Keyboard+Mouse preview with full QWERTY keyboard and mouse graphic. Click any element to jump to its mapping. |
| ⇄ | Button and Axis Mappings | Map inputs through a grid showing output, source dropdown, live value, record button, invert and half-axis options, and per-mapping axis-to-button deadzone sliders. Record by pressing a button, moving an axis, or shifting the mouse. Map All, auto-map recognized gamepads, and Copy/Paste/Copy From with cross-layout translation (Xbox, PlayStation, Extended, MIDI, KB+M). Half-axis deadzone awareness for centered joystick axes mapped to buttons. |
Fine-tune stick response, trigger feel, and force feedback to match your play style.
| Page | Description | |
|---|---|---|
| ○ | Stick Deadzones | Per-axis deadzone and anti-deadzone sliders (X/Y independent, 0.1% precision) across 6 shapes: Scaled Radial, Radial, Axial, Hybrid, Sloped Scaled Axial, and Sloped Axial. Per-axis sensitivity curves with presets (Linear, Smooth, Aggressive, Instant, S-Curve, Delay, Custom) and draggable control points. Calibrate center offset, set per-direction max range (left/right/up/down independently), monitor the live circular preview, and configure up to 4 sticks for custom Extended devices. |
| ▮ | Trigger Deadzones | Floor and ceiling with a dual-handle range slider. Anti-deadzone and per-trigger sensitivity curves using the same presets as sticks. Live value bar at 0.1% precision with raw digit input. Up to 8 triggers sharing 8 axes with sticks for custom Extended devices. Recommended settings for hair-trigger, racing, and default use cases. |
| ∿ | Force Feedback | Overall gain and per-motor (left/right) strength, motor swap, and rumble test with live motor activity bars. Cascade haptic fallback through LeftRight, Sine, and Constant strategies. DirectInput FFB through HIDMaestro PID descriptors with directional forces (polar-to-motor-split), condition effects (Spring, Damper, Friction, Inertia), and audio bass rumble via WASAPI loopback capture with configurable sensitivity, bass cutoff, and per-motor scaling. |
| ∧ | Adaptive Triggers | Seven trigger effect modes for slots with a DualSense assigned: Off, Feedback (constant resistance), Weapon (soft zone + click), Vibration (continuous buzz), Multi-Position Feedback (ratcheting bumps), Slope Feedback (gradient ramp), Multi-Position Vibration (stuttering bursts). Live effect-profile preview draws the resistance / amplitude shape across the trigger pull and updates as you drag the Range, Strength, and Frequency sliders. Per-mode visibility gating, per-parameter reset buttons, and the wire-format crosswalk to the firmware's 0x01 / 0x02 / 0x06 / 0x21 / 0x26 trigger opcodes. |
| ☀ | Lighting | Thirteen lightbar modes for slots with a DS4 / DualSense / DualSense Edge assigned: Static Color, Breathing, Rainbow Cycle, palette-based Color Cycle, three Audio Pulse variants (static color / random color per beat / rainbow cycle), three Audio Bands variants (hard transitions / smooth gradient / crossfade at boundaries), and two Input Reactive variants (random color per press / cycle through palette). Single-color picker, variable-length palette, audio sensitivity + thresholds + crossfade width, pulse decay slider. Plus the Indicator LEDs card (player-pattern row, mute LED mode, brightness). |
Power-user features — macros, per-game profiles, and raw device management.
| Page | Description | |
|---|---|---|
| ⚡ | Macros | Combo triggers (buttons, axes, POV directions, simultaneous activation) and 4 trigger modes (On Press, On Release, While Held, Always). Axis thresholds (1–100%), trigger source (Input Device or Output Controller), and actions: button/key press/release, delay, axis set, system/app volume with limit, and mouse move/click/scroll with sensitivity. Repeat once, a fixed count, or until release. Consume trigger buttons, run continuous parallel actions, target up to 128 Extended buttons, and bind input device axes for volume/mouse control. |
| ⇆ | Profiles | Switch controller configurations automatically when a game takes focus (~30 Hz foreground window detection). Create, clone, edit, load, and delete profiles. Match executables via Browse dialog (case-insensitive, full-path match) with the Default profile as baseline. Assign controller button combos to switch profiles or toggle the PadForge window via controller shortcuts. A taskbar flyout notification shows profile name, initialization progress, and active/offline status on every switch. Topology badges show per-type controller counts. Each profile stores all slot settings, mappings, deadzones, force feedback, and macros. |
| ⌸ | Devices | Browse physical devices as cards with status dots (online/offline), VID/PID, type, capabilities, and slot badges. GUID and HidHide instance path in the detail pane. Live raw input (progress-bar axes, circle-grid buttons, compass POV hats, gyro/accel values, keyboard layout, mouse graphic). Hide input via HidHide (whole device) or input hooks (mapped keys/buttons only) with safety warnings. Force Raw Joystick Mode for devices with wrong SDL3 gamepad mappings. Drag and drop devices onto sidebar slots. |
Stream motion data to emulators, turn a phone into a wireless gamepad, or use a touchscreen as a DS4 touchpad.
| Page | Description | |
|---|---|---|
| ➡ | DSU Motion Server | Stream gyro and accelerometer data to emulators over the DSU/Cemuhook protocol. DualSense, DualShock 4, Switch Pro, and Switch 2 Pro controllers. Enable on the Dashboard, follow setup for Cemu, Dolphin, Ryujinx, and Yuzu, configure the port (default 26760), and work within the 4-slot protocol limit with automatic SDL-to-DSU axis mapping. |
| 🌐 | Web Controller | Turn any phone or tablet into a wireless gamepad. Embedded HTTP/WebSocket server, browser-side Xbox 360 or DualShock 4 layout. Touch buttons, analog sticks (nipplejs virtual joystick), 8-way D-pad, triggers. Tap sticks for stick-click. WebSocket auto-reconnect, browser Vibration API rumble, Add to Home Screen for fullscreen, and network/firewall guidance. |
System settings, driver installation, precision details, and common fixes.
| Page | Description | |
|---|---|---|
| ⚙ | Settings | 10 languages with live switching. Theme (System/Light/Dark). Input engine (auto-start, background polling, master hide toggle, polling interval 1–16 ms, HM inactivity destroy timeout). Window behavior (minimize to tray, start minimized, start at login). Install or uninstall HIDMaestro, HidHide, and Windows MIDI Services. Manage the HidHide whitelist, configure MIDI slot settings (channel/velocity/CC count/note count/start numbers), and run file operations (save/reload/reset/open folder). |
| ⚒ | Driver Management | Install and manage three optional drivers: HIDMaestro (user-mode UMDF2 virtual HID controller engine, 225+ profiles, replaces ViGEmBus and vJoy), HidHide (selective device hiding with built-in blacklist/whitelist/cloaking — no external Configuration Client needed), and Windows MIDI Services (~210 MB GitHub download, virtual MIDI endpoints). Driver status on the Dashboard, troubleshooting table, uninstall guards. The OpenXInput fork ships embedded inside the EXE and needs no separate install. |
| ⏱ | Input Precision | 1000 Hz polling using a 3-tier sleep strategy (HR waitable timer, multimedia timer, Thread.Sleep+SpinWait) with wall-clock drift compensation and a zero-allocation hot path. Full axis value pipeline from SDL3 16-bit input through unsigned conversion, double-precision deadzone processing, to HIDMaestro native output. Bit-perfect passthrough at default settings. Deadzone math (x360ce-validated), continuous POV hat support (hundredths of degrees), single-call batch output. |
| ❓ | Troubleshooting | Common problems: no devices detected, virtual controller not appearing in games, double input, HIDMaestro install failures, rumble issues, audio bass rumble, DSU motion not working, settings not saving, high CPU usage, Steam controller conflicts, wrong button mappings (Force Raw Mode), mouse/keyboard input issues, macros not firing, mouse macro problems, Always-mode macros, web controller connection failures, no MIDI output, sensitivity curve issues, Keyboard+Mouse not working, stick drift after calibration. Quick-reference table. |
The architecture, every layer of PadForge from the SDL3 input pipeline to the XAML view hierarchy.
| Page | Description | |
|---|---|---|
| 🏗 | Architecture Overview | The 2-project .NET 10 solution: PadForge.App (WPF) and PadForge.Engine (library). Project layout, Mermaid architecture diagram, SDL3-only input philosophy, MVVM via CommunityToolkit.Mvvm, multi-thread model (engine at ~1000 Hz, UI at 30 Hz, Raw Input, DSU receive, input hooks, web controller server, HM lifecycle thread pool). Thread safety table, NuGet dependencies, 16-slot system, single-file publish build, localization architecture (10 languages, live switching via weak-event INotifyPropertyChanged). |
| 🔀 | Input Pipeline | The 6-step polling loop. Step 1: SDL device enumeration with HIDMaestro virtual filtering and GUID migration. Step 2: SDL state reading with gamepad vs. joystick API dispatch, FFB forwarding, multi-slot vibration combining. Step 3: mapping engine with descriptor-to-Gamepad conversion, deadzone processing, sensitivity curves, center offset, axis inversion/half-axis. Step 4: multi-device merge per slot (max-wins). Step 4b: macro state machine with trigger evaluation, action execution, volume/mouse continuous actions. Step 5: virtual controller lifecycle for all 5 types (HM thread-pool create/destroy, inactivity timeout, bubble-up cascade), XInput slot mask detection. Step 6: output state copy for UI display. Motion snapshot and DSU broadcast occur between Steps 2 and 3. |
| 📡 | SDL3 Integration | The full P/Invoke layer (SDL3Minimal.cs) covering SDL3 vs. SDL2 API changes, bool/string/array marshaling, initialization flags, and critical hints (JOYSTICK_XINPUT enabled, RAWINPUT must not be set). Device enumeration flow (Phase 1 open, Phase 1b/1c keyboard/mouse, Phase 2 disconnect detection) with the HIDMaestro virtual-controller filter substring list applied at SDL_OpenJoystick. SdlDeviceWrapper open/close order, haptic strategy selection, Force Raw Mode. Gamepad vs. joystick state reading (axis/button/POV layouts), sensor support (gyro/accel with DSU coordinate conversion), GUID construction, HID product string fallback, rumble with change detection, Raw Input for per-device keyboard/mouse, custom SDL3 fork (HIDMaestro filter + Switch 2 Pro Controller WinUSB composite device + Steam conflict handling). |
| 🕹 | Virtual Controllers | The IVirtualController interface and VirtualControllerType enum across 5 backends. Xbox / PlayStation / Extended all route through HIDMaestro; MIDI through Windows MIDI Services; KeyboardMouse via Win32 SendInput. HM lifecycle (create/destroy on a thread pool, AwaitPendingLifecycleTasks barrier on engine stop, HmInactivityDestroyTimeoutSeconds, bubble-up cascade when an HM slot is destroyed mid-stack). |
| 📝 | HIDMaestro Deep Dive | The contract between PadForge and HIDMaestro: SDK surface (HMContext / HMProfile / HMController), the OpenXInput shim that filters PadForge's own slots from its own XInput view (three-surface architecture: SDL3 fork + OpenXInput fork + SetDllDirectory preload), Step 5 lifecycle invariants (lifecycle off the polling thread, inactivity destroy timeout, bubble-up cascade), FFB through HM PID descriptors, and a list of v2 vJoy bugs that no longer apply. |
| 💾 | Settings and Serialization | PadForge.xml file format rooted in SettingsFileData DTO, file discovery order, UserDevice (physical device record, 40+ fields), UserSetting (device-to-slot linkage via MapTo index), PadSetting (200+ mapping/deadzone/force feedback properties, string-based storage), AppSettingsData (engine, window, profile settings), MacroData/ActionData serialization, ProfileData (per-profile PadSettings + macros). SettingsManager with static slot arrays, UserDevices/UserSettings collections, CreateDefaultPadSetting auto-mapping. Load/save/apply pipeline, cross-layout MappingTranslation (positional equivalence across Xbox/PlayStation/Extended/MIDI/KBM), backward compatibility (v2 enum names "Sony" / "VJoy" preserved via XmlEnum, array migration, missing fields). |
| 🔗 | Services Layer | Services bridging the engine and UI. InputService (engine lifecycle, 30 Hz DispatcherTimer, macro snapshot push, audio bass detector, autosave filtered to actual user-config property names so device motion does NOT trigger saves, touchpad overlay show/hide). SettingsService (XML load/save, PadSetting application, slot CRUD, debounced 250 ms autosave timer). DeviceService (ObservableCollection sync from UserDevices, HidHide blacklist/whitelist, device assignment, input hiding coordination). RecorderService (button/axis/POV/mouse detection, Map All sequential flow, threshold-based axis detection). DsuMotionServer (UDP server lifecycle, subscription management). ForegroundMonitorService (GetForegroundWindow at 30 Hz, process name matching, profile switch triggering). WebControllerServer (HttpListener accept loop, WebSocket per-client I/O, static asset serving, WebControllerDevice creation). |
| 📊 | ViewModels | ViewModelBase on CommunityToolkit.Mvvm ObservableObject with weak-event CultureChanged for live language switching. MainViewModel (navigation, sidebar items, profile list, engine status). DashboardViewModel (SlotSummary cards, engine toggle commands, DSU/web controller/touchpad overlay status — derived from a bool so culture changes don't strand the label). PadViewModel (per-slot mapping grid, StickConfigItem/TriggerConfigItem deadzone models with whitelist filter on PropertyChanged so live-state updates don't mark dirty, MacroItem state machine, ExtendedSlotConfig/MidiSlotConfig, output snapshots for all 5 controller types, recording flow). DevicesViewModel/DeviceRowViewModel (device cards, AxisDisplayItem/ButtonDisplayItem/PovDisplayItem for live visualization, slot toggle commands). SettingsViewModel (theme, polling, HM inactivity timeout, driver status, file operations). |
| 🖼 | XAML Views | MainWindow shell (NavigationView sidebar with programmatic controller cards, visibility-swapped pages, drag reordering with adorners, cross-panel device drag-drop, Add Controller popup with per-type capacity checks, status bar, driver overlay). DashboardPage (engine toggle with red flash while Stopping, slot cards in WrapPanel, DSU/web controller/touchpad overlay/driver status). PadPage (custom RadioButton tab strip, 6 tab panels, view switching across 3D/2D/Schematic/KBM/MIDI preview, Extended/MIDI config bars, multi-device selector, Copy From dialog). DevicesPage (card ListBox with accent selection bar, raw input visualization, slot toggle buttons, input hiding toggles). SettingsPage (card-based sections, driver cards, HidHide whitelist). ProfilesPage (profile ListBox with topology badges). 14 value converters, theme switching, Segoe MDL2 icons, code-behind patterns. |
| 🎮 | 3D Model System | Render Xbox 360 and DualShock 4 controller models from Wavefront OBJ meshes via HelixToolkit.WPF (adapted from Handheld Companion, CC BY-NC-SA 4.0). ControllerModelBase abstract class with ButtonMap/ClickMap/DefaultMaterials/HighlightMaterials dictionaries, embedded resource loading, ButtonFileMap for OBJ-to-PadSetting name mapping. Xbox 360 model with colored face button overlays, guide ring/LED, 7-color palette. DS4 model with PlayStation symbol meshes, touchpad screen. ControllerModelView with HelixViewport3D, custom Preview-event rotation/zoom/pan (built-in controls disabled), click-to-record via 3D ray-cast hit testing, stick ring quadrant detection (Sutherland-Hodgman clipping), hover highlighting, 400 ms flash animation with arrow and quadrant ring overlays, gradient material blending for sticks/triggers. |
| 🗺 | 2D Overlay System | Resolution-independent PNG overlays via Canvas inside Viewbox. Auto-generated ControllerOverlayLayout.cs (overlay_positions.py, SVG parsing + OpenCV template matching). ControllerModel2DView (base image + overlay images at Z-layers, trigger gas-tank fill via RectangleGeometry clip, stick translation transforms, quadrant hover/flash via CombinedGeometry clips, click-to-record with quadrant axis detection). ControllerSchematicView (procedural Extended view with StickWidget/TriggerWidget/PovWidget/ButtonWidget structs, dynamic layout from ExtendedSlotConfig.ComputeAxisLayout, hover direction arrows, click-to-record targeting Extended axis/button/POV names). KBMPreviewView (QWERTY keyboard + contoured mouse graphic, per-VK-code highlighting, movement dot tracking). MidiPreviewView (CC vertical bar sliders + musically correct piano keyboard, live CC value and note state rendering). |
| 📨 | DSU Protocol Implementation | MotionSnapshot struct carrying g-force acceleration and degrees/sec gyro with SDL-to-DSU axis mapping and sign inversions. DsuMotionServer (UDP socket on loopback, SIO_UDP_CONNRESET suppression, background receive thread). Packet format (16-byte header, version request/response, controller info request/response with 4-slot limit and fake MAC addresses, pad data request/subscription with per-slot and all-slot modes and 5-second expiry, pad data response with 84-byte payload). CRC32 implementation, subscription management with high-resolution timestamp pruning, DsuDiag standalone diagnostic tool. |
| 🔧 | Driver Installation Internals | DriverInstaller static class with embedded HIDMaestro and HidHide installers. HIDMaestro (single user-mode UMDF2 driver, INF install via pnputil, status detection from registry, profile catalog discovered at runtime from the HM SDK). HidHide (WiX/MSI bootstrapper, product code extraction for uninstall). Windows MIDI Services (GitHub API release query, ~210 MB download, WiX Burn bootstrapper). HidHideController runtime IOCTL API (blacklist/whitelist/cloaking via \.\HidHide device, Multi-SZ buffer format, managed device tracking, DOS device path conversion). Legacy v2 driver cleanup dialog (offers to uninstall ViGEmBus and vJoy on first launch if detected). Uninstall guard conditions and elevation strategy. |
| 📦 | Engine Library | PadForge.Engine assembly. Gamepad struct (XInput layout, button flag constants), ExtendedRawState (dynamic axes/buttons/POVs for HIDMaestro Extended profiles), MidiRawState (dynamic CC/note arrays), KbmRawState (256-bit key bitmask + mouse deltas + scroll + 5 mouse buttons, Combine method). VirtualControllerType enum (Microsoft / PlayStation / Extended / Midi / KeyboardMouse; Microsoft is the on-disk identifier for the Xbox UI category) and IVirtualController interface. CustomInputState (24 axes, 8 sliders, 4 POVs, 256 buttons, 3-axis gyro/accel). ISdlInputDevice (identity, capabilities, haptic, state reading, rumble). WebControllerDevice (browser gamepad, VID 0xBEEF/PID 0xCA7E). DeviceObjectItem and InputTypes (DeviceObjectTypeFlags, ObjectGuid constants matching DirectInput). ForceFeedbackState (change-detection rumble, haptic strategy dispatch, condition effects). Vibration (scalar motors + directional FFB + condition axis data). RumbleLogger, InputHookManager (WH_KEYBOARD_LL/WH_MOUSE_LL with volatile suppression sets), RawInputListener (HWND_MESSAGE thread, per-device keyboard/mouse state), SdlMouseWrapper (scroll wheel intensity tracking), MappingTranslation (positional equivalence across 5 controller layouts). |
| 🛠 | Build and Publish | Prerequisites — .NET 10 SDK, Windows 10/11 x64. Build with dotnet publish -c Release (never dotnet build). Single-file, self-contained, compressed ~107 MB EXE with embedded .NET runtime, OpenXInput shim DLLs (xinput1_4.dll / devobj.dll under Resources/OpenXInput/x64/), HIDMaestro SDK, debug symbols. Project configuration (WinExe, WPF+WinForms for NotifyIcon, WinForms implicit using removal). Manual AssemblyInfo.cs version management. NuGet dependencies (WPF UI, HelixToolkit, CommunityToolkit.Mvvm, NAudio.Wasapi, Windows MIDI Services SDK from local source). Native DLLs (SDL3.dll custom fork with HIDMaestro filter + Switch 2 Pro support, libusb-1.0.dll, OpenXInput DLLs as Content with Link flattening). Embedded resources (driver installers, 3D OBJ meshes, 2D PNG overlays). Portable deployment with no installer. Release workflow (version update, build, deploy, test, commit, GitHub release via gh CLI). Diagnostic tools (DsuDiag, HM diagnostics). Build troubleshooting table. |
Built with SDL3, HIDMaestro, OpenXInput, HelixToolkit, .NET 10 WPF, and Fluent Design.
