Skip to main content

gasm/
sys.rs

1//! Raw ABI. On wasm32 these are the real imports (see spec/ABI.md). On other
2//! targets they are backed by [`crate::native`], an in-process stub host used
3//! for native parity tests and benchmarks.
4//!
5//! GENERATED from spec/abi.json by scripts/gen-abi.mjs. Do not edit by hand.
6
7#![allow(clippy::missing_safety_doc)]
8
9#[cfg(target_arch = "wasm32")]
10mod imports {
11    #[link(wasm_import_module = "gasm")]
12    unsafe extern "C" {
13        /// Write a line to the runner's log.
14        pub fn log(msg: *const u8, msg_len: u32);
15        /// 1 if the runner provides an import module ("gasm:gfx") or a function in one ("gasm.asset_size64", "gasm:gfx.destroy"), else 0. Calling an import the runner lacks traps, so probe optional features first.
16        pub fn has(name: *const u8, name_len: u32) -> i32;
17        /// Monotonic time in milliseconds (virtual, frame-derived in headless runs).
18        pub fn time_ms() -> f64;
19        /// How many worker threads this run lets the game start at once (wasi-threads: thread-spawn); 0 when it allows none (headless runs, browsers), so a game sizes its thread pool from it instead of failing to spawn.
20        pub fn max_threads() -> u32;
21        /// The player's time zone now: minutes east of UTC, daylight saving included (120 for CEST, -300 for EST). 0 in headless runs. Local time is the WASI realtime clock plus this offset.
22        pub fn utc_offset_minutes() -> i32;
23        /// Rate (Hz) at which the runner calls gasm_frame(). Default 60; 1-1000.
24        pub fn set_frame_rate(hz: f64);
25        /// Present RGBA8 pixels (bytes R,G,B,A), stride bytes per row, w,h <= 4096. Copied before returning; letterboxed by the runner.
26        pub fn video_present(rgba: *const u8, width: u32, height: u32, stride: u32);
27        /// Show video_present frames at display aspect num:den (4:3 for 320x200 DOS games) instead of square pixels; 0:0 resets. Both 1..65535 with 1/8 <= num/den <= 8, else traps. Display and the pointer frame position only (not hashed). Newer than has: probe has("gasm.video_set_aspect") first.
28        pub fn video_set_aspect(num: u32, den: u32);
29        /// Format for audio_push: 8-192 kHz, 1 or 2 channels. Default 44100/2.
30        pub fn audio_config(sample_rate: u32, channels: u32);
31        /// Queue frames x channels interleaved f32 samples in [-1, 1]; the runner resamples.
32        pub fn audio_push(samples: *const f32, frames: u32);
33        /// Bitmask of GASM_BTN_* held on virtual pad player (0..3), stable within a frame.
34        pub fn input_pad(player: u32) -> u32;
35        /// UTF-8 text typed since the previous frame (backspace = \b, enter = \n), stable within a frame. Returns its length (copied only if length <= cap; cap = 0 queries), or -1 if the runner has no keyboard.
36        pub fn text_input(dst: *mut u8, cap: u32) -> i32;
37        /// GASM_INPUT_* flags: KEYS_RAW (the runner stops mapping the keyboard to pads; gamepads still map), POINTER_HIDDEN (hide the system cursor over the game), POINTER_LOCKED (capture the pointer for relative motion; best effort, the browser needs a click).
38        pub fn input_mode(flags: u32);
39        /// Held keys as a bitset indexed by GASM_KEY_* (bit k%8 of byte k/8), stable within a frame. Copies min(len, GASM_KEY_STATE_BYTES) bytes; returns GASM_KEY_STATE_BYTES, or -1 if the runner has no keyboard.
40        pub fn key_state(dst: *mut u8, len: u32) -> i32;
41        /// Key presses and releases since the previous frame, in order: 4 bytes each (u16 GASM_KEY_* code, u8 1 = down / 0 = up, u8 0). Returns the byte length (copied only if <= cap; cap = 0 queries), or -1 if the runner has no keyboard.
42        pub fn key_events(dst: *mut u8, cap: u32) -> i32;
43        /// Mouse/touch state for this frame as GASM_POINTER_BYTES bytes (see ABI.md: position in drawable and frame pixels, relative motion, wheel, buttons held/pressed/released, flags). Copied only if cap is large enough; returns GASM_POINTER_BYTES, or -1 if the runner has no pointer.
44        pub fn pointer(dst: *mut u8, cap: u32) -> i32;
45        /// Raw gamepad/joystick in slot 0-3 (connection order) as GASM_GAMEPAD_BYTES bytes: u32 flags (GASM_GAMEPAD_CONNECTED, GASM_GAMEPAD_STANDARD), u32 button count, u32 axis count, f32 buttons[32] (0-1), f32 axes[16] (-1..1). Standard mapping: W3C button and axis order. Copied only if cap is large enough; returns GASM_GAMEPAD_BYTES, or -1 if slot > 3 or the runner has no gamepad support.
46        pub fn gamepad(slot: u32, dst: *mut u8, cap: u32) -> i32;
47        /// Device name of the gamepad in slot: its length (copied only if <= cap), or -1 if the slot is empty.
48        pub fn gamepad_name(slot: u32, dst: *mut u8, cap: u32) -> i32;
49        /// Size in bytes of asset name, -1 if it does not exist, or -2 if it is 2 GiB or larger (use asset_size64).
50        pub fn asset_size(name: *const u8, name_len: u32) -> i32;
51        /// Size in bytes of asset name (any size), or -1 if it does not exist.
52        pub fn asset_size64(name: *const u8, name_len: u32) -> i64;
53        /// Copy up to cap bytes of asset name into dst. Bytes copied, or -1 if missing.
54        pub fn asset_read(name: *const u8, name_len: u32, dst: *mut u8, cap: u32) -> i32;
55        /// Copy up to len bytes of asset name starting at offset (streaming). Bytes copied (0 at the end), or -1 if missing.
56        pub fn asset_read_at(name: *const u8, name_len: u32, offset: u32, dst: *mut u8, len: u32) -> i32;
57        /// asset_read_at with a 64-bit offset, for assets of 4 GiB and more.
58        pub fn asset_read_at64(name: *const u8, name_len: u32, offset: u64, dst: *mut u8, len: u32) -> i32;
59        /// Number of assets.
60        pub fn asset_count() -> u32;
61        /// Name of asset index (0 .. asset_count-1, sorted by UTF-8 bytes; folder entries as named on disk). Its length (copied only if length <= cap; cap = 0 queries), or -1 if index is out of range.
62        pub fn asset_name(index: u32, dst: *mut u8, cap: u32) -> i32;
63        /// Version of asset name, -1 if it does not exist: 0 for assets given at launch, a new, larger number each time the embedder replaces it while the game runs (between frames). Poll it to notice new data; a read spanning frames should check it did not change.
64        pub fn asset_version(name: *const u8, name_len: u32) -> i32;
65        /// Launch parameter value length, or -1 if unset. Copied only if length <= cap (cap = 0 queries the length).
66        pub fn param(name: *const u8, name_len: u32, dst: *mut u8, cap: u32) -> i32;
67        /// Name the game's window or tab (the runner adds its own suffix). Control characters and bidi overrides are removed and the rest is cut to 256 bytes; empty resets to the default. Newer than has: probe has("gasm.set_title") first.
68        pub fn set_title(title: *const u8, title_len: u32);
69        /// End the frame inside gasm_run: the runner suspends the guest and resumes it at the start of the next frame. Traps outside gasm_run (and on runners without stack switching: probe has("gasm.yield_frame")).
70        pub fn yield_frame();
71    }
72
73    #[link(wasm_import_module = "gasm:gfx")]
74    unsafe extern "C" {
75        /// Current drawable width in pixels.
76        #[link_name = "width"]
77        pub fn gfx_width() -> u32;
78        /// Current drawable height in pixels.
79        #[link_name = "height"]
80        pub fn gfx_height() -> u32;
81        /// Compile WGSL source.
82        #[link_name = "create_shader"]
83        pub fn gfx_create_shader(wgsl: *const u8, wgsl_len: u32) -> u32;
84        /// size: non-zero multiple of 4; usage: GASM_BUF_* (WebGPU GPUBufferUsage bits; COPY_DST always added).
85        #[link_name = "create_buffer"]
86        pub fn gfx_create_buffer(size: u32, usage: u32) -> u32;
87        /// GPURenderPipelineDescriptor as JSON. layout: "auto" (default) or an array of bind group layout handles.
88        #[link_name = "create_pipeline"]
89        pub fn gfx_create_pipeline(json: *const u8, json_len: u32) -> u32;
90        /// {"layout":L,"entries":[...]} or {"pipeline":P,"group":G,"entries":[...]}; entries {"binding":B,"buffer":H,"offset":O,"size":S}, {"binding":B,"texture":T} or {"binding":B,"sampler":S}.
91        #[link_name = "create_bind_group"]
92        pub fn gfx_create_bind_group(json: *const u8, json_len: u32) -> u32;
93        /// GPUBindGroupLayoutDescriptor subset: {"entries":[{"binding":B,"visibility":GASM_STAGE_*,"buffer":{"type":"uniform"|"read-only-storage","hasDynamicOffset":bool,"minBindingSize":N} | "texture":{"sampleType":"float"|"unfilterable-float","viewDimension":"2d"} | "sampler":{"type":"filtering"|"non-filtering"}}]}.
94        #[link_name = "create_bind_group_layout"]
95        pub fn gfx_create_bind_group_layout(json: *const u8, json_len: u32) -> u32;
96        /// 2D texture: {"size":[w,h],"format":"rgba8unorm"|"rgba8unorm-srgb","mipLevelCount":n}, w,h 1-8192. Usage is TEXTURE_BINDING | COPY_DST.
97        #[link_name = "create_texture"]
98        pub fn gfx_create_texture(json: *const u8, json_len: u32) -> u32;
99        /// Upload a tightly packed RGBA8 region (len = width*height*4) of mip level mip at (x, y). Queued like write_buffer.
100        #[link_name = "write_texture"]
101        pub fn gfx_write_texture(texture: u32, mip: u32, x: u32, y: u32, width: u32, height: u32, data: *const u8, len: u32);
102        /// GPUSamplerDescriptor subset: addressModeU/V, magFilter, minFilter, mipmapFilter, lodMinClamp, lodMaxClamp, maxAnisotropy (1-16).
103        #[link_name = "create_sampler"]
104        pub fn gfx_create_sampler(json: *const u8, json_len: u32) -> u32;
105        /// Queue a write, applied before the frame's draws. offset/len: multiples of 4.
106        #[link_name = "write_buffer"]
107        pub fn gfx_write_buffer(buffer: u32, offset: u32, data: *const u8, len: u32);
108        /// Start the frame (clears color and depth). 1 = will be shown, 0 = discarded (the guest may skip draws).
109        #[link_name = "begin_frame"]
110        pub fn gfx_begin_frame(r: f32, g: f32, b: f32, a: f32) -> u32;
111        #[link_name = "set_pipeline"]
112        pub fn gfx_set_pipeline(pipeline: u32);
113        #[link_name = "set_bind_group"]
114        pub fn gfx_set_bind_group(index: u32, bind_group: u32);
115        /// set_bind_group with count dynamic offsets (multiples of 256), one per dynamic-offset entry of the layout, in binding order.
116        #[link_name = "set_bind_group_offsets"]
117        pub fn gfx_set_bind_group_offsets(index: u32, bind_group: u32, offsets: *const u32, count: u32);
118        /// Viewport in drawable pixels (clamped to the drawable), depth range 0-1. Reset to the whole drawable by begin_frame.
119        #[link_name = "set_viewport"]
120        pub fn gfx_set_viewport(x: f32, y: f32, width: f32, height: f32, min_depth: f32, max_depth: f32);
121        /// Scissor rectangle in drawable pixels (clamped to the drawable). Reset to the whole drawable by begin_frame.
122        #[link_name = "set_scissor_rect"]
123        pub fn gfx_set_scissor_rect(x: u32, y: u32, width: u32, height: u32);
124        /// slot 0-7; buffer with GASM_BUF_VERTEX; offset a multiple of 4, at most the buffer size.
125        #[link_name = "set_vertex_buffer"]
126        pub fn gfx_set_vertex_buffer(slot: u32, buffer: u32, offset: u32);
127        /// buffer with GASM_BUF_INDEX; format GASM_INDEX_U16 or GASM_INDEX_U32 (anything else traps); offset a multiple of the index size, at most the buffer size.
128        #[link_name = "set_index_buffer"]
129        pub fn gfx_set_index_buffer(buffer: u32, format: u32, offset: u32);
130        /// Needs a pipeline, and a vertex buffer in every slot the pipeline reads, large enough for the vertices and instances drawn (else traps).
131        #[link_name = "draw"]
132        pub fn gfx_draw(vertex_count: u32, instance_count: u32, first_vertex: u32, first_instance: u32);
133        /// Like draw, plus an index buffer holding first_index + index_count indices.
134        #[link_name = "draw_indexed"]
135        pub fn gfx_draw_indexed(index_count: u32, instance_count: u32, first_index: u32, base_vertex: i32, first_instance: u32);
136        /// Submit and present.
137        #[link_name = "end_frame"]
138        pub fn gfx_end_frame();
139        /// Release an object of any kind. The handle becomes invalid (later use, including another destroy, traps) and is never reused; objects created from it stay valid. GPU memory is freed once nothing in a submitted frame uses it.
140        #[link_name = "destroy"]
141        pub fn gfx_destroy(handle: u32);
142    }
143
144    #[link(wasm_import_module = "gasm:gl")]
145    unsafe extern "C" {
146        /// Drawable width in pixels (the default framebuffer follows it).
147        #[link_name = "width"]
148        pub fn gl_width() -> u32;
149        /// Drawable height in pixels.
150        #[link_name = "height"]
151        pub fn gl_height() -> u32;
152        /// 0 during catch-up frames (the runner runs several frames to catch up and shows only the last; the guest may skip drawing); 1 otherwise, headless included.
153        #[link_name = "frame_shown"]
154        pub fn gl_frame_shown() -> u32;
155        /// Show the default framebuffer now; otherwise the runner presents at the end of the frame.
156        #[link_name = "present"]
157        pub fn gl_present();
158        /// The oldest GL error flag (GL rules: a call with an error has no effect), or 0.
159        #[link_name = "get_error"]
160        pub fn gl_get_error() -> u32;
161        /// GL_VENDOR, GL_RENDERER, GL_VERSION, GL_SHADING_LANGUAGE_VERSION or GL_EXTENSIONS (space-separated): its length, copied if it fits; -1 for an invalid name (GL_INVALID_ENUM).
162        #[link_name = "get_string"]
163        pub fn gl_get_string(name: u32, dst: *mut u8, cap: u32) -> i32;
164        /// Turn on a WebGL extension listed in GL_EXTENSIONS (1), or 0 if it isn't there.
165        #[link_name = "enable_extension"]
166        pub fn gl_enable_extension(name: *const u8, name_len: u32) -> u32;
167        /// The parameter's values as i32s: how many it has (copied up to count), or -1 for an invalid pname (GL_INVALID_ENUM).
168        #[link_name = "get_integerv"]
169        pub fn gl_get_integerv(pname: u32, dst: *mut u8, count: u32) -> i32;
170        /// As get_integerv, as f32s.
171        #[link_name = "get_floatv"]
172        pub fn gl_get_floatv(pname: u32, dst: *mut u8, count: u32) -> i32;
173        /// As get_integerv, as i64s.
174        #[link_name = "get_integer64v"]
175        pub fn gl_get_integer64v(pname: u32, dst: *mut u8, count: u32) -> i32;
176        /// Indexed parameters (e.g. GL_UNIFORM_BUFFER_BINDING), as i32s.
177        #[link_name = "get_integeri_v"]
178        pub fn gl_get_integeri_v(target: u32, index: u32, dst: *mut u8, count: u32) -> i32;
179        /// GL_SAMPLES or GL_NUM_SAMPLE_COUNTS of a renderbuffer format.
180        #[link_name = "get_internalformativ"]
181        pub fn gl_get_internalformativ(target: u32, internalformat: u32, pname: u32, dst: *mut u8, count: u32) -> i32;
182        /// Writes 3 i32s: range min, range max, precision.
183        #[link_name = "get_shader_precision_format"]
184        pub fn gl_get_shader_precision_format(shadertype: u32, precisiontype: u32, dst: *mut u8);
185        #[link_name = "active_texture"]
186        pub fn gl_active_texture(texture: u32);
187        #[link_name = "blend_color"]
188        pub fn gl_blend_color(red: f32, green: f32, blue: f32, alpha: f32);
189        #[link_name = "blend_equation"]
190        pub fn gl_blend_equation(mode: u32);
191        #[link_name = "blend_equation_separate"]
192        pub fn gl_blend_equation_separate(mode_rgb: u32, mode_alpha: u32);
193        #[link_name = "blend_func"]
194        pub fn gl_blend_func(sfactor: u32, dfactor: u32);
195        #[link_name = "blend_func_separate"]
196        pub fn gl_blend_func_separate(src_rgb: u32, dst_rgb: u32, src_alpha: u32, dst_alpha: u32);
197        #[link_name = "clear"]
198        pub fn gl_clear(mask: u32);
199        #[link_name = "clear_color"]
200        pub fn gl_clear_color(red: f32, green: f32, blue: f32, alpha: f32);
201        #[link_name = "clear_depthf"]
202        pub fn gl_clear_depthf(depth: f32);
203        #[link_name = "clear_stencil"]
204        pub fn gl_clear_stencil(s: i32);
205        #[link_name = "color_mask"]
206        pub fn gl_color_mask(red: u32, green: u32, blue: u32, alpha: u32);
207        #[link_name = "cull_face"]
208        pub fn gl_cull_face(mode: u32);
209        #[link_name = "depth_func"]
210        pub fn gl_depth_func(func: u32);
211        #[link_name = "depth_mask"]
212        pub fn gl_depth_mask(flag: u32);
213        #[link_name = "depth_rangef"]
214        pub fn gl_depth_rangef(near: f32, far: f32);
215        #[link_name = "disable"]
216        pub fn gl_disable(cap: u32);
217        #[link_name = "enable"]
218        pub fn gl_enable(cap: u32);
219        #[link_name = "is_enabled"]
220        pub fn gl_is_enabled(cap: u32) -> u32;
221        #[link_name = "front_face"]
222        pub fn gl_front_face(mode: u32);
223        #[link_name = "hint"]
224        pub fn gl_hint(target: u32, mode: u32);
225        #[link_name = "line_width"]
226        pub fn gl_line_width(width: f32);
227        #[link_name = "pixel_storei"]
228        pub fn gl_pixel_storei(pname: u32, param: i32);
229        #[link_name = "polygon_offset"]
230        pub fn gl_polygon_offset(factor: f32, units: f32);
231        #[link_name = "sample_coverage"]
232        pub fn gl_sample_coverage(value: f32, invert: u32);
233        #[link_name = "scissor"]
234        pub fn gl_scissor(x: i32, y: i32, width: i32, height: i32);
235        #[link_name = "viewport"]
236        pub fn gl_viewport(x: i32, y: i32, width: i32, height: i32);
237        #[link_name = "stencil_func"]
238        pub fn gl_stencil_func(func: u32, r#ref: i32, mask: u32);
239        #[link_name = "stencil_func_separate"]
240        pub fn gl_stencil_func_separate(face: u32, func: u32, r#ref: i32, mask: u32);
241        #[link_name = "stencil_mask"]
242        pub fn gl_stencil_mask(mask: u32);
243        #[link_name = "stencil_mask_separate"]
244        pub fn gl_stencil_mask_separate(face: u32, mask: u32);
245        #[link_name = "stencil_op"]
246        pub fn gl_stencil_op(fail: u32, zfail: u32, zpass: u32);
247        #[link_name = "stencil_op_separate"]
248        pub fn gl_stencil_op_separate(face: u32, sfail: u32, dpfail: u32, dppass: u32);
249        #[link_name = "finish"]
250        pub fn gl_finish();
251        #[link_name = "flush"]
252        pub fn gl_flush();
253        /// A new buffer name (glGenBuffers).
254        #[link_name = "create_buffer"]
255        pub fn gl_create_buffer() -> u32;
256        #[link_name = "delete_buffer"]
257        pub fn gl_delete_buffer(buffer: u32);
258        #[link_name = "is_buffer"]
259        pub fn gl_is_buffer(buffer: u32) -> u32;
260        #[link_name = "bind_buffer"]
261        pub fn gl_bind_buffer(target: u32, buffer: u32);
262        #[link_name = "bind_buffer_base"]
263        pub fn gl_bind_buffer_base(target: u32, index: u32, buffer: u32);
264        #[link_name = "bind_buffer_range"]
265        pub fn gl_bind_buffer_range(target: u32, index: u32, buffer: u32, offset: u32, size: u32);
266        /// len bytes from data, or zeros if data is 0.
267        #[link_name = "buffer_data"]
268        pub fn gl_buffer_data(target: u32, data: *const u8, len: u32, usage: u32);
269        #[link_name = "buffer_sub_data"]
270        pub fn gl_buffer_sub_data(target: u32, offset: u32, data: *const u8, len: u32);
271        #[link_name = "copy_buffer_sub_data"]
272        pub fn gl_copy_buffer_sub_data(read_target: u32, write_target: u32, read_offset: u32, write_offset: u32, size: u32);
273        /// Read back len bytes (glMapBufferRange for reading).
274        #[link_name = "get_buffer_sub_data"]
275        pub fn gl_get_buffer_sub_data(target: u32, offset: u32, dst: *mut u8, len: u32);
276        #[link_name = "get_buffer_parameteriv"]
277        pub fn gl_get_buffer_parameteriv(target: u32, pname: u32) -> i32;
278        #[link_name = "create_vertex_array"]
279        pub fn gl_create_vertex_array() -> u32;
280        #[link_name = "delete_vertex_array"]
281        pub fn gl_delete_vertex_array(array: u32);
282        #[link_name = "is_vertex_array"]
283        pub fn gl_is_vertex_array(array: u32) -> u32;
284        #[link_name = "bind_vertex_array"]
285        pub fn gl_bind_vertex_array(array: u32);
286        #[link_name = "enable_vertex_attrib_array"]
287        pub fn gl_enable_vertex_attrib_array(index: u32);
288        #[link_name = "disable_vertex_attrib_array"]
289        pub fn gl_disable_vertex_attrib_array(index: u32);
290        /// offset into the bound GL_ARRAY_BUFFER (no client-side arrays).
291        #[link_name = "vertex_attrib_pointer"]
292        pub fn gl_vertex_attrib_pointer(index: u32, size: i32, r#type: u32, normalized: u32, stride: i32, offset: u32);
293        #[link_name = "vertex_attrib_ipointer"]
294        pub fn gl_vertex_attrib_ipointer(index: u32, size: i32, r#type: u32, stride: i32, offset: u32);
295        #[link_name = "vertex_attrib_divisor"]
296        pub fn gl_vertex_attrib_divisor(index: u32, divisor: u32);
297        #[link_name = "vertex_attrib4f"]
298        pub fn gl_vertex_attrib4f(index: u32, x: f32, y: f32, z: f32, w: f32);
299        #[link_name = "vertex_attribi4i"]
300        pub fn gl_vertex_attribi4i(index: u32, x: i32, y: i32, z: i32, w: i32);
301        #[link_name = "vertex_attribi4ui"]
302        pub fn gl_vertex_attribi4ui(index: u32, x: u32, y: u32, z: u32, w: u32);
303        #[link_name = "get_vertex_attribiv"]
304        pub fn gl_get_vertex_attribiv(index: u32, pname: u32) -> i32;
305        /// GL_CURRENT_VERTEX_ATTRIB: 4 f32s.
306        #[link_name = "get_vertex_attribfv"]
307        pub fn gl_get_vertex_attribfv(index: u32, pname: u32, dst: *mut u8, count: u32) -> i32;
308        #[link_name = "get_vertex_attrib_offset"]
309        pub fn gl_get_vertex_attrib_offset(index: u32, pname: u32) -> u32;
310        #[link_name = "draw_arrays"]
311        pub fn gl_draw_arrays(mode: u32, first: i32, count: i32);
312        /// Indices from the bound GL_ELEMENT_ARRAY_BUFFER at offset.
313        #[link_name = "draw_elements"]
314        pub fn gl_draw_elements(mode: u32, count: i32, r#type: u32, offset: u32);
315        #[link_name = "draw_arrays_instanced"]
316        pub fn gl_draw_arrays_instanced(mode: u32, first: i32, count: i32, instances: i32);
317        #[link_name = "draw_elements_instanced"]
318        pub fn gl_draw_elements_instanced(mode: u32, count: i32, r#type: u32, offset: u32, instances: i32);
319        #[link_name = "draw_range_elements"]
320        pub fn gl_draw_range_elements(mode: u32, start: u32, end: u32, count: i32, r#type: u32, offset: u32);
321        /// count GLenums.
322        #[link_name = "draw_buffers"]
323        pub fn gl_draw_buffers(bufs: *const u8, count: u32);
324        /// count i32s (4 for GL_COLOR, 1 for GL_STENCIL).
325        #[link_name = "clear_bufferiv"]
326        pub fn gl_clear_bufferiv(buffer: u32, drawbuffer: i32, value: *const u8, count: u32);
327        #[link_name = "clear_bufferuiv"]
328        pub fn gl_clear_bufferuiv(buffer: u32, drawbuffer: i32, value: *const u8, count: u32);
329        #[link_name = "clear_bufferfv"]
330        pub fn gl_clear_bufferfv(buffer: u32, drawbuffer: i32, value: *const u8, count: u32);
331        #[link_name = "clear_bufferfi"]
332        pub fn gl_clear_bufferfi(buffer: u32, drawbuffer: i32, depth: f32, stencil: i32);
333        #[link_name = "create_texture"]
334        pub fn gl_create_texture() -> u32;
335        #[link_name = "delete_texture"]
336        pub fn gl_delete_texture(texture: u32);
337        #[link_name = "is_texture"]
338        pub fn gl_is_texture(texture: u32) -> u32;
339        #[link_name = "bind_texture"]
340        pub fn gl_bind_texture(target: u32, texture: u32);
341        #[link_name = "tex_parameteri"]
342        pub fn gl_tex_parameteri(target: u32, pname: u32, param: i32);
343        #[link_name = "tex_parameterf"]
344        pub fn gl_tex_parameterf(target: u32, pname: u32, param: f32);
345        #[link_name = "get_tex_parameteriv"]
346        pub fn gl_get_tex_parameteriv(target: u32, pname: u32) -> i32;
347        #[link_name = "get_tex_parameterfv"]
348        pub fn gl_get_tex_parameterfv(target: u32, pname: u32) -> f32;
349        /// pixels 0: no data (or, with a bound GL_PIXEL_UNPACK_BUFFER, len is the offset into it); otherwise len must cover the image.
350        #[link_name = "tex_image_2d"]
351        pub fn gl_tex_image_2d(target: u32, level: i32, internalformat: i32, width: i32, height: i32, border: i32, format: u32, r#type: u32, pixels: *const u8, len: u32);
352        #[link_name = "tex_image_3d"]
353        pub fn gl_tex_image_3d(target: u32, level: i32, internalformat: i32, width: i32, height: i32, depth: i32, border: i32, format: u32, r#type: u32, pixels: *const u8, len: u32);
354        #[link_name = "tex_sub_image_2d"]
355        pub fn gl_tex_sub_image_2d(target: u32, level: i32, x: i32, y: i32, width: i32, height: i32, format: u32, r#type: u32, pixels: *const u8, len: u32);
356        #[link_name = "tex_sub_image_3d"]
357        pub fn gl_tex_sub_image_3d(target: u32, level: i32, x: i32, y: i32, z: i32, width: i32, height: i32, depth: i32, format: u32, r#type: u32, pixels: *const u8, len: u32);
358        #[link_name = "tex_storage_2d"]
359        pub fn gl_tex_storage_2d(target: u32, levels: i32, internalformat: u32, width: i32, height: i32);
360        #[link_name = "tex_storage_3d"]
361        pub fn gl_tex_storage_3d(target: u32, levels: i32, internalformat: u32, width: i32, height: i32, depth: i32);
362        #[link_name = "compressed_tex_image_2d"]
363        pub fn gl_compressed_tex_image_2d(target: u32, level: i32, internalformat: u32, width: i32, height: i32, border: i32, data: *const u8, len: u32);
364        #[link_name = "compressed_tex_image_3d"]
365        pub fn gl_compressed_tex_image_3d(target: u32, level: i32, internalformat: u32, width: i32, height: i32, depth: i32, border: i32, data: *const u8, len: u32);
366        #[link_name = "compressed_tex_sub_image_2d"]
367        pub fn gl_compressed_tex_sub_image_2d(target: u32, level: i32, x: i32, y: i32, width: i32, height: i32, format: u32, data: *const u8, len: u32);
368        #[link_name = "compressed_tex_sub_image_3d"]
369        pub fn gl_compressed_tex_sub_image_3d(target: u32, level: i32, x: i32, y: i32, z: i32, width: i32, height: i32, depth: i32, format: u32, data: *const u8, len: u32);
370        #[link_name = "copy_tex_image_2d"]
371        pub fn gl_copy_tex_image_2d(target: u32, level: i32, internalformat: u32, x: i32, y: i32, width: i32, height: i32, border: i32);
372        #[link_name = "copy_tex_sub_image_2d"]
373        pub fn gl_copy_tex_sub_image_2d(target: u32, level: i32, xoffset: i32, yoffset: i32, x: i32, y: i32, width: i32, height: i32);
374        #[link_name = "copy_tex_sub_image_3d"]
375        pub fn gl_copy_tex_sub_image_3d(target: u32, level: i32, xoffset: i32, yoffset: i32, zoffset: i32, x: i32, y: i32, width: i32, height: i32);
376        /// Runners generate the levels (unlike gasm:gfx).
377        #[link_name = "generate_mipmap"]
378        pub fn gl_generate_mipmap(target: u32);
379        #[link_name = "create_sampler"]
380        pub fn gl_create_sampler() -> u32;
381        #[link_name = "delete_sampler"]
382        pub fn gl_delete_sampler(sampler: u32);
383        #[link_name = "is_sampler"]
384        pub fn gl_is_sampler(sampler: u32) -> u32;
385        #[link_name = "bind_sampler"]
386        pub fn gl_bind_sampler(unit: u32, sampler: u32);
387        #[link_name = "sampler_parameteri"]
388        pub fn gl_sampler_parameteri(sampler: u32, pname: u32, param: i32);
389        #[link_name = "sampler_parameterf"]
390        pub fn gl_sampler_parameterf(sampler: u32, pname: u32, param: f32);
391        #[link_name = "get_sampler_parameteriv"]
392        pub fn gl_get_sampler_parameteriv(sampler: u32, pname: u32) -> i32;
393        #[link_name = "get_sampler_parameterfv"]
394        pub fn gl_get_sampler_parameterfv(sampler: u32, pname: u32) -> f32;
395        #[link_name = "create_framebuffer"]
396        pub fn gl_create_framebuffer() -> u32;
397        #[link_name = "delete_framebuffer"]
398        pub fn gl_delete_framebuffer(framebuffer: u32);
399        #[link_name = "is_framebuffer"]
400        pub fn gl_is_framebuffer(framebuffer: u32) -> u32;
401        /// 0: the default framebuffer (the window).
402        #[link_name = "bind_framebuffer"]
403        pub fn gl_bind_framebuffer(target: u32, framebuffer: u32);
404        #[link_name = "check_framebuffer_status"]
405        pub fn gl_check_framebuffer_status(target: u32) -> u32;
406        #[link_name = "framebuffer_texture_2d"]
407        pub fn gl_framebuffer_texture_2d(target: u32, attachment: u32, textarget: u32, texture: u32, level: i32);
408        #[link_name = "framebuffer_texture_layer"]
409        pub fn gl_framebuffer_texture_layer(target: u32, attachment: u32, texture: u32, level: i32, layer: i32);
410        #[link_name = "framebuffer_renderbuffer"]
411        pub fn gl_framebuffer_renderbuffer(target: u32, attachment: u32, renderbuffertarget: u32, renderbuffer: u32);
412        #[link_name = "get_framebuffer_attachment_parameteriv"]
413        pub fn gl_get_framebuffer_attachment_parameteriv(target: u32, attachment: u32, pname: u32) -> i32;
414        #[link_name = "blit_framebuffer"]
415        pub fn gl_blit_framebuffer(src_x0: i32, src_y0: i32, src_x1: i32, src_y1: i32, dst_x0: i32, dst_y0: i32, dst_x1: i32, dst_y1: i32, mask: u32, filter: u32);
416        #[link_name = "invalidate_framebuffer"]
417        pub fn gl_invalidate_framebuffer(target: u32, attachments: *const u8, count: u32);
418        #[link_name = "invalidate_sub_framebuffer"]
419        pub fn gl_invalidate_sub_framebuffer(target: u32, attachments: *const u8, count: u32, x: i32, y: i32, width: i32, height: i32);
420        #[link_name = "read_buffer"]
421        pub fn gl_read_buffer(src: u32);
422        /// len must cover the rectangle; with a bound GL_PIXEL_PACK_BUFFER, dst is the offset into it.
423        #[link_name = "read_pixels"]
424        pub fn gl_read_pixels(x: i32, y: i32, width: i32, height: i32, format: u32, r#type: u32, dst: *mut u8, len: u32);
425        #[link_name = "create_renderbuffer"]
426        pub fn gl_create_renderbuffer() -> u32;
427        #[link_name = "delete_renderbuffer"]
428        pub fn gl_delete_renderbuffer(renderbuffer: u32);
429        #[link_name = "is_renderbuffer"]
430        pub fn gl_is_renderbuffer(renderbuffer: u32) -> u32;
431        #[link_name = "bind_renderbuffer"]
432        pub fn gl_bind_renderbuffer(target: u32, renderbuffer: u32);
433        #[link_name = "renderbuffer_storage"]
434        pub fn gl_renderbuffer_storage(target: u32, internalformat: u32, width: i32, height: i32);
435        #[link_name = "renderbuffer_storage_multisample"]
436        pub fn gl_renderbuffer_storage_multisample(target: u32, samples: i32, internalformat: u32, width: i32, height: i32);
437        #[link_name = "get_renderbuffer_parameteriv"]
438        pub fn gl_get_renderbuffer_parameteriv(target: u32, pname: u32) -> i32;
439        #[link_name = "create_shader"]
440        pub fn gl_create_shader(r#type: u32) -> u32;
441        #[link_name = "delete_shader"]
442        pub fn gl_delete_shader(shader: u32);
443        #[link_name = "is_shader"]
444        pub fn gl_is_shader(shader: u32) -> u32;
445        /// GLSL ES 3.00 (or 1.00).
446        #[link_name = "shader_source"]
447        pub fn gl_shader_source(shader: u32, source: *const u8, source_len: u32);
448        #[link_name = "compile_shader"]
449        pub fn gl_compile_shader(shader: u32);
450        #[link_name = "get_shaderiv"]
451        pub fn gl_get_shaderiv(shader: u32, pname: u32) -> i32;
452        #[link_name = "get_shader_info_log"]
453        pub fn gl_get_shader_info_log(shader: u32, dst: *mut u8, cap: u32) -> i32;
454        #[link_name = "get_shader_source"]
455        pub fn gl_get_shader_source(shader: u32, dst: *mut u8, cap: u32) -> i32;
456        #[link_name = "create_program"]
457        pub fn gl_create_program() -> u32;
458        #[link_name = "delete_program"]
459        pub fn gl_delete_program(program: u32);
460        #[link_name = "is_program"]
461        pub fn gl_is_program(program: u32) -> u32;
462        #[link_name = "attach_shader"]
463        pub fn gl_attach_shader(program: u32, shader: u32);
464        #[link_name = "detach_shader"]
465        pub fn gl_detach_shader(program: u32, shader: u32);
466        #[link_name = "link_program"]
467        pub fn gl_link_program(program: u32);
468        #[link_name = "use_program"]
469        pub fn gl_use_program(program: u32);
470        #[link_name = "validate_program"]
471        pub fn gl_validate_program(program: u32);
472        #[link_name = "get_programiv"]
473        pub fn gl_get_programiv(program: u32, pname: u32) -> i32;
474        #[link_name = "get_program_info_log"]
475        pub fn gl_get_program_info_log(program: u32, dst: *mut u8, cap: u32) -> i32;
476        /// Shader names (u32), copied up to count; returns how many.
477        #[link_name = "get_attached_shaders"]
478        pub fn gl_get_attached_shaders(program: u32, dst: *mut u8, count: u32) -> i32;
479        #[link_name = "bind_attrib_location"]
480        pub fn gl_bind_attrib_location(program: u32, index: u32, name: *const u8, name_len: u32);
481        #[link_name = "get_attrib_location"]
482        pub fn gl_get_attrib_location(program: u32, name: *const u8, name_len: u32) -> i32;
483        #[link_name = "get_frag_data_location"]
484        pub fn gl_get_frag_data_location(program: u32, name: *const u8, name_len: u32) -> i32;
485        /// info: 2 i32s (size, type). Returns the name's length (copied if it fits), or -1.
486        #[link_name = "get_active_attrib"]
487        pub fn gl_get_active_attrib(program: u32, index: u32, name: *mut u8, cap: u32, info: *mut u8) -> i32;
488        #[link_name = "get_active_uniform"]
489        pub fn gl_get_active_uniform(program: u32, index: u32, name: *mut u8, cap: u32, info: *mut u8) -> i32;
490        /// -1 if the program has no such uniform.
491        #[link_name = "get_uniform_location"]
492        pub fn gl_get_uniform_location(program: u32, name: *const u8, name_len: u32) -> i32;
493        /// glGetUniformIndices for one name (GL_INVALID_INDEX if none).
494        #[link_name = "get_uniform_index"]
495        pub fn gl_get_uniform_index(program: u32, name: *const u8, name_len: u32) -> u32;
496        /// count u32 indices in, count i32s out.
497        #[link_name = "get_active_uniformsiv"]
498        pub fn gl_get_active_uniformsiv(program: u32, indices: *const u8, count: u32, pname: u32, dst: *mut u8);
499        #[link_name = "get_uniform_block_index"]
500        pub fn gl_get_uniform_block_index(program: u32, name: *const u8, name_len: u32) -> u32;
501        #[link_name = "get_active_uniform_block_name"]
502        pub fn gl_get_active_uniform_block_name(program: u32, index: u32, dst: *mut u8, cap: u32) -> i32;
503        #[link_name = "get_active_uniform_blockiv"]
504        pub fn gl_get_active_uniform_blockiv(program: u32, index: u32, pname: u32, dst: *mut u8, count: u32) -> i32;
505        #[link_name = "uniform_block_binding"]
506        pub fn gl_uniform_block_binding(program: u32, index: u32, binding: u32);
507        #[link_name = "get_uniformfv"]
508        pub fn gl_get_uniformfv(program: u32, location: i32, dst: *mut u8, count: u32) -> i32;
509        #[link_name = "get_uniformiv"]
510        pub fn gl_get_uniformiv(program: u32, location: i32, dst: *mut u8, count: u32) -> i32;
511        #[link_name = "get_uniformuiv"]
512        pub fn gl_get_uniformuiv(program: u32, location: i32, dst: *mut u8, count: u32) -> i32;
513        /// count names, each NUL-terminated, in len bytes.
514        #[link_name = "transform_feedback_varyings"]
515        pub fn gl_transform_feedback_varyings(program: u32, names: *const u8, len: u32, count: u32, buffer_mode: u32);
516        #[link_name = "get_transform_feedback_varying"]
517        pub fn gl_get_transform_feedback_varying(program: u32, index: u32, name: *mut u8, cap: u32, info: *mut u8) -> i32;
518        #[link_name = "uniform1f"]
519        pub fn gl_uniform1f(location: i32, x: f32);
520        #[link_name = "uniform2f"]
521        pub fn gl_uniform2f(location: i32, x: f32, y: f32);
522        #[link_name = "uniform3f"]
523        pub fn gl_uniform3f(location: i32, x: f32, y: f32, z: f32);
524        #[link_name = "uniform4f"]
525        pub fn gl_uniform4f(location: i32, x: f32, y: f32, z: f32, w: f32);
526        #[link_name = "uniform1i"]
527        pub fn gl_uniform1i(location: i32, x: i32);
528        #[link_name = "uniform2i"]
529        pub fn gl_uniform2i(location: i32, x: i32, y: i32);
530        #[link_name = "uniform3i"]
531        pub fn gl_uniform3i(location: i32, x: i32, y: i32, z: i32);
532        #[link_name = "uniform4i"]
533        pub fn gl_uniform4i(location: i32, x: i32, y: i32, z: i32, w: i32);
534        #[link_name = "uniform1ui"]
535        pub fn gl_uniform1ui(location: i32, x: u32);
536        #[link_name = "uniform2ui"]
537        pub fn gl_uniform2ui(location: i32, x: u32, y: u32);
538        #[link_name = "uniform3ui"]
539        pub fn gl_uniform3ui(location: i32, x: u32, y: u32, z: u32);
540        #[link_name = "uniform4ui"]
541        pub fn gl_uniform4ui(location: i32, x: u32, y: u32, z: u32, w: u32);
542        /// count vectors (GL semantics).
543        #[link_name = "uniform1fv"]
544        pub fn gl_uniform1fv(location: i32, count: i32, value: *const u8);
545        #[link_name = "uniform2fv"]
546        pub fn gl_uniform2fv(location: i32, count: i32, value: *const u8);
547        #[link_name = "uniform3fv"]
548        pub fn gl_uniform3fv(location: i32, count: i32, value: *const u8);
549        #[link_name = "uniform4fv"]
550        pub fn gl_uniform4fv(location: i32, count: i32, value: *const u8);
551        #[link_name = "uniform1iv"]
552        pub fn gl_uniform1iv(location: i32, count: i32, value: *const u8);
553        #[link_name = "uniform2iv"]
554        pub fn gl_uniform2iv(location: i32, count: i32, value: *const u8);
555        #[link_name = "uniform3iv"]
556        pub fn gl_uniform3iv(location: i32, count: i32, value: *const u8);
557        #[link_name = "uniform4iv"]
558        pub fn gl_uniform4iv(location: i32, count: i32, value: *const u8);
559        #[link_name = "uniform1uiv"]
560        pub fn gl_uniform1uiv(location: i32, count: i32, value: *const u8);
561        #[link_name = "uniform2uiv"]
562        pub fn gl_uniform2uiv(location: i32, count: i32, value: *const u8);
563        #[link_name = "uniform3uiv"]
564        pub fn gl_uniform3uiv(location: i32, count: i32, value: *const u8);
565        #[link_name = "uniform4uiv"]
566        pub fn gl_uniform4uiv(location: i32, count: i32, value: *const u8);
567        #[link_name = "uniform_matrix2fv"]
568        pub fn gl_uniform_matrix2fv(location: i32, count: i32, transpose: u32, value: *const u8);
569        #[link_name = "uniform_matrix3fv"]
570        pub fn gl_uniform_matrix3fv(location: i32, count: i32, transpose: u32, value: *const u8);
571        #[link_name = "uniform_matrix4fv"]
572        pub fn gl_uniform_matrix4fv(location: i32, count: i32, transpose: u32, value: *const u8);
573        #[link_name = "uniform_matrix2x3fv"]
574        pub fn gl_uniform_matrix2x3fv(location: i32, count: i32, transpose: u32, value: *const u8);
575        #[link_name = "uniform_matrix3x2fv"]
576        pub fn gl_uniform_matrix3x2fv(location: i32, count: i32, transpose: u32, value: *const u8);
577        #[link_name = "uniform_matrix2x4fv"]
578        pub fn gl_uniform_matrix2x4fv(location: i32, count: i32, transpose: u32, value: *const u8);
579        #[link_name = "uniform_matrix4x2fv"]
580        pub fn gl_uniform_matrix4x2fv(location: i32, count: i32, transpose: u32, value: *const u8);
581        #[link_name = "uniform_matrix3x4fv"]
582        pub fn gl_uniform_matrix3x4fv(location: i32, count: i32, transpose: u32, value: *const u8);
583        #[link_name = "uniform_matrix4x3fv"]
584        pub fn gl_uniform_matrix4x3fv(location: i32, count: i32, transpose: u32, value: *const u8);
585        #[link_name = "create_query"]
586        pub fn gl_create_query() -> u32;
587        #[link_name = "delete_query"]
588        pub fn gl_delete_query(query: u32);
589        #[link_name = "is_query"]
590        pub fn gl_is_query(query: u32) -> u32;
591        #[link_name = "begin_query"]
592        pub fn gl_begin_query(target: u32, query: u32);
593        #[link_name = "end_query"]
594        pub fn gl_end_query(target: u32);
595        /// GL_CURRENT_QUERY: the active query's name.
596        #[link_name = "get_queryiv"]
597        pub fn gl_get_queryiv(target: u32, pname: u32) -> u32;
598        /// Results are available from the next frame on, on every runner.
599        #[link_name = "get_query_objectuiv"]
600        pub fn gl_get_query_objectuiv(query: u32, pname: u32) -> u32;
601        /// A sync name (not a pointer).
602        #[link_name = "fence_sync"]
603        pub fn gl_fence_sync(condition: u32, flags: u32) -> u32;
604        #[link_name = "is_sync"]
605        pub fn gl_is_sync(sync: u32) -> u32;
606        #[link_name = "delete_sync"]
607        pub fn gl_delete_sync(sync: u32);
608        /// Signaled from the next frame on; a timeout above 0 that isn't met gives GL_TIMEOUT_EXPIRED.
609        #[link_name = "client_wait_sync"]
610        pub fn gl_client_wait_sync(sync: u32, flags: u32, timeout: u64) -> u32;
611        #[link_name = "wait_sync"]
612        pub fn gl_wait_sync(sync: u32, flags: u32, timeout: u64);
613        #[link_name = "get_synciv"]
614        pub fn gl_get_synciv(sync: u32, pname: u32) -> i32;
615        #[link_name = "create_transform_feedback"]
616        pub fn gl_create_transform_feedback() -> u32;
617        #[link_name = "delete_transform_feedback"]
618        pub fn gl_delete_transform_feedback(tf: u32);
619        #[link_name = "is_transform_feedback"]
620        pub fn gl_is_transform_feedback(tf: u32) -> u32;
621        #[link_name = "bind_transform_feedback"]
622        pub fn gl_bind_transform_feedback(target: u32, tf: u32);
623        #[link_name = "begin_transform_feedback"]
624        pub fn gl_begin_transform_feedback(primitive_mode: u32);
625        #[link_name = "end_transform_feedback"]
626        pub fn gl_end_transform_feedback();
627        #[link_name = "pause_transform_feedback"]
628        pub fn gl_pause_transform_feedback();
629        #[link_name = "resume_transform_feedback"]
630        pub fn gl_resume_transform_feedback();
631    }
632
633    #[link(wasm_import_module = "gasm:net")]
634    unsafe extern "C" {
635        /// Open a ws:// or wss:// URL. Handle > 0, or -1 if denied/invalid.
636        #[link_name = "open"]
637        pub fn net_open(url: *const u8, url_len: u32) -> i32;
638        /// GASM_NET_CONNECTING / OPEN / CLOSED / ERROR.
639        #[link_name = "state"]
640        pub fn net_state(conn: i32) -> u32;
641        /// Send one message (len > 0). 0, or -1 if not open.
642        #[link_name = "send"]
643        pub fn net_send(conn: i32, data: *const u8, len: u32) -> i32;
644        /// Next message's length (copied only if <= cap, else it stays queued), 0 if none, -1 if closed and drained.
645        #[link_name = "recv"]
646        pub fn net_recv(conn: i32, dst: *mut u8, cap: u32) -> i32;
647        /// Close (flushing queued messages); closing again does nothing.
648        #[link_name = "close"]
649        pub fn net_close(conn: i32);
650    }
651
652    #[link(wasm_import_module = "gasm:fetch")]
653    unsafe extern "C" {
654        /// Start a request described by JSON {"method":"GET","url":"https://...","headers":{"name":"value"}}, with body_len bytes of body (0: none). Handle > 0, or -1 if denied, invalid or too many are open (16).
655        #[link_name = "request"]
656        pub fn fetch_request(desc: *const u8, desc_len: u32, body: *const u8, body_len: u32) -> i32;
657        /// GASM_FETCH_PENDING / HEADERS (status and headers are in) / DONE (the whole body arrived) / FAILED.
658        #[link_name = "state"]
659        pub fn fetch_state(req: i32) -> u32;
660        /// HTTP status of the final response (after redirects), 0 before the headers or after a failure.
661        #[link_name = "status"]
662        pub fn fetch_status(req: i32) -> i32;
663        /// Response headers as "name: value\n" lines (names lowercase). Length (copied only if <= cap; cap = 0 queries), -1 before GASM_FETCH_HEADERS.
664        #[link_name = "headers"]
665        pub fn fetch_headers(req: i32, dst: *mut u8, cap: u32) -> i32;
666        /// Copy up to cap bytes of body that have arrived; returns the count, 0 if none are waiting yet, -1 once the body is done and drained or the request failed.
667        #[link_name = "read"]
668        pub fn fetch_read(req: i32, dst: *mut u8, cap: u32) -> i32;
669        /// Cancel if still running and free the handle; closing again does nothing.
670        #[link_name = "close"]
671        pub fn fetch_close(req: i32);
672    }
673
674    #[link(wasm_import_module = "gasm:storage")]
675    unsafe extern "C" {
676        /// Value length, or -1 if missing. Copied only if length <= cap.
677        #[link_name = "get"]
678        pub fn storage_get(key: *const u8, key_len: u32, dst: *mut u8, cap: u32) -> i32;
679        /// 0, or a GASM_STORAGE_ERR_* code: invalid key, value too large, quota exceeded, I/O error.
680        #[link_name = "set"]
681        pub fn storage_set(key: *const u8, key_len: u32, data: *const u8, len: u32) -> i32;
682        /// 0 if deleted, -1 if it did not exist.
683        #[link_name = "delete"]
684        pub fn storage_delete(key: *const u8, key_len: u32) -> i32;
685        /// Number of keys in the namespace.
686        #[link_name = "count"]
687        pub fn storage_count() -> u32;
688        /// Key index (0 .. count-1, sorted): its length (copied only if <= cap; cap = 0 queries), or -1 if out of range.
689        #[link_name = "key"]
690        pub fn storage_key(index: u32, dst: *mut u8, cap: u32) -> i32;
691    }
692
693    #[link(wasm_import_module = "gasm:clipboard")]
694    unsafe extern "C" {
695        /// 0: the runner puts it on the clipboard after this frame; -1: refused (over 1 MiB, or no clipboard). Invalid UTF-8 traps.
696        #[link_name = "set_text"]
697        pub fn clipboard_set_text(text: *const u8, text_len: u32) -> i32;
698        /// The pasted text's length in bytes (copied only if <= cap; cap = 0 queries), or -1 outside a paste frame or with nothing to paste.
699        #[link_name = "get_text"]
700        pub fn clipboard_get_text(dst: *mut u8, cap: u32) -> i32;
701    }
702
703    #[link(wasm_import_module = "gasm:files")]
704    unsafe extern "C" {
705        /// A handle > 0 (the runner saves it after this frame), or -1: refused (saving is off, name empty or over 255 bytes, mime not type/subtype, over 256 MiB, or 16 saves still pending). name is a file name; the runner keeps only its last path component and makes it safe and unique. Invalid UTF-8 traps.
706        #[link_name = "save"]
707        pub fn files_save(name: *const u8, name_len: u32, mime: *const u8, mime_len: u32, data: *const u8, len: u32) -> i32;
708        /// GASM_FILES_PENDING (0), GASM_FILES_SAVED (1) or GASM_FILES_FAILED (2: cancelled or not written). A handle save never returned traps.
709        #[link_name = "state"]
710        pub fn files_state(handle: i32) -> i32;
711    }
712
713    #[link(wasm_import_module = "wasi_snapshot_preview1")]
714    unsafe extern "C" {
715        /// End the game; 0 is a normal exit.
716        pub fn proc_exit(code: i32) -> !;
717    }
718}
719
720#[cfg(target_arch = "wasm32")]
721pub use imports::*;
722
723#[cfg(not(target_arch = "wasm32"))]
724pub use crate::native::abi::*;
725
726/// Every import module and `module.function` of this ABI version (what `gasm::has` can report).
727pub const IMPORTS: [&str; 306] = [
728    "gasm", "gasm.log", "gasm.has", "gasm.time_ms",
729    "gasm.max_threads", "gasm.utc_offset_minutes", "gasm.set_frame_rate", "gasm.video_present",
730    "gasm.video_set_aspect", "gasm.audio_config", "gasm.audio_push", "gasm.input_pad",
731    "gasm.text_input", "gasm.input_mode", "gasm.key_state", "gasm.key_events",
732    "gasm.pointer", "gasm.gamepad", "gasm.gamepad_name", "gasm.asset_size",
733    "gasm.asset_size64", "gasm.asset_read", "gasm.asset_read_at", "gasm.asset_read_at64",
734    "gasm.asset_count", "gasm.asset_name", "gasm.asset_version", "gasm.param",
735    "gasm.set_title", "gasm.yield_frame", "gasm:gfx", "gasm:gfx.width",
736    "gasm:gfx.height", "gasm:gfx.create_shader", "gasm:gfx.create_buffer", "gasm:gfx.create_pipeline",
737    "gasm:gfx.create_bind_group", "gasm:gfx.create_bind_group_layout", "gasm:gfx.create_texture", "gasm:gfx.write_texture",
738    "gasm:gfx.create_sampler", "gasm:gfx.write_buffer", "gasm:gfx.begin_frame", "gasm:gfx.set_pipeline",
739    "gasm:gfx.set_bind_group", "gasm:gfx.set_bind_group_offsets", "gasm:gfx.set_viewport", "gasm:gfx.set_scissor_rect",
740    "gasm:gfx.set_vertex_buffer", "gasm:gfx.set_index_buffer", "gasm:gfx.draw", "gasm:gfx.draw_indexed",
741    "gasm:gfx.end_frame", "gasm:gfx.destroy", "gasm:gl", "gasm:gl.width",
742    "gasm:gl.height", "gasm:gl.frame_shown", "gasm:gl.present", "gasm:gl.get_error",
743    "gasm:gl.get_string", "gasm:gl.enable_extension", "gasm:gl.get_integerv", "gasm:gl.get_floatv",
744    "gasm:gl.get_integer64v", "gasm:gl.get_integeri_v", "gasm:gl.get_internalformativ", "gasm:gl.get_shader_precision_format",
745    "gasm:gl.active_texture", "gasm:gl.blend_color", "gasm:gl.blend_equation", "gasm:gl.blend_equation_separate",
746    "gasm:gl.blend_func", "gasm:gl.blend_func_separate", "gasm:gl.clear", "gasm:gl.clear_color",
747    "gasm:gl.clear_depthf", "gasm:gl.clear_stencil", "gasm:gl.color_mask", "gasm:gl.cull_face",
748    "gasm:gl.depth_func", "gasm:gl.depth_mask", "gasm:gl.depth_rangef", "gasm:gl.disable",
749    "gasm:gl.enable", "gasm:gl.is_enabled", "gasm:gl.front_face", "gasm:gl.hint",
750    "gasm:gl.line_width", "gasm:gl.pixel_storei", "gasm:gl.polygon_offset", "gasm:gl.sample_coverage",
751    "gasm:gl.scissor", "gasm:gl.viewport", "gasm:gl.stencil_func", "gasm:gl.stencil_func_separate",
752    "gasm:gl.stencil_mask", "gasm:gl.stencil_mask_separate", "gasm:gl.stencil_op", "gasm:gl.stencil_op_separate",
753    "gasm:gl.finish", "gasm:gl.flush", "gasm:gl.create_buffer", "gasm:gl.delete_buffer",
754    "gasm:gl.is_buffer", "gasm:gl.bind_buffer", "gasm:gl.bind_buffer_base", "gasm:gl.bind_buffer_range",
755    "gasm:gl.buffer_data", "gasm:gl.buffer_sub_data", "gasm:gl.copy_buffer_sub_data", "gasm:gl.get_buffer_sub_data",
756    "gasm:gl.get_buffer_parameteriv", "gasm:gl.create_vertex_array", "gasm:gl.delete_vertex_array", "gasm:gl.is_vertex_array",
757    "gasm:gl.bind_vertex_array", "gasm:gl.enable_vertex_attrib_array", "gasm:gl.disable_vertex_attrib_array", "gasm:gl.vertex_attrib_pointer",
758    "gasm:gl.vertex_attrib_ipointer", "gasm:gl.vertex_attrib_divisor", "gasm:gl.vertex_attrib4f", "gasm:gl.vertex_attribi4i",
759    "gasm:gl.vertex_attribi4ui", "gasm:gl.get_vertex_attribiv", "gasm:gl.get_vertex_attribfv", "gasm:gl.get_vertex_attrib_offset",
760    "gasm:gl.draw_arrays", "gasm:gl.draw_elements", "gasm:gl.draw_arrays_instanced", "gasm:gl.draw_elements_instanced",
761    "gasm:gl.draw_range_elements", "gasm:gl.draw_buffers", "gasm:gl.clear_bufferiv", "gasm:gl.clear_bufferuiv",
762    "gasm:gl.clear_bufferfv", "gasm:gl.clear_bufferfi", "gasm:gl.create_texture", "gasm:gl.delete_texture",
763    "gasm:gl.is_texture", "gasm:gl.bind_texture", "gasm:gl.tex_parameteri", "gasm:gl.tex_parameterf",
764    "gasm:gl.get_tex_parameteriv", "gasm:gl.get_tex_parameterfv", "gasm:gl.tex_image_2d", "gasm:gl.tex_image_3d",
765    "gasm:gl.tex_sub_image_2d", "gasm:gl.tex_sub_image_3d", "gasm:gl.tex_storage_2d", "gasm:gl.tex_storage_3d",
766    "gasm:gl.compressed_tex_image_2d", "gasm:gl.compressed_tex_image_3d", "gasm:gl.compressed_tex_sub_image_2d", "gasm:gl.compressed_tex_sub_image_3d",
767    "gasm:gl.copy_tex_image_2d", "gasm:gl.copy_tex_sub_image_2d", "gasm:gl.copy_tex_sub_image_3d", "gasm:gl.generate_mipmap",
768    "gasm:gl.create_sampler", "gasm:gl.delete_sampler", "gasm:gl.is_sampler", "gasm:gl.bind_sampler",
769    "gasm:gl.sampler_parameteri", "gasm:gl.sampler_parameterf", "gasm:gl.get_sampler_parameteriv", "gasm:gl.get_sampler_parameterfv",
770    "gasm:gl.create_framebuffer", "gasm:gl.delete_framebuffer", "gasm:gl.is_framebuffer", "gasm:gl.bind_framebuffer",
771    "gasm:gl.check_framebuffer_status", "gasm:gl.framebuffer_texture_2d", "gasm:gl.framebuffer_texture_layer", "gasm:gl.framebuffer_renderbuffer",
772    "gasm:gl.get_framebuffer_attachment_parameteriv", "gasm:gl.blit_framebuffer", "gasm:gl.invalidate_framebuffer", "gasm:gl.invalidate_sub_framebuffer",
773    "gasm:gl.read_buffer", "gasm:gl.read_pixels", "gasm:gl.create_renderbuffer", "gasm:gl.delete_renderbuffer",
774    "gasm:gl.is_renderbuffer", "gasm:gl.bind_renderbuffer", "gasm:gl.renderbuffer_storage", "gasm:gl.renderbuffer_storage_multisample",
775    "gasm:gl.get_renderbuffer_parameteriv", "gasm:gl.create_shader", "gasm:gl.delete_shader", "gasm:gl.is_shader",
776    "gasm:gl.shader_source", "gasm:gl.compile_shader", "gasm:gl.get_shaderiv", "gasm:gl.get_shader_info_log",
777    "gasm:gl.get_shader_source", "gasm:gl.create_program", "gasm:gl.delete_program", "gasm:gl.is_program",
778    "gasm:gl.attach_shader", "gasm:gl.detach_shader", "gasm:gl.link_program", "gasm:gl.use_program",
779    "gasm:gl.validate_program", "gasm:gl.get_programiv", "gasm:gl.get_program_info_log", "gasm:gl.get_attached_shaders",
780    "gasm:gl.bind_attrib_location", "gasm:gl.get_attrib_location", "gasm:gl.get_frag_data_location", "gasm:gl.get_active_attrib",
781    "gasm:gl.get_active_uniform", "gasm:gl.get_uniform_location", "gasm:gl.get_uniform_index", "gasm:gl.get_active_uniformsiv",
782    "gasm:gl.get_uniform_block_index", "gasm:gl.get_active_uniform_block_name", "gasm:gl.get_active_uniform_blockiv", "gasm:gl.uniform_block_binding",
783    "gasm:gl.get_uniformfv", "gasm:gl.get_uniformiv", "gasm:gl.get_uniformuiv", "gasm:gl.transform_feedback_varyings",
784    "gasm:gl.get_transform_feedback_varying", "gasm:gl.uniform1f", "gasm:gl.uniform2f", "gasm:gl.uniform3f",
785    "gasm:gl.uniform4f", "gasm:gl.uniform1i", "gasm:gl.uniform2i", "gasm:gl.uniform3i",
786    "gasm:gl.uniform4i", "gasm:gl.uniform1ui", "gasm:gl.uniform2ui", "gasm:gl.uniform3ui",
787    "gasm:gl.uniform4ui", "gasm:gl.uniform1fv", "gasm:gl.uniform2fv", "gasm:gl.uniform3fv",
788    "gasm:gl.uniform4fv", "gasm:gl.uniform1iv", "gasm:gl.uniform2iv", "gasm:gl.uniform3iv",
789    "gasm:gl.uniform4iv", "gasm:gl.uniform1uiv", "gasm:gl.uniform2uiv", "gasm:gl.uniform3uiv",
790    "gasm:gl.uniform4uiv", "gasm:gl.uniform_matrix2fv", "gasm:gl.uniform_matrix3fv", "gasm:gl.uniform_matrix4fv",
791    "gasm:gl.uniform_matrix2x3fv", "gasm:gl.uniform_matrix3x2fv", "gasm:gl.uniform_matrix2x4fv", "gasm:gl.uniform_matrix4x2fv",
792    "gasm:gl.uniform_matrix3x4fv", "gasm:gl.uniform_matrix4x3fv", "gasm:gl.create_query", "gasm:gl.delete_query",
793    "gasm:gl.is_query", "gasm:gl.begin_query", "gasm:gl.end_query", "gasm:gl.get_queryiv",
794    "gasm:gl.get_query_objectuiv", "gasm:gl.fence_sync", "gasm:gl.is_sync", "gasm:gl.delete_sync",
795    "gasm:gl.client_wait_sync", "gasm:gl.wait_sync", "gasm:gl.get_synciv", "gasm:gl.create_transform_feedback",
796    "gasm:gl.delete_transform_feedback", "gasm:gl.is_transform_feedback", "gasm:gl.bind_transform_feedback", "gasm:gl.begin_transform_feedback",
797    "gasm:gl.end_transform_feedback", "gasm:gl.pause_transform_feedback", "gasm:gl.resume_transform_feedback", "gasm:net",
798    "gasm:net.open", "gasm:net.state", "gasm:net.send", "gasm:net.recv",
799    "gasm:net.close", "gasm:fetch", "gasm:fetch.request", "gasm:fetch.state",
800    "gasm:fetch.status", "gasm:fetch.headers", "gasm:fetch.read", "gasm:fetch.close",
801    "gasm:storage", "gasm:storage.get", "gasm:storage.set", "gasm:storage.delete",
802    "gasm:storage.count", "gasm:storage.key", "gasm:clipboard", "gasm:clipboard.set_text",
803    "gasm:clipboard.get_text", "gasm:files", "gasm:files.save", "gasm:files.state",
804    "wasi_snapshot_preview1", "wasi_snapshot_preview1.proc_exit",
805];
806
807// ---- buttons
808/// Virtual gamepad buttons (bit positions). Face buttons by position: East=A, South=B, North=X, West=Y.
809pub const GASM_BTN_A: u32 = 1 << 0;
810pub const GASM_BTN_B: u32 = 1 << 1;
811pub const GASM_BTN_X: u32 = 1 << 2;
812pub const GASM_BTN_Y: u32 = 1 << 3;
813pub const GASM_BTN_L: u32 = 1 << 4;
814pub const GASM_BTN_R: u32 = 1 << 5;
815pub const GASM_BTN_SELECT: u32 = 1 << 6;
816pub const GASM_BTN_START: u32 = 1 << 7;
817pub const GASM_BTN_UP: u32 = 1 << 8;
818pub const GASM_BTN_DOWN: u32 = 1 << 9;
819pub const GASM_BTN_LEFT: u32 = 1 << 10;
820pub const GASM_BTN_RIGHT: u32 = 1 << 11;
821
822// ---- buffer usage
823pub const GASM_BUF_COPY_DST: u32 = 0x08;
824pub const GASM_BUF_INDEX: u32 = 0x10;
825pub const GASM_BUF_VERTEX: u32 = 0x20;
826pub const GASM_BUF_UNIFORM: u32 = 0x40;
827pub const GASM_BUF_STORAGE: u32 = 0x80;
828
829// ---- shader stages
830/// Bind group layout entry visibility (WebGPU GPUShaderStage bits).
831pub const GASM_STAGE_VERTEX: u32 = 0x1;
832pub const GASM_STAGE_FRAGMENT: u32 = 0x2;
833
834// ---- index formats
835pub const GASM_INDEX_U16: u32 = 0;
836pub const GASM_INDEX_U32: u32 = 1;
837
838// ---- net states
839pub const GASM_NET_CONNECTING: u32 = 0;
840pub const GASM_NET_OPEN: u32 = 1;
841pub const GASM_NET_CLOSED: u32 = 2;
842pub const GASM_NET_ERROR: u32 = 3;
843
844// ---- fetch states
845pub const GASM_FETCH_PENDING: u32 = 0;
846pub const GASM_FETCH_HEADERS: u32 = 1;
847pub const GASM_FETCH_DONE: u32 = 2;
848pub const GASM_FETCH_FAILED: u32 = 3;
849
850// ---- input modes
851/// input_mode flags.
852pub const GASM_INPUT_KEYS_RAW: u32 = 1 << 0;
853pub const GASM_INPUT_POINTER_HIDDEN: u32 = 1 << 1;
854pub const GASM_INPUT_POINTER_LOCKED: u32 = 1 << 2;
855
856// ---- file save states
857/// gasm_files_state results.
858pub const GASM_FILES_PENDING: i32 = 0;
859pub const GASM_FILES_SAVED: i32 = 1;
860pub const GASM_FILES_FAILED: i32 = 2;
861
862// ---- storage errors
863/// gasm_storage_set results.
864pub const GASM_STORAGE_OK: i32 = 0;
865pub const GASM_STORAGE_ERR_KEY: i32 = -1;
866pub const GASM_STORAGE_ERR_SIZE: i32 = -2;
867pub const GASM_STORAGE_ERR_QUOTA: i32 = -3;
868pub const GASM_STORAGE_ERR_IO: i32 = -4;
869
870// ---- pointer
871/// pointer() layout and bits: little-endian fields at the GASM_POINTER_OFF_* byte offsets: f32 x, y (drawable px), fx, fy (frame px), dx, dy (relative motion), wheel_x, wheel_y (lines; y > 0 = down), u32 buttons, pressed, released, flags.
872pub const GASM_POINTER_BYTES: u32 = 48;
873pub const GASM_POINTER_OFF_X: u32 = 0;
874pub const GASM_POINTER_OFF_Y: u32 = 4;
875pub const GASM_POINTER_OFF_FX: u32 = 8;
876pub const GASM_POINTER_OFF_FY: u32 = 12;
877pub const GASM_POINTER_OFF_DX: u32 = 16;
878pub const GASM_POINTER_OFF_DY: u32 = 20;
879pub const GASM_POINTER_OFF_WHEEL_X: u32 = 24;
880pub const GASM_POINTER_OFF_WHEEL_Y: u32 = 28;
881pub const GASM_POINTER_OFF_BUTTONS: u32 = 32;
882pub const GASM_POINTER_OFF_PRESSED: u32 = 36;
883pub const GASM_POINTER_OFF_RELEASED: u32 = 40;
884pub const GASM_POINTER_OFF_FLAGS: u32 = 44;
885pub const GASM_MOUSE_LEFT: u32 = 1 << 0;
886pub const GASM_MOUSE_RIGHT: u32 = 1 << 1;
887pub const GASM_MOUSE_MIDDLE: u32 = 1 << 2;
888pub const GASM_MOUSE_BACK: u32 = 1 << 3;
889pub const GASM_MOUSE_FORWARD: u32 = 1 << 4;
890pub const GASM_POINTER_INSIDE: u32 = 1 << 0;
891pub const GASM_POINTER_IS_HIDDEN: u32 = 1 << 1;
892pub const GASM_POINTER_IS_LOCKED: u32 = 1 << 2;
893
894// ---- gamepad
895/// gamepad() layout: little-endian fields at the GASM_GAMEPAD_OFF_* byte offsets: u32 flags, u32 button count, u32 axis count, f32 button values (32), f32 axis values (16). Standard mapping (W3C): buttons 0 south, 1 east, 2 west, 3 north, 4/5 shoulders, 6/7 triggers, 8 select, 9 start, 10/11 stick clicks, 12-15 d-pad up/down/left/right, 16 home; axes 0/1 left stick x/y, 2/3 right stick x/y (y > 0 = down).
896pub const GASM_GAMEPAD_BYTES: u32 = 204;
897pub const GASM_GAMEPAD_BUTTONS: u32 = 32;
898pub const GASM_GAMEPAD_AXES: u32 = 16;
899pub const GASM_GAMEPAD_OFF_FLAGS: u32 = 0;
900pub const GASM_GAMEPAD_OFF_BUTTON_COUNT: u32 = 4;
901pub const GASM_GAMEPAD_OFF_AXIS_COUNT: u32 = 8;
902pub const GASM_GAMEPAD_OFF_BUTTONS: u32 = 12;
903pub const GASM_GAMEPAD_OFF_AXES: u32 = 140;
904pub const GASM_GAMEPAD_CONNECTED: u32 = 1 << 0;
905pub const GASM_GAMEPAD_STANDARD: u32 = 1 << 1;
906
907// ---- keyboard
908/// key_state() size, and the size of one key_events() record.
909pub const GASM_KEY_STATE_BYTES: u32 = 32;
910pub const GASM_KEY_EVENT_BYTES: u32 = 4;
911
912/// Physical keys (W3C KeyboardEvent.code names; layout-independent). The third column is the W3C name.
913pub mod keys {
914    pub const ESCAPE: u32 = 1;
915    pub const F1: u32 = 2;
916    pub const F2: u32 = 3;
917    pub const F3: u32 = 4;
918    pub const F4: u32 = 5;
919    pub const F5: u32 = 6;
920    pub const F6: u32 = 7;
921    pub const F7: u32 = 8;
922    pub const F8: u32 = 9;
923    pub const F9: u32 = 10;
924    pub const F10: u32 = 11;
925    pub const F11: u32 = 12;
926    pub const F12: u32 = 13;
927    pub const BACKQUOTE: u32 = 14;
928    pub const DIGIT0: u32 = 15;
929    pub const DIGIT1: u32 = 16;
930    pub const DIGIT2: u32 = 17;
931    pub const DIGIT3: u32 = 18;
932    pub const DIGIT4: u32 = 19;
933    pub const DIGIT5: u32 = 20;
934    pub const DIGIT6: u32 = 21;
935    pub const DIGIT7: u32 = 22;
936    pub const DIGIT8: u32 = 23;
937    pub const DIGIT9: u32 = 24;
938    pub const MINUS: u32 = 25;
939    pub const EQUAL: u32 = 26;
940    pub const BACKSPACE: u32 = 27;
941    pub const TAB: u32 = 28;
942    pub const KEY_A: u32 = 29;
943    pub const KEY_B: u32 = 30;
944    pub const KEY_C: u32 = 31;
945    pub const KEY_D: u32 = 32;
946    pub const KEY_E: u32 = 33;
947    pub const KEY_F: u32 = 34;
948    pub const KEY_G: u32 = 35;
949    pub const KEY_H: u32 = 36;
950    pub const KEY_I: u32 = 37;
951    pub const KEY_J: u32 = 38;
952    pub const KEY_K: u32 = 39;
953    pub const KEY_L: u32 = 40;
954    pub const KEY_M: u32 = 41;
955    pub const KEY_N: u32 = 42;
956    pub const KEY_O: u32 = 43;
957    pub const KEY_P: u32 = 44;
958    pub const KEY_Q: u32 = 45;
959    pub const KEY_R: u32 = 46;
960    pub const KEY_S: u32 = 47;
961    pub const KEY_T: u32 = 48;
962    pub const KEY_U: u32 = 49;
963    pub const KEY_V: u32 = 50;
964    pub const KEY_W: u32 = 51;
965    pub const KEY_X: u32 = 52;
966    pub const KEY_Y: u32 = 53;
967    pub const KEY_Z: u32 = 54;
968    pub const BRACKET_LEFT: u32 = 55;
969    pub const BRACKET_RIGHT: u32 = 56;
970    pub const BACKSLASH: u32 = 57;
971    pub const CAPS_LOCK: u32 = 58;
972    pub const SEMICOLON: u32 = 59;
973    pub const QUOTE: u32 = 60;
974    pub const ENTER: u32 = 61;
975    pub const SHIFT_LEFT: u32 = 62;
976    pub const INTL_BACKSLASH: u32 = 63;
977    pub const COMMA: u32 = 64;
978    pub const PERIOD: u32 = 65;
979    pub const SLASH: u32 = 66;
980    pub const SHIFT_RIGHT: u32 = 67;
981    pub const CONTROL_LEFT: u32 = 68;
982    pub const META_LEFT: u32 = 69;
983    pub const ALT_LEFT: u32 = 70;
984    pub const SPACE: u32 = 71;
985    pub const ALT_RIGHT: u32 = 72;
986    pub const META_RIGHT: u32 = 73;
987    pub const CONTEXT_MENU: u32 = 74;
988    pub const CONTROL_RIGHT: u32 = 75;
989    pub const PRINT_SCREEN: u32 = 76;
990    pub const SCROLL_LOCK: u32 = 77;
991    pub const PAUSE: u32 = 78;
992    pub const INSERT: u32 = 79;
993    pub const HOME: u32 = 80;
994    pub const PAGE_UP: u32 = 81;
995    pub const DELETE: u32 = 82;
996    pub const END: u32 = 83;
997    pub const PAGE_DOWN: u32 = 84;
998    pub const ARROW_UP: u32 = 85;
999    pub const ARROW_LEFT: u32 = 86;
1000    pub const ARROW_DOWN: u32 = 87;
1001    pub const ARROW_RIGHT: u32 = 88;
1002    pub const NUM_LOCK: u32 = 89;
1003    pub const NUMPAD_DIVIDE: u32 = 90;
1004    pub const NUMPAD_MULTIPLY: u32 = 91;
1005    pub const NUMPAD_SUBTRACT: u32 = 92;
1006    pub const NUMPAD_ADD: u32 = 93;
1007    pub const NUMPAD_ENTER: u32 = 94;
1008    pub const NUMPAD_DECIMAL: u32 = 95;
1009    pub const NUMPAD0: u32 = 96;
1010    pub const NUMPAD1: u32 = 97;
1011    pub const NUMPAD2: u32 = 98;
1012    pub const NUMPAD3: u32 = 99;
1013    pub const NUMPAD4: u32 = 100;
1014    pub const NUMPAD5: u32 = 101;
1015    pub const NUMPAD6: u32 = 102;
1016    pub const NUMPAD7: u32 = 103;
1017    pub const NUMPAD8: u32 = 104;
1018    pub const NUMPAD9: u32 = 105;
1019    pub const NUMPAD_EQUAL: u32 = 106;
1020    pub const NUMPAD_COMMA: u32 = 107;
1021    pub const INTL_RO: u32 = 108;
1022    pub const INTL_YEN: u32 = 109;
1023    pub const F13: u32 = 110;
1024    pub const F14: u32 = 111;
1025    pub const F15: u32 = 112;
1026    pub const F16: u32 = 113;
1027    pub const F17: u32 = 114;
1028    pub const F18: u32 = 115;
1029    pub const F19: u32 = 116;
1030    pub const F20: u32 = 117;
1031    pub const F21: u32 = 118;
1032    pub const F22: u32 = 119;
1033    pub const F23: u32 = 120;
1034    pub const F24: u32 = 121;
1035    /// W3C names by code (index 0 is unused).
1036    pub const NAMES: [&str; 122] = [
1037        "", "Escape", "F1", "F2", "F3", "F4", "F5", "F6", "F7", "F8", "F9", "F10", "F11", "F12", "Backquote", "Digit0", "Digit1", "Digit2", "Digit3", "Digit4", "Digit5", "Digit6", "Digit7", "Digit8", "Digit9", "Minus", "Equal", "Backspace", "Tab", "KeyA", "KeyB", "KeyC", "KeyD", "KeyE", "KeyF", "KeyG", "KeyH", "KeyI", "KeyJ", "KeyK", "KeyL", "KeyM", "KeyN", "KeyO", "KeyP", "KeyQ", "KeyR", "KeyS", "KeyT", "KeyU", "KeyV", "KeyW", "KeyX", "KeyY", "KeyZ", "BracketLeft", "BracketRight", "Backslash", "CapsLock", "Semicolon", "Quote", "Enter", "ShiftLeft", "IntlBackslash", "Comma", "Period", "Slash", "ShiftRight", "ControlLeft", "MetaLeft", "AltLeft", "Space", "AltRight", "MetaRight", "ContextMenu", "ControlRight", "PrintScreen", "ScrollLock", "Pause", "Insert", "Home", "PageUp", "Delete", "End", "PageDown", "ArrowUp", "ArrowLeft", "ArrowDown", "ArrowRight", "NumLock", "NumpadDivide", "NumpadMultiply", "NumpadSubtract", "NumpadAdd", "NumpadEnter", "NumpadDecimal", "Numpad0", "Numpad1", "Numpad2", "Numpad3", "Numpad4", "Numpad5", "Numpad6", "Numpad7", "Numpad8", "Numpad9", "NumpadEqual", "NumpadComma", "IntlRo", "IntlYen", "F13", "F14", "F15", "F16", "F17", "F18", "F19", "F20", "F21", "F22", "F23", "F24",
1038    ];
1039}