code wiki / _hdl_build / nx_input_abstract_part.nx
nx_input_abstract_part.nx
buildroot/runtime/_hdl_build/nx_input_abstract_part.nx
about
nx_input_abstract_part.nx -- RENAMED FROM nx_input_abstract.nx 2026-07-31 (lib-reconcile).
PERMANENT FIX for a two-libraries-one-name collision. runtime/nx_input_abstract.nx is a DIFFERENT
program: the F1102 game-platform input CORE, whose API is ia_init(p) / ia_bind(p, code, act).
THIS file is the gamebench capability-43 composable PART, whose API is ia_init(s, nact) and
ia_bind(s, dev, act, raw) -- same names, INCOMPATIBLE arities. nx_cc binds an import to the
IMPORTER'S OWN DIRECTORY FIRST, so which API a caller got depended on WHICH DIRECTORY IT SAT IN,
and moving a file between directories silently swapped its input API. The rename removes the
ambiguity by construction: one name now denotes one program corpus-wide.
WHY THIS PART EXISTS (measured, not guessed): nx_gamebench 2026-07-25 ranked platform reach and found
platform-desktop-native blocking 21 of 22 reference titles, vr-runtime a GAP for 4, and mobile only
PARTIAL -- while EVERY game in the ecosystem wired its own controls. One loop per platform is how a
codebase forks into four. This part is the single place a raw device code becomes a SEMANTIC ACTION,
so the game loop above it never learns which device the player used.
THE CONTRACT (each clause is a gate tooth):
- DEVICE-INDEPENDENCE BY CONSTRUCTION: the same semantic action sequence delivered from keyboard,
gamepad, touch or a VR controller drives IDENTICAL downstream state. The game cannot tell them
apart because it never sees a device -- it sees actions. This is the flagship property.
- NO DEAD ACTION: an action reachable on one device but not another is a platform that cannot play.
ia_coverage MEASURES this per device; the gate requires 1000 permil on every bound device.
- UNAMBIGUOUS BINDINGS: binding a second action to a (device, raw-code) already in use is REFUSED
(IA_E_DUP) with state bit-identical. Ambiguous input is a bug you cannot debug later.
- AN UNBOUND CODE PRODUCES NOTHING: a stray device code can never fabricate an action.
- DETERMINISTIC REPLAY: the action trace replays to the same actions and the same checksum, and the
serializable span rides nx_gamesave like every other certified part (rpgstats T8 / entity T9).
Bindings are DATA, not code: a game declares its own action set and its own per-device codes, so a new
platform is a binding table, never a fork of the loop.
LIB, no main (ecosystem convention, cf. nx_swgpu.nx / nx_gamehud.nx). license_tier: ORIGINAL
dependencies 1 imports · 1 importers
imports: nx_syscalls.nx
imported by: nx_m2d_engine.nx
structs
| none |
consts
| 33 | const IA_D_KEY: i64 = 0 |
| 34 | const IA_D_PAD: i64 = 1 |
| 35 | const IA_D_TOUCH: i64 = 2 |
| 36 | const IA_D_VR: i64 = 3 |
| 37 | const IA_NDEV: i64 = 4 |
| 41 | const IA_A_PREV: i64 = 0 |
| 42 | const IA_A_NEXT: i64 = 1 |
| 43 | const IA_A_CONFIRM: i64 = 2 |
| 44 | const IA_A_CANCEL: i64 = 3 |
| 45 | const IA_A_PAUSE: i64 = 4 |
| 46 | const IA_A_NONE: i64 = 0-1 |
| 47 | const IA_MAXACT: i64 = 12 |
| 50 | const IA_F_NACT: i64 = 0 // declared action count |
| 51 | const IA_F_NEV: i64 = 1 // events fed (lifetime) |
| 52 | const IA_F_CK: i64 = 2 // order-sensitive rolling action checksum |
| 53 | const IA_F_DEVM: i64 = 3 // bitmask of devices carrying at least one binding |
| 54 | const IA_F_NTR: i64 = 4 // trace length |
| 55 | const IA_O_BIND: i64 = 8 // binding table: IA_NDEV*IA_MAXACT raw codes -> 8 .. 8+48 = 56 |
| 56 | const IA_O_TRACE: i64 = 56 // recorded action trace -> 56 .. 56+64 = 120 |
| 57 | const IA_MAXTRACE: i64 = 64 |
| 58 | const IA_NSV: i64 = 120 // serializable span (IA_O_TRACE + IA_MAXTRACE) |
| 61 | const IA_E_DEV: i64 = 0-1 |
| 62 | const IA_E_ACT: i64 = 0-2 |
| 63 | const IA_E_RAW: i64 = 0-3 |
| 64 | const IA_E_DUP: i64 = 0-4 |
| 65 | const IA_E_FULL: i64 = 0-5 |
| 67 | const IA_CK_SEED: i64 = 1469598103 |
| 68 | const IA_CK_PRIME: i64 = 16777619 |
| 69 | const IA_CK_MASK: i64 = 4611686018427387903 // 2^62-1: keep the checksum bounded and positive |
functions
| 71 | func ia_bit(i: i64) -> i64 { var v: i64=1; var k: i64=0; while k<i { v=v*2; k=k+1 } return v } |
| 72 | func ia_hasbit(m: i64, i: i64) -> i64 { let b: i64=ia_bit(i); if (m/b)%2==1 { return 1 } return 0 } |
| 75 | func ia_init(s: *i64, nact: i64) -> i64 |
| 86 | func ia_binding(s: *i64, dev: i64, act: i64) -> i64 |
| 93 | func ia_bind(s: *i64, dev: i64, act: i64, raw: i64) -> i64 |
| 113 | func ia_lookup(s: *i64, dev: i64, raw: i64) -> i64 called by 1: ia_feed |
| 126 | func ia_mixck(ck: i64, v: i64) -> i64 |
| 136 | func ia_feed(s: *i64, dev: i64, raw: i64) -> i64 |
| 148 | func ia_ck(s: *i64) -> i64 { return s[IA_F_CK] } |
| 149 | func ia_nev(s: *i64) -> i64 { return s[IA_F_NEV] } |
| 150 | func ia_trace_len(s: *i64) -> i64 { return s[IA_F_NTR] } |
| 151 | func ia_trace_at(s: *i64, i: i64) -> i64 |
| 159 | func ia_coverage(s: *i64, dev: i64) -> i64 |
| 174 | func ia_reach(s: *i64, act: i64) -> i64 calls 1: ia_bit |
| 186 | func ia_reach_permil(s: *i64) -> i64 calls 1: ia_hasbit |
| 206 | func ia_replay(src: *i64, dst: *i64) -> i64 |