Lock
LOCK sets how much of one native input the box emits. Injection drives that input at full strength regardless of scale.
-255 min <== 2.55×, reversed
-100 invert <-- all of it, the other way round
0 block --X nothing reaches the PC
40 -.-> 40 of every 100 counts, carried across reports
100 pass --> all of it, byte for byte
255 max ==> 2.55×, clamped to the field's declared range
injection --> full strength whatever the scaleA relative direction weighs native motion against the bearing, in one of two geometries.
| Class | Value | id is |
|---|---|---|
| button | 0 | a button id (0=Left .. 4=Side2, then numeric to the declared count) |
| key | 1 | a HID keyboard usage (0xE0-0xE7 = modifier) |
| media | 2 | a 16-bit Consumer usage |
| axis | 3 | 0=X, 1=Y, 2=wheel, 3=pan (the sign is the direction) |
LOCKBlock, pass, or amplify
A momentary usage shares INJECT's (class, id) space, so a button locks like a key. Opcode 0x0A.
LOCK 0x0A · payload 6 bytes
Fire-and-forget
| Offset | Field | Type | Notes |
|---|---|---|---|
| 0 | class | u8 | input class (table above) |
| 1 | id | u16 | input within the class, little-endian; 0xFFFF = a blanket |
| 3 | direction | u8 | sign or edge, 0-4 |
| 4 | scale | i16 | percent of the native value kept, little-endian, -255 to 255 |
| Name | Value | Effect |
|---|---|---|
| min | -255 | 2.55×, reversed. Anything negative reverses what it keeps. |
| invert | -100 | All of the native value, reversed: an exact inversion. |
| block | 0 | None of the native value is emitted. |
| pass | 100 | All of the native value, byte for byte. |
| max | 255 | 2.55×. Anything above 100 amplifies. |
| Name | Box action |
|---|---|
| combine | A delta picks up one fixed-sign scale and one relative scale, multiplied. A 0 in either blocks. |
| carry | A native delta at 1 kHz is almost always +/-1, so the dropped fraction is banked per axis and sign: 40 on a run of -1 emits 0 0 -1 0 -1. |
| saturate | A weighed value clamps to the field's declared range, never wraps, and forfeits the fraction it could not carry. |
| one bit | A button, key or media usage locks below 100 and passes at 100. The box stores that, not the number sent. |
| sign | A negative reverses what it keeps: the magnitude is weighed and the result flipped, so -100 is an inversion with no rounding. A negative on a momentary usage (one bit, nothing to reverse) is refused. |
| direction | The slot is picked from the sign of the delta before the weigh, so a directional negative does not loop: -100 on positive sends rightward motion left and leaves leftward motion alone. |
| order | A scale takes effect before anything sent after it, a clip's auto-lock included. Once a later command's effect is emitted, no native input passes at the old scale. |
Weighing runs before injected motion drains. A gain that fills an axis leaves injected motion no room. The injected motion is held, not dropped, and is emitted in one report once room opens.
The threshold is the field's declared maximum divided by the gain. At 255 on an 8-bit axis, the field fills at a native delta of 50 and clamps from 51.
MOVE_RIDE doesn't bound the hold: a moved report re-opens the ride window, and riding never gates the immediate accumulator.
| Name | Value | Axis | Button, key, media |
|---|---|---|---|
| both | 0 | Both signs. | Press and release. |
| positive | 1 | Positive sign only (+). | Press only (0 to 1). |
| negative | 2 | Negative sign only (-). | Release only (1 to 0). |
| with | 3 | The sign the box is injecting. | Refused on a button or key. Media locks the whole usage, as 0 would. |
| against | 4 | The sign opposing the injected one. | Refused on a button or key. Media locks the whole usage, as 0 would. |
Media has no sign and no edge, so RESP(LOCKS) always reports its direction as 0. Every shipped client refuses 3 and 4 on all three momentary classes.
On an axis, 0 writes the scale to the two fixed-sign slots and a pass to the relative pair. A both of 50 then means 50%, bearing or not. An unlock clears all four.
An id of 0xFFFF addresses the whole class in one command.
| Class | Covers | Direction | Reads back as |
|---|---|---|---|
| button | Every button the real device declares. | As a named button. | One entry per button and edge, under the button's id. |
| key | Every keyboard usage. | Honoured: 1 blocks press edges, 2 release edges, 0 both. | One entry per blocked edge, id 0xFFFF. |
| media | Every Consumer usage. | Ignored. | One entry, id 0xFFFF, direction 0. |
| axis | X, Y, the wheel, and pan. | As a named axis. | One entry per axis and direction, under the axis's id. |
| Blanket | Storage |
|---|---|
| button, axis | Expanded on arrival, so a later command on one member overwrites only that member. |
| key, media | One flag. A per-usage unlock doesn't lift it. |
unlock the matching unlock (scale = 100); direction 0 clears
all four slots of that target
silence ~1 s with no control-PC frame
RESET a RESET command
link loss the inter-chip link drops
detach the real device goes away
re-clone the box binds a device againA keepalive holds a lock past 1 s of quiet. Injection auto-clears on the same events.
Every clear here except the unlock moves the session count.
Scales are PC-owned and invisible to the game PC. QUERY(LOCKS) reads the active set. The HEALTH LOCK_ON bit is set while any scale differs from a full pass.
Library bindings: scale, lock, unlock, and scale_all. scale_all sends this frame for buttons, keys and media, and per-axis frames for X, Y, the wheel and pan.
Block the wheel's negative (scroll-down) sign: class = 3 (axis), id = 2 (wheel), direction = 2, scale = 0:
Keep 40% of leftward motion while the bearing on X is positive: direction = 4 (against), scale = 40. A native -10 is then emitted as -4, and as -10 again once the bearing lapses:
Invert X on both signs: scale = -100, which is 0xFF9C little-endian.
BearingCurrent injected direction
with and against weigh a native delta by its sign relative to the bearing. The box reads the bearing at the merge point, where pending injection and the arriving report are both present.
MOVE(+10) MOVE(+10) idle
| |
v v
----+----------------+---------------------------------------> t
|<-- restarted ->|<------ window ------->|
bearing +X bearing +X no bearingEach axis has a separate bearing and deadline, set by OPTION(BEARING). A window of 0 holds no bearing, so with and against stop weighing without being cleared.
| Event | Bearing |
|---|---|
An injected delta on that axis, from a MOVE on either accumulator or from a clip | Set, and the deadline restarted. A zero component leaves that axis unchanged. |
| Injected motion still owed on that axis, held for a ride or queued behind a slow emit gate | Keeps restarting the deadline, and points at the net pending delta rather than the last one sent. |
| The window elapses | That axis has no bearing. Both relative directions stop applying, and the axis passes at its fixed-sign scale alone. |
MOVE with DISCARD | Cleared, then set again by the command's delta. Only a zero-delta discard leaves the axis without a bearing. |
| Motion held for a ride goes stale | Cleared with the held motion, on the next native motion report that would have carried it. |
A change to OPTION(MOVE_RIDE) | Cleared, along with the held motion. |
A change to OPTION(BEARING) | Cleared, and the banked carry with it. |
RESET, ~1 s of control-PC silence, link loss, detach | Cleared with the rest of the PC-owned state. |
GeometryPer axis, or projected onto the bearing
Set by OPTION(BEARING). The two modes agree while only one bearing component is nonzero, and differ once both are.
| Mode | Value | Weighs |
|---|---|---|
| per axis | 0 | Each axis against its bearing, independently. |
| vector | 1 | Only the motion along the injected direction. |
the bearing is down-right at 45 degrees, the real device moves straight right
o-----------> h (+12, 0)
\ / across b (+6, -6) untouched by with / against
\ /
\ /
\ /
\ /
+ along b (+6, +6) weighed by with / againstIn vector mode, the relative pair addresses the XY bearing as a whole. The box applies the lower of the X and Y scales to both.
RESP(LOCKS) reports that effective scale on both axes. Replaying a readback as commands lowers the higher stored byte to match.
The wheel and pan are never projected. Each weighs against its bearing.
| Stage | Reads | Acts on |
|---|---|---|
| 1. project | The relative pair, one number for both axes. | The part along the bearing. What survives is written back to both axes. |
| 2. weigh | Each axis's fixed pair, chosen by the sign now in the field. | What stage 1 left, not the delta the report carried. |
A fixed-sign scale governs what is emitted, so it covers the across part as well as the native delta. Only the relative pair is redistributed. The fixed pair is per axis in both modes.
bearing +X +Y
LOCK(axis X, with, 0) LOCK(axis Y, with, 0) the bearing's relative scale is 0
LOCK(axis Y, negative, 0) Y's negative sign is blocked
X Y
native +12 0 straight right, nothing on Y
stage 1 along b +6 +6 scaled by 0, so it goes
across b +6 -6 left alone, and is all that remains
leaves +6 -6
stage 2 scale 100 0 on the sign now in each field
emitted +6 0In per-axis mode, stage 2 would leave Y alone, since the report carried nothing there. With a scale of 200 instead of the block, the same -6 is emitted as -12.