From ae44478b30d890fe0fb04022f44d474dcdcc3f9d Mon Sep 17 00:00:00 2001 From: Lassi Pulkkinen Date: Thu, 31 Oct 2024 03:11:21 +0200 Subject: Initial commit (import old repo) --- sdl2/COPYING | 371 ++++++++++++++++++++++++++++ sdl2/audio.ha | 31 +++ sdl2/blendmode.ha | 11 + sdl2/errors.ha | 31 +++ sdl2/events.ha | 494 +++++++++++++++++++++++++++++++++++++ sdl2/gamecontroller.ha | 99 ++++++++ sdl2/gl.ha | 82 +++++++ sdl2/image/image.ha | 46 ++++ sdl2/joystick.ha | 12 + sdl2/keyboard.ha | 654 +++++++++++++++++++++++++++++++++++++++++++++++++ sdl2/mixer/channels.ha | 20 ++ sdl2/mixer/general.ha | 54 ++++ sdl2/mixer/samples.ha | 38 +++ sdl2/mouse.ha | 58 +++++ sdl2/pixels.ha | 55 +++++ sdl2/rect.ha | 29 +++ sdl2/render.ha | 371 ++++++++++++++++++++++++++++ sdl2/rwops.ha | 134 ++++++++++ sdl2/sdl2.ha | 23 ++ sdl2/surface.ha | 53 ++++ sdl2/timer.ha | 32 +++ sdl2/video.ha | 141 +++++++++++ 22 files changed, 2839 insertions(+) create mode 100644 sdl2/COPYING create mode 100644 sdl2/audio.ha create mode 100644 sdl2/blendmode.ha create mode 100644 sdl2/errors.ha create mode 100644 sdl2/events.ha create mode 100644 sdl2/gamecontroller.ha create mode 100644 sdl2/gl.ha create mode 100644 sdl2/image/image.ha create mode 100644 sdl2/joystick.ha create mode 100644 sdl2/keyboard.ha create mode 100644 sdl2/mixer/channels.ha create mode 100644 sdl2/mixer/general.ha create mode 100644 sdl2/mixer/samples.ha create mode 100644 sdl2/mouse.ha create mode 100644 sdl2/pixels.ha create mode 100644 sdl2/rect.ha create mode 100644 sdl2/render.ha create mode 100644 sdl2/rwops.ha create mode 100644 sdl2/sdl2.ha create mode 100644 sdl2/surface.ha create mode 100644 sdl2/timer.ha create mode 100644 sdl2/video.ha (limited to 'sdl2') 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; -- cgit v1.2.3