-
Notifications
You must be signed in to change notification settings - Fork 2
Home
The universal controller remapping toolkit for Windows
PadForge turns any controller, keyboard, or mouse into a virtual Xbox 360, DualShock 4, DirectInput, 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.

New in this release: Per-mapping axis-to-button deadzones let you control how far an axis must travel before triggering a button press, with half-axis awareness for centered joystick axes. Audio bass rumble vibrates your controller to in-game explosions and music. The mapping grid includes a source input dropdown, and device mappings now persist when controllers are offline. BLE controllers hidden via HidHide remain hidden across reconnects.
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 (ViGEmBus, vJoy, 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 and web controller server, 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 output types: Xbox 360, DualShock 4, DirectInput/vJoy, MIDI, and Keyboard+Mouse. Enable, disable, delete, and drag-reorder slots. Configure vJoy axes, buttons, and 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 DirectInput 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, DS4, vJoy, 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 DirectInput 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 DirectInput devices. Recommended settings for hair-trigger, racing, and default use cases. |
| ∿ | Force Feedback | Overall gain and per-motor (left/right) strength, swap motors, test rumble with live motor activity bars. Haptic fallback cascades through LeftRight, Sine, and Constant strategies. DirectInput FFB through vJoy 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. |
Power-user features: macros, per-game profiles, and raw device management.
| Page | Description | |
|---|---|---|
| ⚡ | Macros | Build macros with combo triggers (buttons + axes + POV directions, simultaneous activation) and 4 trigger modes: On Press, On Release, While Held, and Always. Axis thresholds (1 to 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 DirectInput buttons, and bind input device axes for volume and 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 | 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. Raw input live view: progress-bar axes, circle-grid buttons, compass POV hats, gyro/accel values, keyboard layout, and 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 or turn a phone into a wireless gamepad.
| Page | Description | |
|---|---|---|
| ➡ | DSU Motion Server | Stream gyro and accelerometer data to emulators over the DSU/Cemuhook protocol. Works with DualSense, DualShock 4, Switch Pro, and Switch 2 Pro controllers. Enable the server on the Dashboard. Step-by-step setup for Cemu, Dolphin, Ryujinx, and Yuzu. Configurable port (default 26760). 4-slot protocol limit with automatic SDL-to-DSU axis mapping. |
| 🌐 | Web Controller | Turn any phone or tablet into a wireless gamepad. Launch the embedded HTTP/WebSocket server, open the URL in a touchscreen browser, and pick Xbox 360 or DualShock 4 layout. Touch buttons, analog sticks (nipplejs virtual joystick), 8-way D-pad, and 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 to 16 ms). Window behavior: minimize to tray, start minimized, start at login. Install or uninstall HidHide, ViGEmBus, vJoy, and Windows MIDI Services with one click. HidHide whitelist management. MIDI slot settings (channel, velocity, CC count, note count, start numbers). File operations (save, reload, reset, open folder). |
| ⚒ | Driver Management | Install and manage 4 optional drivers. ViGEmBus (virtual Xbox 360 and DS4, MSI-based). vJoy (custom DirectInput joystick with configurable HID descriptors and FFB, requires auto-elevation). HidHide (selective device hiding with built-in blacklist, whitelist, and cloaking. No external Configuration Client needed). Windows MIDI Services (~210 MB GitHub download, virtual MIDI endpoints). Driver status on the Dashboard, troubleshooting table, and uninstall guard conditions. |
| ⏱ | Input Precision | 1000 Hz polling using a 3-tier sleep strategy: HR waitable timer, multimedia timer, and Thread.Sleep + SpinWait. 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 vJoy 15-bit or ViGEm native output. Bit-perfect passthrough at default settings. Deadzone math (x360ce-validated), continuous POV hat support (hundredths of degrees), and single-call batch output (UpdateVJD, SubmitReport). |
| ❓ | Troubleshooting | Common problems: no devices detected, virtual controller not appearing in games, double input, vJoy failures, rumble issues, audio bass rumble problems, 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, and stick drift after calibration. Includes a quick-reference table. |
Architecture, contribution, and forking documentation covering every layer from the SDL3 input pipeline to the XAML view hierarchy.
| Page | Description | |
|---|---|---|
| 🏗 | Architecture Overview | 2-project .NET 10 solution: PadForge.App (WPF) and PadForge.Engine (library). Full project layout with every file and folder. Mermaid architecture diagram. SDL3-only input philosophy. MVVM via CommunityToolkit.Mvvm. 6-thread model (engine at ~1000 Hz, UI at 30 Hz, Raw Input, DSU receive, input hooks, web controller server). Thread safety table. NuGet dependencies. 16-slot system. Single-file publish build. Localization architecture (10 languages, live switching via weak-event INotifyPropertyChanged). |
| 🔀 | Input Pipeline | 6-step polling loop. Step 1: SDL device enumeration with ViGEm/vJoy filtering and GUID migration. Step 2: SDL state reading with gamepad vs. joystick API dispatch, FFB forwarding, and multi-slot vibration combining. Step 3: mapping engine with descriptor-to-Gamepad conversion, deadzone processing, sensitivity curves, center offset, and axis inversion/half-axis. Step 4: multi-device merge per slot (max-wins strategy). Step 4b: macro state machine with trigger evaluation, action execution, and volume/mouse continuous actions. Step 5: virtual controller lifecycle for all 5 types, XInput slot mask detection, and vJoy device management. Step 6: output state copy for UI display. Motion snapshot capture and DSU broadcast run between Steps 2 and 3. |
| 📡 | SDL3 Integration | 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 counter-based ViGEm/vJoy filtering. SdlDeviceWrapper open/close order, haptic strategy selection, and 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, and the custom SDL3 fork for Switch 2 Pro Controller (WinUSB composite device, Steam conflict). |
| 🕹 | Virtual Controllers | IVirtualController interface and VirtualControllerType enum across 5 backends. Xbox360VirtualController (ViGEm-based, Gamepad-to-Xbox360 mapping, change detection, FeedbackReceived callback). DS4VirtualController (ViGEm-based, DS4 naming, D-Pad, Y-inversion, digital triggers, DualShock4DPadDirection). VJoyVirtualController (P/Invoke to vJoyInterface.dll, single UpdateVJD batch call, Y-axis HID inversion, SubmitRawState for custom configs, FFB architecture with FfbDeviceState/FfbEffectState/FfbConditionAxis, global FfbCallback routing by device ID, ApplyMotorOutput with condition effects, static device management, generation-based re-acquire). MidiVirtualController (Windows MIDI Services SDK, virtual endpoint creation, CC/Note change detection, auto-mapping). KeyboardMouseVirtualController (Win32 SendInput, KbmRawState with 256-bit key bitmask, mouse delta/scroll, change-detection key up/down). |
| 📝 | vJoy Deep Dive | Phantom controller bug (N nodes x N registry keys = N-squared controllers) and the single-node fix. HID report descriptor format: fixed 97-byte layout with 16 axes, 4 continuous POVs, and 128 buttons using active/constant padding. Registry structure (DeviceNN descriptors, OEMForceFeedback keys for DirectInput FFB enumeration). FFB HID PID descriptor with report ID offset formula, 13 output reports, 4 feature reports, and 11 effect types including condition effects. FFB communication paths (HID vs. IOCTL). Device creation via SetupAPI PowerShell script (DIF_REGISTERDEVICE, critical DeviceName="HIDClass" requirement) and removal order (nodes before service). Generation-based re-acquire mechanism and runtime fixes (stale config leak, DLL namespace cache, config swap during reorder). |
| 💾 | 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 plus macros). SettingsManager with static slot arrays, UserDevices/UserSettings collections, and CreateDefaultPadSetting auto-mapping. Load/save/apply pipeline. Cross-layout MappingTranslation (positional equivalence across Xbox/DS4/vJoy/MIDI/KBM). Backward compatibility (array migration, missing fields). |
| 🔗 | Services Layer | Seven service classes bridging the engine and UI. InputService: engine lifecycle, 30 Hz DispatcherTimer for UI sync, macro snapshot push, audio bass detector, auto-save. SettingsService: XML load/save, PadSetting application to InputManager, slot creation/deletion/reorder. DeviceService: ObservableCollection sync from UserDevices, HidHide blacklist/whitelist, device assignment/unassignment, input hiding coordination. RecorderService: input recording state machine for 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 built 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 status. PadViewModel: per-slot mapping grid (MappingItem rows), StickConfigItem/TriggerConfigItem deadzone models, MacroItem state machine, VJoySlotConfig/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, driver status, file operations. Supporting types: MappingItem source dropdown, MacroItem trigger/action/repeat models. |
| 🖼 | 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, and driver overlay. DashboardPage: engine toggle, slot cards in WrapPanel, DSU/web controller/driver status. PadPage: custom RadioButton tab strip, 6 tab panels (Controller, Macros, Mappings, Sticks, Triggers, Force Feedback), view switching across 3D/2D/Schematic/KBM/MIDI preview, vJoy/MIDI config bars, multi-device selector, Copy From dialog. DevicesPage: card ListBox with accent selection bar, raw input visualization (axes/buttons/POV/gyro/keyboard/mouse), 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, and code-behind patterns (Bind/Unbind, CompositionTarget.Rendering with dirty flag, flash animation). |
| 🎮 | 3D Model System | 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 (MSBuild digit-prefix suffix matching), and ButtonFileMap for OBJ-to-PadSetting name mapping. Xbox 360 model: colored face button overlays, guide ring/LED, 7-color palette. DS4 model: PlayStation symbol meshes, touchpad screen. ControllerModelView: HelixViewport3D with custom Preview-event rotation/zoom/pan (all 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, and 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 plus OpenCV template matching). ControllerModel2DView: base image plus overlay images at Z-layers, trigger gas-tank fill (RectangleGeometry clip), stick translation transforms, quadrant hover/flash (CombinedGeometry clips), click-to-record with quadrant axis detection. ControllerSchematicView: procedural vJoy view with StickWidget/TriggerWidget/PovWidget/ButtonWidget structs, dynamic layout from VJoySlotConfig.ComputeAxisLayout, hover direction arrows, click-to-record targeting VJoyAxis/VJoyBtn/VJoyPov names. KBMPreviewView: QWERTY keyboard (KeyboardKeyItem.BuildLayout) plus contoured mouse graphic (LMB/RMB/scroll/movement circle/X1/X2), per-VK-code highlighting, movement dot tracking. MidiPreviewView: CC vertical bar sliders plus musically correct piano keyboard (white/black key layout), live CC value and note state rendering. |
| 📨 | DSU Protocol Implementation | MotionSnapshot struct carrying g-force acceleration and degrees-per-second 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 (magic, version, CRC32, server ID), version request/response, controller info request/response (4-slot limit, fake MAC addresses), pad data request/subscription (per-slot and all-slot modes, 5-second expiry), pad data response (84-byte payload with zeroed button/stick/touch data, real motion timestamp, 6-axis accel/gyro floats). CRC32 implementation, subscription management with high-resolution timestamp pruning, and DsuDiag standalone diagnostic tool. |
| 🔧 | Driver Installation Internals | DriverInstaller static class with embedded resources (ViGEmBus EXE, HidHide EXE, vJoyDriver.zip). ViGEmBus: WiX bootstrapper extraction, MSI via msiexec with UAC, registry version detection. HidHide: same WiX/MSI pattern, product code extraction for uninstall. vJoy: single elevated PowerShell script: pre-install cleanup (critical node-before-service removal order), ZIP extraction to Program Files, pnputil driver store add, SetupAPI device node creation with inline C# P/Invoke. vJoy uninstall: batch script with exhaustive registry cleanup across all ControlSets. 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. Uninstall guard conditions and elevation strategy. |
| 📦 | Engine Library | PadForge.Engine assembly. Gamepad struct (XInput layout, button flag constants). VJoyRawState (dynamic axes/buttons/POVs for custom DirectInput). MidiRawState (dynamic CC/note arrays). KbmRawState (256-bit key bitmask plus mouse deltas plus scroll plus 5 mouse buttons, Combine method). VirtualControllerType enum 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), and 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). Produces a single-file, self-contained, compressed ~85 MB EXE with embedded .NET runtime and debug symbols. Project configuration: WinExe, WPF plus WinForms for NotifyIcon, WinForms implicit using removal. Version management via manual AssemblyInfo.cs. NuGet dependencies: ModernWpfUI, HelixToolkit, CommunityToolkit.Mvvm, ViGEm.Client, NAudio.Wasapi, Windows MIDI Services SDK from local source. Native DLLs: SDL3.dll and libusb-1.0.dll 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, VJoyTest, FfbTest. Build troubleshooting table. |
Built with SDL3, ViGEmBus, vJoy, HelixToolkit, .NET 10 WPF, and Fluent Design.