Skip to content

History

Revisions

  • Services-Layer: IsVirtualOrShadowDevice filters ViGEm names, not HIDMaestro The IsVirtualOrShadowDevice description said 'Checks name for HIDMaestro/Virtual Gamepad'. The actual method (InputService.cs:4681) doesn't look for HIDMaestro in the name — HIDMaestro is already filtered at Step 1 before this defense-in- depth check runs. The actual matches are: - online-only (offline = always false) - name contains 'ViGEm' or 'Virtual Gamepad' - path lowercase contains 'vigem' or 'virtual' - IsHidden flag is true Rewrote the bullet to describe the actual signature. Mainly catches v2-era ViGEm/vJoy installs that survived the legacy cleanup dialog.

    @hifihedgehog hifihedgehog committed May 21, 2026
    b11071d
  • HIDMaestro-Deep-Dive: OpenXInput fork filters by HIDMAESTRO substring, not product string The OpenXInput section said 'the fork's XInputGetState / XInputGetCapabilities filter out controllers whose product string matches HM's virtual-controller signature'. That's wrong — the fork doesn't read product strings. OpenXinput.cpp IsHidMaestroInterface (src/OpenXinput.cpp:18) does: 1. Fast path: substring-match the literal 'HIDMAESTRO' against the interface symlink (no CM API calls). 2. PnP walk: CM_Locate_DevNodeW then walk up to 4 ancestors, looking for 'HIDMAESTRO' in each one's hardware-ID list. Depth 4 covers the case where the HID child spoofs the real gamepad's hardware IDs (HM Xbox-family profiles) and the marker only appears on a depth-1+ ancestor. Rewrote the prose to describe what the classifier actually does.

    @hifihedgehog hifihedgehog committed May 21, 2026
    54eac03
  • Driver-Management: list the right three HM filter surfaces The OpenXInput section closed with 'three filter surfaces (SDL3 fork, OpenXInput fork, SetDllDirectory preload)'. SetDllDirectory is a load-order mechanism (so PadForge's xinput1_4.dll wins over System32's), not a filter. The three actual filter surfaces, per HIDMaestro-Deep-Dive line 82: - OpenXInput fork (XInput API) - SDL3 fork (DirectInput + Raw Input + HIDAPI enumeration) - PnP-walk in InputManager.Step1.UpdateDevices (device-card view) Updated the sentence to name each surface accurately.

    @hifihedgehog hifihedgehog committed May 21, 2026
    8aed226
  • Architecture-Overview: SDL3 fork has 4 features, not 2 Three places listed the SDL3 fork's contents as 'HM filter + Switch 2 Pro' (Mermaid diagram label, project-tree comment, native-DLL table description). User correction: the feat/hidmaestro-filter branch carries 6 commits across 4 features (Switch 2 Pro, HIDMaestro filter, 16-XInput XUSER_MAX_COUNT bump, XInput Share button via XInputGetSystemButtons). Updated all three call-out strings to 'HM filter + Switch 2 Pro + 16-XInput + Share button'.

    @hifihedgehog hifihedgehog committed May 21, 2026
    286aab4
  • Wiki: more accurate SDL3 fork descriptions in page intros + HM filter file list SDL3-Integration.md page intro framed the fork as Switch-2-Pro-only ('the custom SDL3 fork for Switch 2 Pro Controller support'). Updated to '6 commits across four features: HIDMaestro filter, Switch 2 Pro Controller, 16-XInput, XInput Share'. HIDMaestro-Deep-Dive.md filter-cascade bullet claimed the HIDMaestro filter substring list lives in 'joystick/windows/SDL_xinputjoystick.c'. That's wrong: the XInput backend is pristine upstream, XInput-side filtering happens through the OpenXInput fork. The actual SDL3-side patch touches three files: src/hidapi/windows/hid.c (classifier + 256-entry path cache), and one SDL_HidmaestroIsAnsiHidPathHm call site each in src/joystick/windows/SDL_dinputjoystick.c and SDL_rawinputjoystick.c. Updated the bullet to match.

    @hifihedgehog hifihedgehog committed May 21, 2026
    bb38015
  • SDL3-Integration: SDL3 fork is 6 commits across 4 features, not 2 Previous edit framed the fork as carrying just two patches (HIDMaestro filter + Switch 2 Pro Controller). User correction: the feat/hidmaestro-filter branch is actually 6 commits across 4 features: 1. Switch 2 Pro Controller WinUSB bulk I/O (7c4118c49) 2. HIDMaestro filter + HMXINPUT dead-branch cleanup (60d06e2f4 + 14f883872) - PadForge-specific 3. 16 XInput controllers (XUSER_MAX_COUNT 4 -> 16) at ba25d3671 - paired with hifihedgehog/OpenXinput OpenXinput1_4 commit 45c91b1 (CMake default bump) 4. XInput Share button (reads XInputGetSystemButtons ordinal 109 via OpenXInput) at 1b266767c (loader/dispatch) + 3fbf1429f (gamepad-db misc1:b11) Rewrote the 'Why a Fork' section as a 4-row table that lists each feature, its SDL3 commit hashes, and any paired OpenXInput work. Also added the cross-reference to the hidmaestro-fork-resync recipe since changing the HM enumerator name now needs to stay in sync across three places (SDL3 filter, OpenXInput filter, Step 1 PnP walk).

    @hifihedgehog hifihedgehog committed May 21, 2026
    d00b1ad
  • SDL3-Integration: fix SDL3-fork section (purpose, source, build cmd) The 'SDL3 Fork: Switch 2 Pro Controller Support' section had three accuracy issues: 1) Title and intro said the fork's purpose is Switch 2 Pro Controller support. Per the project memory rule sdl3-fork-rebase-priority.md, the HIDMaestro filter is PRIMARY (branch 'feat/hidmaestro-filter', 3 files); Switch 2 Pro is secondary. Rewrote the section to lead with the HM filter and explain Switch 2 Pro as the second patch. 2) Cited a local dev path ('C:\Users\sonic\GitHub\SDL3-build\SDL\') as the fork source. Replaced with the public fork URL (github.com/hifihedgehog/SDL, branch feat/hidmaestro-filter). 3) Build instructions started with 'cd C:\Users\sonic\...'. Rewrote as a git clone + cmake build sequence that any reader can run. Also dropped a stale '2026 Steam Controller' reference into the fork purpose since Valve's upstream PR now lives on libsdl-org/SDL mainline and the fork just rebases against it. Updated the ToC entry + the section-link in the P/Invoke intro.

    @hifihedgehog hifihedgehog committed May 21, 2026
    6bb47dc
  • Engine-Library: 'Device Wrappers' subgraph label is PadForge.Engine Mermaid diagram subgraph labeled 'Device Wrappers. PadForge.Engine .Common' but every type in it (ISdlInputDevice, SdlDeviceWrapper, SdlKeyboardWrapper, SdlMouseWrapper, WebControllerDevice, TouchpadOverlayDevice) declares 'namespace PadForge.Engine'. The files live in the Common/ folder but the namespace is just PadForge.Engine. InputHookManager is the only Common/ file that sits in the PadForge.Engine.Common namespace. Fixed the subgraph label.

    @hifihedgehog hifihedgehog committed May 21, 2026
    af0ec4b
  • Settings-and-Serialization: GlobalMacroData XmlArrayItem name is 'Index', not 'Btn' The LegacyTriggerRawButtons attribute was documented as [XmlArrayItem("Btn")] in the wiki but the actual class uses [XmlArrayItem("Index")] (SettingsService.cs:3892). Anyone copying the wiki snippet into a hand-crafted PadForge.xml would get the wrong element name and the array wouldn't round-trip. Fixed to match the live attribute.

    @hifihedgehog hifihedgehog committed May 21, 2026
    c024c69
  • Settings-and-Serialization: Source files list adds v3.2 schema files The 'Source files' bullet list at the top of the page covered only the v2-era schema files (PadSetting / UserDevice / UserSetting plus SettingsService / SettingsManager). v3.2 added the MappingSet family (MappingSet.cs + MappingRow.cs + MappingSource.cs + ShiftActivator.cs) and the DeviceTuning placeholder. Without those in the list, dev readers can't find the multi-source / shift-layer schema sources from the top of the page. Added both bullets.

    @hifihedgehog hifihedgehog committed May 21, 2026
    a52dbac
  • Engine-Library: namespace table reflects v3.2 .Common.Mapping namespace The namespace summary listed four namespaces (PadForge.Engine, PadForge.Engine.Data, PadForge.Engine.Common, SDL3). v3.2 added a fifth: PadForge.Engine.Common.Mapping, which holds the multi-source mapping helpers (CombineHelper, SourceEvaluator, SourceCoercion, SourceKindRuntime, MappingExpression). Documented the new namespace and tightened the descriptions on the other three so each row actually says what lives there.

    @hifihedgehog hifihedgehog committed May 21, 2026
    0533e8d
  • Engine-Library: add v3.2 TouchpadOverlayDevice + diagram link The mermaid diagram's 'Device Wrappers' subgraph listed SdlDeviceWrapper / SdlKeyboardWrapper / SdlMouseWrapper / WebControllerDevice but not TouchpadOverlayDevice. It's a real ISdlInputDevice in PadForge.Engine that the v3.2 overlay window uses to publish touch state to PlayStation slots. Added the diagram node + the 'implements ISDI' edge. Wrote a full TouchpadOverlayDevice reference section between WebControllerDevice and DeviceObjectItem documenting the device identity (fixed VID/PID/GUIDs), button shape (NumButtons=17, SupportedButtonIndices=[16] for the touchpad click slot), and the 'one device per session' nature (SdlInstanceId=0xFFFFFFFE). Added the ToC entry.

    @hifihedgehog hifihedgehog committed May 21, 2026
    137058a
  • Engine-Library: ToC reflects the two new type sections Added TouchpadState and CustomControllerLayout entries to the Table of Contents so the new sections land in the page navigation.

    @hifihedgehog hifihedgehog committed May 21, 2026
    2057604
  • Engine-Library: add missing TouchpadState + CustomControllerLayout sections Two PadForge.Engine types weren't documented in the dev reference: TouchpadState (GamepadTypes.cs:73) Two-finger touchpad surface state. Used by the v3.2 PlayStation SubmitGamepadState overload so games see finger positions on the DS4 / DualSense extended report. Documented field-by-field including PacketCounter which only ticks on finger-state edges. CustomControllerLayout (CustomControllerLayout.cs) Per-slot HID descriptor shape for Extended slots. Replaces the v2 ExtendedDeviceConfig nested type. Documented the five count fields and called out IsTriggerSlot's role in keeping Step 3 / Step 4 / deadzone-pipeline in agreement about which axis indices are triggers vs sticks.

    @hifihedgehog hifihedgehog committed May 21, 2026
    0cae4c9
  • Force-Feedback: note that Extended FFB is toggle-able via Customize 'The Extended virtual controller advertises full PID FFB capability' read as absolute. v3.0.3 added a ForceFeedbackEnabled toggle on ExtendedSlotConfigData (Customize-gated); when it's off, Step 5 rebuilds the HID descriptor without the PID block so DirectInput games see a non-FFB joystick. Documented the toggle so users chasing a 'why doesn't my game see PID FFB?' question can find the switch.

    @hifihedgehog hifihedgehog committed May 21, 2026
    9eefad9
  • Settings-and-Serialization: ExtendedSlotConfigData includes ForceFeedbackEnabled The DTO snippet was missing the ForceFeedbackEnabled XmlAttribute (default true) added in v3.0.3. Without it the docs implied v3 had no per-slot toggle for the HID PID FFB descriptor block, but the Extended config bar exposes that switch and Step 5 reads the value through ExtendedSlotConfigData on every Customize-aware rebuild.

    @hifihedgehog hifihedgehog committed May 21, 2026
    7aca1a5
  • Settings-and-Serialization: SwitchProfileMode includes ToggleVCsDisabled (v3.2) The enum block listed four values (Specific / Next / Previous / ToggleWindow) but the actual enum has a fifth, ToggleVCsDisabled, added in v3.2 to support the bulk virtual-controller on/off shortcut (see release notes 'Profiles and shortcuts'). Added the value and explained its bulk-flip + flyout behavior so the dev reference matches the user-facing Profiles.md description.

    @hifihedgehog hifihedgehog committed May 21, 2026
    ac5b970
  • Settings-and-Serialization: MacroData + ActionData match current shape MacroData was missing three v3.2 trigger fields: - TriggerInputs (pipe-sep multi-device trigger combo) - TriggerExpression (Custom Expression formula text) - TriggerExpressionVariables (a/b/c/... variable bindings) ActionData was missing ten v3.1+ Lightbar override fields: - LightbarR / G / B - LightbarHoldMode (Reactive / Sticky) - LightbarColorSource (Fixed / RandomHue / PaletteStep) - LightbarHoldMs / LightbarFadeMs (Reactive timing window) - LightbarPaletteCsv (per-action palette) - LightbarTargetMode (LightbarModeSet target) - LightbarCycleModesCsv (LightbarModeCycle mode list) Also updated the MacroActionType list to cover the v3.1+ Lightbar action types (LightbarColor / LightbarColorClear / LightbarModeSet / LightbarModeCycle), the v3.1+ Rumble / RumbleStop pair, and v3.2's ToggleTouchpadOverlay action. Noted that the Rumble action's strength/hold/fade fields live on the MacroAction VM and don't yet round-trip through the serialized ActionData DTO.

    @hifihedgehog hifihedgehog committed May 21, 2026
    ca2506b
  • Settings-and-Serialization: SettingsFileData + AppSettingsData match current code SettingsFileData class skeleton was missing two top-level arrays that have been on it since v3.2: - SlotMappingSets (multi-source / shift-layer mapping tables) - DeviceTunings (per-device tuning placeholder) AppSettingsData property reference table was missing ~16 fields covering v3.0-3.2 additions: v3.0: HmInactivityDestroyTimeoutSeconds, SlotProfileIds, LegacyDriverCleanupOffered v3.1: XboxSlotOrder + the four other per-group SlotOrder arrays, PlayStationConfigs v3.2: EnableTouchpadOverlay + 6 overlay position/size fields, UserProfiles (HMDeviceExtractor imports), GlobalMacros plus MainWindow Left/Top/Width/Height/State/FullScreen, KeepHidHideCloaksBetweenLaunches Also corrected SlotControllerTypes value 0 from 'Microsoft' to 'Xbox' (the C# enum name; the v2 XmlEnum 'Microsoft' alias is for on-disk back-compat only).

    @hifihedgehog hifihedgehog committed May 21, 2026
    19034e1
  • Settings-and-Serialization: ProfileData property reference table matches class The class skeleton was updated last commit but the property reference table below it still listed only the v2 fields. Added rows for the v3.0-3.2 additions: v3.0: SlotProfileIds v3.1: PlayStationConfigs, all five SlotOrder arrays v3.2: SlotMappingSets, EnableTouchpadOverlay + 6 overlay position / size / opacity / monitor fields Tagged each addition with the version it landed in. Called out the v2-back-compat 'ProfileMicrosoftSlotOrder' XML name for the Xbox slot-order array since the C# property is XboxSlotOrder.

    @hifihedgehog hifihedgehog committed May 21, 2026
    30a7ee6
  • Settings-and-Serialization: ProfileData class block adds v3.0-3.2 fields The class skeleton was the v2 shape. Added 11 missing fields that have landed on ProfileData since v3.0: v3.0: - SlotProfileIds (per-slot HM profile slug) v3.1: - PlayStationConfigs (per-slot Adaptive Triggers + Lighting) - XboxSlotOrder / PlayStationSlotOrder / ExtendedSlotOrder / KeyboardMouseSlotOrder / MidiSlotOrder (per-group visual order) v3.2: - SlotMappingSets (per-VC multi-source / shift-layer tables) - EnableTouchpadOverlay + TouchpadOverlayOpacity / Monitor / Left / Top / Width / Height (the touchpad-overlay window's per-profile state) Grouped fields with category comments so it's clear what each one relates to and tagged the version on each addition.

    @hifihedgehog hifihedgehog committed May 21, 2026
    363d242
  • Settings-and-Serialization: tighten ButtonShare-not-in-checksum claim Prior commit speculated about WHY ButtonShare is excluded (descriptor 'lives elsewhere'). I haven't traced that, and ButtonShare is in the MappingPropertyNames set at PadSetting.cs:1659. State the observable fact only: it's on the class but not appended to ComputeChecksum's StringBuilder. Could be an oversight or by design; the docs shouldn't guess.

    @hifihedgehog hifihedgehog committed May 21, 2026
    fab4f11
  • Settings-and-Serialization: ComputeChecksum() field list covers v3.2 additions The ComputeChecksum() group enumeration listed 13 groups but the actual code hashes 19. Missing groups added (with explicit v3.2 tag where applicable): Touchpad (7 fields, contact + click descriptors) Impulse triggers (4 fields, v3.2) Constant trigger force (3 fields, v3.2) Audio bass trigger rumble (5 fields, v3.2) Constant force (3 fields) Gyro tuning (~24 fields, v3.2 — sensitivity / smoothing / space / bias / aim-engage / real-world calibration) Also noted that ButtonShare is on the class for Xbox Series mapping but is intentionally excluded from the checksum (its descriptor lives in the slot config, not in PadSetting).

    @hifihedgehog hifihedgehog committed May 21, 2026
    9ac96aa
  • Settings-and-Serialization: LoadFrom* method list includes Web + Overlay UserDevice loading-methods section listed only LoadFromSdlDevice / LoadFromKeyboardDevice / LoadFromMouseDevice and claimed LoadFromSdlDevice 'sets DevRevision' (no such field exists; the method just delegates to LoadFromDevice). Added the missing LoadFromWebDevice (v3.x web-controller browser pads) and LoadFromOverlayDevice (v3.2 on-screen touchpad overlay) entry points and dropped the bogus DevRevision claim.

    @hifihedgehog hifihedgehog committed May 21, 2026
    33c2935
  • Settings-and-Serialization: UserDevice schema matches actual class Identity table dropped DevRevision (no such field in the class) and added the missing SdlGuid (used by gamecontrollerdb matching). Capability table dropped CapSubType (no such field) and CapFlags (no such field), and added the missing HasTouchpad and HasRumbleTriggers (driven by SDL_PROP_JOYSTICK_CAP_TRIGGER_RUMBLE _BOOLEAN, used for the v3.2 impulse-trigger routing). HasGyro device list expanded to include the v3.2 additions (Switch 2 Pro, Steam Controller / Deck).

    @hifihedgehog hifihedgehog committed May 21, 2026
    bb8ba44
  • Settings-and-Serialization: ShiftActivator schema matches actual class Field names matched the v3 design doc, not what shipped: <Input> (MappingSource) -> DeviceGuid + Descriptor (two strings) <ChordSecondInput> (MappingSource) -> ChordSecondDeviceGuid + ChordSecondDescriptor (two strings) <EmojiIcon> -> Icon <CycleLayerList> -> CycleLayers <CustomTargetLayer> -> JumpToLayer Restructured the table to show C# member name, type, default, and description, switched the column header to 'Member' since every field is an XmlAttribute (no <element> form), and called out the defaults explicitly so authors writing PadForge.xml by hand know what each attribute looks like when absent.

    @hifihedgehog hifihedgehog committed May 21, 2026
    21aea2e
  • Settings-and-Serialization: MappingSource schema matches actual class The table mixed v3-design-doc names with actual code names and was missing ~half the fields. Replaced with the live shape: - Half -> HalfAxis (the actual XmlAttribute name) - Deadzone -> DeadZone (case) - InvertOnHoldModifier with type MappingSource -> ParamModifier (string descriptor; just one of several Param* attributes, not a nested MappingSource) - Added ParamUp / ParamDown / ParamRate / ParamSticky / ParamMin / ParamMax for the Incremental kind (previously listed only Rate / Sticky / Min / Max as one row, no Up/Down) - Added the v3.3 NoInherit reserved slot - Switched from <element> to attribute form throughout (every field is an XmlAttribute, no child elements) - Added defaults column

    @hifihedgehog hifihedgehog committed May 21, 2026
    888f452
  • Settings-and-Serialization: MappingRow schema matches actual class Field names were the v3-design-doc draft, not what shipped: <Output> -> Target ([XmlAttribute]) <Sources> -> Sources ([XmlElement("Source")]) — wraps List<MappingSource> <Combine> -> CombineMode ([XmlAttribute]); values are MaxAbs/Sum/ Average/OR/AND/XOR/Custom (not the UI labels) <Formula> -> CombineExpression ([XmlAttribute]) <LayerMask>, <NoInherit> exist but are XmlAttributes, not elements Restructured the table to show the C# member name, the actual XML serialization attribute, the type, and the description. Also added the mapping note that the seven internal CombineMode strings show up in the UI as Strongest / Combined / Average / Either / Both / Only one / Custom.

    @hifihedgehog hifihedgehog committed May 21, 2026
    6059e5e
  • Settings-and-Serialization: MappingSet schema matches actual class shape The table for MappingSet element schema listed three children: <Layers> (MappingLayer[]) - does not exist <Activators> (ShiftActivator[]) - actual name is <ShiftActivator> <DefaultCombineModes> (dictionary) - does not exist anywhere The actual MappingSet class (PadForge.Engine/Data/MappingSet.cs) has two XmlElement-annotated lists: <Row> (Rows) and <ShiftActivator> (ShiftActivators). Rows are flat: every row across every layer is in the same list and tags itself with LayerMask. There's no MappingLayer wrapper and no DefaultCombineModes; the default-combine behavior is auto-mapping logic, not a persisted field. Rewrote the table and the layer-resolution explanation underneath.

    @hifihedgehog hifihedgehog committed May 21, 2026
    5a60ded
  • Macros: macro rumble routing covers all three writer families The Rumble action description said 'Sony slots write through the dispatcher; non-Sony slots use the SDL rumble path.' That's the v3.1 routing. v3.2 introduced XboxImpulseHidWriter as the sole writer for Xbox One+ pads (Xbox One / Elite / Series); the macro rumble merge flows through ApplyForceFeedback's per-pad-family fan-out the same way game rumble does, so the same three branches apply. Rewrote to list all three writer families.

    @hifihedgehog hifihedgehog committed May 21, 2026
    91b53c6