{"_id":"@bun-win32/gameinput","_rev":"4-a7b2263429a1cc61228440f0899204c0","name":"@bun-win32/gameinput","dist-tags":{"latest":"2.0.1"},"versions":{"1.0.0":{"name":"@bun-win32/gameinput","version":"1.0.0","keywords":["bun","ffi","win32","windows","gameinput","bindings","typescript","dll"],"author":"Stev Peifer <stev@bell.net>","license":"MIT","_id":"@bun-win32/gameinput@1.0.0","maintainers":[{"name":"obscuritysrl","email":"stev@bell.net"}],"homepage":"https://github.com/ObscuritySRL/bun-win32#readme","bugs":{"url":"https://github.com/ObscuritySRL/bun-win32/issues"},"dist":{"shasum":"4d75ece23bf85bce489846813018a19dabb07a7e","tarball":"https://registry.npmjs.org/@bun-win32/gameinput/-/gameinput-1.0.0.tgz","fileCount":6,"integrity":"sha512-U03u+vngWDXj+w9ehTQ7Exk17R+oASIY80su5SqP9UFThATKASm55c5cHvTgjY0oxeTXYZLLrD3k4Lx4RS6i0Q==","signatures":[{"sig":"MEQCIBe65Cx1FkXy/Es2sHsus+xBYNkN4VRA4/jhTzLcMOgDAiBKgI8ffWuZeYiRGUuNtZVHCXWPkpOwFiT83AGWzF+STQ==","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":13673},"main":"./index.ts","type":"module","module":"index.ts","shasum":"4d75ece23bf85bce489846813018a19dabb07a7e","engines":{"bun":">=1.1.0"},"exports":{".":"./index.ts"},"private":false,"scripts":{"example:gameinput-diagnostic":"bun ./example/gameinput-diagnostic.ts","example:gameinput-oscilloscope":"bun ./example/gameinput-oscilloscope.ts"},"_npmUser":{"name":"obscuritysrl","email":"stev@bell.net"},"_integrity":"sha512-U03u+vngWDXj+w9ehTQ7Exk17R+oASIY80su5SqP9UFThATKASm55c5cHvTgjY0oxeTXYZLLrD3k4Lx4RS6i0Q==","repository":{"url":"git://github.com/ObscuritySRL/bun-win32.git","type":"git","directory":"packages/gameinput"},"_npmVersion":"10.8.3","description":"Zero-dependency, zero-overhead Win32 GameInput bindings for Bun (FFI) on Windows.","directories":{},"sideEffects":false,"_nodeVersion":"24.3.0","dependencies":{"@bun-win32/core":"1.1.2"},"_hasShrinkwrap":false,"devDependencies":{"@types/bun":"latest"},"peerDependencies":{"typescript":"^5"},"_npmOperationalInternal":{"tmp":"tmp/gameinput_1.0.0_1779222170771_0.759359244236413","host":"s3://npm-registry-packages-npm-production"}},"1.0.1":{"name":"@bun-win32/gameinput","version":"1.0.1","keywords":["bun","ffi","win32","windows","gameinput","bindings","typescript","dll"],"author":"Stev Peifer <stev.p@outlook.com>","license":"MIT","_id":"@bun-win32/gameinput@1.0.1","maintainers":[{"name":"obscuritysrl","email":"stev@bell.net"}],"homepage":"https://github.com/ObscuritySRL/bun-win32#readme","bugs":{"url":"https://github.com/ObscuritySRL/bun-win32/issues"},"dist":{"shasum":"5e69733576841616be7b6865be43695c3a95fb80","tarball":"https://registry.npmjs.org/@bun-win32/gameinput/-/gameinput-1.0.1.tgz","fileCount":6,"integrity":"sha512-t9sznIJcJU9dd5OuV2yz46rBx1BA7Iz+kzfUUEpJlmnFlpef8cYleozn34tUZjfWTs3n1NxQTNRAnyBmbVvEeA==","signatures":[{"sig":"MEQCICKgV+mlvGZiSJbqKOgwfX09NTWBaiNlpVd/2mpnA7uXAiBPrMUJBmUy4C14tA4vjjheQFey7P/MPqZF5lWxl36vKw==","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":13678},"main":"./index.ts","type":"module","module":"index.ts","shasum":"5e69733576841616be7b6865be43695c3a95fb80","engines":{"bun":">=1.1.0"},"exports":{".":"./index.ts"},"private":false,"scripts":{"example:gameinput-diagnostic":"bun ./example/gameinput-diagnostic.ts","example:gameinput-oscilloscope":"bun ./example/gameinput-oscilloscope.ts"},"_npmUser":{"name":"obscuritysrl","email":"stev@bell.net"},"_integrity":"sha512-t9sznIJcJU9dd5OuV2yz46rBx1BA7Iz+kzfUUEpJlmnFlpef8cYleozn34tUZjfWTs3n1NxQTNRAnyBmbVvEeA==","repository":{"url":"git://github.com/ObscuritySRL/bun-win32.git","type":"git","directory":"packages/gameinput"},"_npmVersion":"10.8.3","description":"Zero-dependency, zero-overhead Win32 GameInput bindings for Bun (FFI) on Windows.","directories":{},"sideEffects":false,"_nodeVersion":"24.3.0","dependencies":{"@bun-win32/core":"1.1.4"},"_hasShrinkwrap":false,"devDependencies":{"@types/bun":"latest"},"peerDependencies":{"typescript":"^5"},"_npmOperationalInternal":{"tmp":"tmp/gameinput_1.0.1_1781130836598_0.9108213301771289","host":"s3://npm-registry-packages-npm-production"}},"2.0.0":{"name":"@bun-win32/gameinput","version":"2.0.0","keywords":["bun","ffi","win32","windows","gameinput","bindings","typescript","dll"],"author":"Stev Peifer <stev.p@outlook.com>","license":"MIT","_id":"@bun-win32/gameinput@2.0.0","maintainers":[{"name":"obscuritysrl","email":"stev.p@outlook.com"}],"homepage":"https://github.com/ObscuritySRL/bun-win32#readme","bugs":{"url":"https://github.com/ObscuritySRL/bun-win32/issues"},"dist":{"shasum":"08c471db178c3f7e0b92d3bead538d21d85562b9","tarball":"https://registry.npmjs.org/@bun-win32/gameinput/-/gameinput-2.0.0.tgz","fileCount":6,"integrity":"sha512-Zc7fi1IqsCSnDO5XnJtfLiEdVfboSFqvEhmb45vYxw+oqI1Xtr9cKL4l8jRTTi88/EYQOrN0phDGoG0F4ulKWg==","signatures":[{"sig":"MEQCIGHJEgOCmTZq9sSa7BcoApA/KeQTymH+9wPaGR4EX6lVAiBTzH6Y29Wbf9RtE62/sMKNMJMslv8YZuSPt3R9hE20rw==","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":14934},"main":"./index.ts","type":"module","module":"index.ts","shasum":"08c471db178c3f7e0b92d3bead538d21d85562b9","engines":{"bun":">=1.1.0"},"exports":{".":"./index.ts"},"private":false,"scripts":{"example:gameinput-diagnostic":"bun ./example/gameinput-diagnostic.ts","example:gameinput-oscilloscope":"bun ./example/gameinput-oscilloscope.ts"},"_npmUser":{"name":"obscuritysrl","email":"stev.p@outlook.com"},"_integrity":"sha512-Zc7fi1IqsCSnDO5XnJtfLiEdVfboSFqvEhmb45vYxw+oqI1Xtr9cKL4l8jRTTi88/EYQOrN0phDGoG0F4ulKWg==","repository":{"url":"git://github.com/ObscuritySRL/bun-win32.git","type":"git","directory":"packages/gameinput"},"_npmVersion":"10.8.3","description":"Zero-dependency, zero-overhead Win32 GameInput bindings for Bun (FFI) on Windows.","directories":{},"sideEffects":false,"_nodeVersion":"26.3.0","dependencies":{"@bun-win32/core":"2.0.0"},"_hasShrinkwrap":false,"devDependencies":{"@types/bun":"latest"},"peerDependencies":{"typescript":"^5"},"_npmOperationalInternal":{"tmp":"tmp/gameinput_2.0.0_1782435314275_0.14593799780466998","host":"s3://npm-registry-packages-npm-production"}},"2.0.1":{"author":"Stev Peifer <stev.p@outlook.com>","bugs":{"url":"https://github.com/ObscuritySRL/bun-win32/issues"},"dependencies":{"@bun-win32/core":"2.0.1"},"description":"Zero-dependency, zero-overhead Win32 GameInput bindings for Bun (FFI) on Windows.","devDependencies":{"@types/bun":"latest"},"exports":{".":"./index.ts"},"license":"MIT","module":"index.ts","name":"@bun-win32/gameinput","peerDependencies":{"typescript":"^5"},"private":false,"homepage":"https://github.com/ObscuritySRL/bun-win32#readme","repository":{"type":"git","url":"git://github.com/ObscuritySRL/bun-win32.git","directory":"packages/gameinput"},"type":"module","version":"2.0.1","main":"./index.ts","keywords":["bun","ffi","win32","windows","gameinput","bindings","typescript","dll"],"sideEffects":false,"engines":{"bun":">=1.1.0"},"scripts":{"example:gameinput-diagnostic":"bun ./example/gameinput-diagnostic.ts","example:gameinput-oscilloscope":"bun ./example/gameinput-oscilloscope.ts"},"_id":"@bun-win32/gameinput@2.0.1","_integrity":"sha512-a/wThHiF/poCf9JE/yztMTx8jbDB+vEh1LzDVHcHtUYWpPjr0kN1YrHujbv1sLVqRrRzXxL7rHRWNNNQ4jyiew==","_nodeVersion":"26.3.0","_npmVersion":"10.8.3","shasum":"ea1810eab267117b3e8f05bf94c62c5b30e3c30a","dist":{"integrity":"sha512-a/wThHiF/poCf9JE/yztMTx8jbDB+vEh1LzDVHcHtUYWpPjr0kN1YrHujbv1sLVqRrRzXxL7rHRWNNNQ4jyiew==","shasum":"ea1810eab267117b3e8f05bf94c62c5b30e3c30a","tarball":"https://registry.npmjs.org/@bun-win32/gameinput/-/gameinput-2.0.1.tgz","fileCount":6,"unpackedSize":14934,"signatures":[{"keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U","sig":"MEYCIQCVCoEjI8EboWc9BZT9EfvdY6UUwn3SVCi9u3r5mvfUrAIhANRDQOqNI89qdgfQmkvebu22kwJmRHKgrAwCMCjFfOE1"}]},"_npmUser":{"name":"obscuritysrl","email":"stev.p@outlook.com"},"directories":{},"maintainers":[{"name":"obscuritysrl","email":"stev.p@outlook.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages-npm-production","tmp":"tmp/gameinput_2.0.1_1782437776943_0.3497933112433751"},"_hasShrinkwrap":false}},"time":{"created":"2026-05-19T20:22:50.669Z","modified":"2026-06-26T01:36:17.227Z","1.0.0":"2026-05-19T20:22:50.903Z","1.0.1":"2026-06-10T22:33:56.728Z","2.0.0":"2026-06-26T00:55:14.425Z","2.0.1":"2026-06-26T01:36:17.105Z"},"bugs":{"url":"https://github.com/ObscuritySRL/bun-win32/issues"},"author":"Stev Peifer <stev.p@outlook.com>","license":"MIT","homepage":"https://github.com/ObscuritySRL/bun-win32#readme","keywords":["bun","ffi","win32","windows","gameinput","bindings","typescript","dll"],"repository":{"type":"git","url":"git://github.com/ObscuritySRL/bun-win32.git","directory":"packages/gameinput"},"description":"Zero-dependency, zero-overhead Win32 GameInput bindings for Bun (FFI) on Windows.","maintainers":[{"name":"obscuritysrl","email":"stev.p@outlook.com"}],"readme":"# @bun-win32/gameinput\n\nZero-dependency, zero-overhead Win32 GameInput bindings for [Bun](https://bun.sh) on Windows.\n\n## Overview\n\n`@bun-win32/gameinput` exposes the `gameinput.dll` exports — Microsoft's modern, unified input model — using [Bun](https://bun.sh)'s FFI. It provides a single class, `GameInput`, which lazily binds native symbols on first use. You can optionally preload a subset or all symbols up-front via `Preload()`.\n\nGameInput is the successor to XInput and DirectInput: one API for gamepads, arcade sticks, flight sticks, racing wheels, keyboards, mice, touch, and motion — with a high-resolution microsecond input clock and a unified reading stream. `gameinput.dll` exposes only a tiny flat surface: a single Nano-COM factory, `GameInputCreate`, hands back the per-process `IGameInput` singleton, and everything else (readings, devices, callbacks) is reached by invoking that interface's COM vtable directly.\n\nThe bindings are strongly typed for a smooth DX in TypeScript.\n\n## Features\n\n- [Bun](https://bun.sh)-first ergonomics on Windows 10/11.\n- Direct FFI to `gameinput.dll` (Nano-COM `IGameInput` factory + the standard `Dll*` COM-server entries).\n- All 3 documented `gameinput.dll` exports bound.\n- The full `GameInputKind` and `GameInputGamepadButtons` flag enums, ready for filtering and decoding readings.\n- In-source docs in `structs/GameInput.ts` with links to Microsoft Docs.\n- Lazy binding on first call; optional eager preload (`GameInput.Preload()`).\n- No wrapper overhead; calls map 1:1 to native APIs.\n- Strongly-typed aliases (see `types/GameInput.ts`).\n\n## Requirements\n\n- [Bun](https://bun.sh) runtime\n- Windows 10 or later (GameInput redistributable / GDK runtime)\n\n## Installation\n\n```sh\nbun add @bun-win32/gameinput\n```\n\n## Quick Start\n\n```ts\nimport { FFIType, dlopen, linkSymbols } from 'bun:ffi';\nimport GameInput from '@bun-win32/gameinput';\n\n// GameInputCreate is a Nano-COM factory: it returns the per-process\n// IGameInput singleton through an out-pointer.\nconst ppGameInput = Buffer.alloc(8);\nconst hr = GameInput.GameInputCreate(ppGameInput.ptr!);\nconst gameInput = ppGameInput.readBigUInt64LE(0);\nconsole.log('GameInputCreate → 0x' + (hr >>> 0).toString(16), 'IGameInput @ 0x' + gameInput.toString(16));\n\n// Walk the IGameInput COM vtable to read the microsecond input clock.\n// IUnknown (3 slots) + GetCurrentTimestamp at slot index 3 → offset 0x18.\nconst k = dlopen('kernel32.dll', {\n  GetCurrentProcess: { args: [], returns: FFIType.u64 },\n  ReadProcessMemory: { args: [FFIType.u64, FFIType.u64, FFIType.ptr, FFIType.u64, FFIType.ptr], returns: FFIType.i32 },\n});\nconst proc = k.symbols.GetCurrentProcess();\nconst readPtr = (a: bigint) => {\n  const b = Buffer.alloc(8);\n  k.symbols.ReadProcessMemory(proc, a, b.ptr!, 8n, null!);\n  return b.readBigUInt64LE(0);\n};\nconst vtable = readPtr(gameInput);\nconst getTimestamp = linkSymbols({\n  call: { args: [FFIType.u64], ptr: readPtr(vtable + 0x18n), returns: FFIType.u64 },\n});\nconsole.log('Input clock:', getTimestamp.symbols.call(gameInput), 'µs');\ngetTimestamp.close();\nk.close();\n```\n\n> [!NOTE]\n> AI agents: see `AI.md` for the package binding contract and source-navigation guidance. It explains how to use the package without scanning the entire implementation.\n\n## Examples\n\nRun the included examples:\n\n```sh\nbun run example:gameinput-diagnostic\nbun run example:gameinput-oscilloscope\n```\n\n- **gameinput-diagnostic** — a thorough diagnostic: bootstraps the `IGameInput` singleton, walks the COM vtable to read the microsecond input clock (with a deterministic, CPU-verifiable monotonic-delta check), probes every `GameInputKind` (gamepad / keyboard / mouse / controller / flight stick / arcade stick / racing wheel / sensors) for a current reading, decodes any live gamepad / mouse / keyboard reading struct, and verifies the singleton ref-count drains via `DllCanUnloadNow`.\n- **gameinput-oscilloscope** — a live full-screen terminal scope: scrolls the real per-frame `IGameInput::GetCurrentTimestamp` delta across the screen as a colored waveform (you watch the OS input clock advance in real time), and renders live analog-stick / trigger signal bars plus a lit button grid when a controller is connected (with an idle sweep when none is).\n\n## Notes\n\n- The GameInput surface is COM. `GameInputCreate` returns the `IGameInput` singleton through the out-pointer; read it with `Buffer.readBigUInt64LE`. Everything else — readings, devices, callbacks — is reached by walking the interface's vtable (`ReadProcessMemory` + `linkSymbols`), exactly as the examples show.\n- Vtable layout (8-byte slots, `IUnknown` first): `IGameInput` — `GetCurrentTimestamp` @ 0x18, `GetCurrentReading` @ 0x20. `IGameInputReading` — `GetInputKind` @ 0x18, `GetGamepadState` @ 0xB0, `GetMouseState` @ 0x80.\n- `GameInputKind` values are flags and can be OR-combined to filter the reading stream for multiple device kinds at once.\n- Call `GameInputCreate` once at startup and keep the `IGameInput` reference until shutdown; the first call constructs the per-process singleton and can be briefly slow.\n- `DllCanUnloadNow` returns `S_FALSE` (`0x1`) while the OS input service still references the singleton — this is expected, not an error.\n- Either rely on lazy binding or call `GameInput.Preload()`.\n- Windows only. Bun runtime required.\n- **SAL types & naming:** nullability is in the **type** — `Optional<T>` (formally optional, SAL `_*opt_`) and `Nullable<T>` (plain `[in]`/`[out]` the docs say can be NULL), the null sentinel derived from `T` (`null` for pointers `LP*`/`P*`, `0n` for handles/by-value addresses); direction is in the **parameter name** — `_out` (`_Out_`), `_in_out` (`_Inout_`), `_In_` bare. See `AI.md` and the repo `AGENTS.md`.\n","readmeFilename":"README.md"}