nx_input_abstract.nx
buildroot/runtime/nx_input_abstract.nx
about
nx_input_abstract.nx -- SOVEREIGN device-agnostic input core (F1102, game-platform lane).
ONE semantic action state (up/down/left/right/A/B/menu/pause) driven by FOUR sources -- keyboard,
gamepad buttons, gamepad axes, touch -- so a game loop reads ACTIONS, never devices. This moves the
key->meaning mapping OUT of the JS shim and INTO the sovereign organ (the shim stays pure transport),
and it is the enabler for platform-desktop-native (F1105) and vr-runtime (F1106): a VR controller
surfaces as gamepad buttons/axes (WebXR gamepad), so it enters through the SAME ia_pad/ia_axis doors.
Base-relative + integer-only + no syscalls CALLED (imports only for consts/compose) => the identical
code runs natively (base=mmap) and in wasm (base=0), like nx_wasm_breeders.
Per-source held masks are kept SEPARATE and unioned on read, so releasing a key can never eat a
gamepad hold (the classic cross-device release bug -- gate tooth T4). Edge detection lives here too:
ia_frame() returns the RISING edge, so "interact fires every frame while held" cannot recur (T2).
Bindings are DATA rows (code,action) seeded by ia_init and rewritable at runtime via ia_bind (T6).
Touch composes the EXISTING nx_touch_zone SSOT (virtual d-pad -> legacy keycode) then routes the
code through the SAME binding table, so touch inherits rebinds for free.
license_tier: ORIGINAL
dependencies 2 imports · 4 importers
imports: nx_syscalls.nxnx_game_touch.nx
imported by: nx_desktop_game.nxnx_input_abstract_gate.nxnx_wasm_breeders.nxnx_wasm_craft.nx
structs
| none |
consts
| 23 | const IA_UP: i64 = 1 |
| 24 | const IA_DOWN: i64 = 2 |
| 25 | const IA_LEFT: i64 = 4 |
| 26 | const IA_RIGHT: i64 = 8 |
| 27 | const IA_A: i64 = 16 |
| 28 | const IA_B: i64 = 32 |
| 29 | const IA_MENU: i64 = 64 |
| 30 | const IA_PAUSE: i64 = 128 |
| 31 | const IA_JUMP: i64 = 256 |
| 32 | const IA_LUP: i64 = 512 // look up (keyboard pitch fallback) |
| 33 | const IA_LDOWN: i64 = 1024 // look down |
| 34 | const IA_MOD: i64 = 2048 // spare modifier |
| 35 | const IA_HOME: i64 = 4096 // return-to-spawn (void-fall rescue) |
| 38 | const IA_KB: i64 = 0 // keyboard-held action mask |
| 39 | const IA_PAD: i64 = 1 // gamepad-button-held action mask |
| 40 | const IA_AX: i64 = 2 // gamepad-axis-derived action mask (hysteresis state) |
| 41 | const IA_TOUCH: i64 = 3 // touch-held action mask |
| 42 | const IA_PREV: i64 = 4 // union mask latched by the previous ia_frame (edge detector) |
| 43 | const IA_AXX: i64 = 5 // last raw x axis, milli (-1000..1000) |
| 44 | const IA_AXY: i64 = 6 // last raw y axis, milli (+ = down, browser gamepad convention) |
| 45 | const IA_NBIND: i64 = 7 // live binding rows |
| 46 | const IA_BROW0: i64 = 8 // rows begin: (code, action) pairs |
| 47 | const IA_MAXBIND: i64 = 24 |
| 48 | const IA_LOOKX: i64 = 56 // analog LOOK channel: accumulated relative deltas (mouse/touch-drag), |
| 49 | const IA_LOOKY: i64 = 57 // drained once per frame by ia_look_take -- actions are bits, look is motion |
| 50 | const IA_LOOK_CLAMP: i64 = 30000 |
| 51 | const IA_WORDS: i64 = 64 // 8 + 2*24 = 56 bind area, +2 look, rounded up for slack |
| 54 | const IA_TH_PRESS: i64 = 350 |
| 55 | const IA_TH_HOLD: i64 = 250 |
functions
| 57 | func ia_words() -> i64 { return IA_WORDS } called by 1: main |
| 60 | func ia_lookup(p: *i64, code: i64) -> i64 |
| 71 | func ia_bind(p: *i64, code: i64, act: i64) -> i64 |
| 88 | func ia_init(p: *i64) -> i64 |
| 108 | func ia_key(p: *i64, code: i64, down: i64) -> i64 |
| 118 | func ia_pad_decode(btn: i64) -> i64 called by 1: ia_pad |
| 130 | func ia_pad(p: *i64, btn: i64, down: i64) -> i64 |
| 139 | func ia_ax1(active: i64, v: i64) -> i64 called by 1: ia_axis |
| 147 | func ia_axis(p: *i64, idx: i64, milli: i64) -> i64 |
| 162 | func ia_touch(p: *i64, tx: i64, ty: i64, w: i64, h: i64, down: i64) -> i64 |
| 170 | func ia_held(p: *i64) -> i64 |
| 176 | func ia_frame(p: *i64) -> i64 |
| 185 | func ia_look(p: *i64, dx: i64, dy: i64) -> i64 |
| 199 | func ia_look_take(p: *i64, out: *i64) -> i64 |