summaryrefslogtreecommitdiff
path: root/sdl2
diff options
context:
space:
mode:
Diffstat (limited to 'sdl2')
-rw-r--r--sdl2/COPYING371
-rw-r--r--sdl2/audio.ha31
-rw-r--r--sdl2/blendmode.ha11
-rw-r--r--sdl2/errors.ha31
-rw-r--r--sdl2/events.ha494
-rw-r--r--sdl2/gamecontroller.ha99
-rw-r--r--sdl2/gl.ha82
-rw-r--r--sdl2/image/image.ha46
-rw-r--r--sdl2/joystick.ha12
-rw-r--r--sdl2/keyboard.ha654
-rw-r--r--sdl2/mixer/channels.ha20
-rw-r--r--sdl2/mixer/general.ha54
-rw-r--r--sdl2/mixer/samples.ha38
-rw-r--r--sdl2/mouse.ha58
-rw-r--r--sdl2/pixels.ha55
-rw-r--r--sdl2/rect.ha29
-rw-r--r--sdl2/render.ha371
-rw-r--r--sdl2/rwops.ha134
-rw-r--r--sdl2/sdl2.ha23
-rw-r--r--sdl2/surface.ha53
-rw-r--r--sdl2/timer.ha32
-rw-r--r--sdl2/video.ha141
22 files changed, 2839 insertions, 0 deletions
diff --git a/sdl2/COPYING b/sdl2/COPYING
new file mode 100644
index 0000000..1ad757e
--- /dev/null
+++ b/sdl2/COPYING
@@ -0,0 +1,371 @@
+sample.ogg: lancelottjones CC-BY 3.0
+
+hare-sdl2:
+
+Mozilla Public License Version 2.0
+==================================
+
+1. Definitions
+--------------
+
+1.1. "Contributor"
+ means each individual or legal entity that creates, contributes to
+ the creation of, or owns Covered Software.
+
+1.2. "Contributor Version"
+ means the combination of the Contributions of others (if any) used
+ by a Contributor and that particular Contributor's Contribution.
+
+1.3. "Contribution"
+ means Covered Software of a particular Contributor.
+
+1.4. "Covered Software"
+ means Source Code Form to which the initial Contributor has attached
+ the notice in Exhibit A, the Executable Form of such Source Code
+ Form, and Modifications of such Source Code Form, in each case
+ including portions thereof.
+
+1.5. "Incompatible With Secondary Licenses"
+ means
+
+ (a) that the initial Contributor has attached the notice described
+ in Exhibit B to the Covered Software; or
+
+ (b) that the Covered Software was made available under the terms of
+ version 1.1 or earlier of the License, but not also under the
+ terms of a Secondary License.
+
+1.6. "Executable Form"
+ means any form of the work other than Source Code Form.
+
+1.7. "Larger Work"
+ means a work that combines Covered Software with other material, in
+ a separate file or files, that is not Covered Software.
+
+1.8. "License"
+ means this document.
+
+1.9. "Licensable"
+ means having the right to grant, to the maximum extent possible,
+ whether at the time of the initial grant or subsequently, any and
+ all of the rights conveyed by this License.
+
+1.10. "Modifications"
+ means any of the following:
+
+ (a) any file in Source Code Form that results from an addition to,
+ deletion from, or modification of the contents of Covered
+ Software; or
+
+ (b) any new file in Source Code Form that contains any Covered
+ Software.
+
+1.11. "Patent Claims" of a Contributor
+ means any patent claim(s), including without limitation, method,
+ process, and apparatus claims, in any patent Licensable by such
+ Contributor that would be infringed, but for the grant of the
+ License, by the making, using, selling, offering for sale, having
+ made, import, or transfer of either its Contributions or its
+ Contributor Version.
+
+1.12. "Secondary License"
+ means either the GNU General Public License, Version 2.0, the GNU
+ Lesser General Public License, Version 2.1, the GNU Affero General
+ Public License, Version 3.0, or any later versions of those
+ licenses.
+
+1.13. "Source Code Form"
+ means the form of the work preferred for making modifications.
+
+1.14. "You" (or "Your")
+ means an individual or a legal entity exercising rights under this
+ License. For legal entities, "You" includes any entity that
+ controls, is controlled by, or is under common control with You. For
+ purposes of this definition, "control" means (a) the power, direct
+ or indirect, to cause the direction or management of such entity,
+ whether by contract or otherwise, or (b) ownership of more than
+ fifty percent (50%) of the outstanding shares or beneficial
+ ownership of such entity.
+
+2. License Grants and Conditions
+--------------------------------
+
+2.1. Grants
+
+Each Contributor hereby grants You a world-wide, royalty-free,
+non-exclusive license:
+
+(a) under intellectual property rights (other than patent or trademark)
+ Licensable by such Contributor to use, reproduce, make available,
+ modify, display, perform, distribute, and otherwise exploit its
+ Contributions, either on an unmodified basis, with Modifications, or
+ as part of a Larger Work; and
+
+(b) under Patent Claims of such Contributor to make, use, sell, offer
+ for sale, have made, import, and otherwise transfer either its
+ Contributions or its Contributor Version.
+
+2.2. Effective Date
+
+The licenses granted in Section 2.1 with respect to any Contribution
+become effective for each Contribution on the date the Contributor first
+distributes such Contribution.
+
+2.3. Limitations on Grant Scope
+
+The licenses granted in this Section 2 are the only rights granted under
+this License. No additional rights or licenses will be implied from the
+distribution or licensing of Covered Software under this License.
+Notwithstanding Section 2.1(b) above, no patent license is granted by a
+Contributor:
+
+(a) for any code that a Contributor has removed from Covered Software;
+ or
+
+(b) for infringements caused by: (i) Your and any other third party's
+ modifications of Covered Software, or (ii) the combination of its
+ Contributions with other software (except as part of its Contributor
+ Version); or
+
+(c) under Patent Claims infringed by Covered Software in the absence of
+ its Contributions.
+
+This License does not grant any rights in the trademarks, service marks,
+or logos of any Contributor (except as may be necessary to comply with
+the notice requirements in Section 3.4).
+
+2.4. Subsequent Licenses
+
+No Contributor makes additional grants as a result of Your choice to
+distribute the Covered Software under a subsequent version of this
+License (see Section 10.2) or under the terms of a Secondary License (if
+permitted under the terms of Section 3.3).
+
+2.5. Representation
+
+Each Contributor represents that the Contributor believes its
+Contributions are its original creation(s) or it has sufficient rights
+to grant the rights to its Contributions conveyed by this License.
+
+2.6. Fair Use
+
+This License is not intended to limit any rights You have under
+applicable copyright doctrines of fair use, fair dealing, or other
+equivalents.
+
+2.7. Conditions
+
+Sections 3.1, 3.2, 3.3, and 3.4 are conditions of the licenses granted
+in Section 2.1.
+
+3. Responsibilities
+-------------------
+
+3.1. Distribution of Source Form
+
+All distribution of Covered Software in Source Code Form, including any
+Modifications that You create or to which You contribute, must be under
+the terms of this License. You must inform recipients that the Source
+Code Form of the Covered Software is governed by the terms of this
+License, and how they can obtain a copy of this License. You may not
+attempt to alter or restrict the recipients' rights in the Source Code
+Form.
+
+3.2. Distribution of Executable Form
+
+If You distribute Covered Software in Executable Form then:
+
+(a) such Covered Software must also be made available in Source Code
+ Form, as described in Section 3.1, and You must inform recipients of
+ the Executable Form how they can obtain a copy of such Source Code
+ Form by reasonable means in a timely manner, at a charge no more
+ than the cost of distribution to the recipient; and
+
+(b) You may distribute such Executable Form under the terms of this
+ License, or sublicense it under different terms, provided that the
+ license for the Executable Form does not attempt to limit or alter
+ the recipients' rights in the Source Code Form under this License.
+
+3.3. Distribution of a Larger Work
+
+You may create and distribute a Larger Work under terms of Your choice,
+provided that You also comply with the requirements of this License for
+the Covered Software. If the Larger Work is a combination of Covered
+Software with a work governed by one or more Secondary Licenses, and the
+Covered Software is not Incompatible With Secondary Licenses, this
+License permits You to additionally distribute such Covered Software
+under the terms of such Secondary License(s), so that the recipient of
+the Larger Work may, at their option, further distribute the Covered
+Software under the terms of either this License or such Secondary
+License(s).
+
+3.4. Notices
+
+You may not remove or alter the substance of any license notices
+(including copyright notices, patent notices, disclaimers of warranty,
+or limitations of liability) contained within the Source Code Form of
+the Covered Software, except that You may alter any license notices to
+the extent required to remedy known factual inaccuracies.
+
+3.5. Application of Additional Terms
+
+You may choose to offer, and to charge a fee for, warranty, support,
+indemnity or liability obligations to one or more recipients of Covered
+Software. However, You may do so only on Your own behalf, and not on
+behalf of any Contributor. You must make it absolutely clear that any
+such warranty, support, indemnity, or liability obligation is offered by
+You alone, and You hereby agree to indemnify every Contributor for any
+liability incurred by such Contributor as a result of warranty, support,
+indemnity or liability terms You offer. You may include additional
+disclaimers of warranty and limitations of liability specific to any
+jurisdiction.
+
+4. Inability to Comply Due to Statute or Regulation
+---------------------------------------------------
+
+If it is impossible for You to comply with any of the terms of this
+License with respect to some or all of the Covered Software due to
+statute, judicial order, or regulation then You must: (a) comply with
+the terms of this License to the maximum extent possible; and (b)
+describe the limitations and the code they affect. Such description must
+be placed in a text file included with all distributions of the Covered
+Software under this License. Except to the extent prohibited by statute
+or regulation, such description must be sufficiently detailed for a
+recipient of ordinary skill to be able to understand it.
+
+5. Termination
+--------------
+
+5.1. The rights granted under this License will terminate automatically
+if You fail to comply with any of its terms. However, if You become
+compliant, then the rights granted under this License from a particular
+Contributor are reinstated (a) provisionally, unless and until such
+Contributor explicitly and finally terminates Your grants, and (b) on an
+ongoing basis, if such Contributor fails to notify You of the
+non-compliance by some reasonable means prior to 60 days after You have
+come back into compliance. Moreover, Your grants from a particular
+Contributor are reinstated on an ongoing basis if such Contributor
+notifies You of the non-compliance by some reasonable means, this is the
+first time You have received notice of non-compliance with this License
+from such Contributor, and You become compliant prior to 30 days after
+Your receipt of the notice.
+
+5.2. If You initiate litigation against any entity by asserting a patent
+infringement claim (excluding declaratory judgment actions,
+counter-claims, and cross-claims) alleging that a Contributor Version
+directly or indirectly infringes any patent, then the rights granted to
+You by any and all Contributors for the Covered Software under Section
+2.1 of this License shall terminate.
+
+5.3. In the event of termination under Sections 5.1 or 5.2 above, all
+end user license agreements (excluding distributors and resellers) which
+have been validly granted by You or Your distributors under this License
+prior to termination shall survive termination.
+
+************************************************************************
+* *
+* 6. Disclaimer of Warranty *
+* ------------------------- *
+* *
+* Covered Software is provided under this License on an "as is" *
+* basis, without warranty of any kind, either expressed, implied, or *
+* statutory, including, without limitation, warranties that the *
+* Covered Software is free of defects, merchantable, fit for a *
+* particular purpose or non-infringing. The entire risk as to the *
+* quality and performance of the Covered Software is with You. *
+* Should any Covered Software prove defective in any respect, You *
+* (not any Contributor) assume the cost of any necessary servicing, *
+* repair, or correction. This disclaimer of warranty constitutes an *
+* essential part of this License. No use of any Covered Software is *
+* authorized under this License except under this disclaimer. *
+* *
+************************************************************************
+
+************************************************************************
+* *
+* 7. Limitation of Liability *
+* -------------------------- *
+* *
+* Under no circumstances and under no legal theory, whether tort *
+* (including negligence), contract, or otherwise, shall any *
+* Contributor, or anyone who distributes Covered Software as *
+* permitted above, be liable to You for any direct, indirect, *
+* special, incidental, or consequential damages of any character *
+* including, without limitation, damages for lost profits, loss of *
+* goodwill, work stoppage, computer failure or malfunction, or any *
+* and all other commercial damages or losses, even if such party *
+* shall have been informed of the possibility of such damages. This *
+* limitation of liability shall not apply to liability for death or *
+* personal injury resulting from such party's negligence to the *
+* extent applicable law prohibits such limitation. Some *
+* jurisdictions do not allow the exclusion or limitation of *
+* incidental or consequential damages, so this exclusion and *
+* limitation may not apply to You. *
+* *
+************************************************************************
+
+8. Litigation
+-------------
+
+Any litigation relating to this License may be brought only in the
+courts of a jurisdiction where the defendant maintains its principal
+place of business and such litigation shall be governed by laws of that
+jurisdiction, without reference to its conflict-of-law provisions.
+Nothing in this Section shall prevent a party's ability to bring
+cross-claims or counter-claims.
+
+9. Miscellaneous
+----------------
+
+This License represents the complete agreement concerning the subject
+matter hereof. If any provision of this License is held to be
+unenforceable, such provision shall be reformed only to the extent
+necessary to make it enforceable. Any law or regulation which provides
+that the language of a contract shall be construed against the drafter
+shall not be used to construe this License against a Contributor.
+
+10. Versions of the License
+---------------------------
+
+10.1. New Versions
+
+Mozilla Foundation is the license steward. Except as provided in Section
+10.3, no one other than the license steward has the right to modify or
+publish new versions of this License. Each version will be given a
+distinguishing version number.
+
+10.2. Effect of New Versions
+
+You may distribute the Covered Software under the terms of the version
+of the License under which You originally received the Covered Software,
+or under the terms of any subsequent version published by the license
+steward.
+
+10.3. Modified Versions
+
+If you create software not governed by this License, and you want to
+create a new license for such software, you may create and use a
+modified version of this License if you rename the license and remove
+any references to the name of the license steward (except to note that
+such modified license differs from this License).
+
+10.4. Distributing Source Code Form that is Incompatible With Secondary
+Licenses
+
+If You choose to distribute Source Code Form that is Incompatible With
+Secondary Licenses under the terms of this version of the License, the
+notice described in Exhibit B of this License must be attached.
+
+Exhibit A - Source Code Form License Notice
+-------------------------------------------
+
+ This Source Code Form is subject to the terms of the Mozilla Public
+ License, v. 2.0. If a copy of the MPL was not distributed with this
+ file, You can obtain one at http://mozilla.org/MPL/2.0/.
+
+If it is not possible or desirable to put the notice in a particular
+file, then You may include the notice in a location (such as a LICENSE
+file in a relevant directory) where a recipient would be likely to look
+for such a notice.
+
+You may add additional accurate notices of copyright ownership.
diff --git a/sdl2/audio.ha b/sdl2/audio.ha
new file mode 100644
index 0000000..1b78880
--- /dev/null
+++ b/sdl2/audio.ha
@@ -0,0 +1,31 @@
+// Audio format flags.
+//
+// Current representation (unspecified bits are always zero):
+//
+// ++-----------------------sample is signed if set
+// ||
+// || ++-----------sample is bigendian if set
+// || ||
+// || || ++---sample is float if set
+// || || ||
+// || || || +---sample bit size---+
+// || || || | |
+// 15 14 13 12 11 10 09 08 07 06 05 04 03 02 01 00
+export type SDL_AudioFormat = u16;
+
+// Unsigned 8-bit samples
+export def AUDIO_U8: SDL_AudioFormat = 0x0008;
+// Signed 8-bit samples
+export def AUDIO_S8: SDL_AudioFormat = 0x8008;
+// Unsigned 16-bit samples, little-endian
+export def AUDIO_U16LSB: SDL_AudioFormat = 0x0010;
+// Signed 16-bit samples, little-endian
+export def AUDIO_S16LSB: SDL_AudioFormat = 0x8010;
+// Unsigned 16-bit samples, big-endian
+export def AUDIO_U16MSB: SDL_AudioFormat = 0x1010;
+// Signed 16-bit samples, big-endian
+export def AUDIO_S16MSB: SDL_AudioFormat = 0x9010;
+// Unsigned 16-bit samples
+export def AUDIO_U16: SDL_AudioFormat = AUDIO_U16LSB;
+// Signed 16-bit samples
+export def AUDIO_S16: SDL_AudioFormat = AUDIO_S16LSB;
diff --git a/sdl2/blendmode.ha b/sdl2/blendmode.ha
new file mode 100644
index 0000000..25acab6
--- /dev/null
+++ b/sdl2/blendmode.ha
@@ -0,0 +1,11 @@
+// TODO: Flesh me out
+
+// The blend mode used in SDL_RenderCopy() and drawing operations.
+export type SDL_BlendMode = enum {
+ NONE = 0x00000000,
+ BLEND = 0x00000001,
+ ADD = 0x00000002,
+ MOD = 0x00000004,
+ MUL = 0x00000008,
+ INVALID = 0x7FFFFFFF
+};
diff --git a/sdl2/errors.ha b/sdl2/errors.ha
new file mode 100644
index 0000000..a848667
--- /dev/null
+++ b/sdl2/errors.ha
@@ -0,0 +1,31 @@
+use types::c;
+
+// Returned when an error occurs in an SDL function.
+export type error = !str;
+
+// Converts an SDL error into a human-friendly string.
+export fn strerror(err: error) str = {
+ return err: str;
+};
+
+@symbol("SDL_GetError") fn SDL_GetError() const *c::char;
+
+export fn wrapvoid(ret: int) (void | error) = {
+ wrapint(ret)?;
+};
+
+export fn wrapint(ret: int) (int | error) = {
+ if (ret < 0) {
+ return c::tostr(SDL_GetError()): error;
+ };
+ return ret;
+};
+
+export fn wrapptr(ret: nullable *opaque) (*opaque | error) = {
+ match (ret) {
+ case let v: *opaque =>
+ return v;
+ case null =>
+ return c::tostr(SDL_GetError()): error;
+ };
+};
diff --git a/sdl2/events.ha b/sdl2/events.ha
new file mode 100644
index 0000000..35b7808
--- /dev/null
+++ b/sdl2/events.ha
@@ -0,0 +1,494 @@
+use types::c;
+
+export type SDL_EventType = enum u32 {
+ FIRSTEVENT = 0,
+
+ QUIT = 0x100,
+
+ APP_TERMINATING,
+ APP_LOWMEMORY,
+ APP_WILLENTERBACKGROUND,
+ APP_DIDENTERBACKGROUND,
+ APP_WILLENTERFOREGROUND,
+ APP_DIDENTERFOREGROUND,
+
+ DISPLAYEVENT = 0x150,
+
+ WINDOWEVENT = 0x200,
+ SYSWMEVENT,
+
+ KEYDOWN = 0x300,
+ KEYUP,
+ TEXTEDITING,
+ TEXTINPUT,
+ KEYMAPCHANGED,
+
+ MOUSEMOTION = 0x400,
+ MOUSEBUTTONDOWN,
+ MOUSEBUTTONUP,
+ MOUSEWHEEL,
+
+ JOYAXISMOTION = 0x600,
+ JOYBALLMOTION,
+ JOYHATMOTION,
+ JOYBUTTONDOWN,
+ JOYBUTTONUP,
+ JOYDEVICEADDED,
+ JOYDEVICEREMOVED,
+
+ CONTROLLERAXISMOTION = 0x650,
+ CONTROLLERBUTTONDOWN,
+ CONTROLLERBUTTONUP,
+ CONTROLLERDEVICEADDED,
+ CONTROLLERDEVICEREMOVED,
+ CONTROLLERDEVICEREMAPPED,
+
+ FINGERDOWN = 0x700,
+ FINGERUP,
+ FINGERMOTION,
+
+ DOLLARGESTURE = 0x800,
+ DOLLARRECORD,
+ MULTIGESTURE,
+
+ CLIPBOARDUPDATE = 0x900,
+
+ DROPFILE = 0x1000,
+ DROPTEXT,
+ DROPBEGIN,
+ DROPCOMPLETE,
+
+ AUDIODEVICEADDED = 0x1100,
+ AUDIODEVICEREMOVED,
+
+ SENSORUPDATE = 0x1200,
+
+ RENDER_TARGETS_RESET = 0x2000,
+ RENDER_DEVICE_RESET,
+
+ USEREVENT = 0x8000,
+
+ LASTEVENT = 0xFFFF
+};
+
+// Fields shared by every event
+export type SDL_CommonEvent = struct {
+ event_type: SDL_EventType,
+ timestamp: u32,
+};
+
+// Display state change event data (event.display.*)
+export type SDL_DisplayEvent = struct {
+ SDL_CommonEvent,
+ display: u32,
+ event: u8,
+ padding1: u8,
+ padding2: u8,
+ padding3: u8,
+ data1: i32,
+};
+
+// Event subtype for window events
+export type SDL_WindowEventID = enum u8 {
+ NONE,
+ SHOWN,
+ HIDDEN,
+ EXPOSED,
+ MOVED,
+ RESIZED,
+ SIZE_CHANGED,
+ MINIMIZED,
+ MAXIMIZED,
+ RESTORED,
+ ENTER,
+ LEAVE,
+ FOCUS_GAINED,
+ FOCUS_LOST,
+ CLOSE,
+ TAKE_FOCUS,
+ HIT_TEST,
+ ICCPROF_CHANGED,
+ DISPLAY_CHANGED
+};
+
+// Window state change event data (event.window.*)
+export type SDL_WindowEvent = struct {
+ SDL_CommonEvent,
+ window_id: u32,
+ event: SDL_WindowEventID,
+ padding1: u8,
+ padding2: u8,
+ padding3: u8,
+ data1: i32,
+ data2: i32,
+};
+
+// Keyboard button event structure (event.key.*)
+export type SDL_KeyboardEvent = struct {
+ SDL_CommonEvent,
+ window_id: u32,
+ state: u8,
+ repeat: u8,
+ padding2: u8,
+ padding3: u8,
+ keysym: SDL_Keysym,
+};
+
+// Size of the [[SDL_TextEditingEvent]] 'text' field.
+export def TEXTEDITINGEVENT_TEXT_SIZE: size = 32;
+
+// Keyboard text editing event structure (event.edit.*)
+export type SDL_TextEditingEvent = struct {
+ SDL_CommonEvent,
+ window_id: u32,
+ text: [TEXTEDITINGEVENT_TEXT_SIZE]c::char,
+ start: i32,
+ length: i32,
+};
+
+// Size of the [[SDL_TextInputEvent]] 'text' field.
+export def TEXTINPUTEVENT_TEXT_SIZE: size = 32;
+
+// Keyboard text input event structure (event.text.*)
+export type SDL_TextInputEvent = struct {
+ SDL_CommonEvent,
+ window_id: u32,
+ text: [TEXTINPUTEVENT_TEXT_SIZE]c::char,
+};
+
+// Mouse motion event structure (event.motion.*)
+export type SDL_MouseMotionEvent = struct {
+ SDL_CommonEvent,
+ window_id: u32,
+ which: u32,
+ state: u32,
+ x: i32,
+ y: i32,
+ xrel: i32,
+ yrel: i32,
+};
+
+// Mouse button event structure (event.button.*)
+export type SDL_MouseButtonEvent = struct {
+ SDL_CommonEvent,
+ window_id: u32,
+ which: u32,
+ button: u8,
+ state: u8,
+ clicks: u8,
+ padding1: u8,
+ x: i32,
+ y: i32,
+};
+
+// Mouse wheel event structure (event.wheel.*)
+export type SDL_MouseWheelEvent = struct {
+ SDL_CommonEvent,
+ window_id: u32,
+ which: u32,
+ x: i32,
+ y: i32,
+ direction: u32,
+};
+
+// Joystick axis motion event structure (event.jaxis.*)
+export type SDL_JoyAxisEvent = struct {
+ SDL_CommonEvent,
+ which: i32, // TODO: Rig me up with the JoystickID type
+ axis: u8,
+ padding1: u8,
+ padding2: u8,
+ padding3: u8,
+ value: i16,
+ padding4: u16,
+};
+
+// Joystick trackball motion event structure (event.jball.*)
+export type SDL_JoyBallEvent = struct {
+ SDL_CommonEvent,
+ which: i32, // TODO: Rig me up with the JoystickID type
+ ball: u8,
+ padding1: u8,
+ padding2: u8,
+ padding3: u8,
+ xrel: i16,
+ yrel: i16,
+};
+
+// Joystick hat position change event structure (event.jhat.*)
+export type SDL_JoyHatEvent = struct {
+ SDL_CommonEvent,
+ which: i32, // TODO: Rig me up with the JoystickID type
+ hat: u8,
+ value: u8, // TODO: Rig me up with HAT_UP et al
+ padding1: u8,
+ padding2: u8,
+};
+
+// Joystick button event structure (event.jbutton.*)
+export type SDL_JoyButtonEvent = struct {
+ SDL_CommonEvent,
+ which: i32, // TODO: Rig me up with the JoystickID type
+ button: u8,
+ state: u8,
+ padding1: u8,
+ padding2: u8,
+};
+
+// Joystick device event structure (event.jdevice.*)
+export type SDL_JoyDeviceEvent = struct {
+ SDL_CommonEvent,
+ which: i32,
+};
+
+// Game controller axis motion event structure (event.caxis.*)
+export type SDL_ControllerAxisEvent = struct {
+ SDL_CommonEvent,
+ which: i32, // TODO
+ axis: SDL_GameControllerAxis,
+ padding1: u8,
+ padding2: u8,
+ padding3: u8,
+ value: i16,
+ padding4: u16,
+};
+
+// Game controller button event structure (event.cbutton.*)
+export type SDL_ControllerButtonEvent = struct {
+ SDL_CommonEvent,
+ which: i32,
+ button: u8,
+ state: u8,
+ padding1: u8,
+ padding2: u8,
+};
+
+// Controller device event structure (event.cdevice.*)
+export type SDL_ControllerDeviceEvent = struct {
+ SDL_CommonEvent,
+ which: i32,
+};
+
+// Audio device event structure (event.adevice.*)
+export type SDL_AudioDeviceEvent = struct {
+ SDL_CommonEvent,
+ which: u32,
+ iscapture: u8,
+ padding1: u8,
+ padding2: u8,
+ padding3: u8,
+};
+
+// Touch finger event structure (event.tfinger.*)
+export type SDL_TouchFingerEvent = struct {
+ SDL_CommonEvent,
+ touch_id: i64, // TODO
+ finger_id: i64, // TODO
+ x: f32,
+ y: f32,
+ dx: f32,
+ dy: f32,
+ pressure: f32,
+};
+
+// Multiple Finger Gesture Event (event.mgesture.*)
+export type SDL_MultiGestureEvent = struct {
+ SDL_CommonEvent,
+ touch_id: i64, // TODO
+ dtheta: f32,
+ ddist: f32,
+ x: f32,
+ y: f32,
+ num_fingers: u16,
+ padding: u16,
+};
+
+// Dollar Gesture Event (event.dgesture.*)
+export type SDL_DollarGestureEvent = struct {
+ SDL_CommonEvent,
+ touch_id: i64, // TODO
+ gesture_id: i64, // TODO
+ num_fingers: u32,
+ error: f32,
+ x: f32,
+ y: f32,
+};
+
+// An event used to request a file open by the system (event.drop.*)
+// This event is enabled by default, you can disable it with [[eventstate]].
+// If this event is enabled, you must free the filename in the event.
+export type SDL_DropEvent = struct {
+ SDL_CommonEvent,
+ file: *c::char,
+ window_id: u32,
+};
+
+// Sensor event structure (event.sensor.*)
+export type SDL_SensorEvent = struct {
+ SDL_CommonEvent,
+ which: i32,
+ data: [6]f32,
+};
+
+// The "quit requested" event
+export type SDL_QuitEvent = struct {
+ SDL_CommonEvent,
+};
+
+// OS Specific event
+export type SDL_OSEvent = struct {
+ SDL_CommonEvent,
+};
+
+// A user-defined event type (event.user.*)
+export type SDL_UserEvent = struct {
+ SDL_CommonEvent,
+ window_id: u32,
+ code: i32,
+ data1: *opaque,
+ data2: *opaque,
+};
+
+// A video driver dependent system event (event.syswm.*)
+// This event is disabled by default, you can enable it with [[eventstate]].
+export type SDL_SysWMEvent = struct {
+ SDL_CommonEvent,
+ msg: *opaque, // TODO
+};
+
+// General event structure
+export type event = union {
+ event_type: SDL_EventType,
+ common: SDL_CommonEvent,
+ display: SDL_DisplayEvent,
+ window: SDL_WindowEvent,
+ key: SDL_KeyboardEvent,
+ edit: SDL_TextEditingEvent,
+ text: SDL_TextInputEvent,
+ motion: SDL_MouseMotionEvent,
+ button: SDL_MouseButtonEvent,
+ wheel: SDL_MouseWheelEvent,
+ jaxis: SDL_JoyAxisEvent,
+ jball: SDL_JoyBallEvent,
+ jhat: SDL_JoyHatEvent,
+ jbutton: SDL_JoyButtonEvent,
+ jdevice: SDL_JoyDeviceEvent,
+ caxis: SDL_ControllerAxisEvent,
+ cbutton: SDL_ControllerButtonEvent,
+ cdevice: SDL_ControllerDeviceEvent,
+ adevice: SDL_AudioDeviceEvent,
+ sensor: SDL_SensorEvent,
+ quit: SDL_QuitEvent,
+ user: SDL_UserEvent,
+ syswm: SDL_SysWMEvent,
+ tfinger: SDL_TouchFingerEvent,
+ mgesture: SDL_MultiGestureEvent,
+ dgestures: SDL_DollarGestureEvent,
+ drop: SDL_DropEvent,
+
+ padding: [56]u8,
+};
+
+// Pumps the event loop, gathering events from the input devices.
+//
+// This function updates the event queue and internal input device state.
+//
+// This should only be run in the thread that sets the video mode.
+export @symbol("SDL_PumpEvents") fn SDL_PumpEvents() void;
+
+export type eventaction = enum {
+ ADDEVENT,
+ PEEKEVENT,
+ GETEVENT,
+};
+
+@symbol("SDL_PeepEvents") fn _peep_events(events: *event, numevents: int,
+ action: eventaction, mintype: SDL_EventType, maxtype: SDL_EventType) int;
+
+// Checks the event queue for messages and optionally returns them.
+//
+// If 'action' is ADDEVENT, up to 'numevents' events will be added to the back
+// of the event queue.
+//
+// If 'action' is PEEKEVENT, up to 'numevents' events at the front of the event
+// queue, within the specified minimum and maximum type, will be returned and
+// will not be removed from the queue.
+//
+// If 'action' is GETEVENT, up to 'numevents' events at the front of the event
+// queue, within the specified minimum and maximum type, will be returned and
+// will be removed from the queue.
+//
+// This function is thread-safe.
+export fn SDL_PeepEvents(
+ events: *event,
+ numevents: int,
+ action: eventaction,
+ mintype: SDL_EventType,
+ maxtype: SDL_EventType,
+) (int | error) = {
+ return wrapint(_peep_events(events, numevents, action, mintype, maxtype));
+};
+
+// Checks to see if certain event types are in the event queue.
+export @symbol("SDL_HasEvent") fn SDL_HasEvent(SDL_EventType: SDL_EventType) bool;
+
+// Checks to see if certain event types are in the event queue.
+export @symbol("SDL_HasEvents") fn SDL_HasEvents(mintype: SDL_EventType, maxtype: SDL_EventType) bool;
+
+// This function clears events from the event queue
+// This function only affects currently queued events. If you want to make
+// sure that all pending OS events are flushed, you can call SDL_PumpEvents()
+// on the main thread immediately before the flush call.
+export @symbol("SDL_FlushEvent") fn flush_event(SDL_EventType: SDL_EventType) void;
+
+// This function clears events from the event queue
+// This function only affects currently queued events. If you want to make
+// sure that all pending OS events are flushed, you can call SDL_PumpEvents()
+// on the main thread immediately before the flush call.
+export @symbol("SDL_FlushEvents") fn SDL_FlushEvents(mintype: SDL_EventType, maxtype: SDL_EventType) void;
+
+@symbol("SDL_PollEvent") fn _poll_event(event: nullable *event) int;
+
+// Polls for currently pending events.
+//
+// Returns 1 if there are any pending events, or 0 if there are none available.
+//
+// If 'event' is not null, the next event is removed from the queue and stored
+// in that area.
+export fn SDL_PollEvent(event: nullable *event) (int | error) = {
+ return wrapint(_poll_event(event));
+};
+
+@symbol("SDL_WaitEvent") fn _wait_event(event: nullable *event) int;
+
+// Waits indefinitely for the next available event.
+//
+// If 'event' is not null, the next event is removed from the queue and stored
+// in that area.
+export fn SDL_WaitEvent(event: nullable *event) (void | error) = {
+ return wrapvoid(_wait_event(event));
+};
+
+@symbol("SDL_WaitEventTimeout") fn _wait_event_timeout(
+ event: nullable *event, timeout: int) int;
+
+// Waits until the specified timeout (in milliseconds) for the next available event.
+//
+// If 'event' is not null, the next event is removed from the queue and stored
+// in that area. The 'timeout' is the time (in milliseconds) to wait for next
+// event.
+export fn SDL_WaitEventTimeout(
+ event: nullable *event,
+ timeout: int,
+) (void | error) = {
+ return wrapvoid(_wait_event_timeout(event, timeout));
+};
+
+@symbol("SDL_PushEvent") fn _push_event(event: *event) int;
+
+// Add an event to the event queue.
+export fn SDL_PushEvent(event: *event) (void | error) = {
+ return wrapvoid(_push_event(event));
+};
+
+// TODO: Finish rigging up other SDL_events.h bits
diff --git a/sdl2/gamecontroller.ha b/sdl2/gamecontroller.ha
new file mode 100644
index 0000000..4cab9ce
--- /dev/null
+++ b/sdl2/gamecontroller.ha
@@ -0,0 +1,99 @@
+// TODO: Flesh me out
+
+// The SDL_GameController structure used to identify an SDL game controller.
+// (Opaque)
+export type SDL_GameController = opaque;
+
+// The list of axes available from a controller
+//
+// Thumbstick axis values range from [[SDL_JOYSTICK_AXIS_MIN]] to
+// [[SDL_JOYSTICK_AXIS_MAX]], and are centered within ~8000 of zero, though advanced
+// UI will allow users to set or autodetect the dead zone, which varies between
+// controllers.
+//
+// Trigger axis values range from 0 to [[SDL_JOYSTICK_AXIS_MAX]].
+export type SDL_GameControllerAxis = enum u8 {
+ LEFTX,
+ LEFTY,
+ RIGHTX,
+ RIGHTY,
+ TRIGGERLEFT,
+ TRIGGERRIGHT,
+ INVALID = 255,
+};
+
+// The list of buttons available from a controller
+export type SDL_GameControllerButton = enum u8 {
+ INVALID = 255,
+ A = 0,
+ B,
+ X,
+ Y,
+ BACK,
+ GUIDE,
+ START,
+ LEFTSTICK,
+ RIGHTSTICK,
+ LEFTSHOULDER,
+ RIGHTSHOULDER,
+ DPAD_UP,
+ DPAD_DOWN,
+ DPAD_LEFT,
+ DPAD_RIGHT,
+ MISC1,
+ PADDLE1,
+ PADDLE2,
+ PADDLE3,
+ PADDLE4,
+ TOUCHPAD,
+};
+
+// Check if the given joystick is supported by the game controller interface.
+//
+// 'joystick_index' is the same as the 'device_index' passed to
+// [[joystick_open]].
+//
+// Returns true if the given joystick is supported by the game controller
+// interface, false if it isn't or it's an invalid index.
+export @symbol("SDL_IsGameController") fn SDL_IsGameController(
+ joystick_index: int) bool;
+
+@symbol("SDL_GameControllerOpen") fn _game_controller_open(
+ joystick_index: int) nullable *SDL_GameController;
+
+// Get the SDL_GameController associated with an instance id.
+export fn SDL_GameControllerOpen(
+ joystick_index: int,
+) (*SDL_GameController | error) = {
+ return wrapptr(_game_controller_open(joystick_index))?: *SDL_GameController;
+};
+
+// Close a game controller previously opened with [[game_controller_open]].
+export @symbol("SDL_GameControllerClose") fn SDL_GameControllerClose(
+ gamecontroller: *SDL_GameController) void;
+
+@symbol("SDL_GameControllerRumble") fn _SDL_GameControllerRumble(
+ gamecontroller: *SDL_GameController,
+ low_frequency_rumble: u16,
+ high_frequency_rumble: u16,
+ duration_ms: u32) int;
+
+// Start a rumble effect on a game controller.
+//
+// Each call to this function cancels any previous rumble effect, and calling
+// it with 0 intensity stops any rumbling.
+//
+// The low-frequency motor is generally on the left, and the high-frequency
+// motor is generally on the right.
+export fn SDL_GameControllerRumble(
+ gamecontroller: *SDL_GameController,
+ low_frequency_rumble: u16,
+ high_frequency_rumble: u16,
+ duration_ms: u32,
+) (void | error) = {
+ return wrapvoid(_SDL_GameControllerRumble(
+ gamecontroller,
+ low_frequency_rumble,
+ high_frequency_rumble,
+ duration_ms));
+};
diff --git a/sdl2/gl.ha b/sdl2/gl.ha
new file mode 100644
index 0000000..b609f6c
--- /dev/null
+++ b/sdl2/gl.ha
@@ -0,0 +1,82 @@
+use types::c;
+
+export type SDL_GLContext = opaque;
+
+export type SDL_GLprofile = enum int {
+ GL_CONTEXT_PROFILE_CORE = 0x0001,
+ GL_CONTEXT_PROFILE_COMPATIBILITY = 0x0002,
+ GL_CONTEXT_PROFILE_ES = 0x0004,
+};
+
+export type SDL_GLcontextFlag = enum int {
+ GL_CONTEXT_DEBUG_FLAG = 0x0001,
+ GL_CONTEXT_FORWARD_COMPATIBLE_FLAG = 0x0002,
+ GL_CONTEXT_ROBUST_ACCESS_FLAG = 0x0004,
+ GL_CONTEXT_RESET_ISOLATION_FLAG = 0x0008,
+};
+
+export type SDL_GLattr = enum {
+ GL_RED_SIZE,
+ GL_GREEN_SIZE,
+ GL_BLUE_SIZE,
+ GL_ALPHA_SIZE,
+ GL_BUFFER_SIZE,
+ GL_DOUBLEBUFFER,
+ GL_DEPTH_SIZE,
+ GL_STENCIL_SIZE,
+ GL_ACCUM_RED_SIZE,
+ GL_ACCUM_GREEN_SIZE,
+ GL_ACCUM_BLUE_SIZE,
+ GL_ACCUM_ALPHA_SIZE,
+ GL_STEREO,
+ GL_MULTISAMPLEBUFFERS,
+ GL_MULTISAMPLESAMPLES,
+ GL_ACCELERATED_VISUAL,
+ GL_RETAINED_BACKING,
+ GL_CONTEXT_MAJOR_VERSION,
+ GL_CONTEXT_MINOR_VERSION,
+ GL_CONTEXT_EGL,
+ GL_CONTEXT_FLAGS,
+ GL_CONTEXT_PROFILE_MASK,
+ GL_SHARE_WITH_CURRENT_CONTEXT,
+ GL_FRAMEBUFFER_SRGB_CAPABLE,
+ GL_CONTEXT_RELEASE_BEHAVIOR,
+ GL_CONTEXT_RESET_NOTIFICATION,
+ GL_CONTEXT_NO_ERROR,
+};
+
+@symbol("SDL_GL_CreateContext") fn _SDL_GL_CreateContext(
+ window: *SDL_Window) *SDL_GLContext;
+
+export fn SDL_GL_CreateContext(window: *SDL_Window) (*SDL_GLContext | error) = {
+ return wrapptr(_SDL_GL_CreateContext(window))?: *SDL_GLContext;
+};
+
+export @symbol("SDL_GL_GetProcAddress") fn SDL_GL_GetProcAddress(
+ proc: *const c::char) *opaque;
+
+@symbol("SDL_GL_SetAttribute") fn _SDL_GL_SetAttribute(
+ attr: SDL_GLattr, value: int) int;
+@symbol("SDL_GL_GetAttribute") fn _SDL_GL_GetAttribute(
+ attr: SDL_GLattr, value: *int) int;
+
+export fn SDL_GL_SetAttribute(attr: SDL_GLattr, value: int) (void | error) = {
+ return wrapvoid(_SDL_GL_SetAttribute(attr, value));
+};
+
+export fn SDL_GL_GetAttribute(attr: SDL_GLattr) (int | error) = {
+ let value = 0;
+ wrapvoid(_SDL_GL_GetAttribute(attr, &value))?;
+ return value;
+};
+
+export @symbol("SDL_GL_SwapWindow") fn SDL_GL_SwapWindow(window: *SDL_Window) void;
+export @symbol("SDL_GL_GetSwapInterval") fn SDL_GL_GetSwapInterval() int;
+export @symbol("SDL_GL_GetDrawableSize") fn SDL_GL_GetDrawableSize(
+ window: *SDL_Window, w: *int, h: *int) void;
+
+@symbol("SDL_GL_SetSwapInterval") fn _SDL_GL_SetSwapInterval(interval: int) int;
+
+export fn SDL_GL_SetSwapInterval(interval: int) (void | error) = {
+ return wrapvoid(_SDL_GL_SetSwapInterval(interval));
+};
diff --git a/sdl2/image/image.ha b/sdl2/image/image.ha
new file mode 100644
index 0000000..32f8f3d
--- /dev/null
+++ b/sdl2/image/image.ha
@@ -0,0 +1,46 @@
+// TODO: Flesh me out
+// TODO: SDL_RWops
+use sdl2;
+use types::c;
+
+// Flags for [[IMG_Init]].
+export type IMG_InitFlags = enum int {
+ NONE = 0,
+ JPG = 0x00000001,
+ PNG = 0x00000002,
+ TIF = 0x00000004,
+ WEBP = 0x00000008,
+};
+
+@symbol("IMG_Init") fn _IMG_Init(flags: IMG_InitFlags) int;
+
+// Loads dynamic libraries and prepares them for use. Flags should be one or
+// more flags from [[IMG_InitFlags]] OR'd together.
+export fn IMG_Init(flags: IMG_InitFlags) (void | sdl2::error) = {
+ return sdl2::wrapvoid(_IMG_Init(flags));
+};
+
+// Unloads libraries loaded with [[IMG_Init]]
+export @symbol("IMG_Quit") fn IMG_Quit() void;
+
+@symbol("IMG_Load") fn _IMG_Load(file: const *c::char) nullable *sdl2::SDL_Surface;
+
+// Load an image from a file path.
+export fn IMG_Load(file: str) (*sdl2::SDL_Surface | sdl2::error) = {
+ const file = c::fromstr(file);
+ defer free(file);
+ return sdl2::wrapptr(_IMG_Load(file))?: *sdl2::SDL_Surface;
+};
+
+@symbol("IMG_LoadTexture") fn _IMG_LoadTexture(SDL_Renderer: *sdl2::SDL_Renderer,
+ file: const *c::char) nullable *sdl2::SDL_Texture;
+
+// Load an image directly into a render texture.
+export fn IMG_LoadTexture(
+ SDL_Renderer: *sdl2::SDL_Renderer,
+ file: str,
+) (*sdl2::SDL_Texture | sdl2::error) = {
+ const file = c::fromstr(file);
+ defer free(file);
+ return sdl2::wrapptr(_IMG_LoadTexture(SDL_Renderer, file))?: *sdl2::SDL_Texture;
+};
diff --git a/sdl2/joystick.ha b/sdl2/joystick.ha
new file mode 100644
index 0000000..2234aff
--- /dev/null
+++ b/sdl2/joystick.ha
@@ -0,0 +1,12 @@
+// TODO: Flesh me out
+
+// Minimum value for a joystick axis.
+export def SDL_JOYSTICK_AXIS_MIN: i16 = -32768;
+
+// Minimum value for a joystick axis.
+export def SDL_JOYSTICK_AXIS_MAX: i16 = 32767;
+
+@symbol("SDL_NumJoysticks") fn _SDL_NumJoysticks() int;
+
+// Returns the number of joysticks attached to the system.
+export fn SDL_NumJoysticks() (int | error) = wrapint(_SDL_NumJoysticks());
diff --git a/sdl2/keyboard.ha b/sdl2/keyboard.ha
new file mode 100644
index 0000000..8c82184
--- /dev/null
+++ b/sdl2/keyboard.ha
@@ -0,0 +1,654 @@
+use types::c;
+
+export type SDL_Scancode = enum uint {
+ UNKNOWN = 0,
+
+ // Usage page 0x07
+ // These values are from usage page 0x07 (USB keyboard page).
+
+ A = 4,
+ B = 5,
+ C = 6,
+ D = 7,
+ E = 8,
+ F = 9,
+ G = 10,
+ H = 11,
+ I = 12,
+ J = 13,
+ K = 14,
+ L = 15,
+ M = 16,
+ N = 17,
+ O = 18,
+ P = 19,
+ Q = 20,
+ R = 21,
+ S = 22,
+ T = 23,
+ U = 24,
+ V = 25,
+ W = 26,
+ X = 27,
+ Y = 28,
+ Z = 29,
+
+ ONE = 30,
+ TWO = 31,
+ THREE = 32,
+ FOUR = 33,
+ FIVE = 34,
+ SIX = 35,
+ SEVEN = 36,
+ EIGHT = 37,
+ NINE = 38,
+ ZERO = 39,
+
+ RETURN = 40,
+ ESCAPE = 41,
+ BACKSPACE = 42,
+ TAB = 43,
+ SPACE = 44,
+
+ MINUS = 45,
+ EQUALS = 46,
+ LEFTBRACKET = 47,
+ RIGHTBRACKET = 48,
+ // Located at the lower left of the return
+ // key on ISO keyboards and at the right end
+ // of the QWERTY row on ANSI keyboards.
+ // Produces REVERSE SOLIDUS (backslash) and
+ // VERTICAL LINE in a US layout, REVERSE
+ // SOLIDUS and VERTICAL LINE in a UK Mac
+ // layout, NUMBER SIGN and TILDE in a UK
+ // Windows layout, DOLLAR SIGN and POUND SIGN
+ // in a Swiss German layout, NUMBER SIGN and
+ // APOSTROPHE in a German layout, GRAVE
+ // ACCENT and POUND SIGN in a French Mac
+ // layout, and ASTERISK and MICRO SIGN in a
+ // French Windows layout.
+ BACKSLASH = 49,
+ NONUSHASH = 50,
+ // ISO USB keyboards actually use this code
+ // instead of 49 for the same key, but all
+ // OSes I've seen treat the two codes
+ // identically. So, as an implementor, unless
+ // your keyboard generates both of those
+ // codes and your OS treats them differently,
+ // you should generate BACKSLASH
+ // instead of this code. As a user, you
+ // should not rely on this code because SDL
+ // will never generate it with most (all?)
+ // keyboards.
+ SEMICOLON = 51,
+ APOSTROPHE = 52,
+ // Located in the top left corner (on both ANSI
+ // and ISO keyboards). Produces GRAVE ACCENT and
+ // TILDE in a US Windows layout and in US and UK
+ // Mac layouts on ANSI keyboards, GRAVE ACCENT
+ // and NOT SIGN in a UK Windows layout, SECTION
+ // SIGN and PLUS-MINUS SIGN in US and UK Mac
+ // layouts on ISO keyboards, SECTION SIGN and
+ // DEGREE SIGN in a Swiss German layout (Mac:
+ // only on ISO keyboards), CIRCUMFLEX ACCENT and
+ // DEGREE SIGN in a German layout (Mac: only on
+ // ISO keyboards), SUPERSCRIPT TWO and TILDE in a
+ // French Windows layout, COMMERCIAL AT and
+ // NUMBER SIGN in a French Mac layout on ISO
+ // keyboards, and LESS-THAN SIGN and GREATER-THAN
+ // SIGN in a Swiss German, German, or French Mac
+ // layout on ANSI keyboards.
+ GRAVE = 53,
+ COMMA = 54,
+ PERIOD = 55,
+ SLASH = 56,
+
+ CAPSLOCK = 57,
+
+ F1 = 58,
+ F2 = 59,
+ F3 = 60,
+ F4 = 61,
+ F5 = 62,
+ F6 = 63,
+ F7 = 64,
+ F8 = 65,
+ F9 = 66,
+ F10 = 67,
+ F11 = 68,
+ F12 = 69,
+
+ PRINTSCREEN = 70,
+ SCROLLLOCK = 71,
+ PAUSE = 72,
+ // insert on PC, help on some Mac keyboards (but does send code 73,
+ // not 117)
+ INSERT = 73,
+ HOME = 74,
+ PAGEUP = 75,
+ DELETE = 76,
+ END = 77,
+ PAGEDOWN = 78,
+ RIGHT = 79,
+ LEFT = 80,
+ DOWN = 81,
+ UP = 82,
+
+ NUMLOCKCLEAR = 83, // num lock on PC, clear on Mac keyboards
+ KP_DIVIDE = 84,
+ KP_MULTIPLY = 85,
+ KP_MINUS = 86,
+ KP_PLUS = 87,
+ KP_ENTER = 88,
+ KP_1 = 89,
+ KP_2 = 90,
+ KP_3 = 91,
+ KP_4 = 92,
+ KP_5 = 93,
+ KP_6 = 94,
+ KP_7 = 95,
+ KP_8 = 96,
+ KP_9 = 97,
+ KP_0 = 98,
+ KP_PERIOD = 99,
+
+ // This is the additional key that ISO
+ // keyboards have over ANSI ones,
+ // located between left shift and Y.
+ // Produces GRAVE ACCENT and TILDE in a
+ // US or UK Mac layout, REVERSE SOLIDUS
+ // (backslash) and VERTICAL LINE in a
+ // US or UK Windows layout, and
+ // LESS-THAN SIGN and GREATER-THAN SIGN
+ // in a Swiss German, German, or French
+ // layout. */
+ NONUSBACKSLASH = 100,
+ APPLICATION = 101, // windows contextual menu, compose
+ // The USB document says this is a status flag, not a physical key - but
+ // some Mac keyboards do have a power key.
+ POWER = 102,
+ KP_EQUALS = 103,
+ F13 = 104,
+ F14 = 105,
+ F15 = 106,
+ F16 = 107,
+ F17 = 108,
+ F18 = 109,
+ F19 = 110,
+ F20 = 111,
+ F21 = 112,
+ F22 = 113,
+ F23 = 114,
+ F24 = 115,
+ EXECUTE = 116,
+ HELP = 117,
+ MENU = 118,
+ SELECT = 119,
+ STOP = 120,
+ AGAIN = 121, // redo
+ UNDO = 122,
+ CUT = 123,
+ COPY = 124,
+ PASTE = 125,
+ FIND = 126,
+ MUTE = 127,
+ VOLUMEUP = 128,
+ VOLUMEDOWN = 129,
+// not sure whether there's a reason to enable these
+// LOCKINGCAPSLOCK = 130,
+// LOCKINGNUMLOCK = 131,
+// LOCKINGSCROLLLOCK = 132,
+ KP_COMMA = 133,
+ KP_EQUALSAS400 = 134,
+
+ // used on Asian keyboards, see footnotes in USB doc
+ INTERNATIONAL1 = 135,
+ INTERNATIONAL2 = 136,
+ INTERNATIONAL3 = 137, // Yen
+ INTERNATIONAL4 = 138,
+ INTERNATIONAL5 = 139,
+ INTERNATIONAL6 = 140,
+ INTERNATIONAL7 = 141,
+ INTERNATIONAL8 = 142,
+ INTERNATIONAL9 = 143,
+ LANG1 = 144, // Hangul/English toggle
+ LANG2 = 145, // Hanja conversion
+ LANG3 = 146, // Katakana
+ LANG4 = 147, // Hiragana
+ LANG5 = 148, // Zenkaku/Hankaku
+ LANG6 = 149, // reserved
+ LANG7 = 150, // reserved
+ LANG8 = 151, // reserved
+ LANG9 = 152, // reserved
+
+ ALTERASE = 153, // Erase-Eaze
+ SYSREQ = 154,
+ CANCEL = 155,
+ CLEAR = 156,
+ PRIOR = 157,
+ RETURN2 = 158,
+ SEPARATOR = 159,
+ OUT = 160,
+ OPER = 161,
+ CLEARAGAIN = 162,
+ CRSEL = 163,
+ EXSEL = 164,
+
+ KP_00 = 176,
+ KP_000 = 177,
+ THOUSANDSSEPARATOR = 178,
+ DECIMALSEPARATOR = 179,
+ CURRENCYUNIT = 180,
+ CURRENCYSUBUNIT = 181,
+ KP_LEFTPAREN = 182,
+ KP_RIGHTPAREN = 183,
+ KP_LEFTBRACE = 184,
+ KP_RIGHTBRACE = 185,
+ KP_TAB = 186,
+ KP_BACKSPACE = 187,
+ KP_A = 188,
+ KP_B = 189,
+ KP_C = 190,
+ KP_D = 191,
+ KP_E = 192,
+ KP_F = 193,
+ KP_XOR = 194,
+ KP_POWER = 195,
+ KP_PERCENT = 196,
+ KP_LESS = 197,
+ KP_GREATER = 198,
+ KP_AMPERSAND = 199,
+ KP_DBLAMPERSAND = 200,
+ KP_VERTICALBAR = 201,
+ KP_DBLVERTICALBAR = 202,
+ KP_COLON = 203,
+ KP_HASH = 204,
+ KP_SPACE = 205,
+ KP_AT = 206,
+ KP_EXCLAM = 207,
+ KP_MEMSTORE = 208,
+ KP_MEMRECALL = 209,
+ KP_MEMCLEAR = 210,
+ KP_MEMADD = 211,
+ KP_MEMSUBTRACT = 212,
+ KP_MEMMULTIPLY = 213,
+ KP_MEMDIVIDE = 214,
+ KP_PLUSMINUS = 215,
+ KP_CLEAR = 216,
+ KP_CLEARENTRY = 217,
+ KP_BINARY = 218,
+ KP_OCTAL = 219,
+ KP_DECIMAL = 220,
+ KP_HEXADECIMAL = 221,
+
+ LCTRL = 224,
+ LSHIFT = 225,
+ LALT = 226, // alt, option
+ LGUI = 227, // windows, command (apple), meta
+ RCTRL = 228,
+ RSHIFT = 229,
+ RALT = 230, // alt gr, option
+ RGUI = 231, // windows, command (apple), meta
+
+ // I'm not sure if this is really not covered by any of the above, but
+ // since there's a special KMOD_MODE for it I'm adding it here
+ MODE = 257,
+
+ // Usage page 0x0C
+ // These values are mapped from usage page 0x0C (USB consumer page).
+
+ AUDIONEXT = 258,
+ AUDIOPREV = 259,
+ AUDIOSTOP = 260,
+ AUDIOPLAY = 261,
+ AUDIOMUTE = 262,
+ MEDIASELECT = 263,
+ WWW = 264,
+ MAIL = 265,
+ CALCULATOR = 266,
+ COMPUTER = 267,
+ AC_SEARCH = 268,
+ AC_HOME = 269,
+ AC_BACK = 270,
+ AC_FORWARD = 271,
+ AC_STOP = 272,
+ AC_REFRESH = 273,
+ AC_BOOKMARKS = 274,
+
+ // Walther keys
+ // These are values that Christian Walther added (for mac keyboard?).
+
+ BRIGHTNESSDOWN = 275,
+ BRIGHTNESSUP = 276,
+ // display mirroring/dual display switch, video mode switch
+ DISPLAYSWITCH = 277,
+ KBDILLUMTOGGLE = 278,
+ KBDILLUMDOWN = 279,
+ KBDILLUMUP = 280,
+ EJECT = 281,
+ SLEEP = 282,
+
+ APP1 = 283,
+ APP2 = 284,
+
+ // Usage page 0x0C (additional media keys)
+ // These values are mapped from usage page 0x0C (USB consumer page).
+
+ AUDIOREWIND = 285,
+ AUDIOFASTFORWARD = 286,
+
+ // Add any other keys here.
+
+ // not a key, just marks the number of scancodes for array bounds
+ NUM_SCANCODES = 512,
+};
+
+export type SDL_Keycode = enum uint {
+ UNKNOWN = 0,
+
+ RETURN = '\r',
+ ESCAPE = '\x1B',
+ BACKSPACE = '\b',
+ TAB = '\t',
+ SPACE = ' ',
+ EXCLAIM = '!',
+ QUOTEDBL = '"',
+ HASH = '#',
+ PERCENT = '%',
+ DOLLAR = '$',
+ AMPERSAND = '&',
+ QUOTE = '\'',
+ LEFTPAREN = '(',
+ RIGHTPAREN = ')',
+ ASTERISK = '*',
+ PLUS = '+',
+ COMMA = ',',
+ MINUS = '-',
+ PERIOD = '.',
+ SLASH = '/',
+ ZERO = '0',
+ ONE = '1',
+ TWO = '2',
+ THREE = '3',
+ FOUR = '4',
+ FIVE = '5',
+ SIX = '6',
+ SEVEN = '7',
+ EIGHT = '8',
+ NINE = '9',
+ COLON = ':',
+ SEMICOLON = ';',
+ LESS = '<',
+ EQUALS = '=',
+ GREATER = '>',
+ QUESTION = '?',
+ AT = '@',
+
+ // Skip uppercase letters
+
+ LEFTBRACKET = '[',
+ BACKSLASH = '\\',
+ RIGHTBRACKET = ']',
+ CARET = '^',
+ UNDERSCORE = '_',
+ BACKQUOTE = '`',
+ a = 'a',
+ b = 'b',
+ c = 'c',
+ d = 'd',
+ e = 'e',
+ f = 'f',
+ g = 'g',
+ h = 'h',
+ i = 'i',
+ j = 'j',
+ k = 'k',
+ l = 'l',
+ m = 'm',
+ n = 'n',
+ o = 'o',
+ p = 'p',
+ q = 'q',
+ r = 'r',
+ s = 's',
+ t = 't',
+ u = 'u',
+ v = 'v',
+ w = 'w',
+ x = 'x',
+ y = 'y',
+ z = 'z',
+
+ CAPSLOCK = SDL_Scancode::CAPSLOCK | 1: SDL_Scancode << 30: SDL_Scancode,
+
+ F1 = SDL_Scancode::F1 | 1: SDL_Scancode << 30,
+ F2 = SDL_Scancode::F2 | 1: SDL_Scancode << 30,
+ F3 = SDL_Scancode::F3 | 1: SDL_Scancode << 30,
+ F4 = SDL_Scancode::F4 | 1: SDL_Scancode << 30,
+ F5 = SDL_Scancode::F5 | 1: SDL_Scancode << 30,
+ F6 = SDL_Scancode::F6 | 1: SDL_Scancode << 30,
+ F7 = SDL_Scancode::F7 | 1: SDL_Scancode << 30,
+ F8 = SDL_Scancode::F8 | 1: SDL_Scancode << 30,
+ F9 = SDL_Scancode::F9 | 1: SDL_Scancode << 30,
+ F10 = SDL_Scancode::F10 | 1: SDL_Scancode << 30,
+ F11 = SDL_Scancode::F11 | 1: SDL_Scancode << 30,
+ F12 = SDL_Scancode::F12 | 1: SDL_Scancode << 30,
+
+ PRINTSCREEN = SDL_Scancode::PRINTSCREEN | 1: SDL_Scancode << 30,
+ SCROLLLOCK = SDL_Scancode::SCROLLLOCK | 1: SDL_Scancode << 30,
+ PAUSE = SDL_Scancode::PAUSE | 1: SDL_Scancode << 30,
+ INSERT = SDL_Scancode::INSERT | 1: SDL_Scancode << 30,
+ HOME = SDL_Scancode::HOME | 1: SDL_Scancode << 30,
+ PAGEUP = SDL_Scancode::PAGEUP | 1: SDL_Scancode << 30,
+ DELETE = '\x7F',
+ END = SDL_Scancode::END | 1: SDL_Scancode << 30,
+ PAGEDOWN = SDL_Scancode::PAGEDOWN | 1: SDL_Scancode << 30,
+ RIGHT = SDL_Scancode::RIGHT | 1: SDL_Scancode << 30,
+ LEFT = SDL_Scancode::LEFT | 1: SDL_Scancode << 30,
+ DOWN = SDL_Scancode::DOWN | 1: SDL_Scancode << 30,
+ UP = SDL_Scancode::UP | 1: SDL_Scancode << 30,
+
+ NUMLOCKCLEAR = SDL_Scancode::NUMLOCKCLEAR | 1: SDL_Scancode << 30,
+ KP_DIVIDE = SDL_Scancode::KP_DIVIDE | 1: SDL_Scancode << 30,
+ KP_MULTIPLY = SDL_Scancode::KP_MULTIPLY | 1: SDL_Scancode << 30,
+ KP_MINUS = SDL_Scancode::KP_MINUS | 1: SDL_Scancode << 30,
+ KP_PLUS = SDL_Scancode::KP_PLUS | 1: SDL_Scancode << 30,
+ KP_ENTER = SDL_Scancode::KP_ENTER | 1: SDL_Scancode << 30,
+ KP_1 = SDL_Scancode::KP_1 | 1: SDL_Scancode << 30,
+ KP_2 = SDL_Scancode::KP_2 | 1: SDL_Scancode << 30,
+ KP_3 = SDL_Scancode::KP_3 | 1: SDL_Scancode << 30,
+ KP_4 = SDL_Scancode::KP_4 | 1: SDL_Scancode << 30,
+ KP_5 = SDL_Scancode::KP_5 | 1: SDL_Scancode << 30,
+ KP_6 = SDL_Scancode::KP_6 | 1: SDL_Scancode << 30,
+ KP_7 = SDL_Scancode::KP_7 | 1: SDL_Scancode << 30,
+ KP_8 = SDL_Scancode::KP_8 | 1: SDL_Scancode << 30,
+ KP_9 = SDL_Scancode::KP_9 | 1: SDL_Scancode << 30,
+ KP_0 = SDL_Scancode::KP_0 | 1: SDL_Scancode << 30,
+ KP_PERIOD = SDL_Scancode::KP_PERIOD | 1: SDL_Scancode << 30,
+
+ APPLICATION = SDL_Scancode::APPLICATION | 1: SDL_Scancode << 30,
+ POWER = SDL_Scancode::POWER | 1: SDL_Scancode << 30,
+ KP_EQUALS = SDL_Scancode::KP_EQUALS | 1: SDL_Scancode << 30,
+ F13 = SDL_Scancode::F13 | 1: SDL_Scancode << 30,
+ F14 = SDL_Scancode::F14 | 1: SDL_Scancode << 30,
+ F15 = SDL_Scancode::F15 | 1: SDL_Scancode << 30,
+ F16 = SDL_Scancode::F16 | 1: SDL_Scancode << 30,
+ F17 = SDL_Scancode::F17 | 1: SDL_Scancode << 30,
+ F18 = SDL_Scancode::F18 | 1: SDL_Scancode << 30,
+ F19 = SDL_Scancode::F19 | 1: SDL_Scancode << 30,
+ F20 = SDL_Scancode::F20 | 1: SDL_Scancode << 30,
+ F21 = SDL_Scancode::F21 | 1: SDL_Scancode << 30,
+ F22 = SDL_Scancode::F22 | 1: SDL_Scancode << 30,
+ F23 = SDL_Scancode::F23 | 1: SDL_Scancode << 30,
+ F24 = SDL_Scancode::F24 | 1: SDL_Scancode << 30,
+ EXECUTE = SDL_Scancode::EXECUTE | 1: SDL_Scancode << 30,
+ HELP = SDL_Scancode::HELP | 1: SDL_Scancode << 30,
+ MENU = SDL_Scancode::MENU | 1: SDL_Scancode << 30,
+ SELECT = SDL_Scancode::SELECT | 1: SDL_Scancode << 30,
+ STOP = SDL_Scancode::STOP | 1: SDL_Scancode << 30,
+ AGAIN = SDL_Scancode::AGAIN | 1: SDL_Scancode << 30,
+ UNDO = SDL_Scancode::UNDO | 1: SDL_Scancode << 30,
+ CUT = SDL_Scancode::CUT | 1: SDL_Scancode << 30,
+ COPY = SDL_Scancode::COPY | 1: SDL_Scancode << 30,
+ PASTE = SDL_Scancode::PASTE | 1: SDL_Scancode << 30,
+ FIND = SDL_Scancode::FIND | 1: SDL_Scancode << 30,
+ MUTE = SDL_Scancode::MUTE | 1: SDL_Scancode << 30,
+ VOLUMEUP = SDL_Scancode::VOLUMEUP | 1: SDL_Scancode << 30,
+ VOLUMEDOWN = SDL_Scancode::VOLUMEDOWN | 1: SDL_Scancode << 30,
+ KP_COMMA = SDL_Scancode::KP_COMMA | 1: SDL_Scancode << 30,
+ KP_EQUALSAS400 = SDL_Scancode::KP_EQUALSAS400 | 1: SDL_Scancode << 30,
+
+ ALTERASE = SDL_Scancode::ALTERASE | 1: SDL_Scancode << 30,
+ SYSREQ = SDL_Scancode::SYSREQ | 1: SDL_Scancode << 30,
+ CANCEL = SDL_Scancode::CANCEL | 1: SDL_Scancode << 30,
+ CLEAR = SDL_Scancode::CLEAR | 1: SDL_Scancode << 30,
+ PRIOR = SDL_Scancode::PRIOR | 1: SDL_Scancode << 30,
+ RETURN2 = SDL_Scancode::RETURN2 | 1: SDL_Scancode << 30,
+ SEPARATOR = SDL_Scancode::SEPARATOR | 1: SDL_Scancode << 30,
+ OUT = SDL_Scancode::OUT | 1: SDL_Scancode << 30,
+ OPER = SDL_Scancode::OPER | 1: SDL_Scancode << 30,
+ CLEARAGAIN = SDL_Scancode::CLEARAGAIN | 1: SDL_Scancode << 30,
+ CRSEL = SDL_Scancode::CRSEL | 1: SDL_Scancode << 30,
+ EXSEL = SDL_Scancode::EXSEL | 1: SDL_Scancode << 30,
+
+ KP_00 = SDL_Scancode::KP_00 | 1: SDL_Scancode << 30,
+ KP_000 = SDL_Scancode::KP_000 | 1: SDL_Scancode << 30,
+ THOUSANDSSEPARATOR = SDL_Scancode::THOUSANDSSEPARATOR | 1: SDL_Scancode << 30,
+ DECIMALSEPARATOR = SDL_Scancode::DECIMALSEPARATOR | 1: SDL_Scancode << 30,
+ CURRENCYUNIT = SDL_Scancode::CURRENCYUNIT | 1: SDL_Scancode << 30,
+ CURRENCYSUBUNIT = SDL_Scancode::CURRENCYSUBUNIT | 1: SDL_Scancode << 30,
+ KP_LEFTPAREN = SDL_Scancode::KP_LEFTPAREN | 1: SDL_Scancode << 30,
+ KP_RIGHTPAREN = SDL_Scancode::KP_RIGHTPAREN | 1: SDL_Scancode << 30,
+ KP_LEFTBRACE = SDL_Scancode::KP_LEFTBRACE | 1: SDL_Scancode << 30,
+ KP_RIGHTBRACE = SDL_Scancode::KP_RIGHTBRACE | 1: SDL_Scancode << 30,
+ KP_TAB = SDL_Scancode::KP_TAB | 1: SDL_Scancode << 30,
+ KP_BACKSPACE = SDL_Scancode::KP_BACKSPACE | 1: SDL_Scancode << 30,
+ KP_A = SDL_Scancode::KP_A | 1: SDL_Scancode << 30,
+ KP_B = SDL_Scancode::KP_B | 1: SDL_Scancode << 30,
+ KP_C = SDL_Scancode::KP_C | 1: SDL_Scancode << 30,
+ KP_D = SDL_Scancode::KP_D | 1: SDL_Scancode << 30,
+ KP_E = SDL_Scancode::KP_E | 1: SDL_Scancode << 30,
+ KP_F = SDL_Scancode::KP_F | 1: SDL_Scancode << 30,
+ KP_XOR = SDL_Scancode::KP_XOR | 1: SDL_Scancode << 30,
+ KP_POWER = SDL_Scancode::KP_POWER | 1: SDL_Scancode << 30,
+ KP_PERCENT = SDL_Scancode::KP_PERCENT | 1: SDL_Scancode << 30,
+ KP_LESS = SDL_Scancode::KP_LESS | 1: SDL_Scancode << 30,
+ KP_GREATER = SDL_Scancode::KP_GREATER | 1: SDL_Scancode << 30,
+ KP_AMPERSAND = SDL_Scancode::KP_AMPERSAND | 1: SDL_Scancode << 30,
+ KP_DBLAMPERSAND = SDL_Scancode::KP_DBLAMPERSAND | 1: SDL_Scancode << 30,
+ KP_VERTICALBAR = SDL_Scancode::KP_VERTICALBAR | 1: SDL_Scancode << 30,
+ KP_DBLVERTICALBAR = SDL_Scancode::KP_DBLVERTICALBAR | 1: SDL_Scancode << 30,
+ KP_COLON = SDL_Scancode::KP_COLON | 1: SDL_Scancode << 30,
+ KP_HASH = SDL_Scancode::KP_HASH | 1: SDL_Scancode << 30,
+ KP_SPACE = SDL_Scancode::KP_SPACE | 1: SDL_Scancode << 30,
+ KP_AT = SDL_Scancode::KP_AT | 1: SDL_Scancode << 30,
+ KP_EXCLAM = SDL_Scancode::KP_EXCLAM | 1: SDL_Scancode << 30,
+ KP_MEMSTORE = SDL_Scancode::KP_MEMSTORE | 1: SDL_Scancode << 30,
+ KP_MEMRECALL = SDL_Scancode::KP_MEMRECALL | 1: SDL_Scancode << 30,
+ KP_MEMCLEAR = SDL_Scancode::KP_MEMCLEAR | 1: SDL_Scancode << 30,
+ KP_MEMADD = SDL_Scancode::KP_MEMADD | 1: SDL_Scancode << 30,
+ KP_MEMSUBTRACT = SDL_Scancode::KP_MEMSUBTRACT | 1: SDL_Scancode << 30,
+ KP_MEMMULTIPLY = SDL_Scancode::KP_MEMMULTIPLY | 1: SDL_Scancode << 30,
+ KP_MEMDIVIDE = SDL_Scancode::KP_MEMDIVIDE | 1: SDL_Scancode << 30,
+ KP_PLUSMINUS = SDL_Scancode::KP_PLUSMINUS | 1: SDL_Scancode << 30,
+ KP_CLEAR = SDL_Scancode::KP_CLEAR | 1: SDL_Scancode << 30,
+ KP_CLEARENTRY = SDL_Scancode::KP_CLEARENTRY | 1: SDL_Scancode << 30,
+ KP_BINARY = SDL_Scancode::KP_BINARY | 1: SDL_Scancode << 30,
+ KP_OCTAL = SDL_Scancode::KP_OCTAL | 1: SDL_Scancode << 30,
+ KP_DECIMAL = SDL_Scancode::KP_DECIMAL | 1: SDL_Scancode << 30,
+ KP_HEXADECIMAL = SDL_Scancode::KP_HEXADECIMAL | 1: SDL_Scancode << 30,
+
+ LCTRL = SDL_Scancode::LCTRL | 1: SDL_Scancode << 30,
+ LSHIFT = SDL_Scancode::LSHIFT | 1: SDL_Scancode << 30,
+ LALT = SDL_Scancode::LALT | 1: SDL_Scancode << 30,
+ LGUI = SDL_Scancode::LGUI | 1: SDL_Scancode << 30,
+ RCTRL = SDL_Scancode::RCTRL | 1: SDL_Scancode << 30,
+ RSHIFT = SDL_Scancode::RSHIFT | 1: SDL_Scancode << 30,
+ RALT = SDL_Scancode::RALT | 1: SDL_Scancode << 30,
+ RGUI = SDL_Scancode::RGUI | 1: SDL_Scancode << 30,
+
+ MODE = SDL_Scancode::MODE | 1: SDL_Scancode << 30,
+
+ AUDIONEXT = SDL_Scancode::AUDIONEXT | 1: SDL_Scancode << 30,
+ AUDIOPREV = SDL_Scancode::AUDIOPREV | 1: SDL_Scancode << 30,
+ AUDIOSTOP = SDL_Scancode::AUDIOSTOP | 1: SDL_Scancode << 30,
+ AUDIOPLAY = SDL_Scancode::AUDIOPLAY | 1: SDL_Scancode << 30,
+ AUDIOMUTE = SDL_Scancode::AUDIOMUTE | 1: SDL_Scancode << 30,
+ MEDIASELECT = SDL_Scancode::MEDIASELECT | 1: SDL_Scancode << 30,
+ WWW = SDL_Scancode::WWW | 1: SDL_Scancode << 30,
+ MAIL = SDL_Scancode::MAIL | 1: SDL_Scancode << 30,
+ CALCULATOR = SDL_Scancode::CALCULATOR | 1: SDL_Scancode << 30,
+ COMPUTER = SDL_Scancode::COMPUTER | 1: SDL_Scancode << 30,
+ AC_SEARCH = SDL_Scancode::AC_SEARCH | 1: SDL_Scancode << 30,
+ AC_HOME = SDL_Scancode::AC_HOME | 1: SDL_Scancode << 30,
+ AC_BACK = SDL_Scancode::AC_BACK | 1: SDL_Scancode << 30,
+ AC_FORWARD = SDL_Scancode::AC_FORWARD | 1: SDL_Scancode << 30,
+ AC_STOP = SDL_Scancode::AC_STOP | 1: SDL_Scancode << 30,
+ AC_REFRESH = SDL_Scancode::AC_REFRESH | 1: SDL_Scancode << 30,
+ AC_BOOKMARKS = SDL_Scancode::AC_BOOKMARKS | 1: SDL_Scancode << 30,
+
+ BRIGHTNESSDOWN = SDL_Scancode::BRIGHTNESSDOWN | 1: SDL_Scancode << 30,
+ BRIGHTNESSUP = SDL_Scancode::BRIGHTNESSUP | 1: SDL_Scancode << 30,
+ DISPLAYSWITCH = SDL_Scancode::DISPLAYSWITCH | 1: SDL_Scancode << 30,
+ KBDILLUMTOGGLE = SDL_Scancode::KBDILLUMTOGGLE | 1: SDL_Scancode << 30,
+ KBDILLUMDOWN = SDL_Scancode::KBDILLUMDOWN | 1: SDL_Scancode << 30,
+ KBDILLUMUP = SDL_Scancode::KBDILLUMUP | 1: SDL_Scancode << 30,
+ EJECT = SDL_Scancode::EJECT | 1: SDL_Scancode << 30,
+ SLEEP = SDL_Scancode::SLEEP | 1: SDL_Scancode << 30,
+ APP1 = SDL_Scancode::APP1 | 1: SDL_Scancode << 30,
+ APP2 = SDL_Scancode::APP2 | 1: SDL_Scancode << 30,
+
+ AUDIOREWIND = SDL_Scancode::AUDIOREWIND | 1: SDL_Scancode << 30,
+ AUDIOFASTFORWARD = SDL_Scancode::AUDIOFASTFORWARD | 1: SDL_Scancode << 30
+};
+
+export type SDL_Keymod = enum u16 {
+ NONE = 0x0000,
+ LSHIFT = 0x0001,
+ RSHIFT = 0x0002,
+ LCTRL = 0x0040,
+ RCTRL = 0x0080,
+ LALT = 0x0100,
+ RALT = 0x0200,
+ LGUI = 0x0400,
+ RGUI = 0x0800,
+ NUM = 0x1000,
+ CAPS = 0x2000,
+ MODE = 0x4000,
+ SCROLL = 0x8000,
+
+ CTRL = LCTRL | RCTRL,
+ SHIFT = LSHIFT | RSHIFT,
+ ALT = LALT | RALT,
+ GUI = LGUI | RGUI,
+
+ RESERVED = SCROLL,
+};
+
+export type SDL_Keysym = struct {
+ scancode: SDL_Scancode,
+ sym: SDL_Keycode,
+ mod: SDL_Keymod,
+ unused: u32,
+};
+
+@symbol("SDL_GetKeyFromName") fn _SDL_GetKeyFromName(name: *const c::char) SDL_Keycode;
+
+export fn SDL_GetKeyFromName(name: str) (SDL_Keycode | error) = {
+ const name = c::fromstr(name);
+ defer free(name);
+ const sym = _SDL_GetKeyFromName(name);
+ if (sym == SDL_Keycode::UNKNOWN) {
+ return c::tostr(SDL_GetError()): error;
+ };
+ return sym;
+};
+
+@symbol("SDL_GetKeyboardState") fn _SDL_GetKeyboardState(numkeys: *int) *[*]bool;
+
+export fn SDL_GetKeyboardState() []bool = {
+ let numkeys: int = 0;
+ let arr = _SDL_GetKeyboardState(&numkeys);
+ let arr = arr[..numkeys];
+ return arr;
+};
diff --git a/sdl2/mixer/channels.ha b/sdl2/mixer/channels.ha
new file mode 100644
index 0000000..fffccd0
--- /dev/null
+++ b/sdl2/mixer/channels.ha
@@ -0,0 +1,20 @@
+use sdl2;
+
+@symbol("Mix_PlayChannelTimed") fn _Mix_PlayChannelTimed(
+ channel: int,
+ sample: *Mix_Chunk,
+ loops: int,
+ ticks: int,
+) int;
+
+// Play chunk on channel, or if channel is -1, pick the first free unreserved
+// channel. The sample will play for loops+1 number of times, unless stopped by
+// halt, or fade out, or setting a new expiration time of less time than it
+// would have originally taken to play the loops, or closing the mixer.
+export fn Mix_PlayChannelTimed(
+ channel: int,
+ sample: *Mix_Chunk,
+ loops: int,
+) (void | sdl2::error) = {
+ return sdl2::wrapvoid(_Mix_PlayChannelTimed(channel, sample, loops, -1));
+};
diff --git a/sdl2/mixer/general.ha b/sdl2/mixer/general.ha
new file mode 100644
index 0000000..87a729f
--- /dev/null
+++ b/sdl2/mixer/general.ha
@@ -0,0 +1,54 @@
+use sdl2;
+
+// Flags for [[init]].
+export type MIX_InitFlags = enum {
+ FLAC = 0x00000001,
+ MOD = 0x00000002,
+ MP3 = 0x00000008,
+ OGG = 0x00000010,
+ MID = 0x00000020,
+ OPUS = 0x00000040
+};
+
+// The default mixer has 8 simultaneous mixing channels
+export def MIX_CHANNELS: int = 8;
+
+// Good default frequency for a PC soundcard
+export def MIX_DEFAULT_FREQUENCY: int = 22050;
+
+// Good default channels for a PC soundcard
+export def MIX_DEFAULT_CHANNELS: int = 2;
+
+// XXX: This should choose MSB on a big-endian system:
+
+// Good default format for a PC soundcard
+export def MIX_DEFAULT_FORMAT: sdl2::SDL_AudioFormat = sdl2::AUDIO_S16LSB;
+
+@symbol("Mix_Init") fn _Mix_Init(flags: int) int;
+
+// Loads dynamic libraries and prepares them for use. Flags should be
+// one or more flags from [[MIX_InitFlags]] OR'd together.
+export fn Mix_Init(flags: MIX_InitFlags) (void | sdl2::error) = {
+ if (flags & _Mix_Init(flags) != flags) {
+ return "Mixer flags not initialized": sdl2::error;
+ };
+};
+
+// Unloads libraries loaded with [[Mix_Init]].
+export @symbol("Mix_Quit") fn Mix_Quit() void;
+
+@symbol("Mix_OpenAudio") fn _Mix_OpenAudio(frequency: int,
+ format: u16, channels: int, chunksize: int) int;
+
+// Open the mixer with a certain audio format
+export fn Mix_OpenAudio(
+ frequency: int,
+ format: sdl2::SDL_AudioFormat,
+ channels: int,
+ chunksize: int,
+) (void | sdl2::error) = {
+ return sdl2::wrapvoid(_Mix_OpenAudio(frequency, format, channels, chunksize));
+};
+
+// Close the mixer, halting all playing audio
+export @symbol("Mix_CloseAudio") fn Mix_CloseAudio() void;
diff --git a/sdl2/mixer/samples.ha b/sdl2/mixer/samples.ha
new file mode 100644
index 0000000..ad1ecc1
--- /dev/null
+++ b/sdl2/mixer/samples.ha
@@ -0,0 +1,38 @@
+use fs;
+use io;
+use os;
+use sdl2;
+
+// The internal format for an audio Mix_Chunk
+export type Mix_Chunk = struct {
+ allocated: int,
+ abuf: *u8,
+ alen: u32,
+ volume: u8,
+};
+
+@symbol("Mix_LoadWAV_RW") fn _Mix_LoadWAV_RW(src: *sdl2::SDL_RWops, freesrc: int) nullable *Mix_Chunk;
+
+// Loads a sample from an [[io::handle]].
+export fn Mix_LoadWAV_RW(src: io::handle) (*Mix_Chunk | sdl2::error) = {
+ const rw = sdl2::rw_from_handle(src);
+ return sdl2::wrapptr(_Mix_LoadWAV_RW(rw, 0))?: *Mix_Chunk;
+};
+
+// Loads a sample from a file path.
+export fn load_file(src: str) (*Mix_Chunk | fs::error | sdl2::error) = {
+ const file = os::open(src)?;
+ defer io::close(file)!;
+ return Mix_LoadWAV_RW(file);
+};
+
+// Free the memory used in Mix_Chunk, and free Mix_Chunk itself as well. Do not use
+// Mix_Chunk after this without loading a new sample to it. Note: It's a bad idea to
+// free a Mix_Chunk that is still being played...
+export @symbol("Mix_FreeChunk") fn Mix_FreeChunk(Mix_Chunk: *Mix_Chunk) void;
+
+// Maximum volume for a Mix_Chunk.
+export def MIX_MAX_VOLUME: int = 128; // XXX: SDL_mixer derives this from SDL_MIX_MAXVOLUME
+
+// Sets the Mix_Chunk volume as specified, returning the previous value.
+export @symbol("Mix_VolumeChunk") fn Mix_VolumeChunk(Mix_Chunk: *Mix_Chunk, volume: int) int;
diff --git a/sdl2/mouse.ha b/sdl2/mouse.ha
new file mode 100644
index 0000000..78ceb4d
--- /dev/null
+++ b/sdl2/mouse.ha
@@ -0,0 +1,58 @@
+export type SDL_Cursor = opaque;
+
+// Cursor types for [[SDL_CreateSystemCursor]]
+export type SDL_SystemCursor = enum uint {
+ ARROW, // Arrow
+ IBEAM, // I-beam
+ WAIT, // Wait
+ CROSSHAIR, // Crosshair
+ WAITARROW, // Small wait cursor (or Wait if not available)
+ SIZENWSE, // Double arrow pointing northwest and southeast
+ SIZENESW, // Double arrow pointing northeast and southwest
+ SIZEWE, // Double arrow pointing west and east
+ SIZENS, // Double arrow pointing north and south
+ SIZEALL, // Four pointed arrow pointing north, south, east, and west
+ NO, // Slashed circle or crossbones
+ HAND, // Hand
+};
+
+// Scroll direction types for the Scroll event
+export type SDL_MouseWheelDirection = enum uint {
+ NORMAL, // The scroll direction is normal
+ FLIPPED // The scroll direction is flipped / natural
+};
+
+// Get the window which currently has mouse focus.
+export @symbol("SDL_GetMouseFocus") fn SDL_GetMouseFocus() nullable *SDL_Window;
+
+// Retrieve the current state of the mouse.
+export @symbol("SDL_GetMouseState") fn SDL_GetMouseState(x: *int, y: *int) u32;
+
+@symbol("SDL_SetRelativeMouseMode") fn _SDL_SetRelativeMouseMode(
+ enabled: bool) int;
+
+// Set relative mouse mode.
+export fn SDL_SetRelativeMouseMode(enabled: bool) (void | error) = {
+ return wrapvoid(_SDL_SetRelativeMouseMode(enabled));
+};
+
+export @symbol("SDL_GetRelativeMouseState") fn SDL_GetRelativeMouseState(
+ x: *int, y: *int) u32;
+
+
+// Capture the mouse and to track input outside an SDL window.
+export @symbol("SDL_CaptureMouse") fn SDL_CaptureMouse(enabled: bool) int;
+
+// Toggle whether or not the cursor is shown.
+export @symbol("SDL_ShowCursor") fn SDL_ShowCursor(toggle: int) int;
+
+export def SDL_BUTTON_LEFT = 1;
+export def SDL_BUTTON_MIDDLE = 2;
+export def SDL_BUTTON_RIGHT = 3;
+export def SDL_BUTTON_X1 = 4;
+export def SDL_BUTTON_X2 = 5;
+export def SDL_BUTTON_LMASK = 1 << 0;
+export def SDL_BUTTON_MMASK = 1 << 1;
+export def SDL_BUTTON_RMASK = 1 << 2;
+export def SDL_BUTTON_X1MASK = 1 << 3;
+export def SDL_BUTTON_X2MASK = 1 << 4;
diff --git a/sdl2/pixels.ha b/sdl2/pixels.ha
new file mode 100644
index 0000000..7aa8733
--- /dev/null
+++ b/sdl2/pixels.ha
@@ -0,0 +1,55 @@
+// TODO: Flesh me out
+use types::c;
+
+export type SDL_Color = struct {
+ r: u8,
+ g: u8,
+ b: u8,
+ a: u8,
+};
+
+export type SDL_Palette = struct {
+ ncolors: int,
+ colors: *SDL_Color,
+ version: u32,
+ refcount: int,
+};
+
+// Note: Everything in the pixel format structure is read-only.
+export type SDL_PixelFormat = struct {
+ format: u32, // TODO
+ palette: *SDL_Palette,
+ bitsperpixel: u8,
+ bytesperpixel: u8,
+ padding: [2]u8,
+ rmask: u32,
+ gmask: u32,
+ bmask: u32,
+ amask: u32,
+ rloss: u8,
+ gloss: u8,
+ bloss: u8,
+ aloss: u8,
+ rshift: u8,
+ gshift: u8,
+ bshift: u8,
+ ashift: u8,
+ refcount: int,
+ next: nullable *SDL_PixelFormat,
+};
+
+export def SDL_PIXELFORMAT_ARGB8888: u32 = 0x16362004;
+
+@symbol("SDL_GetPixelFormatName") fn _SDL_GetPixelFormatName(format: u32)
+ const *c::char;
+
+// Get the human readable name of a pixel format.
+export fn SDL_GetPixelFormatName(format: u32) str = {
+ return c::tostr(_SDL_GetPixelFormatName(format))!;
+};
+
+// Map an RGB triple to an opaque pixel value for a given pixel format.
+export @symbol("SDL_MapRGB") fn SDL_MapRGB(format: *SDL_PixelFormat, r: u8, g: u8, b: u8) u32;
+
+// Map an RGBA quadruple to a pixel value for a given pixel format.
+export @symbol("SDL_MapRGBA") fn SDL_MapRGBA(format: *SDL_PixelFormat, r: u8, g: u8, b: u8, a: u8) u32;
diff --git a/sdl2/rect.ha b/sdl2/rect.ha
new file mode 100644
index 0000000..012088e
--- /dev/null
+++ b/sdl2/rect.ha
@@ -0,0 +1,29 @@
+// TODO: Flesh me out
+
+// The structure that defines a point (integer)
+export type SDL_Point = struct {
+ x: int,
+ y: int,
+};
+
+// The structure that defines a point (floating point)
+export type SDL_FPoint = struct {
+ x: f32,
+ y: f32,
+};
+
+// A rectangle, with the origin at the upper left (integer).
+export type SDL_Rect = struct {
+ x: int,
+ y: int,
+ w: int,
+ h: int,
+};
+
+// A rectangle, with the origin at the upper left (floating point).
+export type SDL_FRect = struct {
+ x: f32,
+ y: f32,
+ w: f32,
+ h: f32,
+};
diff --git a/sdl2/render.ha b/sdl2/render.ha
new file mode 100644
index 0000000..192d608
--- /dev/null
+++ b/sdl2/render.ha
@@ -0,0 +1,371 @@
+// TODO: Flesh me out
+
+// A structure representing rendering state. (Opaque)
+export type SDL_Renderer = opaque;
+
+// An efficient driver-specific representation of pixel data. (Opaque)
+export type SDL_Texture = opaque;
+
+export type SDLPixelFormatValues = enum u32 {
+ SDL_PIXELFORMAT_UNKNOWN,
+ SDL_PIXELFORMAT_INDEX1LSB,
+ SDL_PIXELFORMAT_INDEX1MSB,
+ SDL_PIXELFORMAT_INDEX4LSB,
+ SDL_PIXELFORMAT_INDEX4MSB,
+ SDL_PIXELFORMAT_INDEX8,
+ SDL_PIXELFORMAT_RGB332,
+ SDL_PIXELFORMAT_RGB444,
+ SDL_PIXELFORMAT_RGB555,
+ SDL_PIXELFORMAT_BGR555,
+ SDL_PIXELFORMAT_ARGB4444,
+ SDL_PIXELFORMAT_RGBA4444,
+ SDL_PIXELFORMAT_ABGR4444,
+ SDL_PIXELFORMAT_BGRA4444,
+ SDL_PIXELFORMAT_ARGB1555,
+ SDL_PIXELFORMAT_RGBA5551,
+ SDL_PIXELFORMAT_ABGR1555,
+ SDL_PIXELFORMAT_BGRA5551,
+ SDL_PIXELFORMAT_RGB565,
+ SDL_PIXELFORMAT_BGR565,
+ SDL_PIXELFORMAT_RGB24,
+ SDL_PIXELFORMAT_BGR24,
+ SDL_PIXELFORMAT_RGB888,
+ SDL_PIXELFORMAT_RGBX8888,
+ SDL_PIXELFORMAT_BGR888,
+ SDL_PIXELFORMAT_BGRX8888,
+ SDL_PIXELFORMAT_ARGB8888,
+ SDL_PIXELFORMAT_RGBA8888,
+ SDL_PIXELFORMAT_ABGR8888,
+ SDL_PIXELFORMAT_BGRA8888,
+};
+
+// Flags used when creating a rendering context.
+export type SDL_RendererFlags = enum u32 {
+ NONE = 0,
+ SOFTWARE = 0x00000001,
+ ACCELERATED = 0x00000002,
+ PRESENTVSYNC = 0x00000004,
+ TARGETTEXTURE = 0x00000008,
+};
+
+export type SDL_RendererFlip = enum u32 {
+ SDL_FLIP_NONE,
+ SDL_FLIP_HORIZONTAL,
+ SDL_FLIP_VERTICAL,
+ SDL_FLIP_BOTH,
+};
+
+export type SDL_TextureAccess = enum {
+ SDL_TEXTUREACCESS_STATIC,
+ SDL_TEXTUREACCESS_STREAMING,
+ SDL_TEXTUREACCESS_TARGET,
+};
+
+@symbol("SDL_CreateWindowAndRenderer") fn _SDL_CreateWindowAndRenderer(
+ width: int, height: int, SDL_WindowFlags: SDL_WindowFlags,
+ window: nullable **SDL_Window, renderer: nullable **SDL_Renderer) int;
+
+// Create a window and default renderer.
+//
+// 'width' and 'height' set the width and height of the window, in screen
+// coordinates. 'SDL_WindowFlags' configure additional window parameters.
+//
+// 'window' and 'renderer' are out parameters, or null, which are filled in with
+// the created window and renderer respectively.
+export fn SDL_CreateWindowAndRenderer(
+ width: int,
+ height: int,
+ SDL_WindowFlags: SDL_WindowFlags,
+ window: nullable **SDL_Window,
+ renderer: nullable **SDL_Renderer,
+) (void | error) = wrapvoid(_SDL_CreateWindowAndRenderer(width, height,
+ SDL_WindowFlags, window, renderer));
+
+@symbol("SDL_CreateRenderer") fn _SDL_CreateRenderer(window: *SDL_Window,
+ index: int, flags: SDL_RendererFlags) nullable *SDL_Renderer;
+
+// Create a 2D rendering context for a window.
+//
+// 'window' is the window where rendering is displayed. 'index' is the index of
+// the rendering driver to initialize, or -1 to initialize the first one
+// supporting the requested flags.
+//
+// See also: [[create_software_renderer]], [[get_renderer_info]],
+// [[SDL_DestroyRenderer]].
+export fn SDL_CreateRenderer(
+ window: *SDL_Window,
+ index: int,
+ flags: SDL_RendererFlags,
+) (*SDL_Renderer | error) =
+ wrapptr(_SDL_CreateRenderer(window, index, flags))?: *SDL_Renderer;
+
+// Destroy the rendering context for a window and free associated textures.
+//
+// See also: [[SDL_CreateRenderer]].
+export @symbol("SDL_DestroyRenderer") fn SDL_DestroyRenderer(renderer: *SDL_Renderer) void;
+
+@symbol("SDL_GetRendererOutputSize") fn _SDL_GetRendererOutputSize(renderer: *SDL_Renderer,
+ w: *int, h: *int) int;
+
+// Get the output size in pixels of a rendering context.
+export fn SDL_GetRendererOutputSize(
+ renderer: *SDL_Renderer,
+ w: *int, h: *int,
+) (void | error) = wrapvoid(_SDL_GetRendererOutputSize(renderer, w, h));
+
+// Opaque value for the alpha channel (255).
+export def ALPHA_OPAQUE: u8 = 255;
+
+@symbol("SDL_SetRenderDrawColor") fn _SDL_SetRenderDrawColor(renderer: *SDL_Renderer,
+ r: u8, g: u8, b: u8, a: u8) int;
+
+// Set the color used for drawing operations (Rect, Line and Clear).
+//
+// 'renderer' is the renderer for which drawing color should be set. 'r', 'g',
+// 'b', and 'a' respectively set the red, gree, blue, and alpha channels.
+export fn SDL_SetRenderDrawColor(
+ renderer: *SDL_Renderer,
+ r: u8, g: u8, b: u8, a: u8,
+) (void | error) = wrapvoid(_SDL_SetRenderDrawColor(renderer, r, g, b, a));
+
+@symbol("SDL_RenderClear") fn _SDL_RenderClear(renderer: *SDL_Renderer) int;
+
+// Clear the current rendering target with the drawing color
+//
+// This function clears the entire rendering target, ignoring the viewport and
+// the clip rectangle.
+export fn SDL_RenderClear(renderer: *SDL_Renderer) (void | error) = {
+ return wrapvoid(_SDL_RenderClear(renderer));
+};
+
+// Update the screen with rendering performed.
+export @symbol("SDL_RenderPresent") fn SDL_RenderPresent(renderer: *SDL_Renderer) void;
+
+// Destroy the specified texture.
+export @symbol("SDL_DestroyTexture") fn SDL_DestroyTexture(texture: *SDL_Texture) void;
+
+@symbol("SDL_QueryTexture") fn _SDL_QueryTexture(texture: *SDL_Texture,
+ format: nullable *u32, access: nullable *int,
+ w: nullable *int, h: nullable *int) int;
+
+// Query the attributes of a texture
+export fn SDL_QueryTexture(
+ texture: *SDL_Texture,
+ format: nullable *u32,
+ access: nullable *int,
+ w: nullable *int, h: nullable *int,
+) (void | error) = {
+ return wrapvoid(_SDL_QueryTexture(texture, format, access, w, h));
+};
+
+@symbol("SDL_SetTextureColorMod") fn _SDL_SetTextureColorMod(
+ texture: *SDL_Texture, r: u8, g: u8, b: u8) int;
+
+// Set an additional color value multiplied into render copy operations.
+//
+// When this texture is rendered, during the copy operation each source color
+// channel is modulated by the appropriate color value according to the
+// following formula:
+//
+// srcC = srcC * (color / 255)
+//
+// Color modulation is not always supported by the renderer; it will return -1
+// if color modulation is not supported.
+export fn SDL_SetTextureColorMod(
+ texture: *SDL_Texture,
+ r: u8, g: u8, b: u8,
+) (void | error) = {
+ return wrapvoid(_SDL_SetTextureColorMod(texture, r, g, b));
+};
+
+@symbol("SDL_SetTextureAlphaMod") fn _SDL_SetTextureAlphaMod(texture: *SDL_Texture, a: u8) int;
+
+// Set an additional alpha value multiplied into render copy operations.
+//
+// When this texture is rendered, during the copy operation the source alpha
+// value is modulated by this alpha value according to the following formula:
+//
+// `srcA = srcA * (alpha / 255)`
+//
+// Alpha modulation is not always supported by the renderer; it will return an
+// error if alpha modulation is not supported.
+export fn SDL_SetTextureAlphaMod(texture: *SDL_Texture, a: u8) (void | error) = {
+ // TODO: Double check errors
+ return wrapvoid(_SDL_SetTextureAlphaMod(texture, a));
+};
+
+@symbol("SDL_SetTextureBlendMode") fn _SDL_SetTextureBlendMode(
+ texture: *SDL_Texture, mode: SDL_BlendMode) int;
+
+// Set the blend mode for a texture, used by SDL_RenderCopy().
+export fn SDL_SetTextureBlendMode(
+ texture: *SDL_Texture,
+ mode: SDL_BlendMode,
+) (void | error) = {
+ return wrapvoid(_SDL_SetTextureBlendMode(texture, mode));
+};
+
+@symbol("SDL_SetRenderDrawBlendMode") fn _SDL_SetRenderDrawBlendMode(
+ renderer: *SDL_Renderer, mode: SDL_BlendMode) int;
+
+// Set the blend mode used for drawing operations (fill and line).
+export fn SDL_SetRenderDrawBlendMode(
+ renderer: *SDL_Renderer,
+ mode: SDL_BlendMode,
+) (void | error) = {
+ return wrapvoid(_SDL_SetRenderDrawBlendMode(renderer, mode));
+};
+
+@symbol("SDL_RenderDrawPoint") fn _SDL_RenderDrawPoint(
+ renderer: *SDL_Renderer,
+ x: int,
+ y: int,
+) int;
+
+// Draws a point (pixel) at the given coordinates
+export fn SDL_RenderDrawPoint(
+ renderer: *SDL_Renderer,
+ x: int,
+ y: int,
+) (void | error) = {
+ return wrapvoid(_SDL_RenderDrawPoint(renderer, x, y));
+};
+
+@symbol("SDL_RenderCopy") fn _SDL_RenderCopy(renderer: *SDL_Renderer,
+ texture: *SDL_Texture, srcrect: nullable *SDL_Rect, dstrect: nullable *SDL_Rect) int;
+
+// Copy a portion of the texture to the current rendering target.
+export fn SDL_RenderCopy(
+ renderer: *SDL_Renderer,
+ texture: *SDL_Texture,
+ srcrect: nullable *SDL_Rect,
+ dstrect: nullable *SDL_Rect,
+) (void | error) = {
+ return wrapvoid(_SDL_RenderCopy(renderer, texture, srcrect, dstrect));
+};
+
+@symbol("SDL_RenderCopyEx") fn _SDL_RenderCopyEx(
+ renderer: *SDL_Renderer,
+ texture: *SDL_Texture,
+ srcrect: nullable *SDL_Rect,
+ dstrect: nullable *SDL_Rect,
+ angle : f64,
+ center: nullable *SDL_Point,
+ flip: SDL_RendererFlip,
+) int;
+
+// Sets the rendering pixel scale
+export fn SDL_RenderCopyEx(
+ renderer: *SDL_Renderer,
+ texture: *SDL_Texture,
+ srcrect: nullable *SDL_Rect,
+ dstrect: nullable *SDL_Rect,
+ angle : f64,
+ center: nullable *SDL_Point,
+ flip: SDL_RendererFlip,
+) (void | error) = {
+ return wrapvoid(_SDL_RenderCopyEx(
+ renderer, texture, srcrect, dstrect, angle, center, flip)
+ );
+};
+
+@symbol("SDL_RenderDrawRect") fn _SDL_RenderDrawRect(
+ renderer: *SDL_Renderer, rect: const nullable *SDL_Rect) int;
+
+// Draw a rectangle on the current rendering target.
+export fn SDL_RenderDrawRect(
+ renderer: *SDL_Renderer,
+ rect: const nullable *SDL_Rect,
+) (void | error) = {
+ return wrapvoid(_SDL_RenderDrawRect(renderer, rect));
+};
+
+@symbol("SDL_RenderFillRect") fn _SDL_RenderFillRect(
+ renderer: *SDL_Renderer, rect: const nullable *SDL_Rect) int;
+
+// Fills a rectangle on the current rendering target.
+export fn SDL_RenderFillRect(
+ renderer: *SDL_Renderer,
+ rect: const nullable *SDL_Rect,
+) (void | error) = {
+ return wrapvoid(_SDL_RenderFillRect(renderer, rect));
+};
+
+@symbol("SDL_RenderSetLogicalSize") fn _SDL_RenderSetLogicalSize(
+ renderer: *SDL_Renderer, w: int, h: int) int;
+
+// Sets the rendering pixel scale
+export fn SDL_RenderSetLogicalSize(
+ renderer: *SDL_Renderer,
+ w: int,
+ h: int,
+) (void | error) = {
+ return wrapvoid(_SDL_RenderSetLogicalSize(
+ renderer, w, h)
+ );
+};
+
+@symbol("SDL_CreateTexture") fn _SDL_CreateTexture(
+ renderer: *SDL_Renderer,
+ format: u32,
+ access: int,
+ w: int,
+ h: int) nullable *SDL_Texture;
+
+export fn SDL_CreateTexture(
+ renderer: *SDL_Renderer,
+ format: u32,
+ access: int,
+ w: int,
+ h: int
+) (*SDL_Texture | error) = {
+ return wrapptr(_SDL_CreateTexture(
+ renderer, format, access, w, h)
+ )?: *SDL_Texture;
+};
+
+@symbol("SDL_CreateTextureFromSurface") fn _SDL_CreateTextureFromSurface(
+ renderer: *SDL_Renderer,
+ surface: *SDL_Surface) nullable *SDL_Texture;
+
+export fn SDL_CreateTextureFromSurface(
+ renderer: *SDL_Renderer,
+ surface: *SDL_Surface
+) (*SDL_Texture | error) = {
+ return wrapptr(_SDL_CreateTextureFromSurface(renderer, surface))?: *SDL_Texture;
+};
+
+@symbol("SDL_UpdateTexture") fn _SDL_UpdateTexture(texture: *SDL_Texture,
+ rect: const nullable *SDL_Rect, pixels: const nullable *opaque, pitch: int) int;
+
+// Update the given texture rectangle with new pixel data.
+export fn SDL_UpdateTexture(texture: *SDL_Texture,
+ rect: const nullable *SDL_Rect, pixels: const nullable *opaque, pitch: int)
+ (int | error) = {
+ return wrapint(_SDL_UpdateTexture(texture, rect, pixels, pitch))?: int;
+};
+
+@symbol("SDL_LockTexture") fn _SDL_LockTexture(texture: *SDL_Texture,
+ rect: const nullable *SDL_Rect, pixels: nullable * nullable *opaque, pitch: *int) int;
+
+// Lock a portion of the texture for write-only pixel access.
+export fn SDL_LockTexture(texture: *SDL_Texture,
+ rect: const nullable *SDL_Rect, pixels: nullable * nullable *opaque, pitch: *int)
+ (int | error) = {
+ return wrapint(_SDL_LockTexture(texture, rect, pixels, pitch))?: int;
+};
+
+// Unlock a texture, uploading the changes to video memory, if needed.
+export @symbol("SDL_UnlockTexture") fn SDL_UnlockTexture(texture: *SDL_Texture) void;
+
+@symbol("SDL_RenderSetScale") fn _SDL_RenderSetScale(
+ renderer: *SDL_Renderer, scaleX: f32, scaleY: f32) int;
+
+// Sets the rendering pixel scale
+export fn SDL_RenderSetScale(
+ renderer: *SDL_Renderer,
+ scaleX: f32,
+ scaleY: f32,
+) (void | error) = {
+ return wrapvoid(_SDL_RenderSetScale(renderer, scaleX, scaleY));
+};
diff --git a/sdl2/rwops.ha b/sdl2/rwops.ha
new file mode 100644
index 0000000..4605a3a
--- /dev/null
+++ b/sdl2/rwops.ha
@@ -0,0 +1,134 @@
+use io;
+use types::c;
+
+// RWops types
+export type rwops_type = enum u32 {
+ UNKNOWN = 0,
+ WINFILE = 1,
+ STDFILE = 2,
+ JNIFILE = 3,
+ MEMORY = 4,
+ MEMORY_RO = 5,
+};
+
+// The read/write operation structure -- very basic.
+export type SDL_RWops = struct {
+ sz: *fn(ctx: *SDL_RWops) i64,
+ seek: *fn(ctx: *SDL_RWops, offs: i64, whence: int) i64,
+ read: *fn(ctx: *SDL_RWops, ptr: *opaque, sz: size, maxnum: size) size,
+ write: *fn(ctx: *SDL_RWops, ptr: *const opaque, sz: size, num: size) size,
+ close: *fn(ctx: *SDL_RWops) int,
+
+ type_: rwops_type,
+ // XXX: This union is platform-specific
+ hidden: union {
+ stdio: struct {
+ autoclose: bool,
+ fp: nullable *opaque, // FILE *
+ },
+ mem: struct {
+ base: nullable *u8,
+ here: nullable *u8,
+ stop: nullable *u8,
+ },
+ unknown: struct {
+ data1: nullable *opaque,
+ data2: nullable *opaque,
+ },
+ },
+};
+
+@symbol("SDL_RWFromFile") fn _rw_from_file(
+ file: const *c::char,
+ mode: const *c::char,
+) *SDL_RWops;
+
+// Returns the size of an [[SDL_RWops]], or 0 if unknown or error.
+//
+// See [[stream_from_rw]] for a more idiomatic Hare interface to SDL_RWops.
+export @symbol("SDL_RWsize") fn SDL_RWsize(ctx: *SDL_RWops) i64;
+
+// Closes an [[SDL_RWops]], returning 1 on success or 0 on error.
+//
+// See [[stream_from_rw]] for a more idiomatic Hare interface to SDL_RWops.
+export @symbol("SDL_RWclose") fn SDL_RWclose(ctx: *SDL_RWops) int;
+
+// TODO: Other RWops wrappers
+
+// Creates an [[SDL_RWops]] from an [[io::handle]]. Closing the rwops does not close
+// the underlying stream.
+export fn rw_from_handle(in: io::handle) *SDL_RWops = {
+ // TODO: Add stream_from_rw
+ let rw = alloc(SDL_RWops {
+ sz = &stream_size,
+ seek = &stream_seek,
+ read = &stream_read,
+ write = &stream_write,
+ close = &stream_close,
+ type_ = rwops_type::UNKNOWN,
+ ...
+ });
+ // Assert that we can cram an io::handle into the SDL_RWops struct
+ static assert(size(io::handle) <= size(nullable *u8) * 2);
+ let ptr = &rw.hidden.unknown.data1: *io::handle;
+ *ptr = in;
+ return rw;
+};
+
+fn stream_size(ctx: *SDL_RWops) i64 = {
+ const handle = *(&ctx.hidden.unknown.data1: *io::handle);
+ const old = match (io::tell(handle)) {
+ case let o: io::off =>
+ yield o;
+ case io::error =>
+ return -1;
+ };
+ io::seek(handle, 0, io::whence::END)!;
+ const sz = io::tell(handle)!;
+ io::seek(handle, old, io::whence::SET)!;
+ return sz;
+};
+
+fn stream_seek(ctx: *SDL_RWops, offs: i64, whence: int) i64 = {
+ const handle = *(&ctx.hidden.unknown.data1: *io::handle);
+ // Note: whence values in stdio.h match io::whence
+ match (io::seek(handle, offs: io::off, whence: io::whence)) {
+ case let o: io::off =>
+ return o;
+ case io::error =>
+ return -1;
+ };
+};
+
+fn stream_read(ctx: *SDL_RWops, ptr: *opaque, sz: size, maxnum: size) size = {
+ const handle = *(&ctx.hidden.unknown.data1: *io::handle);
+ let buf = ptr: *[*]u8;
+ match (io::readall(handle, buf[..sz * maxnum])) {
+ case let n: size =>
+ return n / sz;
+ case io::EOF =>
+ return 0;
+ case io::error =>
+ return 0;
+ };
+};
+
+fn stream_write(ctx: *SDL_RWops, ptr: *const opaque, sz: size, num: size) size = {
+ const handle = *(&ctx.hidden.unknown.data1: *io::handle);
+ let buf = ptr: *[*]const u8;
+ match (io::writeall(handle, buf[..sz * num])) {
+ case let n: size =>
+ return n / sz;
+ case io::error =>
+ return 0;
+ };
+};
+
+fn stream_close(ctx: *SDL_RWops) int = {
+ const handle = *(&ctx.hidden.unknown.data1: *io::handle);
+ free(ctx);
+ match (io::close(handle)) {
+ case void => return 0;
+ case io::error => return -1;
+ };
+};
diff --git a/sdl2/sdl2.ha b/sdl2/sdl2.ha
new file mode 100644
index 0000000..7035e04
--- /dev/null
+++ b/sdl2/sdl2.ha
@@ -0,0 +1,23 @@
+export def SDL_INIT_TIMER: uint = 0x00000001u;
+export def SDL_INIT_AUDIO: uint = 0x00000010u;
+export def SDL_INIT_VIDEO: uint = 0x00000020u;
+export def SDL_INIT_JOYSTICK: uint = 0x00000200u;
+export def SDL_INIT_HAPTIC: uint = 0x00001000u;
+export def SDL_INIT_GAMECONTROLLER: uint = 0x00002000u;
+export def SDL_INIT_EVENTS: uint = 0x00004000u;
+export def SDL_INIT_SENSOR: uint = 0x00008000u;
+export def SDL_INIT_NOPARACHUTE: uint = 0x00100000u;
+export def SDL_INIT_EVERYTHING: uint = SDL_INIT_TIMER | SDL_INIT_AUDIO | SDL_INIT_VIDEO
+ | SDL_INIT_EVENTS | SDL_INIT_JOYSTICK | SDL_INIT_HAPTIC
+ | SDL_INIT_GAMECONTROLLER | SDL_INIT_SENSOR;
+
+@symbol("SDL_Init") fn _SDL_Init(flags: uint) int;
+
+// This function initializes the subsystems specified by 'flags'.
+export fn SDL_Init(flags: uint) (void | error) = {
+ return wrapvoid(_SDL_Init(flags));
+};
+
+// This function cleans up all initialized subsystems. You should call it upon
+// all exit conditions.
+export @symbol("SDL_Quit") fn SDL_Quit() void;
diff --git a/sdl2/surface.ha b/sdl2/surface.ha
new file mode 100644
index 0000000..afca40c
--- /dev/null
+++ b/sdl2/surface.ha
@@ -0,0 +1,53 @@
+// A collection of pixels used in software blitting.
+//
+// This structure should be treated as read-only, except for 'pixels', which, if
+// not null, contains the raw pixel data for the surface.
+export type SDL_Surface = struct {
+ flags: u32,
+ format: *SDL_PixelFormat,
+ w: int,
+ h: int,
+ pitch: int,
+ pixels: nullable *opaque,
+
+ userdata: *opaque,
+
+ locked: int,
+ lock_data: *opaque,
+
+ clip_rect: SDL_Rect,
+
+ map: *SDL_BlitMap,
+
+ refcount: int,
+};
+
+export type SDL_BlitMap = opaque;
+
+@symbol("SDL_CreateRGBSurface") fn _SDL_CreateRGBSurface(flags: u32,
+ width: int, height: int, depth: int, Rmask: u32, Gmask: u32, Bmask: u32,
+ Amask: u32) *SDL_Surface;
+
+// Allocate a new RGB surface.
+export fn SDL_CreateRGBSurface(flags: u32,
+ width: int, height: int, depth: int, Rmask: u32, Gmask: u32, Bmask: u32,
+ Amask: u32) (*SDL_Surface | error) = {
+ return wrapptr(_SDL_CreateRGBSurface(flags, width, height, depth, Rmask,
+ Gmask, Bmask, Amask))?: *SDL_Surface;
+};
+
+@symbol("SDL_FreeSurface") fn _SDL_FreeSurface(surface: nullable *SDL_Surface) void;
+
+// Free an RGB surface.
+export fn SDL_FreeSurface(surface: nullable *SDL_Surface) void = {
+ _SDL_FreeSurface(surface);
+};
+
+// NB SDL_BlitSurface is aliased to SDL_UpperBlit via a macro in the SDL header
+@symbol("SDL_UpperBlit") fn _SDL_BlitSurface(src: *SDL_Surface,
+ srcrect: nullable *SDL_Rect, dst: *SDL_Surface, dstrect: nullable *SDL_Rect) int;
+
+// Perform a fast surface copy to a destination surface.
+export fn SDL_BlitSurface(src: *SDL_Surface, srcrect: nullable *SDL_Rect, dst: *SDL_Surface, dstrect: nullable *SDL_Rect) (void | error) = {
+ return wrapvoid(_SDL_BlitSurface(src, srcrect, dst, dstrect));
+};
diff --git a/sdl2/timer.ha b/sdl2/timer.ha
new file mode 100644
index 0000000..d90511a
--- /dev/null
+++ b/sdl2/timer.ha
@@ -0,0 +1,32 @@
+// Get the number of milliseconds since SDL library initialization.
+//
+// This value wraps if the program runs for more than ~49 days.
+//
+// Returns an unsigned 32-bit value representing the number of milliseconds
+// since the SDL library initialized.
+export @symbol("SDL_GetTicks") fn SDL_GetTicks() u32;
+
+// Get the current value of the high resolution counter.
+//
+// This function is typically used for profiling.
+//
+// The counter values are only meaningful relative to each other. Differences
+// between values can be converted to times by using
+// [[SDL_GetPerformanceFrequency]].
+//
+// Returns the current counter value.
+export @symbol("SDL_GetPerformanceCounter") fn SDL_GetPerformanceCounter() u64;
+
+// Get the count per second of the high resolution counter.
+//
+// Returns a platform-specific count per second.
+export @symbol("SDL_GetPerformanceFrequency") fn SDL_GetPerformanceFrequency() u64;
+
+// Wait a specified number of milliseconds before returning.
+//
+// This function waits a specified number of milliseconds before returning. It
+// waits at least the specified time, but possibly longer due to OS
+// scheduling.
+export @symbol("SDL_Delay") fn SDL_Delay(ms: u32) void;
+
+// TODO: Timers
diff --git a/sdl2/video.ha b/sdl2/video.ha
new file mode 100644
index 0000000..c786122
--- /dev/null
+++ b/sdl2/video.ha
@@ -0,0 +1,141 @@
+// TODO: Flesh me out
+use types::c;
+
+// The type used to identify a window. (Opaque)
+export type SDL_Window = opaque;
+
+// The flags on a window
+export type SDL_WindowFlags = enum u32 {
+ NONE = 0,
+ FULLSCREEN = 0x00000001,
+ OPENGL = 0x00000002,
+ SHOWN = 0x00000004,
+ HIDDEN = 0x00000008,
+ BORDERLESS = 0x00000010,
+ RESIZABLE = 0x00000020,
+ MINIMIZED = 0x00000040,
+ MAXIMIZED = 0x00000080,
+ INPUT_GRABBED = 0x00000100,
+ INPUT_FOCUS = 0x00000200,
+ MOUSE_FOCUS = 0x00000400,
+ FULLSCREEN_DESKTOP = 0x00001001,
+ FOREIGN = 0x00000800,
+ ALLOW_HIGHDPI = 0x00002000,
+ MOUSE_CAPTURE = 0x00004000,
+ ALWAYS_ON_TOP = 0x00008000,
+ SKIP_TASKBAR = 0x00010000,
+ UTILITY = 0x00020000,
+ TOOLTIP = 0x00040000,
+ POPUP_MENU = 0x00080000,
+ VULKAN = 0x10000000
+};
+
+export def SDL_WINDOWPOS_UNDEFINED: int = 0x1FFF0000;
+export def SDL_WINDOWPOS_CENTERED: int = 0x2FFF0000;
+
+@symbol("SDL_CreateWindow") fn _SDL_CreateWindow(title: const *c::char,
+ x: int, y: int, w: int, h: int, flags: SDL_WindowFlags) nullable *SDL_Window;
+
+// Create a window with the specified position, dimensions, and flags.
+//
+// 'title' is the title of the window, in UTF-8 encoding. See [[types::c::fromstr]]
+// to prepare a suitable string.
+//
+// 'x' and 'y' set the position of the window, or use [[SDL_WINDOWPOS_CENTERED]] or
+// [[SDL_WINDOWPOS_UNDEFINED]].
+//
+// 'w' and 'h' set the width and height of the window, in screen coordinates.
+//
+// 'flags' configure additional window parameters.
+//
+// Returns the created window, or null if window creation failed.
+//
+// If the window is created with the SDL_WINDOW_ALLOW_HIGHDPI flag, its size
+// in pixels may differ from its size in screen coordinates on platforms with
+// high-DPI support (e.g. iOS and Mac OS X). Use SDL_GetWindowSize() to query
+// the client area's size in screen coordinates, and SDL_GL_GetDrawableSize(),
+// SDL_Vulkan_GetDrawableSize(), or SDL_GetRendererOutputSize() to query the
+// drawable size in pixels.
+//
+// If the window is created with any of the SDL_WINDOW_OPENGL or
+// SDL_WINDOW_VULKAN flags, then the corresponding LoadLibrary function
+// (SDL_GL_LoadLibrary or SDL_Vulkan_LoadLibrary) is called and the
+// corresponding UnloadLibrary function is called by SDL_DestroyWindow().
+//
+// If SDL_WINDOW_VULKAN is specified and there isn't a working Vulkan driver,
+// SDL_CreateWindow() will fail because SDL_Vulkan_LoadLibrary() will fail.
+//
+// Note: On non-Apple devices, SDL requires you to either not link to the
+// Vulkan loader or link to a dynamic library version. This limitation may be
+// removed in a future version of SDL.
+//
+// See also: [[SDL_DestroyWindow]] [[gl_loadlibrary]], [[vulkan_loadlibrary]].
+export fn SDL_CreateWindow(
+ title: str,
+ x: int,
+ y: int,
+ w: int,
+ h: int,
+ flags: SDL_WindowFlags,
+) (*SDL_Window | error) = {
+ let title = c::fromstr(title);
+ defer free(title);
+ return wrapptr(_SDL_CreateWindow(title, x, y, w, h, flags))?: *SDL_Window;
+};
+
+// Destroy a window.
+export @symbol("SDL_DestroyWindow") fn SDL_DestroyWindow(window: *SDL_Window) void;
+
+// Get the size of a window's client area.
+//
+// Null may safely be passed as the 'w' or 'h' parameter if the width or
+// height value is not desired.
+//
+// The window size in screen coordinates may differ from the size in pixels, if
+// the window was created with `ALLOW_HIGHDPI` on a platform with high-dpi
+// support (e.g. iOS or macOS). Use [[gl_getdrawablesize]],
+// [[vulkan_getdrawablesize]], or [[getrendereroutputsize]] to get the real
+// client area size in pixels.
+export @symbol("SDL_GetWindowSize") fn SDL_GetWindowSize(window: *SDL_Window,
+ w: nullable *int, h: nullable *int) void;
+
+@symbol("SDL_GetWindowSurface") fn _SDL_GetWindowSurface(window: *SDL_Window)
+ *SDL_Surface;
+
+// Get the SDL surface associated with the window.
+export fn SDL_GetWindowSurface(window: *SDL_Window) (*SDL_Surface | error) = {
+ return wrapptr(_SDL_GetWindowSurface(window))?: *SDL_Surface;
+};
+
+// Copy the window surface to the screen.
+@symbol("SDL_UpdateWindowSurface") fn _SDL_UpdateWindowSurface(window: *SDL_Window)
+ int;
+
+export fn SDL_UpdateWindowSurface(window: *SDL_Window) (void | error) = {
+ return wrapvoid(_SDL_UpdateWindowSurface(window));
+};
+
+@symbol("SDL_GetCurrentVideoDriver") fn _SDL_GetCurrentVideoDriver()
+ nullable *const c::char;
+
+export fn SDL_GetCurrentVideoDriver() str = {
+ match (_SDL_GetCurrentVideoDriver()) {
+ case null =>
+ return "";
+ case let s: *const c::char =>
+ return c::tostr(s)!;
+ };
+};
+
+@symbol("SDL_SetWindowFullscreen") fn _SDL_SetWindowFullscreen(
+ window: *SDL_Window, flags: SDL_WindowFlags) int;
+
+export fn SDL_SetWindowFullscreen(
+ window: *SDL_Window,
+ flags: SDL_WindowFlags,
+) (void | error) = {
+ return wrapvoid(_SDL_SetWindowFullscreen(window, flags));
+};
+
+export @symbol("SDL_GetWindowFlags") fn SDL_GetWindowFlags(window: *SDL_Window)
+ SDL_WindowFlags;