Semicolon → period across dev pages
The "X; Y" pattern where the two clauses are separately complete
reads as the AI-tell pseudo-period semicolon called out in the
project's writing style notes. Replace with a period (or comma
where the relation is conjunctive) across:
- Architecture-Overview (PtpDeviceState description, added in this
sweep)
- Controller-Slots (Impulse Triggers parenthetical)
- Engine-Library (three slot-assignment / template-preprocess
paragraphs added in this sweep)
- Home (Driver-Installation-Internals table row)
- Services-Layer (move-slot-to-group-tail flow)
- Settings-and-Serialization (v2 Preset enum migration note)
- Troubleshooting (UAC accept step)
- Virtual-Controllers (Gamepad struct dispatch note)
No semantic changes.
$Q attribution: include Magrofuoco in brief refs
Magrofuoco contributed the canonical qdollar.js implementation
and is a joint copyright holder on the reference; the Touchpad
page already cites all four authors. Bring Engine-Library and
Architecture-Overview into line.
Touchpad pipeline: full class-by-class dev reference
Engine-Library:
- Add GestureRecognizer, ShapeRecognizer, AngularMarginRecognizer,
ShapeTemplate, InBoxShapeTemplates, TouchpadCustomGesture,
TouchpadGestureContext, TouchpadGestureSettings sections with
file path, namespace, purpose, key API, defaults.
- GestureRecognizer notes the three-tier breakdown, the long-press
recent-stillness metric, LongPress/RadialZones path-clear
interaction, and per-slot fan-out semantics.
- ShapeRecognizer documents the matched[] tracking + LUT-based
ComputeLowerBound + bidirectional CloudMatch (port of the
canonical qdollar.js reference).
- AngularMarginRecognizer covers the circular-variance gate,
closed-path detection, and direction-agnostic matching.
- Default values for TouchpadGestureSettings cross-checked
against the source (SwipeDistanceThreshold 0.15 not 0.12;
SwipeTimeWindowMs 500 not 350; RadialCenterDeadzone 0.30 not
0.10; LongPressTimeWindowMs 500 not 600; PinchThreshold 0.25
not 0.15).
Architecture-Overview:
- Add Precision Touchpad Reader as its own background-thread
section alongside RawInputListener / DSU / hooks / web server.
- Note RawInput mouse path skips MOUSE_MOVE_ABSOLUTE events and
doesn't surface RI_MOUSE_HWHEEL.
- Renumber DSU / Input Hook / Web Controller thread headings
to accommodate the new PTP reader entry.
Document the PTP reader: tip-switch, frame assembly, slot stability
Adds a full PrecisionTouchpadReader section to Engine-Library with
the four spec-mandatory behaviors (tip-switch usage 0x42, multi-report
frame assembly via contact-count, HID-contact-id-stable slot
assignment, staleness clear), per-device state fields, and the public
API. The four behaviors are what made 3- to 5-finger taps reliable on
PTP hardware.
Also:
- Engine-Library RawInputListener: note the MOUSE_MOVE_ABSOLUTE skip.
- Architecture-Overview: extend PrecisionTouchpadReader.cs line.
- Touchpad: add a PTP-reader development subsection that summarizes
the four behaviors and links to the Engine-Library field reference.
Drop a pseudo-period semicolon in the recorder paragraph.
- Input-Pipeline Step 2: show both newState paths (PTP via
_ptpReader.ReadInto, SDL via ud.Device.GetCurrentState). The
prior text only showed the SDL path.
Architecture-Overview: add Touchpad/ to the Engine project layout
The 'PadForge.Engine' file-tree section in Architecture-Overview
listed Common/ and Data/ but skipped Touchpad/ entirely - even though
v3.3's gesture pipeline lives there. Added the directory with one
line per file (GestureRecognizer, ShapeRecognizer, ShapeTemplate,
AngularMarginRecognizer, InBoxShapeTemplates, TouchpadCustomGesture,
TouchpadGestureContext, TouchpadGestureSettings, TouchpadSettingsEntry).
Also added PerDeviceSettingsEntry.cs to the Data/ section, which
covers the v3.3 Copy / Paste / Copy From per-device clipboard payload
that the prior commit (Engine-Library namespace table) referenced
but the source-tree didn't surface here.
Wiki: scrub pseudo-colon em-dashes across user + dev pages
Wiki: tidy two small dev-doc seams
Architecture-Overview Mermaid graph: DSU_CLIENT and BROWSER node labels
were using a bare '.' as the separator between names (Cemu . Dolphin,
Phone . tablet). Changed to ' / ' to match the rest of the graph and
extended the DSU client list to the real four (Cemu / Dolphin / Yuzu /
Ryujinx) the wiki documents elsewhere.
ViewModels.md Per-Device Test Routing row: dropped the reference to
the private Claude memory file (feedback_per_device_test_isolation.md);
restated the rule in-doc and noted the same gate covers the dispatcher
/ routing branches that emit physical effects from those tabs.
Wiki: CopyFromDialog notes now reflect per-device tuning carry-along
Architecture-Overview source-tree comment: the dialog copies mappings
plus per-device tuning, not just the table.
XAML-Views Copy From Dialog (slot-level section) and CopyFromDialog
(dialog-detail section) both gain the per-device payload story: each
source device is matched to a target device by InstanceGuid then
ProductGuid, mapping table replaced wholesale, and per-device tuning
(deadzones, sensitivity, FFB, impulse triggers, adaptive triggers,
lighting, gyro, TouchpadSettings) is carried along through the
InputService BuildPerDeviceSettingsSnapshot / ApplyPerDeviceSettingsToSlot
pair documented one page over.
Architecture-Overview: drop two dead file refs from repo tree
InputEventArgs.cs and InputException.cs no longer exist anywhere in
the repo (refactored out). InputExceptionEventArgs.cs is the surviving
one. Updated its description to mention what it actually wraps
(an exception raised on the polling thread).
Architecture-Overview: SDL3.dll + libusb ARE bundled in single-file EXE
The page said "They are not embedded in the single-file exe. They must
sit adjacent to PadForge.exe." Both wrong:
- PadForge.App.csproj sets PublishSingleFile=true, SelfContained=true,
AND IncludeNativeLibrariesForSelfExtract=true. The
IncludeNativeLibrariesForSelfExtract flag (.NET 5+) folds <Content>
native DLLs into the single-file bundle. They get extracted to
%TEMP%\.net\PadForge\<hash>\ on first launch.
- PadForge.exe is shipped standalone (the deploy recipe in
feedback_deploy_recipe.md copies ONLY PadForge.exe to the install
dir; HM Maestro stays installed and SDL3/libusb extract from the
bundle on next launch).
Re-stated the mechanism: <Content> declarations are what cause the
build to pick them up; IncludeNativeLibrariesForSelfExtract is what
bundles them; ship-time copy is just PadForge.exe.
Wiki: purge references to four classes removed from the codebase
CustomInputUpdate, CustomInputHelper, DeviceEffectItem, and
RumbleLogger no longer exist in PadForge.Engine — they were
removed at some point and the wiki still documented them in
detail across five pages. Cross-checked with grep across both
projects: zero call sites remain in source.
Removed:
- Engine-Library.md: ToC entries + full sections for all four,
plus UserDevice.InputUpdates / OldInputUpdates rows that
referenced the dead CustomInputUpdate[] type.
- Architecture-Overview.md: file-tree entries for the four .cs
files + the RumbleLogger row in the static-class table.
Added the two real Engine/Common touchpad files
(PrecisionTouchpadReader, TouchpadOverlayDevice) that were
missing from the tree.
- Settings-and-Serialization.md: UserDevice.InputUpdates and
UserDevice.DeviceEffects rows.
- Input-Pipeline.md, SDL3-Integration.md: the step-(e) buffered-
update code samples rewrote into the current per-(slot,
device, padIdx) gesture-engine tick — that's what actually
runs after the InputState swap in Step 2 today.
SDL3 rumble fn is SDL_RumbleJoystick, not SDL_RumbleGamepad (fix 5 wiki sites + release notes draft)
Architecture-Overview: HIDMaestro driver is bundled in HIDMaestro.Core.dll, not downloaded by DriverInstaller
Architecture/Input-Pipeline: HMController.SubmitState (not HMContext); rewrite reverse data flow against per-family writer dispatch
Polish: Xbox writer HID-not-XUSB, fold ScpVBus comparison to ViGEm+vJoy, list v3.2 effect-writer files in tree, fix Adaptive-Triggers sentence
Polish: more pseudo-period semicolons fixed; correct stale v2-dev branch refs in Build-and-Publish
Strip em-dash pseudo-colons and pseudo-period semicolons across wiki prose
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'.
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'.
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.
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.
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.
Architecture overview: list all 4 3D model files + 5 2D / 3D asset dirs
Models3D directory listing was missing ControllerModelXboxOne.cs and
ControllerModelDualSense.cs. 2DModels and 3DModels directory listings
were missing XBOXONE, XBOXSERIES, and DualSense subdirectories.
Drop math-tuple 'Per-(device, slot)' jargon — 'per pad per slot' reads cleaner
Pass 27: punchy-voice sweep — drop 'various', 'not just X but Y' defensive parenthetical, 'actually' filler
Pass 24: Architecture-Overview mermaid OpenXInput label drops devobj (only xinput1_4.dll is bundled; devobj resolves from System32)
Pass 8: assembly versioning lives in repo-root SharedVersion.cs, not Properties/AssemblyInfo.cs
App and Engine share one version via the linked SharedVersion.cs at the
repo root. Wiki claimed AssemblyInfo.cs held the version (and listed
stale 2.1.0.0 / 2.0.0.0 values), which is wrong on three counts: wrong
file, wrong version numbers, wrong drift model (versions are shared
now, not independent).
Also fix the release-workflow step that pointed at AssemblyInfo.cs.
Architecture-Overview: Step 1 no longer filters HM virtuals; SDL3 fork does it upstream
Wiki Pass 3: dev-deep-dive accuracy corrections
ViewModels: HMaestro SDK assembly is HIDMaestro.Core (not
Microsoft.HIDMaestro.SDK); user-mode driver still needs first-run
installation, not just an embedded assembly.
SDL3-Integration: drop the _filteredVigemInstanceIds field documentation.
That field is gone from current InputService.cs. HM virtuals are filtered
upstream by the SDL3 fork's patched SDL_GetJoysticks (walks container ID
to the HM root enumerator and drops matches before returning the list),
so the engine no longer needs the rumble-killing-close guard.
Architecture-Overview / Driver-Installation-Internals / Build-and-Publish /
HIDMaestro-Deep-Dive: OpenXInput corrections. xinput1_4.dll is bundled
inside the single-file EXE via Content + IncludeNativeLibrariesForSelfExtract,
not "copied adjacent to PadForge.exe". devobj.dll is deliberately NOT
shipped (a bundled stub would hijack setupapi.dll's own DevObj* imports
and crash HID class enumeration per PadForge #69). System devobj.dll
resolves from System32 unaided.
Also: refresh pad-playstation-configbar.jpg to match the canonical PS
slot screenshot (DualSense (PS5, Bluetooth) profile, dualsense-bt).
Wiki: Pass 2 — dev-deep-dive accuracy + Home page voice match
Architecture-Overview: AssemblyInfo.cs → SharedVersion.cs; expanded
Data/ file list to include MappingSet/MappingSource/MappingRow/
ShiftActivator/MappingSetMigrator/DeviceTuning.
Input-Pipeline: drop preserveExtendedNodes parameter; rebuild field
table to match current InputService.
Virtual-Controllers: VendorId==0xBEEF check replaced with
DescriptorHasPidFfbBlock(descriptorHex) gate in three locations.
HIDMaestro-Deep-Dive: Microsoft.HIDMaestro.SDK → HIDMaestro.Core
(bundled at Resources/HIDMaestro/HIDMaestro.Core.dll); fix
context.CreateController(profile) call shape.
Services-Layer: drop preserveExtendedNodes from Stop(); remove the
"step 9" preserve-nodes branch.
Engine-Library: add TOUCHPAD = 0x0800 button flag row.
SDL3-Integration: SDL3 fork now filters HM virtuals at
SDL_GetJoysticks, so the engine no longer maintains
_filteredVigemInstanceIds. Updated Mermaid flowchart and renumbered
the connect-side step list.
Home: "New in 3.2" rewritten from bullet lists to story paragraphs to
match the website voice. Added Gyro / Impulse Triggers / Shift Layers
to the navigation tables.