Troubleshooting: three small accuracy fixes
- 'Double Input in Games' step 9 referenced PadForge v2.2.1 as the
BLE-HidHide-peek-through fix version. v2.2.1 is a v2 release; the
fix shipped on current v3 builds. Rewrote to give the user a
diagnostic step (check per-device toggle + master switch) instead
of a stale 'upgrade to v2.2.1' instruction.
- 'Extended Controllers Not Working' step 1 said to right-click +
'Run as administrator' if UAC was cancelled, and that 'HIDMaestro
install/uninstall requires elevation'. There is no install /
uninstall button for HIDMaestro (status only on Settings), and
cancelling UAC blocks PadForge startup entirely (manifest
requireAdministrator). Replaced with the accurate flow.
- 'MIDI Not Available' step 2 said 'requires Windows 11. Not
available on Windows 10.' Tightened to 'Windows 11 24H2 (build
26100) or later' to match Settings.md and Driver-Management.md,
which both already use the build-26100 wording.
7852499
Wiki: 'auto-elevate' -> 'requireAdministrator' across 3 pages
PadForge's app.manifest declares requireAdministrator. 'Auto-elevate'
is v2 terminology from when PadForge ran unelevated and relaunched
itself elevated mid-session via Verb=runas — that path is gone.
Architecture-Overview: 'Entry point, auto-elevation' in the App.xaml
file-tree comment is wrong; replaced with the actual entry-point
responsibility (single-file OpenXInput SetDllDirectory).
Driver-Management Common Issues 'UAC prompt on every launch' row:
explain the manifest cause + that downstream installer spawns reuse
the already-elevated session without re-prompting.
Troubleshooting: same explanation in the main UAC troubleshooting
step. Also fixed a critical accuracy bug in step 2 that said
'clicking No on UAC lets PadForge run without elevation' — Windows
does NOT start a requireAdministrator app when the user declines.
Quick Reference table row 'PadForge auto-elevates' likewise corrected
to 'manifest declares requireAdministrator'.
7eb5d2b
HIDMaestro-Deep-Dive: 'Auto-elevation' bullet was inverted
The 'What's gone from the v2 vJoy story' list had:
Auto-elevation for vJoy SetupAPI calls - still required, but for
HM it's so the user-mode driver can register its INF...
But v3 dropped auto-elevation: PadForge's manifest declares
requireAdministrator, so the whole process starts elevated and HM's
InstallDriver() runs inside that already-elevated session. No
v2-style mid-session Verb=runas relaunch happens. Rewrote the
bullet so the 'gone' classification matches the other six items in
the same list.
6ff751e
HIDMaestro-Deep-Dive: refresh stale CompactSlots(rebuildHmVcs=true) name
Bubble-up cascade invariant said CompactSlots(rebuildHmVcs=true)
destroys + recreates the surviving Xbox HM virtuals. The actual
method is InputService.CompactSlotsForGaps() (parameterless), which
drives compaction by calling ApplyProfile. Updated to match.
c420dc9
HIDMaestro-Deep-Dive: rewrite FFB section to match current decoder shape
The FFB-through-PID-descriptors section cited four class names that
do not exist in the v3.x codebase:
- FfbDeviceState (no such class)
- FfbEffectState (actual nested name: EffectState)
- FfbConditionAxis (actual nested name: ConditionAxis)
- ApplyMotorOutput (v2 method name; the code's only mention is a
historical 'Mirrors the v2 ApplyMotorOutput' comment)
Also said callbacks register via 'HMController.FeedbackReceived'.
The actual event is HMController.OutputReceived (FFB is one kind of
output packet alongside rumble).
Rewrote the whole section to match HMaestroFfbDecoder's current
internals (EffectState, ConditionAxis as private nested types),
explain the OutputReceived hook, and trace the path forward into
Step 2 ApplyForceFeedback + the per-pad-family writers.
452e624
HIDMaestro-Deep-Dive: restore valid HMProfile properties dropped in last pass
Previous edit cut .AxisCount, .ButtonCount, and .HasHat from the
HMProfile comment block when removing the stale .HasFeedback /
.HasMotion / .HasTouchpad lines (which never existed). Those three
do exist on HMProfile, plus there's .VendorId/.ProductId,
.StickBits/.TriggerBits/.InputReportSize, and the ExtendedReport /
ExtendedOutputReport specs that carry the DS4/DualSense extras.
Restored them so the example shows the full readable surface.
fd1270c
HIDMaestro-Deep-Dive: fix SDK usage example (every line had a name issue)
The illustrative SDK usage block had 5 separate naming issues vs the
actual HIDMaestro.Core API:
- 'context.Initialize()' does not exist; the real init pair is
LoadDefaultProfiles() + InstallDriver().
- 'controller.IsConnected' lives on PadForge's wrapper class
(HMaestroVirtualController), not on HMController itself.
- 'controller.XInputSlot' does not exist as an HM SDK property.
- 'controller.SubmitGamepadState(...)' is PadForge wrapper naming;
HM's own method is SubmitState(in HMGamepadState).
- 'controller.SubmitRawReport(byte[])' actually takes
ReadOnlySpan<byte>, not byte[].
- 'controller.FeedbackReceived' is the wrapper name; HM emits
OutputReceived and OutputDecoded events.
- 'controller.Destroy()' does not exist; HMController : IDisposable
uses Dispose().
Rewrote the block to use the live HMContext / HMProfile / HMController
API surface so the example is copy-pasteable against the actual SDK.
39fc719
Lighting: DS4 supports all 13 lightbar modes, not just 10
The DS4 section enumerated only 10 modes (Static, Breathing,
Rainbow, Color Cycle, 3 Audio Pulse, 3 Audio Bands). Off works
trivially, Battery uses the same Ds4EffectSynthesizer battery
gradient path (the synth's RGB resolution method takes
batteryPercent on both DS4 and DS5), and Strobe is a generic
square-wave any RGB lightbar supports. List all 13 to match the
DualSense feature set and the v3.2 release-note claim
('two new modes for DualSense and DualShock 4').
3401e79
DSU Motion Server: list 2026 Steam Controller in motion-capable table
Release notes (line 89 of release-v3.2.0-body.md) explicitly call out
the 2026 Steam Controller as a DSU motion source: 'DualSense,
DualShock 4, Switch Pro, and the new 2026 Steam Controller sources
all work out of the box.' DSU-Motion-Server.md's 'Controllers that
report motion' table was missing it. Added the row.
57a8fca
Settings: drop misleading 'each button click triggers one UAC prompt'
Driver-card buttons spawn installers with Verb=runas, but PadForge is
already elevated (requireAdministrator), so Windows passes elevation
through without showing the prompt again. Rewrote the line to match
Driver-Management's now-correct UAC cadence description.
2b15ed6
Driver-Management: drop 'Approve UAC' from HidHide install/uninstall
The HidHide and MIDI Services install/uninstall paths spawn external
installers with Verb=runas. When the parent (PadForge) is already
elevated, Windows passes elevation through without showing a second
UAC prompt. Updated the HidHide Install / Uninstall steps to match
reality.
84293ae
Driver-Management: fix HIDMaestro Install steps (no button exists) + UAC cadence
HIDMaestro section had a six-line 'Install steps' / 'Uninstall steps'
recipe instructing readers to click Install / Uninstall on the
Settings page and approve UAC. The Settings page's HIDMaestro card
is status-only (no buttons). Install happens automatically on first
engine start inside PadForge's already-elevated process; removal
isn't supported in-app per memory rule
hidmaestro-not-a-normal-driver-removal.md. Rewrote both sub-sections
to match reality without recommending pnputil / Device Manager
removal as user actions.
Admin-rights subsection said 'Driver install and uninstall trigger
one more UAC prompt of their own.' Not true: HIDMaestro install runs
in-process; the HidHide / MIDI Services Install buttons spawn
msiexec with Verb=runas, but a runas spawn from an already-elevated
parent skips the prompt.
bfd0bc2
Wiki: 'Custom preset' -> 'Customize toggle on' (Extended slot UI naming)
Stick-Deadzones and Trigger-Deadzones both said 'Extended output
with the Custom preset' to introduce the count-adaptive tab section.
The v2 'ExtendedPreset' enum (Xbox360 / DualShock4 / Custom) was
dropped in v3 (commit d57a725). The v3 UI exposes a 'Customize'
checkbox that overrides counts on top of whichever HM profile is
selected. Updated both pages to match the live label.
b93bd86
Input-Pipeline: correct the VID/PID-routing attribution
Last pass attributed the VID/PID early-route to
ForceFeedbackState.SetDeviceForces, but that's where SDL-rumble
devices land AFTER the Sony / Xbox One+ skip checks. The actual
early-route happens in InputManager.Step2's ApplyForceFeedback(ud)
which fans out to UserEffectsDispatcher, XboxImpulseHidWriter, or
SetDeviceForces. Rewrote the Step 2 'Output' description so the
Sony / Xbox One+ / everything-else split is attributed to the
right method.
abc24e8
Build-and-Publish: Development Scripts table reflects actual ~20 capture_*.ps1 files
The table still listed a single 'capture_screenshots.ps1' plus three
specific captures (capture_pads / capture_macros / capture_3d_2d).
Repo actually has ~20 capture_*.ps1 scripts, one per UI surface,
with capture_all_wrapper.ps1 running them in sequence. Collapsed
into a single row with that explanation.
68c6bde
Wiki: per-pad-family rumble routing replaces 'SDL_RumbleJoystick' claim
Two prose passages still described rumble as a single SDL_RumbleJoystick
forward, dropping the v3.x sole-writer architecture for Sony and Xbox
One+ pads.
Virtual-Controllers (HM FeedbackReceived threading note): now lists
the three writers (UserEffectsDispatcher for Sony, XboxImpulseHidWriter
for Xbox One+, SDL for everything else) and calls out that SDL is
explicitly skipped on Sony and Xbox One+ per the architecture-invariant
memory rules.
Input-Pipeline (Step 2 ForceFeedbackState.SetDeviceForces): rewrote
from 'uses SDL_RumbleJoystick' to early-routes-by-VID/PID, matching
the actual dispatch in code.
acdd30a
Input-Pipeline: fix Step 3 sub-bullet + pipeline-diagram stale shape
Step 3 'Type-specific raw mapping' sub-bullet still showed the
v3.0-era MapInputToExtendedRaw call with just (state, ps, cfg) and
'vJoy mappings' wording. Updated to the v3.2 6-arg signature
(SlotCustomLayouts[slot], mappingSet, deviceGuid, slot) with the
generic 'descriptor mappings' wording.
Pipeline diagram (line 1472-1483):
- 'SubmitRawState()' -> 'SubmitExtendedRawState()' (actual method name).
- 'MIDI (WinRT) (joy.cpl)' label was muddled and pointed MIDI at
joy.cpl; cleaned to 'MIDI (Windows MIDI Services)' with the right
endpoint annotation.
- Feedback path collapsed Sony/Xbox/everything-else into a single
'SDL_RumbleJoystick()' call. v3 routes per pad family:
UserEffectsDispatcher for Sony, XboxImpulseHidWriter raw HID for
Xbox One+, SDL for everything else. Architecture-invariant memory
rules already encode this; the diagram now matches.
b353ca4
Input-Pipeline: refresh stale v2-era ExtendedVirtualController refs
Three remaining v3-merge holdovers cleaned up:
- MapInputToExtendedRaw signature was the v3.0 form; updated to the
v3.2 form that takes CustomControllerLayout (Engine type, replaces
the dropped ExtendedVirtualController.ExtendedDeviceConfig nested
type) plus MappingSet/deviceGuid/slot for the new MappingSet eval.
- 'ExtendedVirtualController.UpdateFfbPadIndex' call no longer
exists; FeedbackPadIndex is set directly on the surviving
HMaestroVirtualController instance after a slot swap.
- Pass 3 'Submit reports' code block referenced 'ExtendedVirtualController vjoyVc' and SubmitRawState; the actual
code uses HMaestroVirtualController hmExt and SubmitExtendedRawState
with SlotCustomLayouts[]. Snippet rewritten to match production.
- SlotExtendedConfigs[] table row pointed at the dropped
ExtendedDeviceConfig type; renamed to SlotCustomLayouts (the live
array name) with CustomControllerLayout type. Added rows for the
three companion bool[] arrays (SlotExtendedIsCustom,
SlotExtendedCustomize, SlotExtendedFfbEnabled) that flank it, and
removed a duplicate SlotExtendedIsCustom row.
a728cdf
Services-Layer: refresh stale Step 5 line citations
Profile-restore Topology and Device assignment steps cited
InputManager.Step5.VirtualDevices.cs:514-527 (per-slot HM diff) and
Step 5:590-600 (immediate-destroy path). Both were v3.0-era. Actual
line ranges in current code are :595-604 and :680-700. Refreshed
the citations and stretched the second one to use the full file
path instead of the 'Step 5:' shorthand for consistency.
7eaa174
Virtual-Controllers: refresh stale HMaestroVirtualController.cs line citations
File-line citations were all v3.0-era and had drifted by 100-400+
lines as the class grew. Updated all 11 citations to current file
positions:
Connect :44 -> :150
Disconnect :65 -> :181
SubmitRawReport:86 -> :269 (two occurrences)
SubmitGamepadState:92 -> :275 (two occurrences)
SubmitExtendedRawState:145 -> :457 (two occurrences)
RegisterFeedbackCallback:233 -> :567
MapButtons :325-340 -> :748
MapHat :342-358 -> :803
Also noted the v3.2 second SubmitGamepadState overload at :359 that
carries touchpad/motion/battery payload for PlayStation slots.
InputManager.Step5.VirtualDevices.cs cites likewise refreshed:
_hmaestroContext :1019 -> :100
CreateHMaestroController :1358 -> :1430
HMProfileBuilder.FromProfile :1301 -> :1500
96cba03
Wiki: dedupe asset attribution + complete OBJ/PNG mesh-directory tables
Architecture-Overview.md: previously cited 'Gamepad-Asset-Pack, MIT'
only on the DS4 row of the 2DModels tree and 'Handheld Companion,
CC BY-NC-SA 4.0' only on the DS4 row of the 3DModels tree. Moved the
attribution to the section header so each row doesn't need to
repeat it, and the cross-family asymmetry disappears.
Build-and-Publish.md: 3D Model Assets table listed only XBOX360
(31) and DS4 (36); added XBOXONE (46) and DualSense (48). 2D Model
Assets prose listed only DS4 and XBOX360; expanded to all 5 dirs.
99933f5
Settings-and-Serialization: bump sample-xml dates 2025 -> 2026
Sample PadForge.xml block had DateCreated/DateUpdated stamps of
'2025-01-15T10:30:00' for both the UserDevice and UserSetting
examples. Bumped to 2026 so the example doesn't look year-stale to
new readers.
760631d
Driver-Installation-Internals: drop 'Note that' AI-tell preamble
'Note that X is Y' reads as scaffolding. Direct 'X is Y' is shorter
and matches the surrounding terse style.
17f96f0
Build-and-Publish: devobj.dll em-dash -> period
'deliberately not shipped — see [[Driver Installation Internals]]
for why' em-dash was a pseudo-colon attaching the cross-reference.
Period reads cleaner.
59d6daa
Wiki: a few more em-dash + semicolon pseudo-attachers -> periods
Architecture-Overview.md: 'Note for v3' callout had an em-dash before
'that's the canonical v3 source' and a semicolon before 'treat the
diagrams...'; both glossed the prior clause. devobj.dll aside used
both a semicolon (between IncludeNativeLibrariesForSelfExtract and
App.xaml.cs) and an em-dash (between 'not bundled' and the crash
explanation); three sentences now.
XAML-Views.md: Controller Tab Type Icon prose 'v2 short names — one
icon represents the whole family' was a pseudo-colon attaching the
family-coverage clarification.
2c47833
HIDMaestro-Deep-Dive: two em-dash pseudo-colons -> periods
HmInactivityDestroyTimeoutSeconds description em-dash before 'a slot
with no mappings at all...' and the bubble-up invariant em-dash
before 'slot 3 does NOT shift down...' were both pseudo-colons
attaching contrastive elaborations. Periods read cleaner.
a4a1bce
Dev wiki: more em-dash pseudo-colons -> periods
ViewModels.md: HmInactivityDestroyTimeoutSeconds description em-dash
attaching the 'only the live VC is destroyed' clarification.
Services-Layer.md: Profile-restore Topology step had both a
semicolon (pseudo-period) and an em-dash (pseudo-colon) attaching
slot-diff outcomes; the device-assignment step had another em-dash
attaching the unchanged-mapping promise. Three sentences each now.
Input-Pipeline.md: 'preserve nodes path is gone — HM creates and
destroys...' em-dash was a pseudo-colon attaching the v3 behavior.
f22aab6
Build-and-Publish: em-dash pseudo-colon + stale screenshot script
SharedVersion 'Never re-introduce...' em-dash was a pseudo-colon
attaching the consequence; replaced with a period.
tools/ tree listed 'capture_screenshots.ps1' (singular) but the repo
actually has ~20 capture_*.ps1 scripts, one per wiki surface. Listing
updated to reflect reality.
c5251f7
Wiki dev pages: another round of prose semicolons -> periods
Architecture-Overview: drift-comp contrast, DSU 4-slot cap aside,
slot-reorder consequence sentence. Input-Pipeline: positive/negative
drift contrast, thread-safety sole-writer note. Engine-Library:
back-compat XmlEnum exception path, KBM Open() GUID derivation.
XAML-Views: MainViewModel constructor step, type-switch button
unavailable-state aside, drag-drop type-group rule, HidingToggle
side-effect list, KBM hover/recording color contrast, two
'Constructor only' code-behind glosses.
da81989
Dev wiki: more prose semicolons -> periods (4 more pages)
DSU-Motion-Server: slots 1-4 vs 5-16 contrast.
DSU-Protocol-Implementation: SDL coord system contrast, axis-invert
note, subscriber-resolution algorithm steps, GetSubscribers gloss.
SDL3-Integration: 7 prose constructions across marshaling, haptic
strategy, raw-button mapping, BT-serial priority note, ISdlInputDevice
interface description, ClearRuntimeState side effects, WinUSB notes.
Driver-Installation-Internals: 8 prose constructions across v2/v3
backend swap, UAC-prompt aside, MIDI Services download notes,
GitHub-asset parser, async-void try/catch, ViGEmBus MSI lookup,
HID-class-key cleanup, and v2-relaunch removal note.
c33a8de