From a1f6500c822e46594e635170ae08de8de107a876 Mon Sep 17 00:00:00 2001 From: Drew DeVault Date: Thu, 9 Dec 2021 12:03:25 +0100 Subject: Initial commit --- .gitignore | 2 + COPYING | 367 +++++++++++++++++++++++++++++++++++++++++++++++++++++ Makefile | 10 ++ cmd/demo/main.ha | 8 ++ sdl2/prototypes.ha | 21 +++ 5 files changed, 408 insertions(+) create mode 100644 .gitignore create mode 100644 COPYING create mode 100644 Makefile create mode 100644 cmd/demo/main.ha create mode 100644 sdl2/prototypes.ha diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..245fe5c --- /dev/null +++ b/.gitignore @@ -0,0 +1,2 @@ +demo +!./cmd/demo/ diff --git a/COPYING b/COPYING new file mode 100644 index 0000000..c257317 --- /dev/null +++ b/COPYING @@ -0,0 +1,367 @@ +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/Makefile b/Makefile new file mode 100644 index 0000000..dd2d9dd --- /dev/null +++ b/Makefile @@ -0,0 +1,10 @@ +.POSIX: +.SUFFIXES: + +demo: + hare build -lSDL2 -lc -T+libc cmd/demo + +run: demo + ./demo + +.PHONY: demo run diff --git a/cmd/demo/main.ha b/cmd/demo/main.ha new file mode 100644 index 0000000..1a8e362 --- /dev/null +++ b/cmd/demo/main.ha @@ -0,0 +1,8 @@ +use sdl2; +use os; + +export fn main() void = { + sdl2::init(sdl2::init_flags::VIDEO); + defer sdl2::quit(); + os::exit(0); +}; diff --git a/sdl2/prototypes.ha b/sdl2/prototypes.ha new file mode 100644 index 0000000..b71c890 --- /dev/null +++ b/sdl2/prototypes.ha @@ -0,0 +1,21 @@ +// These are the flags which may be passed to [[init]]. You should specify the +// subsystems which you will be using in your application. +export type init_flags = enum uint { + TIMER = 0x00000001u, + AUDIO = 0x00000010u, + VIDEO = 0x00000020u, + JOYSTICK = 0x00000200u, + HAPTIC = 0x00001000u, + GAMECONTROLLER = 0x00002000u, + EVENTS = 0x00004000u, + SENSOR = 0x00008000u, + NOPARACHUTE = 0x00100000u, + EVERYTHING = TIMER | AUDIO | VIDEO | EVENTS | JOYSTICK | HAPTIC | GAMECONTROLLER | SENSOR, +}; + +// This function initializes the subsystems specified by 'flags'. +export @symbol("SDL_Init") fn init(flags: init_flags) void; + +// This function cleans up all initialized subsystems. You should call it upon +// all exit conditions. +export @symbol("SDL_Quit") fn quit() void; -- cgit v1.2.3 From 01bb53f01d5d8b732bd80a84f25b661e1452faeb Mon Sep 17 00:00:00 2001 From: Drew DeVault Date: Thu, 9 Dec 2021 13:06:45 +0100 Subject: Rig up events, partially rig up video --- Makefile | 4 +- cmd/demo/main.ha | 29 +++- sdl2/events.ha | 448 +++++++++++++++++++++++++++++++++++++++++++++++++++++ sdl2/prototypes.ha | 21 --- sdl2/sdl2.ha | 21 +++ sdl2/video.ha | 73 +++++++++ 6 files changed, 571 insertions(+), 25 deletions(-) create mode 100644 sdl2/events.ha delete mode 100644 sdl2/prototypes.ha create mode 100644 sdl2/sdl2.ha create mode 100644 sdl2/video.ha diff --git a/Makefile b/Makefile index dd2d9dd..fa692a8 100644 --- a/Makefile +++ b/Makefile @@ -4,7 +4,7 @@ demo: hare build -lSDL2 -lc -T+libc cmd/demo -run: demo - ./demo +run: + hare run -lSDL2 -lc -T+libc cmd/demo .PHONY: demo run diff --git a/cmd/demo/main.ha b/cmd/demo/main.ha index 1a8e362..1c780fd 100644 --- a/cmd/demo/main.ha +++ b/cmd/demo/main.ha @@ -1,8 +1,33 @@ -use sdl2; +use fmt; use os; +use sdl2::{event_type, window_flags}; +use sdl2; +use strings; export fn main() void = { sdl2::init(sdl2::init_flags::VIDEO); defer sdl2::quit(); - os::exit(0); + + const title = strings::to_c("Hare SDL2 demo"); + defer free(title); + const win = match (sdl2::create_window(title, + sdl2::WINDOWPOS_UNDEFINED, sdl2::WINDOWPOS_UNDEFINED, + 640, 480, window_flags::NONE)) { + case let win: *sdl2::window => + yield win; + case null => + fmt::fatal("sdl2::create_window failed"); + }; + defer sdl2::destroy_window(win); + + let ev = sdl2::event { ... }; + for (sdl2::wait_event(&ev) == 1) { + switch (ev.event_type) { + case event_type::QUIT => + break; + case => void; + }; + }; + + os::exit(0); // https://todo.sr.ht/~sircmpwn/hare/525 }; diff --git a/sdl2/events.ha b/sdl2/events.ha new file mode 100644 index 0000000..60ac771 --- /dev/null +++ b/sdl2/events.ha @@ -0,0 +1,448 @@ +export type event_type = 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 common_event = struct { + event_type: event_type, + timestamp: u32, +}; + +// Display state change event data (event.display.*) +export type display_event = struct { + common_event, + display: u32, + event: u8, + padding1: u8, + padding2: u8, + padding3: u8, + data1: i32, +}; + +// Window state change event data (event.window.*) +export type window_event = struct { + common_event, + window_id: u32, + event: u8, + padding1: u8, + padding2: u8, + padding3: u8, + data1: i32, + data2: i32, +}; + +// Keyboard button event structure (event.key.*) +export type keyboard_event = struct { + common_event, + window_id: u32, + state: u8, + repeat: u8, + padding2: u8, + padding3: u8, + keysym: uint, // TODO: Rig me up with the keysym type +}; + +// Size of the [[text_editing_event]] 'text' field. +export def TEXTEDITINGEVENT_TEXT_SIZE: size = 32; + +// Keyboard text editing event structure (event.edit.*) +export type text_editing_event = struct { + common_event, + window_id: u32, + text: [TEXTEDITINGEVENT_TEXT_SIZE]char, + start: i32, + length: i32, +}; + +// Size of the [[text_input_event]] 'text' field. +export def TEXTINPUTEVENT_TEXT_SIZE: size = 32; + +// Keyboard text input event structure (event.text.*) +export type text_input_event = struct { + common_event, + window_id: u32, + text: [TEXTINPUTEVENT_TEXT_SIZE]char, +}; + +// Mouse motion event structure (event.motion.*) +export type mouse_motion_event = struct { + common_event, + window_id: u32, + which: u32, + state: u32, + x: i32, + y: i32, + xrel: i32, + yrel: i32, +}; + +// Mouse button event structure (event.button.*) +export type mouse_button_event = struct { + common_event, + 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 mouse_wheel_event = struct { + common_event, + window_id: u32, + which: u32, + x: i32, + y: i32, + direction: u32, +}; + +// Joystick axis motion event structure (event.jaxis.*) +export type joy_axis_event = struct { + common_event, + 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 joy_ball_event = struct { + common_event, + 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 joy_hat_event = struct { + common_event, + 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 joy_button_event = struct { + common_event, + 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 joy_device_event = struct { + common_event, + which: i32, +}; + +// Game controller axis motion event structure (event.caxis.*) +export type controller_axis_event = struct { + common_event, + which: i32, // TODO + axis: u8, + padding1: u8, + padding2: u8, + padding3: u8, + value: i16, + padding4: u16, +}; + +// Game controller button event structure (event.cbutton.*) +export type controller_button_event = struct { + common_event, + which: i32, + button: u8, + state: u8, + padding1: u8, + padding2: u8, +}; + +// Controller device event structure (event.cdevice.*) +export type controller_device_event = struct { + common_event, + which: i32, +}; + +// Audio device event structure (event.adevice.*) +export type audio_device_event = struct { + common_event, + which: u32, + iscapture: u8, + padding1: u8, + padding2: u8, + padding3: u8, +}; + +// Touch finger event structure (event.tfinger.*) +export type touch_finger_event = struct { + common_event, + 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 multi_gesture_event = struct { + common_event, + touch_id: i64, // TODO + dtheta: f32, + ddist: f32, + x: f32, + y: f32, + num_fingers: u16, + padding: u16, +}; + +// Dollar Gesture Event (event.dgesture.*) +export type dollar_gesture_event = struct { + common_event, + 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 drop_event = struct { + common_event, + file: *char, + window_id: u32, +}; + +// Sensor event structure (event.sensor.*) +export type sensor_event = struct { + common_event, + which: i32, + data: [6]f32, +}; + +// The "quit requested" event +export type quit_event = struct { + common_event, +}; + +// OS Specific event +export type os_event = struct { + common_event, +}; + +// A user-defined event type (event.user.*) +export type user_event = struct { + common_event, + window_id: u32, + code: i32, + data1: *void, + data2: *void, +}; + +// A video driver dependent system event (event.syswm.*) +// This event is disabled by default, you can enable it with [[eventstate]]. +export type syswm_event = struct { + common_event, + msg: *void, // TODO +}; + +// General event structure +export type event = union { + event_type: event_type, + common: common_event, + display: display_event, + window: window_event, + key: keyboard_event, + edit: text_editing_event, + text: text_input_event, + motion: mouse_motion_event, + button: mouse_button_event, + wheel: mouse_wheel_event, + jaxis: joy_axis_event, + jball: joy_ball_event, + jhat: joy_hat_event, + jbutton: joy_button_event, + jdevice: joy_device_event, + caxis: controller_axis_event, + cbutton: controller_button_event, + cdevice: controller_device_event, + adevice: audio_device_event, + sensor: sensor_event, + quit: quit_event, + user: user_event, + syswm: syswm_event, + tfinger: touch_finger_event, + mgesture: multi_gesture_event, + dgestures: dollar_gesture_event, + drop: drop_event, + + 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 pump_events() void; + +export type eventaction = enum { + ADDEVENT, + PEEKEVENT, + GETEVENT, +}; + +// 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. +// +// Returns the number of events actually stored, or -1 if there was an error. +// +// This function is thread-safe. +export @symbol("SDL_PeepEvents") fn peep_events(events: *event, numevents: int, + action: eventaction, mintype: event_type, maxtype: event_type) int; + +// Checks to see if certain event types are in the event queue. +export @symbol("SDL_HasEvent") fn has_event(event_type: event_type) bool; + +// Checks to see if certain event types are in the event queue. +export @symbol("SDL_HasEvents") fn has_events(mintype: event_type, maxtype: event_type) 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(event_type: event_type) 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 flush_events(mintype: event_type, maxtype: event_type) void; + +// 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 @symbol("SDL_PollEvent") fn poll_event(event: nullable *event) int; + +// Waits indefinitely for the next available event. +// +// Returns 1, or 0 if there was an error while waiting for events. +// +// If 'event' is not null, the next event is removed from the queue and stored +// in that area. +export @symbol("SDL_WaitEvent") fn wait_event(event: nullable *event) int; + +// Waits until the specified timeout (in milliseconds) for the next available event. +// +// Returns 1, or 0 if there was an error while waiting for events. +// +// 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 @symbol("SDL_WaitEventTimeout") fn wait_event_timeout(event: nullable *event, timeout: int) int; + +// Add an event to the event queue. +// +// Returns 1 on success, 0 if the event was filtered, or -1 if the event queue +// was full or there was some other error. +export @symbol("SDL_PushEvent") fn push_event(event: *event) int; + +// TODO: Finish rigging up other SDL_events.h bits diff --git a/sdl2/prototypes.ha b/sdl2/prototypes.ha deleted file mode 100644 index b71c890..0000000 --- a/sdl2/prototypes.ha +++ /dev/null @@ -1,21 +0,0 @@ -// These are the flags which may be passed to [[init]]. You should specify the -// subsystems which you will be using in your application. -export type init_flags = enum uint { - TIMER = 0x00000001u, - AUDIO = 0x00000010u, - VIDEO = 0x00000020u, - JOYSTICK = 0x00000200u, - HAPTIC = 0x00001000u, - GAMECONTROLLER = 0x00002000u, - EVENTS = 0x00004000u, - SENSOR = 0x00008000u, - NOPARACHUTE = 0x00100000u, - EVERYTHING = TIMER | AUDIO | VIDEO | EVENTS | JOYSTICK | HAPTIC | GAMECONTROLLER | SENSOR, -}; - -// This function initializes the subsystems specified by 'flags'. -export @symbol("SDL_Init") fn init(flags: init_flags) void; - -// This function cleans up all initialized subsystems. You should call it upon -// all exit conditions. -export @symbol("SDL_Quit") fn quit() void; diff --git a/sdl2/sdl2.ha b/sdl2/sdl2.ha new file mode 100644 index 0000000..b71c890 --- /dev/null +++ b/sdl2/sdl2.ha @@ -0,0 +1,21 @@ +// These are the flags which may be passed to [[init]]. You should specify the +// subsystems which you will be using in your application. +export type init_flags = enum uint { + TIMER = 0x00000001u, + AUDIO = 0x00000010u, + VIDEO = 0x00000020u, + JOYSTICK = 0x00000200u, + HAPTIC = 0x00001000u, + GAMECONTROLLER = 0x00002000u, + EVENTS = 0x00004000u, + SENSOR = 0x00008000u, + NOPARACHUTE = 0x00100000u, + EVERYTHING = TIMER | AUDIO | VIDEO | EVENTS | JOYSTICK | HAPTIC | GAMECONTROLLER | SENSOR, +}; + +// This function initializes the subsystems specified by 'flags'. +export @symbol("SDL_Init") fn init(flags: init_flags) void; + +// This function cleans up all initialized subsystems. You should call it upon +// all exit conditions. +export @symbol("SDL_Quit") fn quit() void; diff --git a/sdl2/video.ha b/sdl2/video.ha new file mode 100644 index 0000000..e12ca12 --- /dev/null +++ b/sdl2/video.ha @@ -0,0 +1,73 @@ +// TODO: Flesh me out + +// The type used to identify a window. (Opaque) +export type window = void; + +// The flags on a window +export type window_flags = 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 WINDOWPOS_UNDEFINED: int = 0x1FFF0000; +export def WINDOWPOS_CENTERED: int = 0x2FFF0000; + +// Create a window with the specified position, dimensions, and flags. +// +// 'title' is the title of the window, in UTF-8 encoding. See [[strings::to_c]] +// to prepare a suitable string. +// +// 'x' and 'y' set the position of the window, or use [[WINDOWPOS_CENTERED]] or +// [[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: [[destroy_window]] [[gl_loadlibrary]], [[vulkan_loadlibrary]]. +export @symbol("SDL_CreateWindow") fn create_window(title: const *char, + x: int, y: int, w: int, h: int, flags: window_flags) nullable *window; + +// Destroy a window. +export @symbol("SDL_DestroyWindow") fn destroy_window(window: *window) void; -- cgit v1.2.3 From c468d6aadfdddbce8898ce2f2b3a8cd700b80dc1 Mon Sep 17 00:00:00 2001 From: Drew DeVault Date: Thu, 9 Dec 2021 13:23:14 +0100 Subject: Initial work on SDL_render --- cmd/demo/main.ha | 14 +++++++++++- sdl2/render.ha | 70 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 83 insertions(+), 1 deletion(-) create mode 100644 sdl2/render.ha diff --git a/cmd/demo/main.ha b/cmd/demo/main.ha index 1c780fd..26025ce 100644 --- a/cmd/demo/main.ha +++ b/cmd/demo/main.ha @@ -1,6 +1,6 @@ use fmt; use os; -use sdl2::{event_type, window_flags}; +use sdl2::{event_type, window_flags, renderer_flags}; use sdl2; use strings; @@ -20,6 +20,18 @@ export fn main() void = { }; defer sdl2::destroy_window(win); + const render = match (sdl2::create_renderer(win, -1, renderer_flags::NONE)) { + case let rend: *sdl2::renderer => + yield rend; + case null => + fmt::fatal("sdl2::create_renderer failed"); + }; + defer sdl2::destroy_renderer(render); + + sdl2::set_render_draw_color(render, 255, 0, 0, 255); + sdl2::render_clear(render); + sdl2::render_present(render); + let ev = sdl2::event { ... }; for (sdl2::wait_event(&ev) == 1) { switch (ev.event_type) { diff --git a/sdl2/render.ha b/sdl2/render.ha new file mode 100644 index 0000000..e1d2c8e --- /dev/null +++ b/sdl2/render.ha @@ -0,0 +1,70 @@ +// TODO: Flesh me out + +// A structure representing rendering state. (Opaque) +export type renderer = void; + +// An efficient driver-specific representation of pixel data. (Opaque) +export type texture = void; + +// Flags used when creating a rendering context. +export type renderer_flags = enum u32 { + NONE = 0, + SOFTWARE = 0x00000001, + ACCELERATED = 0x00000002, + PRESENTVSYNC = 0x00000004, + TARGETTEXTURE = 0x00000008, +}; + +// Create a window and default renderer. +// +// 'width' and 'height' set the width and height of the window, in screen +// coordinates. 'window_flags' configure additional window parameters. +// +// 'window' and 'renderer' are out parameters, or null, which are filled in with +// the created window and renderer respectively. +// +// Returns 0 on success, or -1 on error. +export @symbol("SDL_CreateWindowAndRenderer") fn create_window_and_renderer( + width: int, height: int, window_flags: window_flags, + window: nullable **window, renderer: nullable **renderer) int; + +// 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. +// +// Returns a valid rendering context, or NULL if there was an error. +// +// See also: [[create_software_renderer]], [[get_renderer_info]], +// [[destroy_renderer]]. +export @symbol("SDL_CreateRenderer") fn create_renderer(window: *window, + index: int, flags: renderer_flags) nullable *renderer; + +// Destroy the rendering context for a window and free associated textures. +// +// See also: [[create_renderer]]. +export @symbol("SDL_DestroyRenderer") fn destroy_renderer(renderer: *renderer) void; + +// Opaque value for the alpha channel (255). +export def ALPHA_OPAQUE: u8 = 255; + +// 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. +// +// Returns 0 on success, or -1 on error +export @symbol("SDL_SetRenderDrawColor") fn set_render_draw_color(renderer: *renderer, + r: u8, g: u8, b: u8, a: u8) int; + +// Clear the current rendering target with the drawing color +// +// This function clears the entire rendering target, ignoring the viewport and +// the clip rectangle. +// +// Returns 0 on success, or -1 on error +export @symbol("SDL_RenderClear") fn render_clear(renderer: *renderer) int; + +// Update the screen with rendering performed. +export @symbol("SDL_RenderPresent") fn render_present(renderer: *renderer) void; -- cgit v1.2.3 From 3eb0c138b61e4d3256592ebc993f45b92e2d25f5 Mon Sep 17 00:00:00 2001 From: Drew DeVault Date: Thu, 9 Dec 2021 13:26:59 +0100 Subject: Add README.md --- README.md | 8 ++++++++ 1 file changed, 8 insertions(+) create mode 100644 README.md diff --git a/README.md b/README.md new file mode 100644 index 0000000..6374285 --- /dev/null +++ b/README.md @@ -0,0 +1,8 @@ +# hare-sdl2 + +These are WIP bindings between [Hare] and [SDL2]. + +Please do not make GUIs with this. + +[Hare]: https://harelang.org +[SDL2]: https://libsdl.org -- cgit v1.2.3 From 07046a3b2c2d0b6a5dfaaab70e5ea71e8334df1b Mon Sep 17 00:00:00 2001 From: Drew DeVault Date: Thu, 9 Dec 2021 14:36:32 +0100 Subject: sdl2::image: initial commit Some additional things which were needed to make this work were also added. --- Makefile | 6 ++++-- cat.png | Bin 0 -> 34282 bytes cmd/demo/main.ha | 24 +++++++++++++++++++++++- sdl2/image/image.ha | 28 ++++++++++++++++++++++++++++ sdl2/pixels.ha | 38 ++++++++++++++++++++++++++++++++++++++ sdl2/rect.ha | 29 +++++++++++++++++++++++++++++ sdl2/render.ha | 16 ++++++++++++++++ sdl2/surface.ha | 25 +++++++++++++++++++++++++ 8 files changed, 163 insertions(+), 3 deletions(-) create mode 100644 cat.png create mode 100644 sdl2/image/image.ha create mode 100644 sdl2/pixels.ha create mode 100644 sdl2/rect.ha create mode 100644 sdl2/surface.ha diff --git a/Makefile b/Makefile index fa692a8..f6eb43f 100644 --- a/Makefile +++ b/Makefile @@ -1,10 +1,12 @@ .POSIX: .SUFFIXES: +LIBS=-lc -lSDL2_image -lSDL2 + demo: - hare build -lSDL2 -lc -T+libc cmd/demo + hare build $(LIBS) -T+libc cmd/demo run: - hare run -lSDL2 -lc -T+libc cmd/demo + hare run $(LIBS) -T+libc cmd/demo .PHONY: demo run diff --git a/cat.png b/cat.png new file mode 100644 index 0000000..0bf91cb Binary files /dev/null and b/cat.png differ diff --git a/cmd/demo/main.ha b/cmd/demo/main.ha index 26025ce..35da638 100644 --- a/cmd/demo/main.ha +++ b/cmd/demo/main.ha @@ -2,11 +2,14 @@ use fmt; use os; use sdl2::{event_type, window_flags, renderer_flags}; use sdl2; +use sdl2::image; use strings; export fn main() void = { sdl2::init(sdl2::init_flags::VIDEO); defer sdl2::quit(); + image::init(image::init_flags::PNG); + defer image::quit(); const title = strings::to_c("Hare SDL2 demo"); defer free(title); @@ -28,8 +31,27 @@ export fn main() void = { }; defer sdl2::destroy_renderer(render); - sdl2::set_render_draw_color(render, 255, 0, 0, 255); + const path = strings::to_c("cat.png"); + defer free(path); + const texture = match (image::load_texture(render, path)) { + case let tex: *sdl2::texture => + yield tex; + case null => + fmt::fatal("sdl2::image::load_texture failed"); + }; + defer sdl2::destroy_texture(texture); + + let width = 0, height = 0; + sdl2::query_texture(texture, null, null, &width, &height); + + sdl2::set_render_draw_color(render, 50, 50, 50, 255); sdl2::render_clear(render); + sdl2::render_copy(render, texture, null, &sdl2::rect { + x = 0, + y = 0, + w = width, + h = height, + }); sdl2::render_present(render); let ev = sdl2::event { ... }; diff --git a/sdl2/image/image.ha b/sdl2/image/image.ha new file mode 100644 index 0000000..03301e9 --- /dev/null +++ b/sdl2/image/image.ha @@ -0,0 +1,28 @@ +// TODO: Flesh me out +// TODO: SDL_RWops +use sdl2; + +// Flags for [[init]]. +export type init_flags = enum int { + NONE = 0, + JPG = 0x00000001, + PNG = 0x00000002, + TIF = 0x00000004, + WEBP = 0x00000008, +}; + +// Loads dynamic libraries and prepares them for use. Flags should be one or +// more flags from IMG_InitFlags OR'd together. +// +// Returns the flags successfully initialized, or 0 on failure. +export @symbol("IMG_Init") fn init(flags: init_flags) int; + +// Unloads libraries loaded with [[init]] +export @symbol("IMG_Quit") fn quit() void; + +// Load an image from a file path. +export @symbol("IMG_Load") fn load(file: const *char) nullable *sdl2::surface; + +// Load an image directly into a render texture. +export @symbol("IMG_LoadTexture") fn load_texture(renderer: *sdl2::renderer, + file: const *char) nullable *sdl2::texture; diff --git a/sdl2/pixels.ha b/sdl2/pixels.ha new file mode 100644 index 0000000..8227067 --- /dev/null +++ b/sdl2/pixels.ha @@ -0,0 +1,38 @@ +// TODO: Flesh me out + +export type color = struct { + r: u8, + g: u8, + b: u8, + a: u8, +}; + +export type palette = struct { + ncolors: int, + colors: *color, + version: u32, + refcount: int, +}; + +// Note: Everything in the pixel format structure is read-only. +export type pixelformat = struct { + format: u32, // TODO + palette: *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 *pixelformat, +}; diff --git a/sdl2/rect.ha b/sdl2/rect.ha new file mode 100644 index 0000000..00fae87 --- /dev/null +++ b/sdl2/rect.ha @@ -0,0 +1,29 @@ +// TODO: Flesh me out + +// The structure that defines a point (integer) +export type point = struct { + x: int, + y: int, +}; + +// The structure that defines a point (floating point) +export type fpoint = struct { + x: f32, + y: f32, +}; + +// A rectangle, with the origin at the upper left (integer). +export type rect = struct { + x: int, + y: int, + w: int, + h: int, +}; + +// A rectangle, with the origin at the upper left (floating point). +export type frect = struct { + x: f32, + y: f32, + w: f32, + h: f32, +}; diff --git a/sdl2/render.ha b/sdl2/render.ha index e1d2c8e..d4f0671 100644 --- a/sdl2/render.ha +++ b/sdl2/render.ha @@ -68,3 +68,19 @@ export @symbol("SDL_RenderClear") fn render_clear(renderer: *renderer) int; // Update the screen with rendering performed. export @symbol("SDL_RenderPresent") fn render_present(renderer: *renderer) void; + +// Destroy the specified texture. +export @symbol("SDL_DestroyTexture") fn destroy_texture(texture: *texture) void; + +// Query the attributes of a texture +// +// Returns 0 on success, or -1 if the texture is not valid. +export @symbol("SDL_QueryTexture") fn query_texture(texture: *texture, + format: nullable *u32, access: nullable *int, + w: nullable *int, h: nullable *int) int; + +// Copy a portion of the texture to the current rendering target. +// +// Returns 0 on success, or -1 on error +export @symbol("SDL_RenderCopy") fn render_copy(renderer: *renderer, + texture: *texture, srcrect: nullable *rect, dstrect: nullable *rect) int; diff --git a/sdl2/surface.ha b/sdl2/surface.ha new file mode 100644 index 0000000..7bbe850 --- /dev/null +++ b/sdl2/surface.ha @@ -0,0 +1,25 @@ +// 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 surface = struct { + flags: u32, + format: *pixelformat, + w: int, + h: int, + pitch: int, + pixels: nullable *void, + + userdata: *void, + + locked: int, + lock_data: *void, + + clip_rect: rect, + + map: *blitmap, + + refcount: int, +}; + +export type blitmap = void; -- cgit v1.2.3 From f26df07b04a680a749ad639a99a8f190d4ab2ad6 Mon Sep 17 00:00:00 2001 From: Drew DeVault Date: Thu, 9 Dec 2021 15:04:14 +0100 Subject: cmd/demo: add hare mascot --- cmd/demo/main.ha | 82 +++++++++++++++++++++++++++++++++++++++++-------------- mascot.jpg | Bin 0 -> 39421 bytes 2 files changed, 61 insertions(+), 21 deletions(-) create mode 100644 mascot.jpg diff --git a/cmd/demo/main.ha b/cmd/demo/main.ha index 35da638..f7ece50 100644 --- a/cmd/demo/main.ha +++ b/cmd/demo/main.ha @@ -5,10 +5,19 @@ use sdl2; use sdl2::image; use strings; +type state = struct { + hare: *sdl2::texture, + cat: *sdl2::texture, + hare_x: int, + hare_y: int, + cat_x: int, + cat_y: int, +}; + export fn main() void = { sdl2::init(sdl2::init_flags::VIDEO); defer sdl2::quit(); - image::init(image::init_flags::PNG); + let flags = image::init(image::init_flags::PNG | image::init_flags::JPG); defer image::quit(); const title = strings::to_c("Hare SDL2 demo"); @@ -31,28 +40,35 @@ export fn main() void = { }; defer sdl2::destroy_renderer(render); - const path = strings::to_c("cat.png"); - defer free(path); - const texture = match (image::load_texture(render, path)) { - case let tex: *sdl2::texture => - yield tex; - case null => - fmt::fatal("sdl2::image::load_texture failed"); + let state = state { + hare = { + const path = strings::to_c("mascot.jpg"); + defer free(path); + yield match (image::load_texture(render, path)) { + case let tex: *sdl2::texture => + yield tex; + case null => + fmt::fatal("sdl2::image::load_texture failed for mascot.jpg"); + }; + }, + cat = { + const path = strings::to_c("cat.png"); + defer free(path); + yield match (image::load_texture(render, path)) { + case let tex: *sdl2::texture => + yield tex; + case null => + fmt::fatal("sdl2::image::load_texture failed for cat.png"); + }; + }, + hare_x = 100, + hare_y = 100, + ... }; - defer sdl2::destroy_texture(texture); + defer sdl2::destroy_texture(state.hare); + defer sdl2::destroy_texture(state.cat); - let width = 0, height = 0; - sdl2::query_texture(texture, null, null, &width, &height); - - sdl2::set_render_draw_color(render, 50, 50, 50, 255); - sdl2::render_clear(render); - sdl2::render_copy(render, texture, null, &sdl2::rect { - x = 0, - y = 0, - w = width, - h = height, - }); - sdl2::render_present(render); + draw_frame(&state, render); let ev = sdl2::event { ... }; for (sdl2::wait_event(&ev) == 1) { @@ -65,3 +81,27 @@ export fn main() void = { os::exit(0); // https://todo.sr.ht/~sircmpwn/hare/525 }; + +fn draw_frame(state: *state, render: *sdl2::renderer) void = { + sdl2::set_render_draw_color(render, 50, 50, 50, 255); + sdl2::render_clear(render); + draw_tex(render, state.cat, state.cat_x, state.cat_y); + draw_tex(render, state.hare, state.hare_x, state.hare_y); + sdl2::render_present(render); +}; + +fn draw_tex( + render: *sdl2::renderer, + tex: *sdl2::texture, + x: int, + y: int, +) void = { + let width = 0, height = 0; + sdl2::query_texture(tex, null, null, &width, &height); + sdl2::render_copy(render, tex, null, &sdl2::rect { + x = x, + y = y, + w = width, + h = height, + }); +}; diff --git a/mascot.jpg b/mascot.jpg new file mode 100644 index 0000000..35d1ab0 Binary files /dev/null and b/mascot.jpg differ -- cgit v1.2.3 From 4b9ce55ebe2fce02841a2d5d283b5f02f9a534eb Mon Sep 17 00:00:00 2001 From: Drew DeVault Date: Thu, 9 Dec 2021 16:16:33 +0100 Subject: Add timer.h functions --- cmd/demo/main.ha | 114 ++++++++++++++++++++++++++++++++++--------------------- sdl2/timer.ha | 32 ++++++++++++++++ sdl2/video.ha | 13 +++++++ 3 files changed, 115 insertions(+), 44 deletions(-) create mode 100644 sdl2/timer.ha diff --git a/cmd/demo/main.ha b/cmd/demo/main.ha index f7ece50..43aea33 100644 --- a/cmd/demo/main.ha +++ b/cmd/demo/main.ha @@ -5,11 +5,21 @@ use sdl2; use sdl2::image; use strings; +type texture = struct { + tex: *sdl2::texture, + w: int, + h: int, +}; + type state = struct { - hare: *sdl2::texture, - cat: *sdl2::texture, + window: *sdl2::window, + render: *sdl2::renderer, + hare: texture, + cat: texture, hare_x: int, hare_y: int, + hare_dx: int, + hare_dy: int, cat_x: int, cat_y: int, }; @@ -41,67 +51,83 @@ export fn main() void = { defer sdl2::destroy_renderer(render); let state = state { - hare = { - const path = strings::to_c("mascot.jpg"); - defer free(path); - yield match (image::load_texture(render, path)) { - case let tex: *sdl2::texture => - yield tex; - case null => - fmt::fatal("sdl2::image::load_texture failed for mascot.jpg"); - }; - }, - cat = { - const path = strings::to_c("cat.png"); - defer free(path); - yield match (image::load_texture(render, path)) { - case let tex: *sdl2::texture => - yield tex; - case null => - fmt::fatal("sdl2::image::load_texture failed for cat.png"); - }; - }, + window = win, + render = render, + hare = load_texture(render, "mascot.jpg"), + cat = load_texture(render, "cat.png"), hare_x = 100, hare_y = 100, + hare_dx = 2, + hare_dy = 2, ... }; - defer sdl2::destroy_texture(state.hare); - defer sdl2::destroy_texture(state.cat); - - draw_frame(&state, render); + defer sdl2::destroy_texture(state.hare.tex); + defer sdl2::destroy_texture(state.cat.tex); let ev = sdl2::event { ... }; - for (sdl2::wait_event(&ev) == 1) { - switch (ev.event_type) { + for (true) { + if (sdl2::poll_event(&ev) == 1) switch (ev.event_type) { case event_type::QUIT => break; case => void; }; + + update(&state); + draw(&state); + + sdl2::delay(1000 / 60); }; os::exit(0); // https://todo.sr.ht/~sircmpwn/hare/525 }; -fn draw_frame(state: *state, render: *sdl2::renderer) void = { - sdl2::set_render_draw_color(render, 50, 50, 50, 255); - sdl2::render_clear(render); - draw_tex(render, state.cat, state.cat_x, state.cat_y); - draw_tex(render, state.hare, state.hare_x, state.hare_y); - sdl2::render_present(render); +fn load_texture(render: *sdl2::renderer, path: str) texture = { + const path = strings::to_c(path); + defer free(path); + + const tex = match (image::load_texture(render, path)) { + case let tex: *sdl2::texture => + yield tex; + case null => + fmt::fatal("sdl2::image::load_texture failed for cat.png"); + }; + + let w = 0, h = 0; + sdl2::query_texture(tex, null, null, &w, &h); + return texture { + tex = tex, + w = w, + h = h, + }; }; -fn draw_tex( - render: *sdl2::renderer, - tex: *sdl2::texture, - x: int, - y: int, -) void = { +fn update(state: *state) void = { let width = 0, height = 0; - sdl2::query_texture(tex, null, null, &width, &height); - sdl2::render_copy(render, tex, null, &sdl2::rect { + sdl2::get_window_size(state.window, &width, &height); + + state.hare_x += state.hare_dx; + state.hare_y += state.hare_dy; + if (state.hare_x <= 0 || state.hare_x + state.hare.w >= width) { + state.hare_dx = -state.hare_dx; + }; + if (state.hare_y <= 0 || state.hare_y + state.hare.h >= height) { + state.hare_dy = -state.hare_dy; + }; +}; + +fn draw(state: *state) void = { + sdl2::set_render_draw_color(state.render, 50, 50, 50, 255); + sdl2::render_clear(state.render); + draw_tex(state, &state.hare, state.hare_x, state.hare_y); + draw_tex(state, &state.cat, state.cat_x, state.cat_y); + sdl2::render_present(state.render); +}; + +fn draw_tex(state: *state, tex: *texture, x: int, y: int) void = { + sdl2::render_copy(state.render, tex.tex, null, &sdl2::rect { x = x, y = y, - w = width, - h = height, + w = tex.w, + h = tex.h, }); }; diff --git a/sdl2/timer.ha b/sdl2/timer.ha new file mode 100644 index 0000000..da958b6 --- /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 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 +// [[getperformancefrequency]]. +// +// Returns the current counter value. +export @symbol("SDL_GetPerformanceCounter") fn getperformancecounter() u64; + +// Get the count per second of the high resolution counter. +// +// Returns a platform-specific count per second. +export @symbol("SDL_GetPerformanceFrequency") fn 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 delay(ms: u32) void; + +// TODO: Timers diff --git a/sdl2/video.ha b/sdl2/video.ha index e12ca12..e6dfa58 100644 --- a/sdl2/video.ha +++ b/sdl2/video.ha @@ -71,3 +71,16 @@ export @symbol("SDL_CreateWindow") fn create_window(title: const *char, // Destroy a window. export @symbol("SDL_DestroyWindow") fn destroy_window(window: *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 get_window_size(window: *window, + w: nullable *int, h: nullable *int) void; -- cgit v1.2.3 From 10fe8ef9f8a5bc839eb9b4ebcf0ac2b3c01a9963 Mon Sep 17 00:00:00 2001 From: Drew DeVault Date: Thu, 9 Dec 2021 16:19:28 +0100 Subject: timer: correct naming convention --- sdl2/timer.ha | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/sdl2/timer.ha b/sdl2/timer.ha index da958b6..1b315ec 100644 --- a/sdl2/timer.ha +++ b/sdl2/timer.ha @@ -4,7 +4,7 @@ // // Returns an unsigned 32-bit value representing the number of milliseconds // since the SDL library initialized. -export @symbol("SDL_GetTicks") fn getticks() u32; +export @symbol("SDL_GetTicks") fn get_ticks() u32; // Get the current value of the high resolution counter. // @@ -15,12 +15,12 @@ export @symbol("SDL_GetTicks") fn getticks() u32; // [[getperformancefrequency]]. // // Returns the current counter value. -export @symbol("SDL_GetPerformanceCounter") fn getperformancecounter() u64; +export @symbol("SDL_GetPerformanceCounter") fn get_performance_counter() u64; // Get the count per second of the high resolution counter. // // Returns a platform-specific count per second. -export @symbol("SDL_GetPerformanceFrequency") fn getperformancefrequency() u64; +export @symbol("SDL_GetPerformanceFrequency") fn get_performance_frequency() u64; // Wait a specified number of milliseconds before returning. // -- cgit v1.2.3 From 81bac10cd7c26cf1ca1c0fcb9ee3dcccd7710f22 Mon Sep 17 00:00:00 2001 From: Drew DeVault Date: Thu, 9 Dec 2021 16:46:37 +0100 Subject: Initial gamecontroller support --- cmd/demo/main.ha | 189 +++++++++++++++++++++++++++++++++---------------- sdl2/events.ha | 2 +- sdl2/gamecontroller.ha | 43 +++++++++++ sdl2/joystick.ha | 13 ++++ 4 files changed, 184 insertions(+), 63 deletions(-) create mode 100644 sdl2/gamecontroller.ha create mode 100644 sdl2/joystick.ha diff --git a/cmd/demo/main.ha b/cmd/demo/main.ha index 43aea33..77a24a9 100644 --- a/cmd/demo/main.ha +++ b/cmd/demo/main.ha @@ -1,6 +1,11 @@ use fmt; use os; -use sdl2::{event_type, window_flags, renderer_flags}; +use sdl2::{ + controller_axis, + event_type, + renderer_flags, + window_flags, +}; use sdl2; use sdl2::image; use strings; @@ -12,6 +17,7 @@ type texture = struct { }; type state = struct { + quit: bool, window: *sdl2::window, render: *sdl2::renderer, hare: texture, @@ -22,10 +28,112 @@ type state = struct { hare_dy: int, cat_x: int, cat_y: int, + cat_dx: int, + cat_dy: int, +}; + +fn update(state: *state) void = { + let ev = sdl2::event { ... }; + for (sdl2::poll_event(&ev) == 1) switch (ev.event_type) { + case event_type::QUIT => + state.quit = true; + return; + case event_type::CONTROLLERAXISMOTION => + let delta = ev.caxis.value: int * 10 / sdl2::JOYSTICK_AXIS_MAX; + if (axis_x(ev.caxis.axis)) { + state.cat_dx = delta; + }; + if (axis_y(ev.caxis.axis)) { + state.cat_dy = delta; + }; + case => void; + }; + + let width = 0, height = 0; + sdl2::get_window_size(state.window, &width, &height); + + state.hare_x += state.hare_dx; + state.hare_y += state.hare_dy; + if (state.hare_x <= 0 || state.hare_x + state.hare.w >= width) { + state.hare_dx = -state.hare_dx; + }; + if (state.hare_y <= 0 || state.hare_y + state.hare.h >= height) { + state.hare_dy = -state.hare_dy; + }; + + state.cat_x += state.cat_dx; + state.cat_y += state.cat_dy; + if (state.cat_x <= 0) { + state.cat_x = 0; + }; + if (state.cat_x > width - state.cat.w) { + state.cat_x = width - state.cat.w; + }; + if (state.cat_y <= 0) { + state.cat_y = 0; + }; + if (state.cat_y > height - state.cat.h) { + state.cat_y = height - state.cat.h; + }; +}; + +fn draw(state: *state) void = { + sdl2::set_render_draw_color(state.render, 50, 50, 50, 255); + sdl2::render_clear(state.render); + draw_tex(state, &state.hare, state.hare_x, state.hare_y); + draw_tex(state, &state.cat, state.cat_x, state.cat_y); + sdl2::render_present(state.render); +}; + +fn draw_tex(state: *state, tex: *texture, x: int, y: int) void = { + sdl2::render_copy(state.render, tex.tex, null, &sdl2::rect { + x = x, + y = y, + w = tex.w, + h = tex.h, + }); +}; + +fn axis_x(axis: controller_axis) bool = { + switch (axis) { + case controller_axis::LEFTX, controller_axis::RIGHTX => + return true; + case => + return false; + }; +}; + +fn axis_y(axis: controller_axis) bool = { + switch (axis) { + case controller_axis::LEFTY, controller_axis::RIGHTY => + return true; + case => + return false; + }; +}; + +fn load_texture(render: *sdl2::renderer, path: str) texture = { + const path = strings::to_c(path); + defer free(path); + + const tex = match (image::load_texture(render, path)) { + case let tex: *sdl2::texture => + yield tex; + case null => + fmt::fatal("sdl2::image::load_texture failed for cat.png"); + }; + + let w = 0, h = 0; + sdl2::query_texture(tex, null, null, &w, &h); + return texture { + tex = tex, + w = w, + h = h, + }; }; export fn main() void = { - sdl2::init(sdl2::init_flags::VIDEO); + sdl2::init(sdl2::init_flags::VIDEO | sdl2::init_flags::GAMECONTROLLER); defer sdl2::quit(); let flags = image::init(image::init_flags::PNG | image::init_flags::JPG); defer image::quit(); @@ -50,6 +158,22 @@ export fn main() void = { }; defer sdl2::destroy_renderer(render); + let controller: nullable *sdl2::gamecontroller = null; + for (let i = 0; i < sdl2::numjoysticks(); i += 1) { + if (!sdl2::is_game_controller(i)) { + continue; + }; + controller = sdl2::game_controller_open(i); + if (controller != null) { + break; + }; + }; + defer match (controller) { + case null => void; + case let c: *sdl2::gamecontroller => + sdl2::game_controller_close(c); + }; + let state = state { window = win, render = render, @@ -64,70 +188,11 @@ export fn main() void = { defer sdl2::destroy_texture(state.hare.tex); defer sdl2::destroy_texture(state.cat.tex); - let ev = sdl2::event { ... }; - for (true) { - if (sdl2::poll_event(&ev) == 1) switch (ev.event_type) { - case event_type::QUIT => - break; - case => void; - }; - + for (!state.quit) { update(&state); draw(&state); - sdl2::delay(1000 / 60); }; os::exit(0); // https://todo.sr.ht/~sircmpwn/hare/525 }; - -fn load_texture(render: *sdl2::renderer, path: str) texture = { - const path = strings::to_c(path); - defer free(path); - - const tex = match (image::load_texture(render, path)) { - case let tex: *sdl2::texture => - yield tex; - case null => - fmt::fatal("sdl2::image::load_texture failed for cat.png"); - }; - - let w = 0, h = 0; - sdl2::query_texture(tex, null, null, &w, &h); - return texture { - tex = tex, - w = w, - h = h, - }; -}; - -fn update(state: *state) void = { - let width = 0, height = 0; - sdl2::get_window_size(state.window, &width, &height); - - state.hare_x += state.hare_dx; - state.hare_y += state.hare_dy; - if (state.hare_x <= 0 || state.hare_x + state.hare.w >= width) { - state.hare_dx = -state.hare_dx; - }; - if (state.hare_y <= 0 || state.hare_y + state.hare.h >= height) { - state.hare_dy = -state.hare_dy; - }; -}; - -fn draw(state: *state) void = { - sdl2::set_render_draw_color(state.render, 50, 50, 50, 255); - sdl2::render_clear(state.render); - draw_tex(state, &state.hare, state.hare_x, state.hare_y); - draw_tex(state, &state.cat, state.cat_x, state.cat_y); - sdl2::render_present(state.render); -}; - -fn draw_tex(state: *state, tex: *texture, x: int, y: int) void = { - sdl2::render_copy(state.render, tex.tex, null, &sdl2::rect { - x = x, - y = y, - w = tex.w, - h = tex.h, - }); -}; diff --git a/sdl2/events.ha b/sdl2/events.ha index 60ac771..e26333a 100644 --- a/sdl2/events.ha +++ b/sdl2/events.ha @@ -220,7 +220,7 @@ export type joy_device_event = struct { export type controller_axis_event = struct { common_event, which: i32, // TODO - axis: u8, + axis: controller_axis, padding1: u8, padding2: u8, padding3: u8, diff --git a/sdl2/gamecontroller.ha b/sdl2/gamecontroller.ha new file mode 100644 index 0000000..3b752e1 --- /dev/null +++ b/sdl2/gamecontroller.ha @@ -0,0 +1,43 @@ +// TODO: Flesh me out + +// The gamecontroller structure used to identify an SDL game controller. +// (Opaque) +export type gamecontroller = void; + +// The list of axes available from a controller +// +// Thumbstick axis values range from [[JOYSTICK_AXIS_MIN]] to +// [[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 [[JOYSTICK_AXIS_MAX]]. +export type controller_axis = enum u8 { + LEFTX, + LEFTY, + RIGHTX, + RIGHTY, + TRIGGERLEFT, + TRIGGERRIGHT, + INVALID = 255, +}; + +// 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 SDL_TRUE if the given joystick is supported by the game controller +// interface, SDL_FALSE if it isn't or it's an invalid index. +export @symbol("SDL_IsGameController") fn is_game_controller( + joystick_index: int) bool; + +// Get the SDL_GameController associated with an instance id. +// +// Returns a [[controller]] on success or NULL on failure. +export @symbol("SDL_GameControllerOpen") fn game_controller_open( + joystick_index: int) *gamecontroller; + +// Close a game controller previously opened with [[game_controller_open]]. +export @symbol("SDL_GameControllerClose") fn game_controller_close( + gamecontroller: *gamecontroller) void; diff --git a/sdl2/joystick.ha b/sdl2/joystick.ha new file mode 100644 index 0000000..c4f4c96 --- /dev/null +++ b/sdl2/joystick.ha @@ -0,0 +1,13 @@ +// TODO: Flesh me out + +// Minimum value for a joystick axis. +export def JOYSTICK_AXIS_MIN: i16 = -32768; + +// Minimum value for a joystick axis. +export def JOYSTICK_AXIS_MAX: i16 = 32767; + +// Count the number of joysticks attached to the system. +// +// Returns the number of attached joysticks on success or a negative error code +// on failure. +export @symbol("SDL_NumJoysticks") fn numjoysticks() int; -- cgit v1.2.3 From 4c687437e2638715e50a53785766cdc96a572371 Mon Sep 17 00:00:00 2001 From: Drew DeVault Date: Thu, 9 Dec 2021 16:52:15 +0100 Subject: cmd/demo: refactoring --- cmd/demo/main.ha | 94 ++++++++++++++++++++++++-------------------------------- 1 file changed, 41 insertions(+), 53 deletions(-) diff --git a/cmd/demo/main.ha b/cmd/demo/main.ha index 77a24a9..cdb290c 100644 --- a/cmd/demo/main.ha +++ b/cmd/demo/main.ha @@ -1,35 +1,23 @@ use fmt; use os; -use sdl2::{ - controller_axis, - event_type, - renderer_flags, - window_flags, -}; use sdl2; +use sdl2::{ controller_axis, event_type, renderer_flags, window_flags }; use sdl2::image; use strings; -type texture = struct { +type object = struct { tex: *sdl2::texture, - w: int, - h: int, + w: int, h: int, + x: int, y: int, + dx: int, dy: int, }; type state = struct { quit: bool, window: *sdl2::window, render: *sdl2::renderer, - hare: texture, - cat: texture, - hare_x: int, - hare_y: int, - hare_dx: int, - hare_dy: int, - cat_x: int, - cat_y: int, - cat_dx: int, - cat_dy: int, + hare: object, + cat: object, }; fn update(state: *state) void = { @@ -41,10 +29,10 @@ fn update(state: *state) void = { case event_type::CONTROLLERAXISMOTION => let delta = ev.caxis.value: int * 10 / sdl2::JOYSTICK_AXIS_MAX; if (axis_x(ev.caxis.axis)) { - state.cat_dx = delta; + state.cat.dx = delta; }; if (axis_y(ev.caxis.axis)) { - state.cat_dy = delta; + state.cat.dy = delta; }; case => void; }; @@ -52,45 +40,45 @@ fn update(state: *state) void = { let width = 0, height = 0; sdl2::get_window_size(state.window, &width, &height); - state.hare_x += state.hare_dx; - state.hare_y += state.hare_dy; - if (state.hare_x <= 0 || state.hare_x + state.hare.w >= width) { - state.hare_dx = -state.hare_dx; + state.hare.x += state.hare.dx; + state.hare.y += state.hare.dy; + if (state.hare.x <= 0 || state.hare.x + state.hare.w >= width) { + state.hare.dx = -state.hare.dx; }; - if (state.hare_y <= 0 || state.hare_y + state.hare.h >= height) { - state.hare_dy = -state.hare_dy; + if (state.hare.y <= 0 || state.hare.y + state.hare.h >= height) { + state.hare.dy = -state.hare.dy; }; - state.cat_x += state.cat_dx; - state.cat_y += state.cat_dy; - if (state.cat_x <= 0) { - state.cat_x = 0; + state.cat.x += state.cat.dx; + state.cat.y += state.cat.dy; + if (state.cat.x <= 0) { + state.cat.x = 0; }; - if (state.cat_x > width - state.cat.w) { - state.cat_x = width - state.cat.w; + if (state.cat.x > width - state.cat.w) { + state.cat.x = width - state.cat.w; }; - if (state.cat_y <= 0) { - state.cat_y = 0; + if (state.cat.y <= 0) { + state.cat.y = 0; }; - if (state.cat_y > height - state.cat.h) { - state.cat_y = height - state.cat.h; + if (state.cat.y > height - state.cat.h) { + state.cat.y = height - state.cat.h; }; }; fn draw(state: *state) void = { sdl2::set_render_draw_color(state.render, 50, 50, 50, 255); sdl2::render_clear(state.render); - draw_tex(state, &state.hare, state.hare_x, state.hare_y); - draw_tex(state, &state.cat, state.cat_x, state.cat_y); + draw_object(state, &state.hare); + draw_object(state, &state.cat); sdl2::render_present(state.render); }; -fn draw_tex(state: *state, tex: *texture, x: int, y: int) void = { - sdl2::render_copy(state.render, tex.tex, null, &sdl2::rect { - x = x, - y = y, - w = tex.w, - h = tex.h, +fn draw_object(state: *state, obj: *object) void = { + sdl2::render_copy(state.render, obj.tex, null, &sdl2::rect { + x = obj.x, + y = obj.y, + w = obj.w, + h = obj.h, }); }; @@ -112,7 +100,7 @@ fn axis_y(axis: controller_axis) bool = { }; }; -fn load_texture(render: *sdl2::renderer, path: str) texture = { +fn load_object(render: *sdl2::renderer, path: str) object = { const path = strings::to_c(path); defer free(path); @@ -125,10 +113,11 @@ fn load_texture(render: *sdl2::renderer, path: str) texture = { let w = 0, h = 0; sdl2::query_texture(tex, null, null, &w, &h); - return texture { + return object { tex = tex, w = w, h = h, + ... }; }; @@ -177,17 +166,16 @@ export fn main() void = { let state = state { window = win, render = render, - hare = load_texture(render, "mascot.jpg"), - cat = load_texture(render, "cat.png"), - hare_x = 100, - hare_y = 100, - hare_dx = 2, - hare_dy = 2, + hare = load_object(render, "mascot.jpg"), + cat = load_object(render, "cat.png"), ... }; defer sdl2::destroy_texture(state.hare.tex); defer sdl2::destroy_texture(state.cat.tex); + state.hare.dx = 2; + state.hare.dy = 2; + for (!state.quit) { update(&state); draw(&state); -- cgit v1.2.3 From 9f2b3b05c669eb2d6d3d4ef244c7ea4e23ebd485 Mon Sep 17 00:00:00 2001 From: Drew DeVault Date: Thu, 9 Dec 2021 16:54:43 +0100 Subject: cmd/demo: fix texture loading error message --- cmd/demo/main.ha | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cmd/demo/main.ha b/cmd/demo/main.ha index cdb290c..50d61b4 100644 --- a/cmd/demo/main.ha +++ b/cmd/demo/main.ha @@ -108,7 +108,7 @@ fn load_object(render: *sdl2::renderer, path: str) object = { case let tex: *sdl2::texture => yield tex; case null => - fmt::fatal("sdl2::image::load_texture failed for cat.png"); + fmt::fatal("sdl2::image::load_texture failed for {}", path); }; let w = 0, h = 0; -- cgit v1.2.3 From 9d229f2a6c728eb96c0fd3c6d9b511ddf545b50a Mon Sep 17 00:00:00 2001 From: Drew DeVault Date: Thu, 9 Dec 2021 16:59:49 +0100 Subject: cmd/demo: remove unused variable --- cmd/demo/main.ha | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cmd/demo/main.ha b/cmd/demo/main.ha index 50d61b4..e3360be 100644 --- a/cmd/demo/main.ha +++ b/cmd/demo/main.ha @@ -124,7 +124,7 @@ fn load_object(render: *sdl2::renderer, path: str) object = { export fn main() void = { sdl2::init(sdl2::init_flags::VIDEO | sdl2::init_flags::GAMECONTROLLER); defer sdl2::quit(); - let flags = image::init(image::init_flags::PNG | image::init_flags::JPG); + image::init(image::init_flags::PNG | image::init_flags::JPG); defer image::quit(); const title = strings::to_c("Hare SDL2 demo"); -- cgit v1.2.3 From c4e22bac297ee3b235b2c41a1a3358bc133e476d Mon Sep 17 00:00:00 2001 From: Drew DeVault Date: Thu, 9 Dec 2021 17:01:29 +0100 Subject: cmd/demo: further refactoring --- cmd/demo/main.ha | 129 ++++++++++++++++++++++++++++--------------------------- 1 file changed, 65 insertions(+), 64 deletions(-) diff --git a/cmd/demo/main.ha b/cmd/demo/main.ha index e3360be..8bd733d 100644 --- a/cmd/demo/main.ha +++ b/cmd/demo/main.ha @@ -20,6 +20,71 @@ type state = struct { cat: object, }; +export fn main() void = { + sdl2::init(sdl2::init_flags::VIDEO | sdl2::init_flags::GAMECONTROLLER); + defer sdl2::quit(); + image::init(image::init_flags::PNG | image::init_flags::JPG); + defer image::quit(); + + const title = strings::to_c("Hare SDL2 demo"); + defer free(title); + const win = match (sdl2::create_window(title, + sdl2::WINDOWPOS_UNDEFINED, sdl2::WINDOWPOS_UNDEFINED, + 640, 480, window_flags::NONE)) { + case let win: *sdl2::window => + yield win; + case null => + fmt::fatal("sdl2::create_window failed"); + }; + defer sdl2::destroy_window(win); + + const render = match (sdl2::create_renderer(win, -1, renderer_flags::NONE)) { + case let rend: *sdl2::renderer => + yield rend; + case null => + fmt::fatal("sdl2::create_renderer failed"); + }; + defer sdl2::destroy_renderer(render); + + let controller: nullable *sdl2::gamecontroller = null; + for (let i = 0; i < sdl2::numjoysticks(); i += 1) { + if (!sdl2::is_game_controller(i)) { + continue; + }; + controller = sdl2::game_controller_open(i); + if (controller != null) { + break; + }; + }; + defer match (controller) { + case null => void; + case let c: *sdl2::gamecontroller => + sdl2::game_controller_close(c); + }; + + let state = state { + window = win, + render = render, + hare = load_object(render, "mascot.jpg"), + cat = load_object(render, "cat.png"), + ... + }; + defer sdl2::destroy_texture(state.hare.tex); + defer sdl2::destroy_texture(state.cat.tex); + + state.hare.dx = 2; + state.hare.dy = 2; + + for (!state.quit) { + update(&state); + draw(&state); + + sdl2::delay(1000 / 60); + }; + + os::exit(0); // https://todo.sr.ht/~sircmpwn/hare/525 +}; + fn update(state: *state) void = { let ev = sdl2::event { ... }; for (sdl2::poll_event(&ev) == 1) switch (ev.event_type) { @@ -120,67 +185,3 @@ fn load_object(render: *sdl2::renderer, path: str) object = { ... }; }; - -export fn main() void = { - sdl2::init(sdl2::init_flags::VIDEO | sdl2::init_flags::GAMECONTROLLER); - defer sdl2::quit(); - image::init(image::init_flags::PNG | image::init_flags::JPG); - defer image::quit(); - - const title = strings::to_c("Hare SDL2 demo"); - defer free(title); - const win = match (sdl2::create_window(title, - sdl2::WINDOWPOS_UNDEFINED, sdl2::WINDOWPOS_UNDEFINED, - 640, 480, window_flags::NONE)) { - case let win: *sdl2::window => - yield win; - case null => - fmt::fatal("sdl2::create_window failed"); - }; - defer sdl2::destroy_window(win); - - const render = match (sdl2::create_renderer(win, -1, renderer_flags::NONE)) { - case let rend: *sdl2::renderer => - yield rend; - case null => - fmt::fatal("sdl2::create_renderer failed"); - }; - defer sdl2::destroy_renderer(render); - - let controller: nullable *sdl2::gamecontroller = null; - for (let i = 0; i < sdl2::numjoysticks(); i += 1) { - if (!sdl2::is_game_controller(i)) { - continue; - }; - controller = sdl2::game_controller_open(i); - if (controller != null) { - break; - }; - }; - defer match (controller) { - case null => void; - case let c: *sdl2::gamecontroller => - sdl2::game_controller_close(c); - }; - - let state = state { - window = win, - render = render, - hare = load_object(render, "mascot.jpg"), - cat = load_object(render, "cat.png"), - ... - }; - defer sdl2::destroy_texture(state.hare.tex); - defer sdl2::destroy_texture(state.cat.tex); - - state.hare.dx = 2; - state.hare.dy = 2; - - for (!state.quit) { - update(&state); - draw(&state); - sdl2::delay(1000 / 60); - }; - - os::exit(0); // https://todo.sr.ht/~sircmpwn/hare/525 -}; -- cgit v1.2.3 From bac9223ff1a79173455d7605800e4d7f04e927c3 Mon Sep 17 00:00:00 2001 From: Drew DeVault Date: Thu, 9 Dec 2021 17:09:17 +0100 Subject: cmd/demo: remove workaround --- cmd/demo/main.ha | 3 --- 1 file changed, 3 deletions(-) diff --git a/cmd/demo/main.ha b/cmd/demo/main.ha index 8bd733d..9b89ecf 100644 --- a/cmd/demo/main.ha +++ b/cmd/demo/main.ha @@ -78,11 +78,8 @@ export fn main() void = { for (!state.quit) { update(&state); draw(&state); - sdl2::delay(1000 / 60); }; - - os::exit(0); // https://todo.sr.ht/~sircmpwn/hare/525 }; fn update(state: *state) void = { -- cgit v1.2.3 From 43961db3a6f82450dc495a1c6c67d78474a89308 Mon Sep 17 00:00:00 2001 From: Drew DeVault Date: Thu, 9 Dec 2021 17:14:37 +0100 Subject: cmd/demo: change background on controller button --- cmd/demo/main.ha | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/cmd/demo/main.ha b/cmd/demo/main.ha index 9b89ecf..3898376 100644 --- a/cmd/demo/main.ha +++ b/cmd/demo/main.ha @@ -16,6 +16,7 @@ type state = struct { quit: bool, window: *sdl2::window, render: *sdl2::renderer, + nbutton: int, hare: object, cat: object, }; @@ -96,6 +97,10 @@ fn update(state: *state) void = { if (axis_y(ev.caxis.axis)) { state.cat.dy = delta; }; + case event_type::CONTROLLERBUTTONDOWN => + state.nbutton += 1; + case event_type::CONTROLLERBUTTONUP => + state.nbutton -= 1; case => void; }; @@ -128,8 +133,13 @@ fn update(state: *state) void = { }; fn draw(state: *state) void = { - sdl2::set_render_draw_color(state.render, 50, 50, 50, 255); + if (state.nbutton == 0) { + sdl2::set_render_draw_color(state.render, 50, 50, 50, 255); + } else { + sdl2::set_render_draw_color(state.render, 50, 50, 200, 255); + }; sdl2::render_clear(state.render); + draw_object(state, &state.hare); draw_object(state, &state.cat); sdl2::render_present(state.render); -- cgit v1.2.3 From 35b7fbd12bc11fd5aac6c4c509ea0990735ab0b1 Mon Sep 17 00:00:00 2001 From: Drew DeVault Date: Thu, 9 Dec 2021 17:36:54 +0100 Subject: Add sdl2::set_texture_color_mod --- sdl2/render.ha | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/sdl2/render.ha b/sdl2/render.ha index d4f0671..5bf1b09 100644 --- a/sdl2/render.ha +++ b/sdl2/render.ha @@ -79,6 +79,21 @@ export @symbol("SDL_QueryTexture") fn query_texture(texture: *texture, format: nullable *u32, access: nullable *int, w: nullable *int, h: nullable *int) 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. +// +// Returns 0 on success or a negative error code on failure. +export @symbol("SDL_SetTextureColorMod") fn set_texture_color_mod( + texture: *texture, r: u8, g: u8, b: u8) int; + // Copy a portion of the texture to the current rendering target. // // Returns 0 on success, or -1 on error -- cgit v1.2.3 From 2d470043e9e6c6bb01e8ae740643bf67ee7066f6 Mon Sep 17 00:00:00 2001 From: Drew DeVault Date: Thu, 9 Dec 2021 17:39:24 +0100 Subject: cmd/demo: remove unused import --- cmd/demo/main.ha | 1 - 1 file changed, 1 deletion(-) diff --git a/cmd/demo/main.ha b/cmd/demo/main.ha index 3898376..71c747f 100644 --- a/cmd/demo/main.ha +++ b/cmd/demo/main.ha @@ -1,5 +1,4 @@ use fmt; -use os; use sdl2; use sdl2::{ controller_axis, event_type, renderer_flags, window_flags }; use sdl2::image; -- cgit v1.2.3 From 1307e019183ed0032e112fcc6c6b840c2946fa05 Mon Sep 17 00:00:00 2001 From: Drew DeVault Date: Thu, 9 Dec 2021 17:51:53 +0100 Subject: Makefile: drop -T+libc This is implied by -l --- Makefile | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Makefile b/Makefile index f6eb43f..afbbfd2 100644 --- a/Makefile +++ b/Makefile @@ -4,9 +4,9 @@ LIBS=-lc -lSDL2_image -lSDL2 demo: - hare build $(LIBS) -T+libc cmd/demo + hare build $(LIBS) cmd/demo run: - hare run $(LIBS) -T+libc cmd/demo + hare run $(LIBS) cmd/demo .PHONY: demo run -- cgit v1.2.3 From 9607eb0de784fab1a99833f567c0eaca72b67e4a Mon Sep 17 00:00:00 2001 From: Drew DeVault Date: Fri, 10 Dec 2021 09:42:10 +0100 Subject: all: rig up Hare-native error handling --- cmd/demo/main.ha | 77 ++++++++++++++++++------------------------ sdl2/errors.ha | 31 +++++++++++++++++ sdl2/events.ha | 51 ++++++++++++++++++++-------- sdl2/gamecontroller.ha | 16 +++++---- sdl2/image/image.ha | 22 ++++++++++-- sdl2/joystick.ha | 9 +++-- sdl2/render.ha | 92 +++++++++++++++++++++++++++++++++++--------------- sdl2/video.ha | 18 ++++++++-- 8 files changed, 213 insertions(+), 103 deletions(-) create mode 100644 sdl2/errors.ha diff --git a/cmd/demo/main.ha b/cmd/demo/main.ha index 71c747f..081134a 100644 --- a/cmd/demo/main.ha +++ b/cmd/demo/main.ha @@ -21,39 +21,37 @@ type state = struct { }; export fn main() void = { + match (run()) { + case let err: sdl2::error => + fmt::fatal("SDL2 error: {}", sdl2::strerror(err)); + case void => void; + }; +}; + +fn run() (void | sdl2::error) = { sdl2::init(sdl2::init_flags::VIDEO | sdl2::init_flags::GAMECONTROLLER); defer sdl2::quit(); image::init(image::init_flags::PNG | image::init_flags::JPG); defer image::quit(); - const title = strings::to_c("Hare SDL2 demo"); - defer free(title); - const win = match (sdl2::create_window(title, + const win = sdl2::create_window("Hare SDL2 demo", sdl2::WINDOWPOS_UNDEFINED, sdl2::WINDOWPOS_UNDEFINED, - 640, 480, window_flags::NONE)) { - case let win: *sdl2::window => - yield win; - case null => - fmt::fatal("sdl2::create_window failed"); - }; + 640, 480, window_flags::NONE)?; defer sdl2::destroy_window(win); - const render = match (sdl2::create_renderer(win, -1, renderer_flags::NONE)) { - case let rend: *sdl2::renderer => - yield rend; - case null => - fmt::fatal("sdl2::create_renderer failed"); - }; + const render = sdl2::create_renderer(win, -1, renderer_flags::NONE)?; defer sdl2::destroy_renderer(render); let controller: nullable *sdl2::gamecontroller = null; - for (let i = 0; i < sdl2::numjoysticks(); i += 1) { + for (let i = 0; i < sdl2::numjoysticks()?; i += 1) { if (!sdl2::is_game_controller(i)) { continue; }; - controller = sdl2::game_controller_open(i); - if (controller != null) { + match (sdl2::game_controller_open(i)) { + case let c: *sdl2::gamecontroller => + controller = c; break; + case sdl2::error => void; }; }; defer match (controller) { @@ -65,8 +63,8 @@ export fn main() void = { let state = state { window = win, render = render, - hare = load_object(render, "mascot.jpg"), - cat = load_object(render, "cat.png"), + hare = load_object(render, "mascot.jpg")?, + cat = load_object(render, "cat.png")?, ... }; defer sdl2::destroy_texture(state.hare.tex); @@ -76,15 +74,15 @@ export fn main() void = { state.hare.dy = 2; for (!state.quit) { - update(&state); - draw(&state); + update(&state)?; + draw(&state)?; sdl2::delay(1000 / 60); }; }; -fn update(state: *state) void = { +fn update(state: *state) (void | sdl2::error) = { let ev = sdl2::event { ... }; - for (sdl2::poll_event(&ev) == 1) switch (ev.event_type) { + for (sdl2::poll_event(&ev)? == 1) switch (ev.event_type) { case event_type::QUIT => state.quit = true; return; @@ -131,26 +129,26 @@ fn update(state: *state) void = { }; }; -fn draw(state: *state) void = { +fn draw(state: *state) (void | sdl2::error) = { if (state.nbutton == 0) { - sdl2::set_render_draw_color(state.render, 50, 50, 50, 255); + sdl2::set_render_draw_color(state.render, 50, 50, 50, 255)?; } else { - sdl2::set_render_draw_color(state.render, 50, 50, 200, 255); + sdl2::set_render_draw_color(state.render, 50, 50, 200, 255)?; }; - sdl2::render_clear(state.render); + sdl2::render_clear(state.render)?; - draw_object(state, &state.hare); - draw_object(state, &state.cat); + draw_object(state, &state.hare)?; + draw_object(state, &state.cat)?; sdl2::render_present(state.render); }; -fn draw_object(state: *state, obj: *object) void = { +fn draw_object(state: *state, obj: *object) (void | sdl2::error) = { sdl2::render_copy(state.render, obj.tex, null, &sdl2::rect { x = obj.x, y = obj.y, w = obj.w, h = obj.h, - }); + })?; }; fn axis_x(axis: controller_axis) bool = { @@ -171,19 +169,10 @@ fn axis_y(axis: controller_axis) bool = { }; }; -fn load_object(render: *sdl2::renderer, path: str) object = { - const path = strings::to_c(path); - defer free(path); - - const tex = match (image::load_texture(render, path)) { - case let tex: *sdl2::texture => - yield tex; - case null => - fmt::fatal("sdl2::image::load_texture failed for {}", path); - }; - +fn load_object(render: *sdl2::renderer, path: str) (object | sdl2::error) = { + const tex = image::load_texture(render, path)?; let w = 0, h = 0; - sdl2::query_texture(tex, null, null, &w, &h); + sdl2::query_texture(tex, null, null, &w, &h)?; return object { tex = tex, w = w, diff --git a/sdl2/errors.ha b/sdl2/errors.ha new file mode 100644 index 0000000..bc02505 --- /dev/null +++ b/sdl2/errors.ha @@ -0,0 +1,31 @@ +use strings; + +// 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 geterror() const *char; + +export fn wrapvoid(ret: int) (void | error) = { + wrapint(ret)?; +}; + +export fn wrapint(ret: int) (int | error) = { + if (ret < 0) { + return strings::fromc(geterror()): error; + }; + return ret; +}; + +export fn wrapptr(ret: nullable *void) (*void | error) = { + match (ret) { + case let v: *void => + return v; + case null => + return strings::fromc(geterror()): error; + }; +}; diff --git a/sdl2/events.ha b/sdl2/events.ha index e26333a..58bbfd7 100644 --- a/sdl2/events.ha +++ b/sdl2/events.ha @@ -377,6 +377,9 @@ export type eventaction = enum { GETEVENT, }; +@symbol("SDL_PeepEvents") fn _peep_events(events: *event, numevents: int, + action: eventaction, mintype: event_type, maxtype: event_type) 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 @@ -390,11 +393,16 @@ export type eventaction = enum { // queue, within the specified minimum and maximum type, will be returned and // will be removed from the queue. // -// Returns the number of events actually stored, or -1 if there was an error. -// // This function is thread-safe. -export @symbol("SDL_PeepEvents") fn peep_events(events: *event, numevents: int, - action: eventaction, mintype: event_type, maxtype: event_type) int; +export fn peep_events( + events: *event, + numevents: int, + action: eventaction, + mintype: event_type, + maxtype: event_type, +) (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 has_event(event_type: event_type) bool; @@ -414,35 +422,48 @@ export @symbol("SDL_FlushEvent") fn flush_event(event_type: event_type) void; // on the main thread immediately before the flush call. export @symbol("SDL_FlushEvents") fn flush_events(mintype: event_type, maxtype: event_type) 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 @symbol("SDL_PollEvent") fn poll_event(event: nullable *event) int; +export fn poll_event(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. // -// Returns 1, or 0 if there was an error while waiting for events. -// // If 'event' is not null, the next event is removed from the queue and stored // in that area. -export @symbol("SDL_WaitEvent") fn wait_event(event: nullable *event) int; +export fn wait_event(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. // -// Returns 1, or 0 if there was an error while waiting for events. -// // 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 @symbol("SDL_WaitEventTimeout") fn wait_event_timeout(event: nullable *event, timeout: int) int; +export fn wait_event_timeout( + 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. -// -// Returns 1 on success, 0 if the event was filtered, or -1 if the event queue -// was full or there was some other error. -export @symbol("SDL_PushEvent") fn push_event(event: *event) int; +export fn push_event(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 index 3b752e1..cf78674 100644 --- a/sdl2/gamecontroller.ha +++ b/sdl2/gamecontroller.ha @@ -27,16 +27,20 @@ export type controller_axis = enum u8 { // 'joystick_index' is the same as the 'device_index' passed to // [[joystick_open]]. // -// Returns SDL_TRUE if the given joystick is supported by the game controller -// interface, SDL_FALSE if it isn't or it's an invalid index. +// 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 is_game_controller( joystick_index: int) bool; +@symbol("SDL_GameControllerOpen") fn _game_controller_open( + joystick_index: int) nullable *gamecontroller; + // Get the SDL_GameController associated with an instance id. -// -// Returns a [[controller]] on success or NULL on failure. -export @symbol("SDL_GameControllerOpen") fn game_controller_open( - joystick_index: int) *gamecontroller; +export fn game_controller_open( + joystick_index: int, +) (*gamecontroller | error) = { + return wrapptr(_game_controller_open(joystick_index))?: *gamecontroller; +}; // Close a game controller previously opened with [[game_controller_open]]. export @symbol("SDL_GameControllerClose") fn game_controller_close( diff --git a/sdl2/image/image.ha b/sdl2/image/image.ha index 03301e9..6cabee2 100644 --- a/sdl2/image/image.ha +++ b/sdl2/image/image.ha @@ -1,6 +1,7 @@ // TODO: Flesh me out // TODO: SDL_RWops use sdl2; +use strings; // Flags for [[init]]. export type init_flags = enum int { @@ -20,9 +21,24 @@ export @symbol("IMG_Init") fn init(flags: init_flags) int; // Unloads libraries loaded with [[init]] export @symbol("IMG_Quit") fn quit() void; +@symbol("IMG_Load") fn _load(file: const *char) nullable *sdl2::surface; + // Load an image from a file path. -export @symbol("IMG_Load") fn load(file: const *char) nullable *sdl2::surface; +export fn load(file: str) (*sdl2::surface | sdl2::error) = { + const file = strings::to_c(file); + defer free(file); + return sdl2::wrapptr(_load(file))?: *sdl2::surface; +}; -// Load an image directly into a render texture. -export @symbol("IMG_LoadTexture") fn load_texture(renderer: *sdl2::renderer, +@symbol("IMG_LoadTexture") fn _load_texture(renderer: *sdl2::renderer, file: const *char) nullable *sdl2::texture; + +// Load an image directly into a render texture. +export fn load_texture( + renderer: *sdl2::renderer, + file: str, +) (*sdl2::texture | sdl2::error) = { + const file = strings::to_c(file); + defer free(file); + return sdl2::wrapptr(_load_texture(renderer, file))?: *sdl2::texture; +}; diff --git a/sdl2/joystick.ha b/sdl2/joystick.ha index c4f4c96..adbcd14 100644 --- a/sdl2/joystick.ha +++ b/sdl2/joystick.ha @@ -6,8 +6,7 @@ export def JOYSTICK_AXIS_MIN: i16 = -32768; // Minimum value for a joystick axis. export def JOYSTICK_AXIS_MAX: i16 = 32767; -// Count the number of joysticks attached to the system. -// -// Returns the number of attached joysticks on success or a negative error code -// on failure. -export @symbol("SDL_NumJoysticks") fn numjoysticks() int; +@symbol("SDL_NumJoysticks") fn _numjoysticks() int; + +// Returns the number of joysticks attached to the system. +export fn numjoysticks() (int | error) = wrapint(_numjoysticks()); diff --git a/sdl2/render.ha b/sdl2/render.ha index 5bf1b09..649e786 100644 --- a/sdl2/render.ha +++ b/sdl2/render.ha @@ -15,6 +15,10 @@ export type renderer_flags = enum u32 { TARGETTEXTURE = 0x00000008, }; +@symbol("SDL_CreateWindowAndRenderer") fn _create_window_and_renderer( + width: int, height: int, window_flags: window_flags, + window: nullable **window, renderer: nullable **renderer) int; + // Create a window and default renderer. // // 'width' and 'height' set the width and height of the window, in screen @@ -22,11 +26,17 @@ export type renderer_flags = enum u32 { // // 'window' and 'renderer' are out parameters, or null, which are filled in with // the created window and renderer respectively. -// -// Returns 0 on success, or -1 on error. -export @symbol("SDL_CreateWindowAndRenderer") fn create_window_and_renderer( - width: int, height: int, window_flags: window_flags, - window: nullable **window, renderer: nullable **renderer) int; +export fn create_window_and_renderer( + width: int, + height: int, + window_flags: window_flags, + window: nullable **window, + renderer: nullable **renderer, +) (void | error) = wrapvoid(_create_window_and_renderer(width, height, + window_flags, window, renderer)); + +@symbol("SDL_CreateRenderer") fn _create_renderer(window: *window, + index: int, flags: renderer_flags) nullable *renderer; // Create a 2D rendering context for a window. // @@ -34,12 +44,14 @@ export @symbol("SDL_CreateWindowAndRenderer") fn create_window_and_renderer( // the rendering driver to initialize, or -1 to initialize the first one // supporting the requested flags. // -// Returns a valid rendering context, or NULL if there was an error. -// // See also: [[create_software_renderer]], [[get_renderer_info]], // [[destroy_renderer]]. -export @symbol("SDL_CreateRenderer") fn create_renderer(window: *window, - index: int, flags: renderer_flags) nullable *renderer; +export fn create_renderer( + window: *window, + index: int, + flags: renderer_flags, +) (*renderer | error) = + wrapptr(_create_renderer(window, index, flags))?: *renderer; // Destroy the rendering context for a window and free associated textures. // @@ -49,22 +61,27 @@ export @symbol("SDL_DestroyRenderer") fn destroy_renderer(renderer: *renderer) v // Opaque value for the alpha channel (255). export def ALPHA_OPAQUE: u8 = 255; +@symbol("SDL_SetRenderDrawColor") fn _set_render_draw_color(renderer: *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. -// -// Returns 0 on success, or -1 on error -export @symbol("SDL_SetRenderDrawColor") fn set_render_draw_color(renderer: *renderer, - r: u8, g: u8, b: u8, a: u8) int; +export fn set_render_draw_color( + renderer: *renderer, + r: u8, g: u8, b: u8, a: u8, +) (void | error) = wrapvoid(_set_render_draw_color(renderer, r, g, b, a)); + +@symbol("SDL_RenderClear") fn _render_clear(renderer: *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. -// -// Returns 0 on success, or -1 on error -export @symbol("SDL_RenderClear") fn render_clear(renderer: *renderer) int; +export fn render_clear(renderer: *renderer) (void | error) = { + return wrapvoid(_render_clear(renderer)); +}; // Update the screen with rendering performed. export @symbol("SDL_RenderPresent") fn render_present(renderer: *renderer) void; @@ -72,13 +89,23 @@ export @symbol("SDL_RenderPresent") fn render_present(renderer: *renderer) void; // Destroy the specified texture. export @symbol("SDL_DestroyTexture") fn destroy_texture(texture: *texture) void; -// Query the attributes of a texture -// -// Returns 0 on success, or -1 if the texture is not valid. -export @symbol("SDL_QueryTexture") fn query_texture(texture: *texture, +@symbol("SDL_QueryTexture") fn _query_texture(texture: *texture, format: nullable *u32, access: nullable *int, w: nullable *int, h: nullable *int) int; +// Query the attributes of a texture +export fn query_texture( + texture: *texture, + format: nullable *u32, + access: nullable *int, + w: nullable *int, h: nullable *int, +) (void | error) = { + return wrapvoid(_query_texture(texture, format, access, w, h)); +}; + +@symbol("SDL_SetTextureColorMod") fn _set_texture_color_mod( + texture: *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 @@ -89,13 +116,22 @@ export @symbol("SDL_QueryTexture") fn query_texture(texture: *texture, // // Color modulation is not always supported by the renderer; it will return -1 // if color modulation is not supported. -// -// Returns 0 on success or a negative error code on failure. -export @symbol("SDL_SetTextureColorMod") fn set_texture_color_mod( - texture: *texture, r: u8, g: u8, b: u8) int; +export fn set_texture_color_mod( + texture: *texture, + r: u8, g: u8, b: u8, +) (void | error) = { + return wrapvoid(_set_texture_color_mod(texture, r, g, b)); +}; -// Copy a portion of the texture to the current rendering target. -// -// Returns 0 on success, or -1 on error -export @symbol("SDL_RenderCopy") fn render_copy(renderer: *renderer, +@symbol("SDL_RenderCopy") fn _render_copy(renderer: *renderer, texture: *texture, srcrect: nullable *rect, dstrect: nullable *rect) int; + +// Copy a portion of the texture to the current rendering target. +export fn render_copy( + renderer: *renderer, + texture: *texture, + srcrect: nullable *rect, + dstrect: nullable *rect, +) (void | error) = { + return wrapvoid(_render_copy(renderer, texture, srcrect, dstrect)); +}; diff --git a/sdl2/video.ha b/sdl2/video.ha index e6dfa58..b1f8b22 100644 --- a/sdl2/video.ha +++ b/sdl2/video.ha @@ -1,4 +1,5 @@ // TODO: Flesh me out +use strings; // The type used to identify a window. (Opaque) export type window = void; @@ -32,6 +33,9 @@ export type window_flags = enum u32 { export def WINDOWPOS_UNDEFINED: int = 0x1FFF0000; export def WINDOWPOS_CENTERED: int = 0x2FFF0000; +@symbol("SDL_CreateWindow") fn _create_window(title: const *char, + x: int, y: int, w: int, h: int, flags: window_flags) nullable *window; + // Create a window with the specified position, dimensions, and flags. // // 'title' is the title of the window, in UTF-8 encoding. See [[strings::to_c]] @@ -66,8 +70,18 @@ export def WINDOWPOS_CENTERED: int = 0x2FFF0000; // removed in a future version of SDL. // // See also: [[destroy_window]] [[gl_loadlibrary]], [[vulkan_loadlibrary]]. -export @symbol("SDL_CreateWindow") fn create_window(title: const *char, - x: int, y: int, w: int, h: int, flags: window_flags) nullable *window; +export fn create_window( + title: str, + x: int, + y: int, + w: int, + h: int, + flags: window_flags, +) (*window | error) = { + let title = strings::to_c(title); + defer free(title); + return wrapptr(_create_window(title, x, y, w, h, flags))?: *window; +}; // Destroy a window. export @symbol("SDL_DestroyWindow") fn destroy_window(window: *window) void; -- cgit v1.2.3 From b491c48785b55cc841e11c3f13f307c0d4cc0ef7 Mon Sep 17 00:00:00 2001 From: Drew DeVault Date: Fri, 10 Dec 2021 15:24:31 +0100 Subject: gamecontroller: add button enum --- sdl2/gamecontroller.ha | 26 ++++++++++++++++++++++++++ 1 file changed, 26 insertions(+) diff --git a/sdl2/gamecontroller.ha b/sdl2/gamecontroller.ha index cf78674..46b5f5c 100644 --- a/sdl2/gamecontroller.ha +++ b/sdl2/gamecontroller.ha @@ -22,6 +22,32 @@ export type controller_axis = enum u8 { INVALID = 255, }; +// The list of buttons available from a controller +export type controller_button = 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 -- cgit v1.2.3 From 89dbe1ad56becac574114ecec258dfd464b82633 Mon Sep 17 00:00:00 2001 From: Drew DeVault Date: Sat, 11 Dec 2021 12:50:12 +0100 Subject: Add SetTextureAlphaMod wrapper --- sdl2/render.ha | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/sdl2/render.ha b/sdl2/render.ha index 649e786..0bba541 100644 --- a/sdl2/render.ha +++ b/sdl2/render.ha @@ -123,6 +123,22 @@ export fn set_texture_color_mod( return wrapvoid(_set_texture_color_mod(texture, r, g, b)); }; +@symbol("SDL_SetTextureAlphaMod") fn _set_texture_alpha_mod(texture: *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 set_texture_alpha_mod(texture: *texture, a: u8) (void | error) = { + // TODO: Double check errors + return wrapvoid(_set_texture_alpha_mod(texture, a)); +}; + @symbol("SDL_RenderCopy") fn _render_copy(renderer: *renderer, texture: *texture, srcrect: nullable *rect, dstrect: nullable *rect) int; -- cgit v1.2.3 From b7bb74caa20dbb85ae22da8d74f0b8f2e657f5ad Mon Sep 17 00:00:00 2001 From: Drew DeVault Date: Sat, 11 Dec 2021 12:58:26 +0100 Subject: Add blend modes --- sdl2/blendmode.ha | 11 +++++++++++ sdl2/render.ha | 11 +++++++++++ 2 files changed, 22 insertions(+) create mode 100644 sdl2/blendmode.ha diff --git a/sdl2/blendmode.ha b/sdl2/blendmode.ha new file mode 100644 index 0000000..a32e537 --- /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 blend_mode = enum { + NONE = 0x00000000, + BLEND = 0x00000001, + ADD = 0x00000002, + MOD = 0x00000004, + MUL = 0x00000008, + INVALID = 0x7FFFFFFF +}; diff --git a/sdl2/render.ha b/sdl2/render.ha index 0bba541..19c3940 100644 --- a/sdl2/render.ha +++ b/sdl2/render.ha @@ -139,6 +139,17 @@ export fn set_texture_alpha_mod(texture: *texture, a: u8) (void | error) = { return wrapvoid(_set_texture_alpha_mod(texture, a)); }; +@symbol("SDL_SetTextureBlendMode") fn _set_texture_blend_mode( + texture: *texture, mode: blend_mode) int; + +// Set the blend mode for a texture, used by SDL_RenderCopy(). +export fn set_texture_blend_mode( + texture: *texture, + mode: blend_mode, +) (void | error) = { + return wrapvoid(_set_texture_blend_mode(texture, mode)); +}; + @symbol("SDL_RenderCopy") fn _render_copy(renderer: *renderer, texture: *texture, srcrect: nullable *rect, dstrect: nullable *rect) int; -- cgit v1.2.3 From e5ad22498ca893e96557486a808213b05601e25f Mon Sep 17 00:00:00 2001 From: Drew DeVault Date: Sun, 12 Dec 2021 12:40:47 +0100 Subject: sdl2::mixer: initial commit --- Makefile | 2 +- cmd/demo/main.ha | 7 +++++++ sdl2/audio.ha | 31 ++++++++++++++++++++++++++++++ sdl2/mixer/general.ha | 52 +++++++++++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 91 insertions(+), 1 deletion(-) create mode 100644 sdl2/audio.ha create mode 100644 sdl2/mixer/general.ha diff --git a/Makefile b/Makefile index afbbfd2..c6cdb28 100644 --- a/Makefile +++ b/Makefile @@ -1,7 +1,7 @@ .POSIX: .SUFFIXES: -LIBS=-lc -lSDL2_image -lSDL2 +LIBS=-lc -lSDL2_image -lSDL2_mixer -lSDL2 demo: hare build $(LIBS) cmd/demo diff --git a/cmd/demo/main.ha b/cmd/demo/main.ha index 081134a..73a5517 100644 --- a/cmd/demo/main.ha +++ b/cmd/demo/main.ha @@ -2,6 +2,7 @@ use fmt; use sdl2; use sdl2::{ controller_axis, event_type, renderer_flags, window_flags }; use sdl2::image; +use sdl2::mixer; use strings; type object = struct { @@ -34,6 +35,12 @@ fn run() (void | sdl2::error) = { image::init(image::init_flags::PNG | image::init_flags::JPG); defer image::quit(); + mixer::init(mixer::init_flags::OGG)!; + defer mixer::quit(); + mixer::open_audio(mixer::DEFAULT_FREQUENCY, mixer::DEFAULT_FORMAT, + mixer::DEFAULT_CHANNELS, 1024)!; + defer mixer::close_audio(); + const win = sdl2::create_window("Hare SDL2 demo", sdl2::WINDOWPOS_UNDEFINED, sdl2::WINDOWPOS_UNDEFINED, 640, 480, window_flags::NONE)?; diff --git a/sdl2/audio.ha b/sdl2/audio.ha new file mode 100644 index 0000000..42c4b95 --- /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 audio_format = u16; + +// Unsigned 8-bit samples +export def AUDIO_U8: audio_format = 0x0008; +// Signed 8-bit samples +export def AUDIO_S8: audio_format = 0x8008; +// Unsigned 16-bit samples, little-endian +export def AUDIO_U16LSB: audio_format = 0x0010; +// Signed 16-bit samples, little-endian +export def AUDIO_S16LSB: audio_format = 0x8010; +// Unsigned 16-bit samples, big-endian +export def AUDIO_U16MSB: audio_format = 0x1010; +// Signed 16-bit samples, big-endian +export def AUDIO_S16MSB: audio_format = 0x9010; +// Unsigned 16-bit samples +export def AUDIO_U16: audio_format = AUDIO_U16LSB; +// Signed 16-bit samples +export def AUDIO_S16: audio_format = AUDIO_S16LSB; diff --git a/sdl2/mixer/general.ha b/sdl2/mixer/general.ha new file mode 100644 index 0000000..b87ac4e --- /dev/null +++ b/sdl2/mixer/general.ha @@ -0,0 +1,52 @@ +use sdl2; + +// Flags for [[init]]. +export type init_flags = enum { + FLAC = 0x00000001, + MOD = 0x00000002, + MP3 = 0x00000008, + OGG = 0x00000010, + MID = 0x00000020, + OPUS = 0x00000040 +}; + +// The default mixer has 8 simultaneous mixing channels +export def CHANNELS: int = 8; + +// Good default frequency for a PC soundcard +export def DEFAULT_FREQUENCY: int = 22050; + +// Good default channels for a PC soundcard +export def DEFAULT_CHANNELS: int = 2; + +// XXX: This should choose MSB on a big-endian system: + +// Good default format for a PC soundcard +export def DEFAULT_FORMAT: sdl2::audio_format = sdl2::AUDIO_S16LSB; + +@symbol("Mix_Init") fn _init(flags: int) int; + +// Loads dynamic libraries and prepares them for use. Flags should be +// one or more flags from [[init_flags]] OR'd together. +export fn init(flags: init_flags) (void | sdl2::error) = { + return sdl2::wrapvoid(_init(flags)); +}; + +// Unloads libraries loaded with [[init]]. +export @symbol("Mix_Quit") fn quit() void; + +@symbol("Mix_OpenAudio") fn _openaudio(frequency: int, + format: u16, channels: int, chunksize: int) int; + +// Open the mixer with a certain audio format +export fn open_audio( + frequency: int, + format: sdl2::audio_format, + channels: int, + chunksize: int, +) (void | sdl2::error) = { + return sdl2::wrapvoid(_openaudio(frequency, format, channels, chunksize)); +}; + +// Close the mixer, halting all playing audio +export @symbol("Mix_CloseAudio") fn close_audio() void; -- cgit v1.2.3 From aad6ff05cc6110da6b458d9631604dacb44bcc61 Mon Sep 17 00:00:00 2001 From: Drew DeVault Date: Sun, 12 Dec 2021 13:06:13 +0100 Subject: all: add error handling on init --- cmd/demo/main.ha | 4 ++-- sdl2/image/image.ha | 10 ++++++---- sdl2/sdl2.ha | 6 +++++- 3 files changed, 13 insertions(+), 7 deletions(-) diff --git a/cmd/demo/main.ha b/cmd/demo/main.ha index 73a5517..2b662a2 100644 --- a/cmd/demo/main.ha +++ b/cmd/demo/main.ha @@ -30,9 +30,9 @@ export fn main() void = { }; fn run() (void | sdl2::error) = { - sdl2::init(sdl2::init_flags::VIDEO | sdl2::init_flags::GAMECONTROLLER); + sdl2::init(sdl2::init_flags::VIDEO | sdl2::init_flags::GAMECONTROLLER)!; defer sdl2::quit(); - image::init(image::init_flags::PNG | image::init_flags::JPG); + image::init(image::init_flags::PNG | image::init_flags::JPG)!; defer image::quit(); mixer::init(mixer::init_flags::OGG)!; diff --git a/sdl2/image/image.ha b/sdl2/image/image.ha index 6cabee2..8a48009 100644 --- a/sdl2/image/image.ha +++ b/sdl2/image/image.ha @@ -12,11 +12,13 @@ export type init_flags = enum int { WEBP = 0x00000008, }; +@symbol("IMG_Init") fn _init(flags: init_flags) int; + // Loads dynamic libraries and prepares them for use. Flags should be one or -// more flags from IMG_InitFlags OR'd together. -// -// Returns the flags successfully initialized, or 0 on failure. -export @symbol("IMG_Init") fn init(flags: init_flags) int; +// more flags from [[init_flags]] OR'd together. +export fn init(flags: init_flags) (void | sdl2::error) = { + return sdl2::wrapvoid(_init(flags)); +}; // Unloads libraries loaded with [[init]] export @symbol("IMG_Quit") fn quit() void; diff --git a/sdl2/sdl2.ha b/sdl2/sdl2.ha index b71c890..08e1234 100644 --- a/sdl2/sdl2.ha +++ b/sdl2/sdl2.ha @@ -13,8 +13,12 @@ export type init_flags = enum uint { EVERYTHING = TIMER | AUDIO | VIDEO | EVENTS | JOYSTICK | HAPTIC | GAMECONTROLLER | SENSOR, }; +@symbol("SDL_Init") fn _init(flags: init_flags) int; + // This function initializes the subsystems specified by 'flags'. -export @symbol("SDL_Init") fn init(flags: init_flags) void; +export fn init(flags: init_flags) (void | error) = { + return wrapvoid(_init(flags)); +}; // This function cleans up all initialized subsystems. You should call it upon // all exit conditions. -- cgit v1.2.3 From 6843b25b2fd4f8286f46403bfaf519e64b5e676d Mon Sep 17 00:00:00 2001 From: Drew DeVault Date: Sun, 12 Dec 2021 13:27:45 +0100 Subject: Add rwops io::stream implementation --- sdl2/rwops.ha | 128 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 128 insertions(+) create mode 100644 sdl2/rwops.ha diff --git a/sdl2/rwops.ha b/sdl2/rwops.ha new file mode 100644 index 0000000..4638c29 --- /dev/null +++ b/sdl2/rwops.ha @@ -0,0 +1,128 @@ +use io; +use strings; + +// 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 rwops = struct { + sz: *fn(ctx: *rwops) i64, + seek: *fn(ctx: *rwops, offs: i64, whence: int) i64, + read: *fn(ctx: *rwops, ptr: *void, sz: size, maxnum: size) size, + write: *fn(ctx: *rwops, ptr: *void, sz: size, num: size) size, + close: *fn(ctx: *rwops) void, + + type_: rwops_type, + // XXX: This union is platform-specific + hidden: union { + stdio: struct { + autoclose: bool, + fp: nullable *void, // FILE * + }, + mem: struct { + base: nullable *u8, + here: nullable *u8, + stop: nullable *u8, + }, + unknown: struct { + data1: nullable *void, + data2: nullable *void, + }, + }, +}; + +@symbol("SDL_RWFromFile") fn _rw_from_file( + file: const *char, + mode: const *char, +) *rwops; + +// Returns the size of an [[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 rwsize(ctx: *rwops) i64; + +// Closes an [[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 rwclose(ctx: *rwops) int; + +// TODO: Other RWops wrappers + +// Creates an [[rwops]] from an [[io::handle]]. Closing the rwops does not close +// the underlying stream. +export fn rw_from_handle(in: io::handle) *rwops = { + // TODO: Add stream_from_rw + let rw = alloc(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: *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: *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: *rwops, ptr: *void, sz: size, maxnum: size) size = { + const handle = *(&ctx.hidden.unknown.data1: *io::handle); + let buf = ptr: *[*]u8; + match (io::readitems(handle, buf[..sz * maxnum], sz)) { + case let n: size => + return n; + case io::error => + return 0; + }; +}; + +fn stream_write(ctx: *rwops, ptr: *void, sz: size, num: size) size = { + const handle = *(&ctx.hidden.unknown.data1: *io::handle); + let buf = ptr: *[*]u8; + match (io::writeitems(handle, buf[..sz * num], sz)) { + case let n: size => + return n; + case io::error => + return 0; + }; +}; + +fn stream_close(ctx: *rwops) void = { + const handle = *(&ctx.hidden.unknown.data1: *io::handle); + free(ctx); +}; -- cgit v1.2.3 From 1bd67672132302c37db6a676cd3598cd49e23f9b Mon Sep 17 00:00:00 2001 From: Drew DeVault Date: Sun, 12 Dec 2021 13:50:07 +0100 Subject: sdl2::mixer: implement sample loading --- COPYING | 4 ++++ cmd/demo/main.ha | 12 ++++++++++-- sample.ogg | Bin 0 -> 17276 bytes sdl2/mixer/samples.ha | 33 +++++++++++++++++++++++++++++++++ 4 files changed, 47 insertions(+), 2 deletions(-) create mode 100644 sample.ogg create mode 100644 sdl2/mixer/samples.ha diff --git a/COPYING b/COPYING index c257317..1ad757e 100644 --- a/COPYING +++ b/COPYING @@ -1,3 +1,7 @@ +sample.ogg: lancelottjones CC-BY 3.0 + +hare-sdl2: + Mozilla Public License Version 2.0 ================================== diff --git a/cmd/demo/main.ha b/cmd/demo/main.ha index 2b662a2..a5e9e68 100644 --- a/cmd/demo/main.ha +++ b/cmd/demo/main.ha @@ -1,4 +1,5 @@ use fmt; +use fs; use sdl2; use sdl2::{ controller_axis, event_type, renderer_flags, window_flags }; use sdl2::image; @@ -25,12 +26,16 @@ export fn main() void = { match (run()) { case let err: sdl2::error => fmt::fatal("SDL2 error: {}", sdl2::strerror(err)); + case let err: fs::error => + fmt::fatal("Error: {}", fs::strerror(err)); case void => void; }; }; -fn run() (void | sdl2::error) = { - sdl2::init(sdl2::init_flags::VIDEO | sdl2::init_flags::GAMECONTROLLER)!; +fn run() (void | fs::error | sdl2::error) = { + sdl2::init(sdl2::init_flags::VIDEO + | sdl2::init_flags::AUDIO + | sdl2::init_flags::GAMECONTROLLER)!; defer sdl2::quit(); image::init(image::init_flags::PNG | image::init_flags::JPG)!; defer image::quit(); @@ -67,6 +72,9 @@ fn run() (void | sdl2::error) = { sdl2::game_controller_close(c); }; + let sample = mixer::load_file("sample.ogg")?; + defer mixer::free_chunk(sample); + let state = state { window = win, render = render, diff --git a/sample.ogg b/sample.ogg new file mode 100644 index 0000000..f3decb6 Binary files /dev/null and b/sample.ogg differ diff --git a/sdl2/mixer/samples.ha b/sdl2/mixer/samples.ha new file mode 100644 index 0000000..49f1e1e --- /dev/null +++ b/sdl2/mixer/samples.ha @@ -0,0 +1,33 @@ +use fs; +use io; +use os; +use sdl2; + +// The internal format for an audio chunk +export type chunk = struct { + allocated: int, + abuf: *u8, + alen: u32, + volume: u8, +}; + +@symbol("Mix_LoadWAV_RW") fn _loadwav_rw(src: *sdl2::rwops, freesrc: int) nullable *chunk; + +// Loads a sample from an [[io::handle]]. The stream will not be closed for you. +export fn load(src: io::handle) (*chunk | sdl2::error) = { + const rw = sdl2::rw_from_handle(src); + defer sdl2::rwclose(rw); + return sdl2::wrapptr(_loadwav_rw(rw, 0))?: *chunk; +}; + +// Loads a sample from a file path. +export fn load_file(src: str) (*chunk | fs::error | sdl2::error) = { + const file = os::open(src)?; + defer io::close(file); + return load(file); +}; + +// Free the memory used in chunk, and free chunk itself as well. Do not use +// chunk after this without loading a new sample to it. Note: It's a bad idea to +// free a chunk that is still being played... +export @symbol("Mix_FreeChunk") fn free_chunk(chunk: *chunk) void; -- cgit v1.2.3 From eae63b218494d3aa077a9ea196abc4c5096e016b Mon Sep 17 00:00:00 2001 From: Drew DeVault Date: Sun, 12 Dec 2021 13:56:23 +0100 Subject: sdl2::mixer: implement channel playback --- cmd/demo/main.ha | 1 + sdl2/mixer/channels.ha | 20 ++++++++++++++++++++ sdl2/mixer/samples.ha | 6 ++++++ 3 files changed, 27 insertions(+) create mode 100644 sdl2/mixer/channels.ha diff --git a/cmd/demo/main.ha b/cmd/demo/main.ha index a5e9e68..e97c433 100644 --- a/cmd/demo/main.ha +++ b/cmd/demo/main.ha @@ -74,6 +74,7 @@ fn run() (void | fs::error | sdl2::error) = { let sample = mixer::load_file("sample.ogg")?; defer mixer::free_chunk(sample); + mixer::play_channel(0, sample, -1)?; let state = state { window = win, diff --git a/sdl2/mixer/channels.ha b/sdl2/mixer/channels.ha new file mode 100644 index 0000000..4bf4820 --- /dev/null +++ b/sdl2/mixer/channels.ha @@ -0,0 +1,20 @@ +use sdl2; + +@symbol("Mix_PlayChannelTimed") fn _play_channel_timed( + channel: int, + sample: *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 play_channel( + channel: int, + sample: *chunk, + loops: int, +) (void | sdl2::error) = { + return sdl2::wrapvoid(_play_channel_timed(channel, sample, loops, -1)); +}; diff --git a/sdl2/mixer/samples.ha b/sdl2/mixer/samples.ha index 49f1e1e..aaf1ad1 100644 --- a/sdl2/mixer/samples.ha +++ b/sdl2/mixer/samples.ha @@ -31,3 +31,9 @@ export fn load_file(src: str) (*chunk | fs::error | sdl2::error) = { // chunk after this without loading a new sample to it. Note: It's a bad idea to // free a chunk that is still being played... export @symbol("Mix_FreeChunk") fn free_chunk(chunk: *chunk) void; + +// Maximum volume for a chunk. +export def MAX_VOLUME: int = 128; // XXX: SDL_mixer derives this from SDL_MIX_MAXVOLUME + +// Sets the chunk volume as specified, returning the previous value. +export @symbol("Mix_VolumeChunk") fn volume_chunk(chunk: *chunk, volume: int) int; -- cgit v1.2.3 From a4845006af09ee33a802e2847ca7617626232ea7 Mon Sep 17 00:00:00 2001 From: Drew DeVault Date: Wed, 15 Dec 2021 10:08:25 +0100 Subject: sdl2: add rect drawing functions --- sdl2/render.ha | 33 +++++++++++++++++++++++++++++++++ 1 file changed, 33 insertions(+) diff --git a/sdl2/render.ha b/sdl2/render.ha index 19c3940..2c53183 100644 --- a/sdl2/render.ha +++ b/sdl2/render.ha @@ -150,6 +150,17 @@ export fn set_texture_blend_mode( return wrapvoid(_set_texture_blend_mode(texture, mode)); }; +@symbol("SDL_SetRenderDrawBlendMode") fn _set_render_draw_blend_mode( + renderer: *renderer, mode: blend_mode) int; + +// Set the blend mode used for drawing operations (fill and line). +export fn set_render_draw_blend_mode( + renderer: *renderer, + mode: blend_mode, +) (void | error) = { + return wrapvoid(_set_render_draw_blend_mode(renderer, mode)); +}; + @symbol("SDL_RenderCopy") fn _render_copy(renderer: *renderer, texture: *texture, srcrect: nullable *rect, dstrect: nullable *rect) int; @@ -162,3 +173,25 @@ export fn render_copy( ) (void | error) = { return wrapvoid(_render_copy(renderer, texture, srcrect, dstrect)); }; + +@symbol("SDL_RenderDrawRect") fn _render_draw_rect( + renderer: *renderer, rect: const nullable *rect) int; + +// Draw a rectangle on the current rendering target. +export fn render_draw_rect( + renderer: *renderer, + rect: const nullable *rect, +) (void | error) = { + return wrapvoid(_render_draw_rect(renderer, rect)); +}; + +@symbol("SDL_RenderFillRect") fn _render_fill_rect( + renderer: *renderer, rect: const nullable *rect) int; + +// Fills a rectangle on the current rendering target. +export fn render_fill_rect( + renderer: *renderer, + rect: const nullable *rect, +) (void | error) = { + return wrapvoid(_render_fill_rect(renderer, rect)); +}; -- cgit v1.2.3 From 7855e717d6af1b4f1e9ed15b7db9bda6686da954 Mon Sep 17 00:00:00 2001 From: Eyal Sawady Date: Wed, 15 Dec 2021 14:07:47 +0000 Subject: sdl2: add keysym typesand get_key_from_name --- sdl2/events.ha | 2 +- sdl2/keyboard.ha | 645 +++++++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 646 insertions(+), 1 deletion(-) create mode 100644 sdl2/keyboard.ha diff --git a/sdl2/events.ha b/sdl2/events.ha index 58bbfd7..9cfce84 100644 --- a/sdl2/events.ha +++ b/sdl2/events.ha @@ -106,7 +106,7 @@ export type keyboard_event = struct { repeat: u8, padding2: u8, padding3: u8, - keysym: uint, // TODO: Rig me up with the keysym type + keysym: keysym, }; // Size of the [[text_editing_event]] 'text' field. diff --git a/sdl2/keyboard.ha b/sdl2/keyboard.ha new file mode 100644 index 0000000..4e1325f --- /dev/null +++ b/sdl2/keyboard.ha @@ -0,0 +1,645 @@ +use strings; + +export type 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 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 = scancode::CAPSLOCK | 1: scancode << 30, + + F1 = scancode::F1 | 1: scancode << 30, + F2 = scancode::F2 | 1: scancode << 30, + F3 = scancode::F3 | 1: scancode << 30, + F4 = scancode::F4 | 1: scancode << 30, + F5 = scancode::F5 | 1: scancode << 30, + F6 = scancode::F6 | 1: scancode << 30, + F7 = scancode::F7 | 1: scancode << 30, + F8 = scancode::F8 | 1: scancode << 30, + F9 = scancode::F9 | 1: scancode << 30, + F10 = scancode::F10 | 1: scancode << 30, + F11 = scancode::F11 | 1: scancode << 30, + F12 = scancode::F12 | 1: scancode << 30, + + PRINTSCREEN = scancode::PRINTSCREEN | 1: scancode << 30, + SCROLLLOCK = scancode::SCROLLLOCK | 1: scancode << 30, + PAUSE = scancode::PAUSE | 1: scancode << 30, + INSERT = scancode::INSERT | 1: scancode << 30, + HOME = scancode::HOME | 1: scancode << 30, + PAGEUP = scancode::PAGEUP | 1: scancode << 30, + DELETE = '\x7F', + END = scancode::END | 1: scancode << 30, + PAGEDOWN = scancode::PAGEDOWN | 1: scancode << 30, + RIGHT = scancode::RIGHT | 1: scancode << 30, + LEFT = scancode::LEFT | 1: scancode << 30, + DOWN = scancode::DOWN | 1: scancode << 30, + UP = scancode::UP | 1: scancode << 30, + + NUMLOCKCLEAR = scancode::NUMLOCKCLEAR | 1: scancode << 30, + KP_DIVIDE = scancode::KP_DIVIDE | 1: scancode << 30, + KP_MULTIPLY = scancode::KP_MULTIPLY | 1: scancode << 30, + KP_MINUS = scancode::KP_MINUS | 1: scancode << 30, + KP_PLUS = scancode::KP_PLUS | 1: scancode << 30, + KP_ENTER = scancode::KP_ENTER | 1: scancode << 30, + KP_1 = scancode::KP_1 | 1: scancode << 30, + KP_2 = scancode::KP_2 | 1: scancode << 30, + KP_3 = scancode::KP_3 | 1: scancode << 30, + KP_4 = scancode::KP_4 | 1: scancode << 30, + KP_5 = scancode::KP_5 | 1: scancode << 30, + KP_6 = scancode::KP_6 | 1: scancode << 30, + KP_7 = scancode::KP_7 | 1: scancode << 30, + KP_8 = scancode::KP_8 | 1: scancode << 30, + KP_9 = scancode::KP_9 | 1: scancode << 30, + KP_0 = scancode::KP_0 | 1: scancode << 30, + KP_PERIOD = scancode::KP_PERIOD | 1: scancode << 30, + + APPLICATION = scancode::APPLICATION | 1: scancode << 30, + POWER = scancode::POWER | 1: scancode << 30, + KP_EQUALS = scancode::KP_EQUALS | 1: scancode << 30, + F13 = scancode::F13 | 1: scancode << 30, + F14 = scancode::F14 | 1: scancode << 30, + F15 = scancode::F15 | 1: scancode << 30, + F16 = scancode::F16 | 1: scancode << 30, + F17 = scancode::F17 | 1: scancode << 30, + F18 = scancode::F18 | 1: scancode << 30, + F19 = scancode::F19 | 1: scancode << 30, + F20 = scancode::F20 | 1: scancode << 30, + F21 = scancode::F21 | 1: scancode << 30, + F22 = scancode::F22 | 1: scancode << 30, + F23 = scancode::F23 | 1: scancode << 30, + F24 = scancode::F24 | 1: scancode << 30, + EXECUTE = scancode::EXECUTE | 1: scancode << 30, + HELP = scancode::HELP | 1: scancode << 30, + MENU = scancode::MENU | 1: scancode << 30, + SELECT = scancode::SELECT | 1: scancode << 30, + STOP = scancode::STOP | 1: scancode << 30, + AGAIN = scancode::AGAIN | 1: scancode << 30, + UNDO = scancode::UNDO | 1: scancode << 30, + CUT = scancode::CUT | 1: scancode << 30, + COPY = scancode::COPY | 1: scancode << 30, + PASTE = scancode::PASTE | 1: scancode << 30, + FIND = scancode::FIND | 1: scancode << 30, + MUTE = scancode::MUTE | 1: scancode << 30, + VOLUMEUP = scancode::VOLUMEUP | 1: scancode << 30, + VOLUMEDOWN = scancode::VOLUMEDOWN | 1: scancode << 30, + KP_COMMA = scancode::KP_COMMA | 1: scancode << 30, + KP_EQUALSAS400 = scancode::KP_EQUALSAS400 | 1: scancode << 30, + + ALTERASE = scancode::ALTERASE | 1: scancode << 30, + SYSREQ = scancode::SYSREQ | 1: scancode << 30, + CANCEL = scancode::CANCEL | 1: scancode << 30, + CLEAR = scancode::CLEAR | 1: scancode << 30, + PRIOR = scancode::PRIOR | 1: scancode << 30, + RETURN2 = scancode::RETURN2 | 1: scancode << 30, + SEPARATOR = scancode::SEPARATOR | 1: scancode << 30, + OUT = scancode::OUT | 1: scancode << 30, + OPER = scancode::OPER | 1: scancode << 30, + CLEARAGAIN = scancode::CLEARAGAIN | 1: scancode << 30, + CRSEL = scancode::CRSEL | 1: scancode << 30, + EXSEL = scancode::EXSEL | 1: scancode << 30, + + KP_00 = scancode::KP_00 | 1: scancode << 30, + KP_000 = scancode::KP_000 | 1: scancode << 30, + THOUSANDSSEPARATOR = scancode::THOUSANDSSEPARATOR | 1: scancode << 30, + DECIMALSEPARATOR = scancode::DECIMALSEPARATOR | 1: scancode << 30, + CURRENCYUNIT = scancode::CURRENCYUNIT | 1: scancode << 30, + CURRENCYSUBUNIT = scancode::CURRENCYSUBUNIT | 1: scancode << 30, + KP_LEFTPAREN = scancode::KP_LEFTPAREN | 1: scancode << 30, + KP_RIGHTPAREN = scancode::KP_RIGHTPAREN | 1: scancode << 30, + KP_LEFTBRACE = scancode::KP_LEFTBRACE | 1: scancode << 30, + KP_RIGHTBRACE = scancode::KP_RIGHTBRACE | 1: scancode << 30, + KP_TAB = scancode::KP_TAB | 1: scancode << 30, + KP_BACKSPACE = scancode::KP_BACKSPACE | 1: scancode << 30, + KP_A = scancode::KP_A | 1: scancode << 30, + KP_B = scancode::KP_B | 1: scancode << 30, + KP_C = scancode::KP_C | 1: scancode << 30, + KP_D = scancode::KP_D | 1: scancode << 30, + KP_E = scancode::KP_E | 1: scancode << 30, + KP_F = scancode::KP_F | 1: scancode << 30, + KP_XOR = scancode::KP_XOR | 1: scancode << 30, + KP_POWER = scancode::KP_POWER | 1: scancode << 30, + KP_PERCENT = scancode::KP_PERCENT | 1: scancode << 30, + KP_LESS = scancode::KP_LESS | 1: scancode << 30, + KP_GREATER = scancode::KP_GREATER | 1: scancode << 30, + KP_AMPERSAND = scancode::KP_AMPERSAND | 1: scancode << 30, + KP_DBLAMPERSAND = scancode::KP_DBLAMPERSAND | 1: scancode << 30, + KP_VERTICALBAR = scancode::KP_VERTICALBAR | 1: scancode << 30, + KP_DBLVERTICALBAR = scancode::KP_DBLVERTICALBAR | 1: scancode << 30, + KP_COLON = scancode::KP_COLON | 1: scancode << 30, + KP_HASH = scancode::KP_HASH | 1: scancode << 30, + KP_SPACE = scancode::KP_SPACE | 1: scancode << 30, + KP_AT = scancode::KP_AT | 1: scancode << 30, + KP_EXCLAM = scancode::KP_EXCLAM | 1: scancode << 30, + KP_MEMSTORE = scancode::KP_MEMSTORE | 1: scancode << 30, + KP_MEMRECALL = scancode::KP_MEMRECALL | 1: scancode << 30, + KP_MEMCLEAR = scancode::KP_MEMCLEAR | 1: scancode << 30, + KP_MEMADD = scancode::KP_MEMADD | 1: scancode << 30, + KP_MEMSUBTRACT = scancode::KP_MEMSUBTRACT | 1: scancode << 30, + KP_MEMMULTIPLY = scancode::KP_MEMMULTIPLY | 1: scancode << 30, + KP_MEMDIVIDE = scancode::KP_MEMDIVIDE | 1: scancode << 30, + KP_PLUSMINUS = scancode::KP_PLUSMINUS | 1: scancode << 30, + KP_CLEAR = scancode::KP_CLEAR | 1: scancode << 30, + KP_CLEARENTRY = scancode::KP_CLEARENTRY | 1: scancode << 30, + KP_BINARY = scancode::KP_BINARY | 1: scancode << 30, + KP_OCTAL = scancode::KP_OCTAL | 1: scancode << 30, + KP_DECIMAL = scancode::KP_DECIMAL | 1: scancode << 30, + KP_HEXADECIMAL = scancode::KP_HEXADECIMAL | 1: scancode << 30, + + LCTRL = scancode::LCTRL | 1: scancode << 30, + LSHIFT = scancode::LSHIFT | 1: scancode << 30, + LALT = scancode::LALT | 1: scancode << 30, + LGUI = scancode::LGUI | 1: scancode << 30, + RCTRL = scancode::RCTRL | 1: scancode << 30, + RSHIFT = scancode::RSHIFT | 1: scancode << 30, + RALT = scancode::RALT | 1: scancode << 30, + RGUI = scancode::RGUI | 1: scancode << 30, + + MODE = scancode::MODE | 1: scancode << 30, + + AUDIONEXT = scancode::AUDIONEXT | 1: scancode << 30, + AUDIOPREV = scancode::AUDIOPREV | 1: scancode << 30, + AUDIOSTOP = scancode::AUDIOSTOP | 1: scancode << 30, + AUDIOPLAY = scancode::AUDIOPLAY | 1: scancode << 30, + AUDIOMUTE = scancode::AUDIOMUTE | 1: scancode << 30, + MEDIASELECT = scancode::MEDIASELECT | 1: scancode << 30, + WWW = scancode::WWW | 1: scancode << 30, + MAIL = scancode::MAIL | 1: scancode << 30, + CALCULATOR = scancode::CALCULATOR | 1: scancode << 30, + COMPUTER = scancode::COMPUTER | 1: scancode << 30, + AC_SEARCH = scancode::AC_SEARCH | 1: scancode << 30, + AC_HOME = scancode::AC_HOME | 1: scancode << 30, + AC_BACK = scancode::AC_BACK | 1: scancode << 30, + AC_FORWARD = scancode::AC_FORWARD | 1: scancode << 30, + AC_STOP = scancode::AC_STOP | 1: scancode << 30, + AC_REFRESH = scancode::AC_REFRESH | 1: scancode << 30, + AC_BOOKMARKS = scancode::AC_BOOKMARKS | 1: scancode << 30, + + BRIGHTNESSDOWN = scancode::BRIGHTNESSDOWN | 1: scancode << 30, + BRIGHTNESSUP = scancode::BRIGHTNESSUP | 1: scancode << 30, + DISPLAYSWITCH = scancode::DISPLAYSWITCH | 1: scancode << 30, + KBDILLUMTOGGLE = scancode::KBDILLUMTOGGLE | 1: scancode << 30, + KBDILLUMDOWN = scancode::KBDILLUMDOWN | 1: scancode << 30, + KBDILLUMUP = scancode::KBDILLUMUP | 1: scancode << 30, + EJECT = scancode::EJECT | 1: scancode << 30, + SLEEP = scancode::SLEEP | 1: scancode << 30, + APP1 = scancode::APP1 | 1: scancode << 30, + APP2 = scancode::APP2 | 1: scancode << 30, + + AUDIOREWIND = scancode::AUDIOREWIND | 1: scancode << 30, + AUDIOFASTFORWARD = scancode::AUDIOFASTFORWARD | 1: scancode << 30 +}; + +export type 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 keysym = struct { + scancode: scancode, + sym: keycode, + mod: keymod, + unused: u32, +}; + +@symbol("SDL_GetKeyFromName") fn _get_key_from_name(name: *const char) keycode; + +export fn get_key_from_name(name: str) (keycode | error) = { + const name = strings::to_c(name); + defer free(name); + const sym = _get_key_from_name(name); + if (sym == keycode::UNKNOWN) { + return strings::fromc(geterror()): error; + }; + return sym; +}; -- cgit v1.2.3 From 4fefaa37f86bc31b164fdd5efd2f5a693c81c2a8 Mon Sep 17 00:00:00 2001 From: Vlad-Stefan Harbuz Date: Mon, 17 Jan 2022 19:47:25 +0100 Subject: sdl2: add usage to README Signed-off-by: Vlad-Stefan Harbuz --- README.md | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/README.md b/README.md index 6374285..b84f65b 100644 --- a/README.md +++ b/README.md @@ -6,3 +6,8 @@ Please do not make GUIs with this. [Hare]: https://harelang.org [SDL2]: https://libsdl.org + +## Usage + +* Install `libsdl2`, `libsdl2-image`, `libsdl2-mixer` and `libopusfile`. +* Run `make run` to run the demo. -- cgit v1.2.3 From 83582bc016d10700d7716a3f08c2a7dc7f263fac Mon Sep 17 00:00:00 2001 From: Vlad-Stefan Harbuz Date: Thu, 3 Feb 2022 18:10:17 +0100 Subject: add gl.ha Signed-off-by: Vlad-Stefan Harbuz --- sdl2/gl.ha | 45 +++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 45 insertions(+) create mode 100644 sdl2/gl.ha diff --git a/sdl2/gl.ha b/sdl2/gl.ha new file mode 100644 index 0000000..3edffa7 --- /dev/null +++ b/sdl2/gl.ha @@ -0,0 +1,45 @@ +export type glcontext = void; + +export type glprofile = enum int { + GL_CONTEXT_PROFILE_CORE = 0x0001, + GL_CONTEXT_PROFILE_COMPATIBILITY = 0x0002, + GL_CONTEXT_PROFILE_ES = 0x0004, +}; + +export type 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, +}; + +export @symbol("SDL_GL_CreateContext") fn gl_create_context( + window: *window) *glcontext; +export @symbol("SDL_GL_GetProcAddress") fn gl_get_proc_address( + proc: *const char) *void; +export @symbol("SDL_GL_SetAttribute") fn gl_set_attribute( + attr: glattr, value: int) *void; +export @symbol("SDL_GL_SwapWindow") fn gl_swap_window(window: *window) void; -- cgit v1.2.3 From 0fdfa823b404fff3d18d72bf2dccfe0ce444cfd5 Mon Sep 17 00:00:00 2001 From: Drew DeVault Date: Sat, 5 Feb 2022 09:41:17 +0100 Subject: Add controller rumble support Signed-off-by: Drew DeVault --- cmd/demo/main.ha | 1 + sdl2/gamecontroller.ha | 26 ++++++++++++++++++++++++++ 2 files changed, 27 insertions(+) diff --git a/cmd/demo/main.ha b/cmd/demo/main.ha index e97c433..3cac391 100644 --- a/cmd/demo/main.ha +++ b/cmd/demo/main.ha @@ -62,6 +62,7 @@ fn run() (void | fs::error | sdl2::error) = { match (sdl2::game_controller_open(i)) { case let c: *sdl2::gamecontroller => controller = c; + sdl2::game_controller_rumble(c, 0x4000, 0x4000, 1000): void; break; case sdl2::error => void; }; diff --git a/sdl2/gamecontroller.ha b/sdl2/gamecontroller.ha index 46b5f5c..4af8677 100644 --- a/sdl2/gamecontroller.ha +++ b/sdl2/gamecontroller.ha @@ -71,3 +71,29 @@ export fn game_controller_open( // Close a game controller previously opened with [[game_controller_open]]. export @symbol("SDL_GameControllerClose") fn game_controller_close( gamecontroller: *gamecontroller) void; + +@symbol("SDL_GameControllerRumble") fn _game_controller_rumble( + gamecontroller: *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 game_controller_rumble( + gamecontroller: *gamecontroller, + low_frequency_rumble: u16, + high_frequency_rumble: u16, + duration_ms: u32, +) (void | error) = { + return wrapvoid(_game_controller_rumble( + gamecontroller, + low_frequency_rumble, + high_frequency_rumble, + duration_ms)); +}; -- cgit v1.2.3 From a4c83d86504c6af40a1870f297952c3802bc8b99 Mon Sep 17 00:00:00 2001 From: Vlad-Stefan Harbuz Date: Mon, 7 Feb 2022 13:08:51 +0100 Subject: correct indentation Signed-off-by: Vlad-Stefan Harbuz --- sdl2/blendmode.ha | 12 +++--- sdl2/events.ha | 108 ++++++++++++++++++++++++------------------------- sdl2/gamecontroller.ha | 14 +++---- sdl2/mixer/general.ha | 12 +++--- 4 files changed, 73 insertions(+), 73 deletions(-) diff --git a/sdl2/blendmode.ha b/sdl2/blendmode.ha index a32e537..11649cf 100644 --- a/sdl2/blendmode.ha +++ b/sdl2/blendmode.ha @@ -2,10 +2,10 @@ // The blend mode used in SDL_RenderCopy() and drawing operations. export type blend_mode = enum { - NONE = 0x00000000, - BLEND = 0x00000001, - ADD = 0x00000002, - MOD = 0x00000004, - MUL = 0x00000008, - INVALID = 0x7FFFFFFF + NONE = 0x00000000, + BLEND = 0x00000001, + ADD = 0x00000002, + MOD = 0x00000004, + MUL = 0x00000008, + INVALID = 0x7FFFFFFF }; diff --git a/sdl2/events.ha b/sdl2/events.ha index 9cfce84..a8be41c 100644 --- a/sdl2/events.ha +++ b/sdl2/events.ha @@ -1,72 +1,72 @@ export type event_type = enum u32 { - FIRSTEVENT = 0, + FIRSTEVENT = 0, - QUIT = 0x100, + QUIT = 0x100, - APP_TERMINATING, - APP_LOWMEMORY, - APP_WILLENTERBACKGROUND, - APP_DIDENTERBACKGROUND, - APP_WILLENTERFOREGROUND, - APP_DIDENTERFOREGROUND, + APP_TERMINATING, + APP_LOWMEMORY, + APP_WILLENTERBACKGROUND, + APP_DIDENTERBACKGROUND, + APP_WILLENTERFOREGROUND, + APP_DIDENTERFOREGROUND, - DISPLAYEVENT = 0x150, + DISPLAYEVENT = 0x150, - WINDOWEVENT = 0x200, - SYSWMEVENT, + WINDOWEVENT = 0x200, + SYSWMEVENT, - KEYDOWN = 0x300, - KEYUP, - TEXTEDITING, - TEXTINPUT, - KEYMAPCHANGED, + KEYDOWN = 0x300, + KEYUP, + TEXTEDITING, + TEXTINPUT, + KEYMAPCHANGED, - MOUSEMOTION = 0x400, - MOUSEBUTTONDOWN, - MOUSEBUTTONUP, - MOUSEWHEEL, + MOUSEMOTION = 0x400, + MOUSEBUTTONDOWN, + MOUSEBUTTONUP, + MOUSEWHEEL, - JOYAXISMOTION = 0x600, - JOYBALLMOTION, - JOYHATMOTION, - JOYBUTTONDOWN, - JOYBUTTONUP, - JOYDEVICEADDED, - JOYDEVICEREMOVED, + JOYAXISMOTION = 0x600, + JOYBALLMOTION, + JOYHATMOTION, + JOYBUTTONDOWN, + JOYBUTTONUP, + JOYDEVICEADDED, + JOYDEVICEREMOVED, - CONTROLLERAXISMOTION = 0x650, - CONTROLLERBUTTONDOWN, - CONTROLLERBUTTONUP, - CONTROLLERDEVICEADDED, - CONTROLLERDEVICEREMOVED, - CONTROLLERDEVICEREMAPPED, + CONTROLLERAXISMOTION = 0x650, + CONTROLLERBUTTONDOWN, + CONTROLLERBUTTONUP, + CONTROLLERDEVICEADDED, + CONTROLLERDEVICEREMOVED, + CONTROLLERDEVICEREMAPPED, - FINGERDOWN = 0x700, - FINGERUP, - FINGERMOTION, + FINGERDOWN = 0x700, + FINGERUP, + FINGERMOTION, - DOLLARGESTURE = 0x800, - DOLLARRECORD, - MULTIGESTURE, + DOLLARGESTURE = 0x800, + DOLLARRECORD, + MULTIGESTURE, - CLIPBOARDUPDATE = 0x900, + CLIPBOARDUPDATE = 0x900, - DROPFILE = 0x1000, - DROPTEXT, - DROPBEGIN, - DROPCOMPLETE, + DROPFILE = 0x1000, + DROPTEXT, + DROPBEGIN, + DROPCOMPLETE, - AUDIODEVICEADDED = 0x1100, - AUDIODEVICEREMOVED, + AUDIODEVICEADDED = 0x1100, + AUDIODEVICEREMOVED, - SENSORUPDATE = 0x1200, + SENSORUPDATE = 0x1200, - RENDER_TARGETS_RESET = 0x2000, - RENDER_DEVICE_RESET, + RENDER_TARGETS_RESET = 0x2000, + RENDER_DEVICE_RESET, - USEREVENT = 0x8000, + USEREVENT = 0x8000, - LASTEVENT = 0xFFFF + LASTEVENT = 0xFFFF }; // Fields shared by every event @@ -372,9 +372,9 @@ export type event = union { export @symbol("SDL_PumpEvents") fn pump_events() void; export type eventaction = enum { - ADDEVENT, - PEEKEVENT, - GETEVENT, + ADDEVENT, + PEEKEVENT, + GETEVENT, }; @symbol("SDL_PeepEvents") fn _peep_events(events: *event, numevents: int, diff --git a/sdl2/gamecontroller.ha b/sdl2/gamecontroller.ha index 4af8677..7bf2e18 100644 --- a/sdl2/gamecontroller.ha +++ b/sdl2/gamecontroller.ha @@ -13,13 +13,13 @@ export type gamecontroller = void; // // Trigger axis values range from 0 to [[JOYSTICK_AXIS_MAX]]. export type controller_axis = enum u8 { - LEFTX, - LEFTY, - RIGHTX, - RIGHTY, - TRIGGERLEFT, - TRIGGERRIGHT, - INVALID = 255, + LEFTX, + LEFTY, + RIGHTX, + RIGHTY, + TRIGGERLEFT, + TRIGGERRIGHT, + INVALID = 255, }; // The list of buttons available from a controller diff --git a/sdl2/mixer/general.ha b/sdl2/mixer/general.ha index b87ac4e..32c7b38 100644 --- a/sdl2/mixer/general.ha +++ b/sdl2/mixer/general.ha @@ -2,12 +2,12 @@ use sdl2; // Flags for [[init]]. export type init_flags = enum { - FLAC = 0x00000001, - MOD = 0x00000002, - MP3 = 0x00000008, - OGG = 0x00000010, - MID = 0x00000020, - OPUS = 0x00000040 + FLAC = 0x00000001, + MOD = 0x00000002, + MP3 = 0x00000008, + OGG = 0x00000010, + MID = 0x00000020, + OPUS = 0x00000040 }; // The default mixer has 8 simultaneous mixing channels -- cgit v1.2.3 From 2276dc7ad067f7af7504783239103c1abd7b4433 Mon Sep 17 00:00:00 2001 From: Vlad-Stefan Harbuz Date: Mon, 7 Feb 2022 13:08:52 +0100 Subject: refactor names from e.g. sdl2::init() to sdl2::SDL_Init() Signed-off-by: Vlad-Stefan Harbuz --- cmd/demo/main.ha | 110 +++++++------- sdl2/audio.ha | 18 +-- sdl2/blendmode.ha | 2 +- sdl2/errors.ha | 6 +- sdl2/events.ha | 200 +++++++++++++------------- sdl2/gamecontroller.ha | 42 +++--- sdl2/gl.ha | 18 +-- sdl2/image/image.ha | 34 ++--- sdl2/joystick.ha | 8 +- sdl2/keyboard.ha | 384 ++++++++++++++++++++++++------------------------- sdl2/mixer/channels.ha | 10 +- sdl2/mixer/general.ha | 32 ++--- sdl2/mixer/samples.ha | 32 ++--- sdl2/pixels.ha | 12 +- sdl2/rect.ha | 8 +- sdl2/render.ha | 158 ++++++++++---------- sdl2/rwops.ha | 38 ++--- sdl2/sdl2.ha | 10 +- sdl2/surface.ha | 12 +- sdl2/timer.ha | 10 +- sdl2/video.ha | 32 ++--- 21 files changed, 588 insertions(+), 588 deletions(-) diff --git a/cmd/demo/main.ha b/cmd/demo/main.ha index 3cac391..a6f2a92 100644 --- a/cmd/demo/main.ha +++ b/cmd/demo/main.ha @@ -1,13 +1,13 @@ use fmt; use fs; use sdl2; -use sdl2::{ controller_axis, event_type, renderer_flags, window_flags }; +use sdl2::{ SDL_GameControllerAxis, SDL_EventType, SDL_RendererFlags, SDL_WindowFlags }; use sdl2::image; use sdl2::mixer; use strings; type object = struct { - tex: *sdl2::texture, + tex: *sdl2::SDL_Texture, w: int, h: int, x: int, y: int, dx: int, dy: int, @@ -15,8 +15,8 @@ type object = struct { type state = struct { quit: bool, - window: *sdl2::window, - render: *sdl2::renderer, + window: *sdl2::SDL_Window, + render: *sdl2::SDL_Renderer, nbutton: int, hare: object, cat: object, @@ -33,49 +33,49 @@ export fn main() void = { }; fn run() (void | fs::error | sdl2::error) = { - sdl2::init(sdl2::init_flags::VIDEO + sdl2::SDL_Init(sdl2::init_flags::VIDEO | sdl2::init_flags::AUDIO | sdl2::init_flags::GAMECONTROLLER)!; - defer sdl2::quit(); - image::init(image::init_flags::PNG | image::init_flags::JPG)!; - defer image::quit(); - - mixer::init(mixer::init_flags::OGG)!; - defer mixer::quit(); - mixer::open_audio(mixer::DEFAULT_FREQUENCY, mixer::DEFAULT_FORMAT, - mixer::DEFAULT_CHANNELS, 1024)!; - defer mixer::close_audio(); - - const win = sdl2::create_window("Hare SDL2 demo", - sdl2::WINDOWPOS_UNDEFINED, sdl2::WINDOWPOS_UNDEFINED, - 640, 480, window_flags::NONE)?; - defer sdl2::destroy_window(win); - - const render = sdl2::create_renderer(win, -1, renderer_flags::NONE)?; - defer sdl2::destroy_renderer(render); - - let controller: nullable *sdl2::gamecontroller = null; - for (let i = 0; i < sdl2::numjoysticks()?; i += 1) { - if (!sdl2::is_game_controller(i)) { + defer sdl2::SDL_Quit(); + image::IMG_Init(image::IMG_InitFlags::PNG | image::IMG_InitFlags::JPG)!; + defer image::IMG_Quit(); + + mixer::Mix_Init(mixer::MIX_InitFlags::OGG)!; + defer mixer::Mix_Quit(); + mixer::Mix_OpenAudio(mixer::MIX_DEFAULT_FREQUENCY, mixer::MIX_DEFAULT_FORMAT, + mixer::MIX_DEFAULT_CHANNELS, 1024)!; + defer mixer::Mix_CloseAudio(); + + const win = sdl2::SDL_CreateWindow("Hare SDL2 demo", + sdl2::SDL_WINDOWPOS_UNDEFINED, sdl2::SDL_WINDOWPOS_UNDEFINED, + 640, 480, SDL_WindowFlags::NONE)?; + defer sdl2::SDL_DestroyWindow(win); + + const render = sdl2::SDL_CreateRenderer(win, -1, SDL_RendererFlags::NONE)?; + defer sdl2::SDL_DestroyRenderer(render); + + let controller: nullable *sdl2::SDL_GameController = null; + for (let i = 0; i < sdl2::SDL_NumJoysticks()?; i += 1) { + if (!sdl2::SDL_IsGameController(i)) { continue; }; - match (sdl2::game_controller_open(i)) { - case let c: *sdl2::gamecontroller => + match (sdl2::SDL_GameControllerOpen(i)) { + case let c: *sdl2::SDL_GameController => controller = c; - sdl2::game_controller_rumble(c, 0x4000, 0x4000, 1000): void; + sdl2::SDL_GameControllerRumble(c, 0x4000, 0x4000, 1000): void; break; case sdl2::error => void; }; }; defer match (controller) { case null => void; - case let c: *sdl2::gamecontroller => - sdl2::game_controller_close(c); + case let c: *sdl2::SDL_GameController => + sdl2::SDL_GameControllerClose(c); }; let sample = mixer::load_file("sample.ogg")?; - defer mixer::free_chunk(sample); - mixer::play_channel(0, sample, -1)?; + defer mixer::Mix_FreeChunk(sample); + mixer::Mix_PlayChannelTimed(0, sample, -1)?; let state = state { window = win, @@ -84,8 +84,8 @@ fn run() (void | fs::error | sdl2::error) = { cat = load_object(render, "cat.png")?, ... }; - defer sdl2::destroy_texture(state.hare.tex); - defer sdl2::destroy_texture(state.cat.tex); + defer sdl2::SDL_DestroyTexture(state.hare.tex); + defer sdl2::SDL_DestroyTexture(state.cat.tex); state.hare.dx = 2; state.hare.dy = 2; @@ -93,33 +93,33 @@ fn run() (void | fs::error | sdl2::error) = { for (!state.quit) { update(&state)?; draw(&state)?; - sdl2::delay(1000 / 60); + sdl2::SDL_Delay(1000 / 60); }; }; fn update(state: *state) (void | sdl2::error) = { let ev = sdl2::event { ... }; - for (sdl2::poll_event(&ev)? == 1) switch (ev.event_type) { - case event_type::QUIT => + for (sdl2::SDL_PollEvent(&ev)? == 1) switch (ev.event_type) { + case SDL_EventType::QUIT => state.quit = true; return; - case event_type::CONTROLLERAXISMOTION => - let delta = ev.caxis.value: int * 10 / sdl2::JOYSTICK_AXIS_MAX; + case SDL_EventType::CONTROLLERAXISMOTION => + let delta = ev.caxis.value: int * 10 / sdl2::SDL_JOYSTICK_AXIS_MAX; if (axis_x(ev.caxis.axis)) { state.cat.dx = delta; }; if (axis_y(ev.caxis.axis)) { state.cat.dy = delta; }; - case event_type::CONTROLLERBUTTONDOWN => + case SDL_EventType::CONTROLLERBUTTONDOWN => state.nbutton += 1; - case event_type::CONTROLLERBUTTONUP => + case SDL_EventType::CONTROLLERBUTTONUP => state.nbutton -= 1; case => void; }; let width = 0, height = 0; - sdl2::get_window_size(state.window, &width, &height); + sdl2::SDL_GetWindowSize(state.window, &width, &height); state.hare.x += state.hare.dx; state.hare.y += state.hare.dy; @@ -148,19 +148,19 @@ fn update(state: *state) (void | sdl2::error) = { fn draw(state: *state) (void | sdl2::error) = { if (state.nbutton == 0) { - sdl2::set_render_draw_color(state.render, 50, 50, 50, 255)?; + sdl2::SDL_SetRenderDrawColor(state.render, 50, 50, 50, 255)?; } else { - sdl2::set_render_draw_color(state.render, 50, 50, 200, 255)?; + sdl2::SDL_SetRenderDrawColor(state.render, 50, 50, 200, 255)?; }; - sdl2::render_clear(state.render)?; + sdl2::SDL_RenderClear(state.render)?; draw_object(state, &state.hare)?; draw_object(state, &state.cat)?; - sdl2::render_present(state.render); + sdl2::SDL_RenderPresent(state.render); }; fn draw_object(state: *state, obj: *object) (void | sdl2::error) = { - sdl2::render_copy(state.render, obj.tex, null, &sdl2::rect { + sdl2::SDL_RenderCopy(state.render, obj.tex, null, &sdl2::SDL_Rect { x = obj.x, y = obj.y, w = obj.w, @@ -168,28 +168,28 @@ fn draw_object(state: *state, obj: *object) (void | sdl2::error) = { })?; }; -fn axis_x(axis: controller_axis) bool = { +fn axis_x(axis: SDL_GameControllerAxis) bool = { switch (axis) { - case controller_axis::LEFTX, controller_axis::RIGHTX => + case SDL_GameControllerAxis::LEFTX, SDL_GameControllerAxis::RIGHTX => return true; case => return false; }; }; -fn axis_y(axis: controller_axis) bool = { +fn axis_y(axis: SDL_GameControllerAxis) bool = { switch (axis) { - case controller_axis::LEFTY, controller_axis::RIGHTY => + case SDL_GameControllerAxis::LEFTY, SDL_GameControllerAxis::RIGHTY => return true; case => return false; }; }; -fn load_object(render: *sdl2::renderer, path: str) (object | sdl2::error) = { - const tex = image::load_texture(render, path)?; +fn load_object(render: *sdl2::SDL_Renderer, path: str) (object | sdl2::error) = { + const tex = image::IMG_LoadTexture(render, path)?; let w = 0, h = 0; - sdl2::query_texture(tex, null, null, &w, &h)?; + sdl2::SDL_QueryTexture(tex, null, null, &w, &h)?; return object { tex = tex, w = w, diff --git a/sdl2/audio.ha b/sdl2/audio.ha index 42c4b95..1b78880 100644 --- a/sdl2/audio.ha +++ b/sdl2/audio.ha @@ -11,21 +11,21 @@ // || || || +---sample bit size---+ // || || || | | // 15 14 13 12 11 10 09 08 07 06 05 04 03 02 01 00 -export type audio_format = u16; +export type SDL_AudioFormat = u16; // Unsigned 8-bit samples -export def AUDIO_U8: audio_format = 0x0008; +export def AUDIO_U8: SDL_AudioFormat = 0x0008; // Signed 8-bit samples -export def AUDIO_S8: audio_format = 0x8008; +export def AUDIO_S8: SDL_AudioFormat = 0x8008; // Unsigned 16-bit samples, little-endian -export def AUDIO_U16LSB: audio_format = 0x0010; +export def AUDIO_U16LSB: SDL_AudioFormat = 0x0010; // Signed 16-bit samples, little-endian -export def AUDIO_S16LSB: audio_format = 0x8010; +export def AUDIO_S16LSB: SDL_AudioFormat = 0x8010; // Unsigned 16-bit samples, big-endian -export def AUDIO_U16MSB: audio_format = 0x1010; +export def AUDIO_U16MSB: SDL_AudioFormat = 0x1010; // Signed 16-bit samples, big-endian -export def AUDIO_S16MSB: audio_format = 0x9010; +export def AUDIO_S16MSB: SDL_AudioFormat = 0x9010; // Unsigned 16-bit samples -export def AUDIO_U16: audio_format = AUDIO_U16LSB; +export def AUDIO_U16: SDL_AudioFormat = AUDIO_U16LSB; // Signed 16-bit samples -export def AUDIO_S16: audio_format = AUDIO_S16LSB; +export def AUDIO_S16: SDL_AudioFormat = AUDIO_S16LSB; diff --git a/sdl2/blendmode.ha b/sdl2/blendmode.ha index 11649cf..25acab6 100644 --- a/sdl2/blendmode.ha +++ b/sdl2/blendmode.ha @@ -1,7 +1,7 @@ // TODO: Flesh me out // The blend mode used in SDL_RenderCopy() and drawing operations. -export type blend_mode = enum { +export type SDL_BlendMode = enum { NONE = 0x00000000, BLEND = 0x00000001, ADD = 0x00000002, diff --git a/sdl2/errors.ha b/sdl2/errors.ha index bc02505..52d23a0 100644 --- a/sdl2/errors.ha +++ b/sdl2/errors.ha @@ -8,7 +8,7 @@ export fn strerror(err: error) str = { return err: str; }; -@symbol("SDL_GetError") fn geterror() const *char; +@symbol("SDL_GetError") fn SDL_GetError() const *char; export fn wrapvoid(ret: int) (void | error) = { wrapint(ret)?; @@ -16,7 +16,7 @@ export fn wrapvoid(ret: int) (void | error) = { export fn wrapint(ret: int) (int | error) = { if (ret < 0) { - return strings::fromc(geterror()): error; + return strings::fromc(SDL_GetError()): error; }; return ret; }; @@ -26,6 +26,6 @@ export fn wrapptr(ret: nullable *void) (*void | error) = { case let v: *void => return v; case null => - return strings::fromc(geterror()): error; + return strings::fromc(SDL_GetError()): error; }; }; diff --git a/sdl2/events.ha b/sdl2/events.ha index a8be41c..1003af1 100644 --- a/sdl2/events.ha +++ b/sdl2/events.ha @@ -1,4 +1,4 @@ -export type event_type = enum u32 { +export type SDL_EventType = enum u32 { FIRSTEVENT = 0, QUIT = 0x100, @@ -70,14 +70,14 @@ export type event_type = enum u32 { }; // Fields shared by every event -export type common_event = struct { - event_type: event_type, +export type SDL_CommonEvent = struct { + event_type: SDL_EventType, timestamp: u32, }; // Display state change event data (event.display.*) -export type display_event = struct { - common_event, +export type SDL_DisplayEvent = struct { + SDL_CommonEvent, display: u32, event: u8, padding1: u8, @@ -87,8 +87,8 @@ export type display_event = struct { }; // Window state change event data (event.window.*) -export type window_event = struct { - common_event, +export type SDL_WindowEvent = struct { + SDL_CommonEvent, window_id: u32, event: u8, padding1: u8, @@ -99,41 +99,41 @@ export type window_event = struct { }; // Keyboard button event structure (event.key.*) -export type keyboard_event = struct { - common_event, +export type SDL_KeyboardEvent = struct { + SDL_CommonEvent, window_id: u32, state: u8, repeat: u8, padding2: u8, padding3: u8, - keysym: keysym, + keysym: SDL_Keysym, }; -// Size of the [[text_editing_event]] 'text' field. +// Size of the [[SDL_TextEditingEvent]] 'text' field. export def TEXTEDITINGEVENT_TEXT_SIZE: size = 32; // Keyboard text editing event structure (event.edit.*) -export type text_editing_event = struct { - common_event, +export type SDL_TextEditingEvent = struct { + SDL_CommonEvent, window_id: u32, text: [TEXTEDITINGEVENT_TEXT_SIZE]char, start: i32, length: i32, }; -// Size of the [[text_input_event]] 'text' field. +// Size of the [[SDL_TextInputEvent]] 'text' field. export def TEXTINPUTEVENT_TEXT_SIZE: size = 32; // Keyboard text input event structure (event.text.*) -export type text_input_event = struct { - common_event, +export type SDL_TextInputEvent = struct { + SDL_CommonEvent, window_id: u32, text: [TEXTINPUTEVENT_TEXT_SIZE]char, }; // Mouse motion event structure (event.motion.*) -export type mouse_motion_event = struct { - common_event, +export type SDL_MouseMotionEvent = struct { + SDL_CommonEvent, window_id: u32, which: u32, state: u32, @@ -144,8 +144,8 @@ export type mouse_motion_event = struct { }; // Mouse button event structure (event.button.*) -export type mouse_button_event = struct { - common_event, +export type SDL_MouseButtonEvent = struct { + SDL_CommonEvent, window_id: u32, which: u32, button: u8, @@ -157,8 +157,8 @@ export type mouse_button_event = struct { }; // Mouse wheel event structure (event.wheel.*) -export type mouse_wheel_event = struct { - common_event, +export type SDL_MouseWheelEvent = struct { + SDL_CommonEvent, window_id: u32, which: u32, x: i32, @@ -167,8 +167,8 @@ export type mouse_wheel_event = struct { }; // Joystick axis motion event structure (event.jaxis.*) -export type joy_axis_event = struct { - common_event, +export type SDL_JoyAxisEvent = struct { + SDL_CommonEvent, which: i32, // TODO: Rig me up with the JoystickID type axis: u8, padding1: u8, @@ -179,8 +179,8 @@ export type joy_axis_event = struct { }; // Joystick trackball motion event structure (event.jball.*) -export type joy_ball_event = struct { - common_event, +export type SDL_JoyBallEvent = struct { + SDL_CommonEvent, which: i32, // TODO: Rig me up with the JoystickID type ball: u8, padding1: u8, @@ -191,8 +191,8 @@ export type joy_ball_event = struct { }; // Joystick hat position change event structure (event.jhat.*) -export type joy_hat_event = struct { - common_event, +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 @@ -201,8 +201,8 @@ export type joy_hat_event = struct { }; // Joystick button event structure (event.jbutton.*) -export type joy_button_event = struct { - common_event, +export type SDL_JoyButtonEvent = struct { + SDL_CommonEvent, which: i32, // TODO: Rig me up with the JoystickID type button: u8, state: u8, @@ -211,16 +211,16 @@ export type joy_button_event = struct { }; // Joystick device event structure (event.jdevice.*) -export type joy_device_event = struct { - common_event, +export type SDL_JoyDeviceEvent = struct { + SDL_CommonEvent, which: i32, }; // Game controller axis motion event structure (event.caxis.*) -export type controller_axis_event = struct { - common_event, +export type SDL_ControllerAxisEvent = struct { + SDL_CommonEvent, which: i32, // TODO - axis: controller_axis, + axis: SDL_GameControllerAxis, padding1: u8, padding2: u8, padding3: u8, @@ -229,8 +229,8 @@ export type controller_axis_event = struct { }; // Game controller button event structure (event.cbutton.*) -export type controller_button_event = struct { - common_event, +export type SDL_ControllerButtonEvent = struct { + SDL_CommonEvent, which: i32, button: u8, state: u8, @@ -239,14 +239,14 @@ export type controller_button_event = struct { }; // Controller device event structure (event.cdevice.*) -export type controller_device_event = struct { - common_event, +export type SDL_ControllerDeviceEvent = struct { + SDL_CommonEvent, which: i32, }; // Audio device event structure (event.adevice.*) -export type audio_device_event = struct { - common_event, +export type SDL_AudioDeviceEvent = struct { + SDL_CommonEvent, which: u32, iscapture: u8, padding1: u8, @@ -255,8 +255,8 @@ export type audio_device_event = struct { }; // Touch finger event structure (event.tfinger.*) -export type touch_finger_event = struct { - common_event, +export type SDL_TouchFingerEvent = struct { + SDL_CommonEvent, touch_id: i64, // TODO finger_id: i64, // TODO x: f32, @@ -267,8 +267,8 @@ export type touch_finger_event = struct { }; // Multiple Finger Gesture Event (event.mgesture.*) -export type multi_gesture_event = struct { - common_event, +export type SDL_MultiGestureEvent = struct { + SDL_CommonEvent, touch_id: i64, // TODO dtheta: f32, ddist: f32, @@ -279,8 +279,8 @@ export type multi_gesture_event = struct { }; // Dollar Gesture Event (event.dgesture.*) -export type dollar_gesture_event = struct { - common_event, +export type SDL_DollarGestureEvent = struct { + SDL_CommonEvent, touch_id: i64, // TODO gesture_id: i64, // TODO num_fingers: u32, @@ -292,32 +292,32 @@ export type dollar_gesture_event = struct { // 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 drop_event = struct { - common_event, +export type SDL_DropEvent = struct { + SDL_CommonEvent, file: *char, window_id: u32, }; // Sensor event structure (event.sensor.*) -export type sensor_event = struct { - common_event, +export type SDL_SensorEvent = struct { + SDL_CommonEvent, which: i32, data: [6]f32, }; // The "quit requested" event -export type quit_event = struct { - common_event, +export type SDL_QuitEvent = struct { + SDL_CommonEvent, }; // OS Specific event -export type os_event = struct { - common_event, +export type SDL_OSEvent = struct { + SDL_CommonEvent, }; // A user-defined event type (event.user.*) -export type user_event = struct { - common_event, +export type SDL_UserEvent = struct { + SDL_CommonEvent, window_id: u32, code: i32, data1: *void, @@ -326,40 +326,40 @@ export type user_event = struct { // A video driver dependent system event (event.syswm.*) // This event is disabled by default, you can enable it with [[eventstate]]. -export type syswm_event = struct { - common_event, +export type SDL_SysWMEvent = struct { + SDL_CommonEvent, msg: *void, // TODO }; // General event structure export type event = union { - event_type: event_type, - common: common_event, - display: display_event, - window: window_event, - key: keyboard_event, - edit: text_editing_event, - text: text_input_event, - motion: mouse_motion_event, - button: mouse_button_event, - wheel: mouse_wheel_event, - jaxis: joy_axis_event, - jball: joy_ball_event, - jhat: joy_hat_event, - jbutton: joy_button_event, - jdevice: joy_device_event, - caxis: controller_axis_event, - cbutton: controller_button_event, - cdevice: controller_device_event, - adevice: audio_device_event, - sensor: sensor_event, - quit: quit_event, - user: user_event, - syswm: syswm_event, - tfinger: touch_finger_event, - mgesture: multi_gesture_event, - dgestures: dollar_gesture_event, - drop: drop_event, + 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, }; @@ -369,7 +369,7 @@ export type event = union { // 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 pump_events() void; +export @symbol("SDL_PumpEvents") fn SDL_PumpEvents() void; export type eventaction = enum { ADDEVENT, @@ -378,7 +378,7 @@ export type eventaction = enum { }; @symbol("SDL_PeepEvents") fn _peep_events(events: *event, numevents: int, - action: eventaction, mintype: event_type, maxtype: event_type) int; + action: eventaction, mintype: SDL_EventType, maxtype: SDL_EventType) int; // Checks the event queue for messages and optionally returns them. // @@ -394,33 +394,33 @@ export type eventaction = enum { // will be removed from the queue. // // This function is thread-safe. -export fn peep_events( +export fn SDL_PeepEvents( events: *event, numevents: int, action: eventaction, - mintype: event_type, - maxtype: event_type, + 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 has_event(event_type: event_type) bool; +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 has_events(mintype: event_type, maxtype: event_type) bool; +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(event_type: event_type) void; +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 flush_events(mintype: event_type, maxtype: event_type) void; +export @symbol("SDL_FlushEvents") fn SDL_FlushEvents(mintype: SDL_EventType, maxtype: SDL_EventType) void; @symbol("SDL_PollEvent") fn _poll_event(event: nullable *event) int; @@ -430,7 +430,7 @@ export @symbol("SDL_FlushEvents") fn flush_events(mintype: event_type, maxtype: // // If 'event' is not null, the next event is removed from the queue and stored // in that area. -export fn poll_event(event: nullable *event) (int | error) = { +export fn SDL_PollEvent(event: nullable *event) (int | error) = { return wrapint(_poll_event(event)); }; @@ -440,7 +440,7 @@ export fn poll_event(event: nullable *event) (int | error) = { // // If 'event' is not null, the next event is removed from the queue and stored // in that area. -export fn wait_event(event: nullable *event) (void | error) = { +export fn SDL_WaitEvent(event: nullable *event) (void | error) = { return wrapvoid(_wait_event(event)); }; @@ -448,11 +448,11 @@ export fn wait_event(event: nullable *event) (void | error) = { 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 wait_event_timeout( +export fn SDL_WaitEventTimeout( event: nullable *event, timeout: int, ) (void | error) = { @@ -462,7 +462,7 @@ export fn wait_event_timeout( @symbol("SDL_PushEvent") fn _push_event(event: *event) int; // Add an event to the event queue. -export fn push_event(event: *event) (void | error) = { +export fn SDL_PushEvent(event: *event) (void | error) = { return wrapvoid(_push_event(event)); }; diff --git a/sdl2/gamecontroller.ha b/sdl2/gamecontroller.ha index 7bf2e18..113bb37 100644 --- a/sdl2/gamecontroller.ha +++ b/sdl2/gamecontroller.ha @@ -1,18 +1,18 @@ // TODO: Flesh me out -// The gamecontroller structure used to identify an SDL game controller. +// The SDL_GameController structure used to identify an SDL game controller. // (Opaque) -export type gamecontroller = void; +export type SDL_GameController = void; // The list of axes available from a controller // -// Thumbstick axis values range from [[JOYSTICK_AXIS_MIN]] to -// [[JOYSTICK_AXIS_MAX]], and are centered within ~8000 of zero, though advanced +// 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 [[JOYSTICK_AXIS_MAX]]. -export type controller_axis = enum u8 { +// Trigger axis values range from 0 to [[SDL_JOYSTICK_AXIS_MAX]]. +export type SDL_GameControllerAxis = enum u8 { LEFTX, LEFTY, RIGHTX, @@ -23,7 +23,7 @@ export type controller_axis = enum u8 { }; // The list of buttons available from a controller -export type controller_button = enum u8 { +export type SDL_GameControllerBUtton = enum u8 { INVALID = 255, A = 0, B, @@ -49,31 +49,31 @@ export type controller_button = enum u8 { }; // 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 is_game_controller( +export @symbol("SDL_IsGameController") fn SDL_IsGameController( joystick_index: int) bool; @symbol("SDL_GameControllerOpen") fn _game_controller_open( - joystick_index: int) nullable *gamecontroller; + joystick_index: int) nullable *SDL_GameController; // Get the SDL_GameController associated with an instance id. -export fn game_controller_open( +export fn SDL_GameControllerOpen( joystick_index: int, -) (*gamecontroller | error) = { - return wrapptr(_game_controller_open(joystick_index))?: *gamecontroller; +) (*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 game_controller_close( - gamecontroller: *gamecontroller) void; +export @symbol("SDL_GameControllerClose") fn SDL_GameControllerClose( + gamecontroller: *SDL_GameController) void; -@symbol("SDL_GameControllerRumble") fn _game_controller_rumble( - gamecontroller: *gamecontroller, +@symbol("SDL_GameControllerRumble") fn _SDL_GameControllerRumble( + gamecontroller: *SDL_GameController, low_frequency_rumble: u16, high_frequency_rumble: u16, duration_ms: u32) int; @@ -85,13 +85,13 @@ export @symbol("SDL_GameControllerClose") fn game_controller_close( // // The low-frequency motor is generally on the left, and the high-frequency // motor is generally on the right. -export fn game_controller_rumble( - gamecontroller: *gamecontroller, +export fn SDL_GameControllerRumble( + gamecontroller: *SDL_GameController, low_frequency_rumble: u16, high_frequency_rumble: u16, duration_ms: u32, ) (void | error) = { - return wrapvoid(_game_controller_rumble( + return wrapvoid(_SDL_GameControllerRumble( gamecontroller, low_frequency_rumble, high_frequency_rumble, diff --git a/sdl2/gl.ha b/sdl2/gl.ha index 3edffa7..023a62f 100644 --- a/sdl2/gl.ha +++ b/sdl2/gl.ha @@ -1,12 +1,12 @@ -export type glcontext = void; +export type SDL_GLContext = void; -export type glprofile = enum int { +export type SDL_GLprofile = enum int { GL_CONTEXT_PROFILE_CORE = 0x0001, GL_CONTEXT_PROFILE_COMPATIBILITY = 0x0002, GL_CONTEXT_PROFILE_ES = 0x0004, }; -export type glattr = enum { +export type SDL_GLattr = enum { GL_RED_SIZE, GL_GREEN_SIZE, GL_BLUE_SIZE, @@ -36,10 +36,10 @@ export type glattr = enum { GL_CONTEXT_NO_ERROR, }; -export @symbol("SDL_GL_CreateContext") fn gl_create_context( - window: *window) *glcontext; -export @symbol("SDL_GL_GetProcAddress") fn gl_get_proc_address( +export @symbol("SDL_GL_CreateContext") fn SDL_GL_CreateContext( + window: *SDL_Window) *SDL_GLContext; +export @symbol("SDL_GL_GetProcAddress") fn SDL_GL_GetProcAddress( proc: *const char) *void; -export @symbol("SDL_GL_SetAttribute") fn gl_set_attribute( - attr: glattr, value: int) *void; -export @symbol("SDL_GL_SwapWindow") fn gl_swap_window(window: *window) void; +export @symbol("SDL_GL_SetAttribute") fn SDL_GL_SetAttribute( + attr: SDL_GLattr, value: int) *void; +export @symbol("SDL_GL_SwapWindow") fn SDL_GL_SwapWindow(window: *SDL_Window) void; diff --git a/sdl2/image/image.ha b/sdl2/image/image.ha index 8a48009..8684f83 100644 --- a/sdl2/image/image.ha +++ b/sdl2/image/image.ha @@ -3,8 +3,8 @@ use sdl2; use strings; -// Flags for [[init]]. -export type init_flags = enum int { +// Flags for [[IMG_Init]]. +export type IMG_InitFlags = enum int { NONE = 0, JPG = 0x00000001, PNG = 0x00000002, @@ -12,35 +12,35 @@ export type init_flags = enum int { WEBP = 0x00000008, }; -@symbol("IMG_Init") fn _init(flags: init_flags) int; +@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 [[init_flags]] OR'd together. -export fn init(flags: init_flags) (void | sdl2::error) = { - return sdl2::wrapvoid(_init(flags)); +// 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 [[init]] -export @symbol("IMG_Quit") fn quit() void; +// Unloads libraries loaded with [[IMG_Init]] +export @symbol("IMG_Quit") fn IMG_Quit() void; -@symbol("IMG_Load") fn _load(file: const *char) nullable *sdl2::surface; +@symbol("IMG_Load") fn _IMG_Load(file: const *char) nullable *sdl2::SDL_Surface; // Load an image from a file path. -export fn load(file: str) (*sdl2::surface | sdl2::error) = { +export fn IMG_Load(file: str) (*sdl2::SDL_Surface | sdl2::error) = { const file = strings::to_c(file); defer free(file); - return sdl2::wrapptr(_load(file))?: *sdl2::surface; + return sdl2::wrapptr(_IMG_Load(file))?: *sdl2::SDL_Surface; }; -@symbol("IMG_LoadTexture") fn _load_texture(renderer: *sdl2::renderer, - file: const *char) nullable *sdl2::texture; +@symbol("IMG_LoadTexture") fn _IMG_LoadTexture(SDL_Renderer: *sdl2::SDL_Renderer, + file: const *char) nullable *sdl2::SDL_Texture; // Load an image directly into a render texture. -export fn load_texture( - renderer: *sdl2::renderer, +export fn IMG_LoadTexture( + SDL_Renderer: *sdl2::SDL_Renderer, file: str, -) (*sdl2::texture | sdl2::error) = { +) (*sdl2::SDL_Texture | sdl2::error) = { const file = strings::to_c(file); defer free(file); - return sdl2::wrapptr(_load_texture(renderer, file))?: *sdl2::texture; + return sdl2::wrapptr(_IMG_LoadTexture(SDL_Renderer, file))?: *sdl2::SDL_Texture; }; diff --git a/sdl2/joystick.ha b/sdl2/joystick.ha index adbcd14..2234aff 100644 --- a/sdl2/joystick.ha +++ b/sdl2/joystick.ha @@ -1,12 +1,12 @@ // TODO: Flesh me out // Minimum value for a joystick axis. -export def JOYSTICK_AXIS_MIN: i16 = -32768; +export def SDL_JOYSTICK_AXIS_MIN: i16 = -32768; // Minimum value for a joystick axis. -export def JOYSTICK_AXIS_MAX: i16 = 32767; +export def SDL_JOYSTICK_AXIS_MAX: i16 = 32767; -@symbol("SDL_NumJoysticks") fn _numjoysticks() int; +@symbol("SDL_NumJoysticks") fn _SDL_NumJoysticks() int; // Returns the number of joysticks attached to the system. -export fn numjoysticks() (int | error) = wrapint(_numjoysticks()); +export fn SDL_NumJoysticks() (int | error) = wrapint(_SDL_NumJoysticks()); diff --git a/sdl2/keyboard.ha b/sdl2/keyboard.ha index 4e1325f..97b0a21 100644 --- a/sdl2/keyboard.ha +++ b/sdl2/keyboard.ha @@ -1,6 +1,6 @@ use strings; -export type scancode = enum uint { +export type SDL_Scancode = enum uint { UNKNOWN = 0, // Usage page 0x07 @@ -343,7 +343,7 @@ export type scancode = enum uint { NUM_SCANCODES = 512, }; -export type keycode = enum uint { +export type SDL_Keycode = enum uint { UNKNOWN = 0, RETURN = '\r', @@ -419,190 +419,190 @@ export type keycode = enum uint { y = 'y', z = 'z', - CAPSLOCK = scancode::CAPSLOCK | 1: scancode << 30, - - F1 = scancode::F1 | 1: scancode << 30, - F2 = scancode::F2 | 1: scancode << 30, - F3 = scancode::F3 | 1: scancode << 30, - F4 = scancode::F4 | 1: scancode << 30, - F5 = scancode::F5 | 1: scancode << 30, - F6 = scancode::F6 | 1: scancode << 30, - F7 = scancode::F7 | 1: scancode << 30, - F8 = scancode::F8 | 1: scancode << 30, - F9 = scancode::F9 | 1: scancode << 30, - F10 = scancode::F10 | 1: scancode << 30, - F11 = scancode::F11 | 1: scancode << 30, - F12 = scancode::F12 | 1: scancode << 30, - - PRINTSCREEN = scancode::PRINTSCREEN | 1: scancode << 30, - SCROLLLOCK = scancode::SCROLLLOCK | 1: scancode << 30, - PAUSE = scancode::PAUSE | 1: scancode << 30, - INSERT = scancode::INSERT | 1: scancode << 30, - HOME = scancode::HOME | 1: scancode << 30, - PAGEUP = scancode::PAGEUP | 1: scancode << 30, + CAPSLOCK = SDL_Scancode::CAPSLOCK | 1: SDL_Scancode << 30, + + 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 = scancode::END | 1: scancode << 30, - PAGEDOWN = scancode::PAGEDOWN | 1: scancode << 30, - RIGHT = scancode::RIGHT | 1: scancode << 30, - LEFT = scancode::LEFT | 1: scancode << 30, - DOWN = scancode::DOWN | 1: scancode << 30, - UP = scancode::UP | 1: scancode << 30, - - NUMLOCKCLEAR = scancode::NUMLOCKCLEAR | 1: scancode << 30, - KP_DIVIDE = scancode::KP_DIVIDE | 1: scancode << 30, - KP_MULTIPLY = scancode::KP_MULTIPLY | 1: scancode << 30, - KP_MINUS = scancode::KP_MINUS | 1: scancode << 30, - KP_PLUS = scancode::KP_PLUS | 1: scancode << 30, - KP_ENTER = scancode::KP_ENTER | 1: scancode << 30, - KP_1 = scancode::KP_1 | 1: scancode << 30, - KP_2 = scancode::KP_2 | 1: scancode << 30, - KP_3 = scancode::KP_3 | 1: scancode << 30, - KP_4 = scancode::KP_4 | 1: scancode << 30, - KP_5 = scancode::KP_5 | 1: scancode << 30, - KP_6 = scancode::KP_6 | 1: scancode << 30, - KP_7 = scancode::KP_7 | 1: scancode << 30, - KP_8 = scancode::KP_8 | 1: scancode << 30, - KP_9 = scancode::KP_9 | 1: scancode << 30, - KP_0 = scancode::KP_0 | 1: scancode << 30, - KP_PERIOD = scancode::KP_PERIOD | 1: scancode << 30, - - APPLICATION = scancode::APPLICATION | 1: scancode << 30, - POWER = scancode::POWER | 1: scancode << 30, - KP_EQUALS = scancode::KP_EQUALS | 1: scancode << 30, - F13 = scancode::F13 | 1: scancode << 30, - F14 = scancode::F14 | 1: scancode << 30, - F15 = scancode::F15 | 1: scancode << 30, - F16 = scancode::F16 | 1: scancode << 30, - F17 = scancode::F17 | 1: scancode << 30, - F18 = scancode::F18 | 1: scancode << 30, - F19 = scancode::F19 | 1: scancode << 30, - F20 = scancode::F20 | 1: scancode << 30, - F21 = scancode::F21 | 1: scancode << 30, - F22 = scancode::F22 | 1: scancode << 30, - F23 = scancode::F23 | 1: scancode << 30, - F24 = scancode::F24 | 1: scancode << 30, - EXECUTE = scancode::EXECUTE | 1: scancode << 30, - HELP = scancode::HELP | 1: scancode << 30, - MENU = scancode::MENU | 1: scancode << 30, - SELECT = scancode::SELECT | 1: scancode << 30, - STOP = scancode::STOP | 1: scancode << 30, - AGAIN = scancode::AGAIN | 1: scancode << 30, - UNDO = scancode::UNDO | 1: scancode << 30, - CUT = scancode::CUT | 1: scancode << 30, - COPY = scancode::COPY | 1: scancode << 30, - PASTE = scancode::PASTE | 1: scancode << 30, - FIND = scancode::FIND | 1: scancode << 30, - MUTE = scancode::MUTE | 1: scancode << 30, - VOLUMEUP = scancode::VOLUMEUP | 1: scancode << 30, - VOLUMEDOWN = scancode::VOLUMEDOWN | 1: scancode << 30, - KP_COMMA = scancode::KP_COMMA | 1: scancode << 30, - KP_EQUALSAS400 = scancode::KP_EQUALSAS400 | 1: scancode << 30, - - ALTERASE = scancode::ALTERASE | 1: scancode << 30, - SYSREQ = scancode::SYSREQ | 1: scancode << 30, - CANCEL = scancode::CANCEL | 1: scancode << 30, - CLEAR = scancode::CLEAR | 1: scancode << 30, - PRIOR = scancode::PRIOR | 1: scancode << 30, - RETURN2 = scancode::RETURN2 | 1: scancode << 30, - SEPARATOR = scancode::SEPARATOR | 1: scancode << 30, - OUT = scancode::OUT | 1: scancode << 30, - OPER = scancode::OPER | 1: scancode << 30, - CLEARAGAIN = scancode::CLEARAGAIN | 1: scancode << 30, - CRSEL = scancode::CRSEL | 1: scancode << 30, - EXSEL = scancode::EXSEL | 1: scancode << 30, - - KP_00 = scancode::KP_00 | 1: scancode << 30, - KP_000 = scancode::KP_000 | 1: scancode << 30, - THOUSANDSSEPARATOR = scancode::THOUSANDSSEPARATOR | 1: scancode << 30, - DECIMALSEPARATOR = scancode::DECIMALSEPARATOR | 1: scancode << 30, - CURRENCYUNIT = scancode::CURRENCYUNIT | 1: scancode << 30, - CURRENCYSUBUNIT = scancode::CURRENCYSUBUNIT | 1: scancode << 30, - KP_LEFTPAREN = scancode::KP_LEFTPAREN | 1: scancode << 30, - KP_RIGHTPAREN = scancode::KP_RIGHTPAREN | 1: scancode << 30, - KP_LEFTBRACE = scancode::KP_LEFTBRACE | 1: scancode << 30, - KP_RIGHTBRACE = scancode::KP_RIGHTBRACE | 1: scancode << 30, - KP_TAB = scancode::KP_TAB | 1: scancode << 30, - KP_BACKSPACE = scancode::KP_BACKSPACE | 1: scancode << 30, - KP_A = scancode::KP_A | 1: scancode << 30, - KP_B = scancode::KP_B | 1: scancode << 30, - KP_C = scancode::KP_C | 1: scancode << 30, - KP_D = scancode::KP_D | 1: scancode << 30, - KP_E = scancode::KP_E | 1: scancode << 30, - KP_F = scancode::KP_F | 1: scancode << 30, - KP_XOR = scancode::KP_XOR | 1: scancode << 30, - KP_POWER = scancode::KP_POWER | 1: scancode << 30, - KP_PERCENT = scancode::KP_PERCENT | 1: scancode << 30, - KP_LESS = scancode::KP_LESS | 1: scancode << 30, - KP_GREATER = scancode::KP_GREATER | 1: scancode << 30, - KP_AMPERSAND = scancode::KP_AMPERSAND | 1: scancode << 30, - KP_DBLAMPERSAND = scancode::KP_DBLAMPERSAND | 1: scancode << 30, - KP_VERTICALBAR = scancode::KP_VERTICALBAR | 1: scancode << 30, - KP_DBLVERTICALBAR = scancode::KP_DBLVERTICALBAR | 1: scancode << 30, - KP_COLON = scancode::KP_COLON | 1: scancode << 30, - KP_HASH = scancode::KP_HASH | 1: scancode << 30, - KP_SPACE = scancode::KP_SPACE | 1: scancode << 30, - KP_AT = scancode::KP_AT | 1: scancode << 30, - KP_EXCLAM = scancode::KP_EXCLAM | 1: scancode << 30, - KP_MEMSTORE = scancode::KP_MEMSTORE | 1: scancode << 30, - KP_MEMRECALL = scancode::KP_MEMRECALL | 1: scancode << 30, - KP_MEMCLEAR = scancode::KP_MEMCLEAR | 1: scancode << 30, - KP_MEMADD = scancode::KP_MEMADD | 1: scancode << 30, - KP_MEMSUBTRACT = scancode::KP_MEMSUBTRACT | 1: scancode << 30, - KP_MEMMULTIPLY = scancode::KP_MEMMULTIPLY | 1: scancode << 30, - KP_MEMDIVIDE = scancode::KP_MEMDIVIDE | 1: scancode << 30, - KP_PLUSMINUS = scancode::KP_PLUSMINUS | 1: scancode << 30, - KP_CLEAR = scancode::KP_CLEAR | 1: scancode << 30, - KP_CLEARENTRY = scancode::KP_CLEARENTRY | 1: scancode << 30, - KP_BINARY = scancode::KP_BINARY | 1: scancode << 30, - KP_OCTAL = scancode::KP_OCTAL | 1: scancode << 30, - KP_DECIMAL = scancode::KP_DECIMAL | 1: scancode << 30, - KP_HEXADECIMAL = scancode::KP_HEXADECIMAL | 1: scancode << 30, - - LCTRL = scancode::LCTRL | 1: scancode << 30, - LSHIFT = scancode::LSHIFT | 1: scancode << 30, - LALT = scancode::LALT | 1: scancode << 30, - LGUI = scancode::LGUI | 1: scancode << 30, - RCTRL = scancode::RCTRL | 1: scancode << 30, - RSHIFT = scancode::RSHIFT | 1: scancode << 30, - RALT = scancode::RALT | 1: scancode << 30, - RGUI = scancode::RGUI | 1: scancode << 30, - - MODE = scancode::MODE | 1: scancode << 30, - - AUDIONEXT = scancode::AUDIONEXT | 1: scancode << 30, - AUDIOPREV = scancode::AUDIOPREV | 1: scancode << 30, - AUDIOSTOP = scancode::AUDIOSTOP | 1: scancode << 30, - AUDIOPLAY = scancode::AUDIOPLAY | 1: scancode << 30, - AUDIOMUTE = scancode::AUDIOMUTE | 1: scancode << 30, - MEDIASELECT = scancode::MEDIASELECT | 1: scancode << 30, - WWW = scancode::WWW | 1: scancode << 30, - MAIL = scancode::MAIL | 1: scancode << 30, - CALCULATOR = scancode::CALCULATOR | 1: scancode << 30, - COMPUTER = scancode::COMPUTER | 1: scancode << 30, - AC_SEARCH = scancode::AC_SEARCH | 1: scancode << 30, - AC_HOME = scancode::AC_HOME | 1: scancode << 30, - AC_BACK = scancode::AC_BACK | 1: scancode << 30, - AC_FORWARD = scancode::AC_FORWARD | 1: scancode << 30, - AC_STOP = scancode::AC_STOP | 1: scancode << 30, - AC_REFRESH = scancode::AC_REFRESH | 1: scancode << 30, - AC_BOOKMARKS = scancode::AC_BOOKMARKS | 1: scancode << 30, - - BRIGHTNESSDOWN = scancode::BRIGHTNESSDOWN | 1: scancode << 30, - BRIGHTNESSUP = scancode::BRIGHTNESSUP | 1: scancode << 30, - DISPLAYSWITCH = scancode::DISPLAYSWITCH | 1: scancode << 30, - KBDILLUMTOGGLE = scancode::KBDILLUMTOGGLE | 1: scancode << 30, - KBDILLUMDOWN = scancode::KBDILLUMDOWN | 1: scancode << 30, - KBDILLUMUP = scancode::KBDILLUMUP | 1: scancode << 30, - EJECT = scancode::EJECT | 1: scancode << 30, - SLEEP = scancode::SLEEP | 1: scancode << 30, - APP1 = scancode::APP1 | 1: scancode << 30, - APP2 = scancode::APP2 | 1: scancode << 30, - - AUDIOREWIND = scancode::AUDIOREWIND | 1: scancode << 30, - AUDIOFASTFORWARD = scancode::AUDIOFASTFORWARD | 1: scancode << 30 + 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 keymod = enum u16 { +export type SDL_Keymod = enum u16 { NONE = 0x0000, LSHIFT = 0x0001, RSHIFT = 0x0002, @@ -625,21 +625,21 @@ export type keymod = enum u16 { RESERVED = SCROLL, }; -export type keysym = struct { - scancode: scancode, - sym: keycode, - mod: keymod, +export type SDL_Keysym = struct { + scancode: SDL_Scancode, + sym: SDL_Keycode, + mod: SDL_Keymod, unused: u32, }; -@symbol("SDL_GetKeyFromName") fn _get_key_from_name(name: *const char) keycode; +@symbol("SDL_GetKeyFromName") fn _SDL_GetKeyFromName(name: *const char) SDL_Keycode; -export fn get_key_from_name(name: str) (keycode | error) = { +export fn SDL_GetKeyFromName(name: str) (SDL_Keycode | error) = { const name = strings::to_c(name); defer free(name); - const sym = _get_key_from_name(name); - if (sym == keycode::UNKNOWN) { - return strings::fromc(geterror()): error; + const sym = _SDL_GetKeyFromName(name); + if (sym == SDL_Keycode::UNKNOWN) { + return strings::fromc(SDL_GetError()): error; }; return sym; }; diff --git a/sdl2/mixer/channels.ha b/sdl2/mixer/channels.ha index 4bf4820..fffccd0 100644 --- a/sdl2/mixer/channels.ha +++ b/sdl2/mixer/channels.ha @@ -1,8 +1,8 @@ use sdl2; -@symbol("Mix_PlayChannelTimed") fn _play_channel_timed( +@symbol("Mix_PlayChannelTimed") fn _Mix_PlayChannelTimed( channel: int, - sample: *chunk, + sample: *Mix_Chunk, loops: int, ticks: int, ) int; @@ -11,10 +11,10 @@ use sdl2; // 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 play_channel( +export fn Mix_PlayChannelTimed( channel: int, - sample: *chunk, + sample: *Mix_Chunk, loops: int, ) (void | sdl2::error) = { - return sdl2::wrapvoid(_play_channel_timed(channel, sample, loops, -1)); + return sdl2::wrapvoid(_Mix_PlayChannelTimed(channel, sample, loops, -1)); }; diff --git a/sdl2/mixer/general.ha b/sdl2/mixer/general.ha index 32c7b38..4f819bf 100644 --- a/sdl2/mixer/general.ha +++ b/sdl2/mixer/general.ha @@ -1,7 +1,7 @@ use sdl2; // Flags for [[init]]. -export type init_flags = enum { +export type MIX_InitFlags = enum { FLAC = 0x00000001, MOD = 0x00000002, MP3 = 0x00000008, @@ -11,42 +11,42 @@ export type init_flags = enum { }; // The default mixer has 8 simultaneous mixing channels -export def CHANNELS: int = 8; +export def MIX_CHANNELS: int = 8; // Good default frequency for a PC soundcard -export def DEFAULT_FREQUENCY: int = 22050; +export def MIX_DEFAULT_FREQUENCY: int = 22050; // Good default channels for a PC soundcard -export def DEFAULT_CHANNELS: int = 2; +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 DEFAULT_FORMAT: sdl2::audio_format = sdl2::AUDIO_S16LSB; +export def MIX_DEFAULT_FORMAT: sdl2::SDL_AudioFormat = sdl2::AUDIO_S16LSB; -@symbol("Mix_Init") fn _init(flags: int) int; +@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 [[init_flags]] OR'd together. -export fn init(flags: init_flags) (void | sdl2::error) = { - return sdl2::wrapvoid(_init(flags)); +// one or more flags from [[MIX_InitFlags]] OR'd together. +export fn Mix_Init(flags: MIX_InitFlags) (void | sdl2::error) = { + return sdl2::wrapvoid(_Mix_Init(flags)); }; -// Unloads libraries loaded with [[init]]. -export @symbol("Mix_Quit") fn quit() void; +// Unloads libraries loaded with [[Mix_Init]]. +export @symbol("Mix_Quit") fn Mix_Quit() void; -@symbol("Mix_OpenAudio") fn _openaudio(frequency: int, +@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 open_audio( +export fn Mix_OpenAudio( frequency: int, - format: sdl2::audio_format, + format: sdl2::SDL_AudioFormat, channels: int, chunksize: int, ) (void | sdl2::error) = { - return sdl2::wrapvoid(_openaudio(frequency, format, channels, chunksize)); + return sdl2::wrapvoid(_Mix_OpenAudio(frequency, format, channels, chunksize)); }; // Close the mixer, halting all playing audio -export @symbol("Mix_CloseAudio") fn close_audio() void; +export @symbol("Mix_CloseAudio") fn Mix_CloseAudio() void; diff --git a/sdl2/mixer/samples.ha b/sdl2/mixer/samples.ha index aaf1ad1..2dce2ef 100644 --- a/sdl2/mixer/samples.ha +++ b/sdl2/mixer/samples.ha @@ -3,37 +3,37 @@ use io; use os; use sdl2; -// The internal format for an audio chunk -export type chunk = struct { +// 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 _loadwav_rw(src: *sdl2::rwops, freesrc: int) nullable *chunk; +@symbol("Mix_LoadWAV_RW") fn _Mix_LoadWAV_RW(src: *sdl2::SDL_RWops, freesrc: int) nullable *Mix_Chunk; // Loads a sample from an [[io::handle]]. The stream will not be closed for you. -export fn load(src: io::handle) (*chunk | sdl2::error) = { +export fn Mix_LoadWAV_RW(src: io::handle) (*Mix_Chunk | sdl2::error) = { const rw = sdl2::rw_from_handle(src); - defer sdl2::rwclose(rw); - return sdl2::wrapptr(_loadwav_rw(rw, 0))?: *chunk; + defer sdl2::SDL_RWclose(rw); + return sdl2::wrapptr(_Mix_LoadWAV_RW(rw, 0))?: *Mix_Chunk; }; // Loads a sample from a file path. -export fn load_file(src: str) (*chunk | fs::error | sdl2::error) = { +export fn load_file(src: str) (*Mix_Chunk | fs::error | sdl2::error) = { const file = os::open(src)?; defer io::close(file); - return load(file); + return Mix_LoadWAV_RW(file); }; -// Free the memory used in chunk, and free chunk itself as well. Do not use -// chunk after this without loading a new sample to it. Note: It's a bad idea to -// free a chunk that is still being played... -export @symbol("Mix_FreeChunk") fn free_chunk(chunk: *chunk) void; +// 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 chunk. -export def MAX_VOLUME: int = 128; // XXX: SDL_mixer derives this from SDL_MIX_MAXVOLUME +// Maximum volume for a Mix_Chunk. +export def MIX_MAX_VOLUME: int = 128; // XXX: SDL_mixer derives this from SDL_MIX_MAXVOLUME -// Sets the chunk volume as specified, returning the previous value. -export @symbol("Mix_VolumeChunk") fn volume_chunk(chunk: *chunk, volume: int) int; +// 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/pixels.ha b/sdl2/pixels.ha index 8227067..618a3c5 100644 --- a/sdl2/pixels.ha +++ b/sdl2/pixels.ha @@ -1,23 +1,23 @@ // TODO: Flesh me out -export type color = struct { +export type SDL_Color = struct { r: u8, g: u8, b: u8, a: u8, }; -export type palette = struct { +export type SDL_Palette = struct { ncolors: int, - colors: *color, + colors: *SDL_Color, version: u32, refcount: int, }; // Note: Everything in the pixel format structure is read-only. -export type pixelformat = struct { +export type SDL_PixelFormat = struct { format: u32, // TODO - palette: *palette, + palette: *SDL_Palette, bitsperpixel: u8, bytesperpixel: u8, padding: [2]u8, @@ -34,5 +34,5 @@ export type pixelformat = struct { bshift: u8, ashift: u8, refcount: int, - next: nullable *pixelformat, + next: nullable *SDL_PixelFormat, }; diff --git a/sdl2/rect.ha b/sdl2/rect.ha index 00fae87..012088e 100644 --- a/sdl2/rect.ha +++ b/sdl2/rect.ha @@ -1,19 +1,19 @@ // TODO: Flesh me out // The structure that defines a point (integer) -export type point = struct { +export type SDL_Point = struct { x: int, y: int, }; // The structure that defines a point (floating point) -export type fpoint = struct { +export type SDL_FPoint = struct { x: f32, y: f32, }; // A rectangle, with the origin at the upper left (integer). -export type rect = struct { +export type SDL_Rect = struct { x: int, y: int, w: int, @@ -21,7 +21,7 @@ export type rect = struct { }; // A rectangle, with the origin at the upper left (floating point). -export type frect = struct { +export type SDL_FRect = struct { x: f32, y: f32, w: f32, diff --git a/sdl2/render.ha b/sdl2/render.ha index 2c53183..d607712 100644 --- a/sdl2/render.ha +++ b/sdl2/render.ha @@ -1,13 +1,13 @@ // TODO: Flesh me out // A structure representing rendering state. (Opaque) -export type renderer = void; +export type SDL_Renderer = void; // An efficient driver-specific representation of pixel data. (Opaque) -export type texture = void; +export type SDL_Texture = void; // Flags used when creating a rendering context. -export type renderer_flags = enum u32 { +export type SDL_RendererFlags = enum u32 { NONE = 0, SOFTWARE = 0x00000001, ACCELERATED = 0x00000002, @@ -15,96 +15,96 @@ export type renderer_flags = enum u32 { TARGETTEXTURE = 0x00000008, }; -@symbol("SDL_CreateWindowAndRenderer") fn _create_window_and_renderer( - width: int, height: int, window_flags: window_flags, - window: nullable **window, renderer: nullable **renderer) int; +@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. 'window_flags' configure additional window parameters. +// 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 create_window_and_renderer( +export fn SDL_CreateWindowAndRenderer( width: int, height: int, - window_flags: window_flags, - window: nullable **window, - renderer: nullable **renderer, -) (void | error) = wrapvoid(_create_window_and_renderer(width, height, - window_flags, window, renderer)); + 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 _create_renderer(window: *window, - index: int, flags: renderer_flags) nullable *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]], -// [[destroy_renderer]]. -export fn create_renderer( - window: *window, +// [[SDL_DestroyRenderer]]. +export fn SDL_CreateRenderer( + window: *SDL_Window, index: int, - flags: renderer_flags, -) (*renderer | error) = - wrapptr(_create_renderer(window, index, flags))?: *renderer; + 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: [[create_renderer]]. -export @symbol("SDL_DestroyRenderer") fn destroy_renderer(renderer: *renderer) void; +// See also: [[SDL_CreateRenderer]]. +export @symbol("SDL_DestroyRenderer") fn SDL_DestroyRenderer(renderer: *SDL_Renderer) void; // Opaque value for the alpha channel (255). export def ALPHA_OPAQUE: u8 = 255; -@symbol("SDL_SetRenderDrawColor") fn _set_render_draw_color(renderer: *renderer, +@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 set_render_draw_color( - renderer: *renderer, +export fn SDL_SetRenderDrawColor( + renderer: *SDL_Renderer, r: u8, g: u8, b: u8, a: u8, -) (void | error) = wrapvoid(_set_render_draw_color(renderer, r, g, b, a)); +) (void | error) = wrapvoid(_SDL_SetRenderDrawColor(renderer, r, g, b, a)); -@symbol("SDL_RenderClear") fn _render_clear(renderer: *renderer) int; +@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 render_clear(renderer: *renderer) (void | error) = { - return wrapvoid(_render_clear(renderer)); +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 render_present(renderer: *renderer) void; +export @symbol("SDL_RenderPresent") fn SDL_RenderPresent(renderer: *SDL_Renderer) void; // Destroy the specified texture. -export @symbol("SDL_DestroyTexture") fn destroy_texture(texture: *texture) void; +export @symbol("SDL_DestroyTexture") fn SDL_DestroyTexture(texture: *SDL_Texture) void; -@symbol("SDL_QueryTexture") fn _query_texture(texture: *texture, +@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 query_texture( - texture: *texture, +export fn SDL_QueryTexture( + texture: *SDL_Texture, format: nullable *u32, access: nullable *int, w: nullable *int, h: nullable *int, ) (void | error) = { - return wrapvoid(_query_texture(texture, format, access, w, h)); + return wrapvoid(_SDL_QueryTexture(texture, format, access, w, h)); }; -@symbol("SDL_SetTextureColorMod") fn _set_texture_color_mod( - texture: *texture, r: u8, g: u8, b: u8) int; +@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. // @@ -116,14 +116,14 @@ export fn query_texture( // // Color modulation is not always supported by the renderer; it will return -1 // if color modulation is not supported. -export fn set_texture_color_mod( - texture: *texture, +export fn SDL_SetTextureColorMod( + texture: *SDL_Texture, r: u8, g: u8, b: u8, ) (void | error) = { - return wrapvoid(_set_texture_color_mod(texture, r, g, b)); + return wrapvoid(_SDL_SetTextureColorMod(texture, r, g, b)); }; -@symbol("SDL_SetTextureAlphaMod") fn _set_texture_alpha_mod(texture: *texture, a: u8) int; +@symbol("SDL_SetTextureAlphaMod") fn _SDL_SetTextureAlphaMod(texture: *SDL_Texture, a: u8) int; // Set an additional alpha value multiplied into render copy operations. // @@ -134,64 +134,64 @@ export fn set_texture_color_mod( // // Alpha modulation is not always supported by the renderer; it will return an // error if alpha modulation is not supported. -export fn set_texture_alpha_mod(texture: *texture, a: u8) (void | error) = { +export fn SDL_SetTextureAlphaMod(texture: *SDL_Texture, a: u8) (void | error) = { // TODO: Double check errors - return wrapvoid(_set_texture_alpha_mod(texture, a)); + return wrapvoid(_SDL_SetTextureAlphaMod(texture, a)); }; -@symbol("SDL_SetTextureBlendMode") fn _set_texture_blend_mode( - texture: *texture, mode: blend_mode) int; +@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 set_texture_blend_mode( - texture: *texture, - mode: blend_mode, +export fn SDL_SetTextureBlendMode( + texture: *SDL_Texture, + mode: SDL_BlendMode, ) (void | error) = { - return wrapvoid(_set_texture_blend_mode(texture, mode)); + return wrapvoid(_SDL_SetTextureBlendMode(texture, mode)); }; -@symbol("SDL_SetRenderDrawBlendMode") fn _set_render_draw_blend_mode( - renderer: *renderer, mode: blend_mode) int; +@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 set_render_draw_blend_mode( - renderer: *renderer, - mode: blend_mode, +export fn SDL_SetRenderDrawBlendMode( + renderer: *SDL_Renderer, + mode: SDL_BlendMode, ) (void | error) = { - return wrapvoid(_set_render_draw_blend_mode(renderer, mode)); + return wrapvoid(_SDL_SetRenderDrawBlendMode(renderer, mode)); }; -@symbol("SDL_RenderCopy") fn _render_copy(renderer: *renderer, - texture: *texture, srcrect: nullable *rect, dstrect: nullable *rect) int; +@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 render_copy( - renderer: *renderer, - texture: *texture, - srcrect: nullable *rect, - dstrect: nullable *rect, +export fn SDL_RenderCopy( + renderer: *SDL_Renderer, + texture: *SDL_Texture, + srcrect: nullable *SDL_Rect, + dstrect: nullable *SDL_Rect, ) (void | error) = { - return wrapvoid(_render_copy(renderer, texture, srcrect, dstrect)); + return wrapvoid(_SDL_RenderCopy(renderer, texture, srcrect, dstrect)); }; -@symbol("SDL_RenderDrawRect") fn _render_draw_rect( - renderer: *renderer, rect: const nullable *rect) int; +@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 render_draw_rect( - renderer: *renderer, - rect: const nullable *rect, +export fn SDL_RenderDrawRect( + renderer: *SDL_Renderer, + rect: const nullable *SDL_Rect, ) (void | error) = { - return wrapvoid(_render_draw_rect(renderer, rect)); + return wrapvoid(_SDL_RenderDrawRect(renderer, rect)); }; -@symbol("SDL_RenderFillRect") fn _render_fill_rect( - renderer: *renderer, rect: const nullable *rect) int; +@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 render_fill_rect( - renderer: *renderer, - rect: const nullable *rect, +export fn SDL_RenderFillRect( + renderer: *SDL_Renderer, + rect: const nullable *SDL_Rect, ) (void | error) = { - return wrapvoid(_render_fill_rect(renderer, rect)); + return wrapvoid(_SDL_RenderFillRect(renderer, rect)); }; diff --git a/sdl2/rwops.ha b/sdl2/rwops.ha index 4638c29..d497750 100644 --- a/sdl2/rwops.ha +++ b/sdl2/rwops.ha @@ -12,12 +12,12 @@ export type rwops_type = enum u32 { }; // The read/write operation structure -- very basic. -export type rwops = struct { - sz: *fn(ctx: *rwops) i64, - seek: *fn(ctx: *rwops, offs: i64, whence: int) i64, - read: *fn(ctx: *rwops, ptr: *void, sz: size, maxnum: size) size, - write: *fn(ctx: *rwops, ptr: *void, sz: size, num: size) size, - close: *fn(ctx: *rwops) void, +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: *void, sz: size, maxnum: size) size, + write: *fn(ctx: *SDL_RWops, ptr: *void, sz: size, num: size) size, + close: *fn(ctx: *SDL_RWops) void, type_: rwops_type, // XXX: This union is platform-specific @@ -41,25 +41,25 @@ export type rwops = struct { @symbol("SDL_RWFromFile") fn _rw_from_file( file: const *char, mode: const *char, -) *rwops; +) *SDL_RWops; -// Returns the size of an [[rwops]], or 0 if unknown or error. +// 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 rwsize(ctx: *rwops) i64; +export @symbol("SDL_RWsize") fn SDL_RWsize(ctx: *SDL_RWops) i64; -// Closes an [[rwops]], returning 1 on success or 0 on error. +// 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 rwclose(ctx: *rwops) int; +export @symbol("SDL_RWclose") fn SDL_RWclose(ctx: *SDL_RWops) int; // TODO: Other RWops wrappers -// Creates an [[rwops]] from an [[io::handle]]. Closing the rwops does not close +// 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) *rwops = { +export fn rw_from_handle(in: io::handle) *SDL_RWops = { // TODO: Add stream_from_rw - let rw = alloc(rwops { + let rw = alloc(SDL_RWops { sz = &stream_size, seek = &stream_seek, read = &stream_read, @@ -75,7 +75,7 @@ export fn rw_from_handle(in: io::handle) *rwops = { return rw; }; -fn stream_size(ctx: *rwops) i64 = { +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 => @@ -89,7 +89,7 @@ fn stream_size(ctx: *rwops) i64 = { return sz; }; -fn stream_seek(ctx: *rwops, offs: i64, whence: int) i64 = { +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)) { @@ -100,7 +100,7 @@ fn stream_seek(ctx: *rwops, offs: i64, whence: int) i64 = { }; }; -fn stream_read(ctx: *rwops, ptr: *void, sz: size, maxnum: size) size = { +fn stream_read(ctx: *SDL_RWops, ptr: *void, sz: size, maxnum: size) size = { const handle = *(&ctx.hidden.unknown.data1: *io::handle); let buf = ptr: *[*]u8; match (io::readitems(handle, buf[..sz * maxnum], sz)) { @@ -111,7 +111,7 @@ fn stream_read(ctx: *rwops, ptr: *void, sz: size, maxnum: size) size = { }; }; -fn stream_write(ctx: *rwops, ptr: *void, sz: size, num: size) size = { +fn stream_write(ctx: *SDL_RWops, ptr: *void, sz: size, num: size) size = { const handle = *(&ctx.hidden.unknown.data1: *io::handle); let buf = ptr: *[*]u8; match (io::writeitems(handle, buf[..sz * num], sz)) { @@ -122,7 +122,7 @@ fn stream_write(ctx: *rwops, ptr: *void, sz: size, num: size) size = { }; }; -fn stream_close(ctx: *rwops) void = { +fn stream_close(ctx: *SDL_RWops) void = { const handle = *(&ctx.hidden.unknown.data1: *io::handle); free(ctx); }; diff --git a/sdl2/sdl2.ha b/sdl2/sdl2.ha index 08e1234..d36ff2b 100644 --- a/sdl2/sdl2.ha +++ b/sdl2/sdl2.ha @@ -1,4 +1,4 @@ -// These are the flags which may be passed to [[init]]. You should specify the +// These are the flags which may be passed to [[SDL_Init]]. You should specify the // subsystems which you will be using in your application. export type init_flags = enum uint { TIMER = 0x00000001u, @@ -13,13 +13,13 @@ export type init_flags = enum uint { EVERYTHING = TIMER | AUDIO | VIDEO | EVENTS | JOYSTICK | HAPTIC | GAMECONTROLLER | SENSOR, }; -@symbol("SDL_Init") fn _init(flags: init_flags) int; +@symbol("SDL_Init") fn _SDL_Init(flags: init_flags) int; // This function initializes the subsystems specified by 'flags'. -export fn init(flags: init_flags) (void | error) = { - return wrapvoid(_init(flags)); +export fn SDL_Init(flags: init_flags) (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 quit() void; +export @symbol("SDL_Quit") fn SDL_Quit() void; diff --git a/sdl2/surface.ha b/sdl2/surface.ha index 7bbe850..39d4d2a 100644 --- a/sdl2/surface.ha +++ b/sdl2/surface.ha @@ -1,10 +1,10 @@ // 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 surface = struct { +export type SDL_Surface = struct { flags: u32, - format: *pixelformat, + format: *SDL_PixelFormat, w: int, h: int, pitch: int, @@ -15,11 +15,11 @@ export type surface = struct { locked: int, lock_data: *void, - clip_rect: rect, + clip_rect: SDL_Rect, - map: *blitmap, + map: *SDL_BlitMap, refcount: int, }; -export type blitmap = void; +export type SDL_BlitMap = void; diff --git a/sdl2/timer.ha b/sdl2/timer.ha index 1b315ec..d90511a 100644 --- a/sdl2/timer.ha +++ b/sdl2/timer.ha @@ -4,7 +4,7 @@ // // Returns an unsigned 32-bit value representing the number of milliseconds // since the SDL library initialized. -export @symbol("SDL_GetTicks") fn get_ticks() u32; +export @symbol("SDL_GetTicks") fn SDL_GetTicks() u32; // Get the current value of the high resolution counter. // @@ -12,21 +12,21 @@ export @symbol("SDL_GetTicks") fn get_ticks() u32; // // The counter values are only meaningful relative to each other. Differences // between values can be converted to times by using -// [[getperformancefrequency]]. +// [[SDL_GetPerformanceFrequency]]. // // Returns the current counter value. -export @symbol("SDL_GetPerformanceCounter") fn get_performance_counter() u64; +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 get_performance_frequency() u64; +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 delay(ms: u32) void; +export @symbol("SDL_Delay") fn SDL_Delay(ms: u32) void; // TODO: Timers diff --git a/sdl2/video.ha b/sdl2/video.ha index b1f8b22..874a8bd 100644 --- a/sdl2/video.ha +++ b/sdl2/video.ha @@ -2,10 +2,10 @@ use strings; // The type used to identify a window. (Opaque) -export type window = void; +export type SDL_Window = void; // The flags on a window -export type window_flags = enum u32 { +export type SDL_WindowFlags = enum u32 { NONE = 0, FULLSCREEN = 0x00000001, OPENGL = 0x00000002, @@ -27,22 +27,22 @@ export type window_flags = enum u32 { UTILITY = 0x00020000, TOOLTIP = 0x00040000, POPUP_MENU = 0x00080000, - VULKAN = 0x10000000 + VULKAN = 0x10000000 }; -export def WINDOWPOS_UNDEFINED: int = 0x1FFF0000; -export def WINDOWPOS_CENTERED: int = 0x2FFF0000; +export def SDL_WINDOWPOS_UNDEFINED: int = 0x1FFF0000; +export def SDL_WINDOWPOS_CENTERED: int = 0x2FFF0000; -@symbol("SDL_CreateWindow") fn _create_window(title: const *char, - x: int, y: int, w: int, h: int, flags: window_flags) nullable *window; +@symbol("SDL_CreateWindow") fn _SDL_CreateWindow(title: const *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 [[strings::to_c]] // to prepare a suitable string. // -// 'x' and 'y' set the position of the window, or use [[WINDOWPOS_CENTERED]] or -// [[WINDOWPOS_UNDEFINED]]. +// '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. // @@ -69,22 +69,22 @@ export def WINDOWPOS_CENTERED: int = 0x2FFF0000; // Vulkan loader or link to a dynamic library version. This limitation may be // removed in a future version of SDL. // -// See also: [[destroy_window]] [[gl_loadlibrary]], [[vulkan_loadlibrary]]. -export fn create_window( +// See also: [[SDL_DestroyWindow]] [[gl_loadlibrary]], [[vulkan_loadlibrary]]. +export fn SDL_CreateWindow( title: str, x: int, y: int, w: int, h: int, - flags: window_flags, -) (*window | error) = { + flags: SDL_WindowFlags, +) (*SDL_Window | error) = { let title = strings::to_c(title); defer free(title); - return wrapptr(_create_window(title, x, y, w, h, flags))?: *window; + return wrapptr(_SDL_CreateWindow(title, x, y, w, h, flags))?: *SDL_Window; }; // Destroy a window. -export @symbol("SDL_DestroyWindow") fn destroy_window(window: *window) void; +export @symbol("SDL_DestroyWindow") fn SDL_DestroyWindow(window: *SDL_Window) void; // Get the size of a window's client area. // @@ -96,5 +96,5 @@ export @symbol("SDL_DestroyWindow") fn destroy_window(window: *window) void; // 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 get_window_size(window: *window, +export @symbol("SDL_GetWindowSize") fn SDL_GetWindowSize(window: *SDL_Window, w: nullable *int, h: nullable *int) void; -- cgit v1.2.3 From 769a28d97890773cf6087254270eba0fdfe98038 Mon Sep 17 00:00:00 2001 From: Sebastian Date: Mon, 28 Mar 2022 17:27:59 -0400 Subject: Rename SDL_GameControllerBUtton to SDL_GameControllerButton Signed-off-by: Sebastian --- sdl2/gamecontroller.ha | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sdl2/gamecontroller.ha b/sdl2/gamecontroller.ha index 113bb37..1ce9384 100644 --- a/sdl2/gamecontroller.ha +++ b/sdl2/gamecontroller.ha @@ -23,7 +23,7 @@ export type SDL_GameControllerAxis = enum u8 { }; // The list of buttons available from a controller -export type SDL_GameControllerBUtton = enum u8 { +export type SDL_GameControllerButton = enum u8 { INVALID = 255, A = 0, B, -- cgit v1.2.3 From f741ea6388b09d321eb42dcaf3d74918b80db6cf Mon Sep 17 00:00:00 2001 From: Drew DeVault Date: Thu, 21 Apr 2022 11:52:47 +0200 Subject: Use def for SDL_INIT_* --- cmd/demo/main.ha | 6 +++--- sdl2/keyboard.ha | 2 +- sdl2/sdl2.ha | 30 ++++++++++++++---------------- 3 files changed, 18 insertions(+), 20 deletions(-) diff --git a/cmd/demo/main.ha b/cmd/demo/main.ha index a6f2a92..82de229 100644 --- a/cmd/demo/main.ha +++ b/cmd/demo/main.ha @@ -33,9 +33,9 @@ export fn main() void = { }; fn run() (void | fs::error | sdl2::error) = { - sdl2::SDL_Init(sdl2::init_flags::VIDEO - | sdl2::init_flags::AUDIO - | sdl2::init_flags::GAMECONTROLLER)!; + sdl2::SDL_Init(sdl2::SDL_INIT_VIDEO + | sdl2::SDL_INIT_AUDIO + | sdl2::SDL_INIT_GAMECONTROLLER)!; defer sdl2::SDL_Quit(); image::IMG_Init(image::IMG_InitFlags::PNG | image::IMG_InitFlags::JPG)!; defer image::IMG_Quit(); diff --git a/sdl2/keyboard.ha b/sdl2/keyboard.ha index 97b0a21..eb38afd 100644 --- a/sdl2/keyboard.ha +++ b/sdl2/keyboard.ha @@ -419,7 +419,7 @@ export type SDL_Keycode = enum uint { y = 'y', z = 'z', - CAPSLOCK = SDL_Scancode::CAPSLOCK | 1: SDL_Scancode << 30, + 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, diff --git a/sdl2/sdl2.ha b/sdl2/sdl2.ha index d36ff2b..7035e04 100644 --- a/sdl2/sdl2.ha +++ b/sdl2/sdl2.ha @@ -1,22 +1,20 @@ -// These are the flags which may be passed to [[SDL_Init]]. You should specify the -// subsystems which you will be using in your application. -export type init_flags = enum uint { - TIMER = 0x00000001u, - AUDIO = 0x00000010u, - VIDEO = 0x00000020u, - JOYSTICK = 0x00000200u, - HAPTIC = 0x00001000u, - GAMECONTROLLER = 0x00002000u, - EVENTS = 0x00004000u, - SENSOR = 0x00008000u, - NOPARACHUTE = 0x00100000u, - EVERYTHING = TIMER | AUDIO | VIDEO | EVENTS | JOYSTICK | HAPTIC | GAMECONTROLLER | SENSOR, -}; +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: init_flags) int; +@symbol("SDL_Init") fn _SDL_Init(flags: uint) int; // This function initializes the subsystems specified by 'flags'. -export fn SDL_Init(flags: init_flags) (void | error) = { +export fn SDL_Init(flags: uint) (void | error) = { return wrapvoid(_SDL_Init(flags)); }; -- cgit v1.2.3 From 6b13ff0b265649746e1d66a1a174d633b551518c Mon Sep 17 00:00:00 2001 From: Sebastian Date: Thu, 21 Apr 2022 15:57:13 -0400 Subject: Makefile: add docs target Signed-off-by: Sebastian --- .gitignore | 1 + Makefile | 9 ++++++++- 2 files changed, 9 insertions(+), 1 deletion(-) diff --git a/.gitignore b/.gitignore index 245fe5c..7568da1 100644 --- a/.gitignore +++ b/.gitignore @@ -1,2 +1,3 @@ +docs/ demo !./cmd/demo/ diff --git a/Makefile b/Makefile index c6cdb28..762ebfa 100644 --- a/Makefile +++ b/Makefile @@ -9,4 +9,11 @@ demo: run: hare run $(LIBS) cmd/demo -.PHONY: demo run +docs: + mkdir -p docs/sdl2/image + haredoc -Fhtml sdl2 > docs/sdl2/index.html + haredoc -Fhtml sdl2::image > docs/sdl2/image/index.html + mkdir -p docs/sdl2/mixer + haredoc -Fhtml sdl2::mixer > docs/sdl2/mixer/index.html + +.PHONY: demo docs run -- cgit v1.2.3 From 7e5c81258e2bfe540c1c51decbab6211f3361296 Mon Sep 17 00:00:00 2001 From: Sebastian Date: Thu, 21 Apr 2022 15:57:14 -0400 Subject: Makefile: add clean target Signed-off-by: Sebastian --- Makefile | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/Makefile b/Makefile index 762ebfa..5f44fee 100644 --- a/Makefile +++ b/Makefile @@ -9,6 +9,9 @@ demo: run: hare run $(LIBS) cmd/demo +clean: + rm -rf docs demo + docs: mkdir -p docs/sdl2/image haredoc -Fhtml sdl2 > docs/sdl2/index.html @@ -16,4 +19,4 @@ docs: mkdir -p docs/sdl2/mixer haredoc -Fhtml sdl2::mixer > docs/sdl2/mixer/index.html -.PHONY: demo docs run +.PHONY: clean demo docs run -- cgit v1.2.3 From 02e827d8499290201a86726b658f8571327b5f18 Mon Sep 17 00:00:00 2001 From: Sebastian Date: Tue, 26 Apr 2022 17:58:54 -0400 Subject: mixer: io::close can error Signed-off-by: Sebastian --- sdl2/mixer/samples.ha | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sdl2/mixer/samples.ha b/sdl2/mixer/samples.ha index 2dce2ef..0a45151 100644 --- a/sdl2/mixer/samples.ha +++ b/sdl2/mixer/samples.ha @@ -23,7 +23,7 @@ export fn Mix_LoadWAV_RW(src: io::handle) (*Mix_Chunk | sdl2::error) = { // 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); + defer io::close(file)!; return Mix_LoadWAV_RW(file); }; -- cgit v1.2.3 From c7bde5d2759c693f918d5a621ada339188d9f9a2 Mon Sep 17 00:00:00 2001 From: Carlos Une Date: Tue, 25 Oct 2022 01:26:08 -0300 Subject: Add SDL_CreateTexture, SDL_UpdateTexture wrappers Signed-off-by: Carlos Une --- sdl2/render.ha | 26 ++++++++++++++++++++++++++ 1 file changed, 26 insertions(+) diff --git a/sdl2/render.ha b/sdl2/render.ha index d607712..667c223 100644 --- a/sdl2/render.ha +++ b/sdl2/render.ha @@ -195,3 +195,29 @@ export fn SDL_RenderFillRect( ) (void | error) = { return wrapvoid(_SDL_RenderFillRect(renderer, rect)); }; + +@symbol("SDL_CreateTexture") fn _SDL_CreateTexture(renderer: *SDL_Renderer, + format: u32, access: int, w: int, h: int) *SDL_Texture; + +// Create a texture for a rendering context. +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_UpdateTexture") fn _SDL_UpdateTexture(texture: *SDL_Texture, + rect: const nullable *SDL_Rect, pixels: const nullable *void, 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 *void, pitch: int) + (int | error) = { + return wrapint(_SDL_UpdateTexture(texture, rect, pixels, pitch))?: int; +}; + +// An enumeration of texture access patterns. +export type SDL_TextureAccess = enum int { + STATIC, + STREAMING, + TARGET +}; -- cgit v1.2.3 From 6150540090fddde83cef08b020bd786db2d0e724 Mon Sep 17 00:00:00 2001 From: Carlos Une Date: Tue, 25 Oct 2022 01:26:09 -0300 Subject: Add SDL_CreateRGBSurface wrapper Signed-off-by: Carlos Une --- sdl2/surface.ha | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/sdl2/surface.ha b/sdl2/surface.ha index 39d4d2a..572bdcc 100644 --- a/sdl2/surface.ha +++ b/sdl2/surface.ha @@ -23,3 +23,15 @@ export type SDL_Surface = struct { }; export type SDL_BlitMap = void; + +@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; +}; -- cgit v1.2.3 From 8633179ad56db7fbf76c783d3e4b7eb4fcc4c7be Mon Sep 17 00:00:00 2001 From: Carlos Une Date: Tue, 25 Oct 2022 01:26:10 -0300 Subject: Add SDL_PIXELFORMAT_ARGB8888 def Signed-off-by: Carlos Une --- sdl2/pixels.ha | 2 ++ 1 file changed, 2 insertions(+) diff --git a/sdl2/pixels.ha b/sdl2/pixels.ha index 618a3c5..75ccb99 100644 --- a/sdl2/pixels.ha +++ b/sdl2/pixels.ha @@ -36,3 +36,5 @@ export type SDL_PixelFormat = struct { refcount: int, next: nullable *SDL_PixelFormat, }; + +export def SDL_PIXELFORMAT_ARGB8888: u32 = 0x16362004; -- cgit v1.2.3 From 15af98a8adaae42e689f777b466cecfc0699c3de Mon Sep 17 00:00:00 2001 From: Carlos Une Date: Tue, 25 Oct 2022 01:26:11 -0300 Subject: Add SDL_GetWindowSurface wrapper Signed-off-by: Carlos Une --- sdl2/video.ha | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/sdl2/video.ha b/sdl2/video.ha index 874a8bd..bfcb3d0 100644 --- a/sdl2/video.ha +++ b/sdl2/video.ha @@ -98,3 +98,11 @@ export @symbol("SDL_DestroyWindow") fn SDL_DestroyWindow(window: *SDL_Window) vo // client area size in pixels. export @symbol("SDL_GetWindowSize") fn SDL_GetWindowSize(window: *SDL_Window, w: nullable *int, h: nullable *int) void; + +// Get the SDL surface associated with the window. +@symbol("SDL_GetWindowSurface") fn _SDL_GetWindowSurface(window: *SDL_Window) + *SDL_Surface; + +export fn SDL_GetWindowSurface(window: *SDL_Window) (*SDL_Surface | error) = { + return wrapptr(_SDL_GetWindowSurface(window))?: *SDL_Surface; +}; -- cgit v1.2.3 From 7c075ca5f30e26ceddc74fd144d3e4ba21a37239 Mon Sep 17 00:00:00 2001 From: Vlad-Stefan Harbuz Date: Fri, 16 Dec 2022 12:25:46 +0000 Subject: add SDL_(Un)LockTexture Signed-off-by: Vlad-Stefan Harbuz --- sdl2/render.ha | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/sdl2/render.ha b/sdl2/render.ha index 667c223..2b0dd07 100644 --- a/sdl2/render.ha +++ b/sdl2/render.ha @@ -215,6 +215,19 @@ export fn SDL_UpdateTexture(texture: *SDL_Texture, 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 *void, 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 *void, 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; + // An enumeration of texture access patterns. export type SDL_TextureAccess = enum int { STATIC, -- cgit v1.2.3 From 467c800413ee22a6d7309ef4e92c92ff36679cc5 Mon Sep 17 00:00:00 2001 From: Autumn! Date: Mon, 23 Jan 2023 23:21:59 +0000 Subject: Swap io::{read,write}items for io::{read,write}all Signed-off-by: Autumn! --- sdl2/rwops.ha | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/sdl2/rwops.ha b/sdl2/rwops.ha index d497750..ec961a2 100644 --- a/sdl2/rwops.ha +++ b/sdl2/rwops.ha @@ -103,7 +103,7 @@ fn stream_seek(ctx: *SDL_RWops, offs: i64, whence: int) i64 = { fn stream_read(ctx: *SDL_RWops, ptr: *void, sz: size, maxnum: size) size = { const handle = *(&ctx.hidden.unknown.data1: *io::handle); let buf = ptr: *[*]u8; - match (io::readitems(handle, buf[..sz * maxnum], sz)) { + match (io::readall(handle, buf[..sz * maxnum])) { case let n: size => return n; case io::error => @@ -114,7 +114,7 @@ fn stream_read(ctx: *SDL_RWops, ptr: *void, sz: size, maxnum: size) size = { fn stream_write(ctx: *SDL_RWops, ptr: *void, sz: size, num: size) size = { const handle = *(&ctx.hidden.unknown.data1: *io::handle); let buf = ptr: *[*]u8; - match (io::writeitems(handle, buf[..sz * num], sz)) { + match (io::writeall(handle, buf[..sz * num])) { case let n: size => return n; case io::error => -- cgit v1.2.3 From 1e5cfa30a7e90b1e1efeb60d1ca0ec12aef75d8e Mon Sep 17 00:00:00 2001 From: mateusmd Date: Mon, 23 Jan 2023 18:22:23 -0300 Subject: added some missing bindings --- sdl2/render.ha | 139 ++++++++++++++++++++++++++++++++++++++++++++++++++++----- 1 file changed, 127 insertions(+), 12 deletions(-) diff --git a/sdl2/render.ha b/sdl2/render.ha index 2b0dd07..545aae5 100644 --- a/sdl2/render.ha +++ b/sdl2/render.ha @@ -6,6 +6,39 @@ export type SDL_Renderer = void; // An efficient driver-specific representation of pixel data. (Opaque) export type SDL_Texture = void; +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, @@ -15,6 +48,19 @@ export type SDL_RendererFlags = enum u32 { 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; @@ -161,6 +207,21 @@ export fn SDL_SetRenderDrawBlendMode( 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; @@ -174,6 +235,31 @@ export fn SDL_RenderCopy( 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; @@ -196,13 +282,37 @@ export fn SDL_RenderFillRect( return wrapvoid(_SDL_RenderFillRect(renderer, rect)); }; -@symbol("SDL_CreateTexture") fn _SDL_CreateTexture(renderer: *SDL_Renderer, - format: u32, access: int, w: int, h: int) *SDL_Texture; +@symbol("SDL_RenderSetLogicalSize") fn _SDL_RenderSetLogicalSize( + renderer: *SDL_Renderer, w: int, h: int) int; -// Create a texture for a rendering context. -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; +// 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_UpdateTexture") fn _SDL_UpdateTexture(texture: *SDL_Texture, @@ -228,9 +338,14 @@ export fn SDL_LockTexture(texture: *SDL_Texture, // Unlock a texture, uploading the changes to video memory, if needed. export @symbol("SDL_UnlockTexture") fn SDL_UnlockTexture(texture: *SDL_Texture) void; -// An enumeration of texture access patterns. -export type SDL_TextureAccess = enum int { - STATIC, - STREAMING, - TARGET -}; +@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)); +}; \ No newline at end of file -- cgit v1.2.3 From 3ca5d97376151d6f1a4a1787b6609c470a05a82c Mon Sep 17 00:00:00 2001 From: Autumn! Date: Wed, 24 May 2023 20:37:00 +0000 Subject: Use types::c:: instead of char and strings:: Signed-off-by: Autumn! --- sdl2/errors.ha | 8 ++++---- sdl2/events.ha | 8 +++++--- sdl2/gl.ha | 4 +++- sdl2/image/image.ha | 10 +++++----- sdl2/keyboard.ha | 8 ++++---- sdl2/rwops.ha | 6 +++--- sdl2/video.ha | 8 ++++---- 7 files changed, 28 insertions(+), 24 deletions(-) diff --git a/sdl2/errors.ha b/sdl2/errors.ha index 52d23a0..b386ebe 100644 --- a/sdl2/errors.ha +++ b/sdl2/errors.ha @@ -1,4 +1,4 @@ -use strings; +use types::c; // Returned when an error occurs in an SDL function. export type error = !str; @@ -8,7 +8,7 @@ export fn strerror(err: error) str = { return err: str; }; -@symbol("SDL_GetError") fn SDL_GetError() const *char; +@symbol("SDL_GetError") fn SDL_GetError() const *c::char; export fn wrapvoid(ret: int) (void | error) = { wrapint(ret)?; @@ -16,7 +16,7 @@ export fn wrapvoid(ret: int) (void | error) = { export fn wrapint(ret: int) (int | error) = { if (ret < 0) { - return strings::fromc(SDL_GetError()): error; + return c::tostr(SDL_GetError()): error; }; return ret; }; @@ -26,6 +26,6 @@ export fn wrapptr(ret: nullable *void) (*void | error) = { case let v: *void => return v; case null => - return strings::fromc(SDL_GetError()): error; + return c::tostr(SDL_GetError()): error; }; }; diff --git a/sdl2/events.ha b/sdl2/events.ha index 1003af1..beb1343 100644 --- a/sdl2/events.ha +++ b/sdl2/events.ha @@ -1,3 +1,5 @@ +use types::c; + export type SDL_EventType = enum u32 { FIRSTEVENT = 0, @@ -116,7 +118,7 @@ export def TEXTEDITINGEVENT_TEXT_SIZE: size = 32; export type SDL_TextEditingEvent = struct { SDL_CommonEvent, window_id: u32, - text: [TEXTEDITINGEVENT_TEXT_SIZE]char, + text: [TEXTEDITINGEVENT_TEXT_SIZE]c::char, start: i32, length: i32, }; @@ -128,7 +130,7 @@ export def TEXTINPUTEVENT_TEXT_SIZE: size = 32; export type SDL_TextInputEvent = struct { SDL_CommonEvent, window_id: u32, - text: [TEXTINPUTEVENT_TEXT_SIZE]char, + text: [TEXTINPUTEVENT_TEXT_SIZE]c::char, }; // Mouse motion event structure (event.motion.*) @@ -294,7 +296,7 @@ export type SDL_DollarGestureEvent = struct { // If this event is enabled, you must free the filename in the event. export type SDL_DropEvent = struct { SDL_CommonEvent, - file: *char, + file: *c::char, window_id: u32, }; diff --git a/sdl2/gl.ha b/sdl2/gl.ha index 023a62f..6599da8 100644 --- a/sdl2/gl.ha +++ b/sdl2/gl.ha @@ -1,3 +1,5 @@ +use types::c; + export type SDL_GLContext = void; export type SDL_GLprofile = enum int { @@ -39,7 +41,7 @@ export type SDL_GLattr = enum { export @symbol("SDL_GL_CreateContext") fn SDL_GL_CreateContext( window: *SDL_Window) *SDL_GLContext; export @symbol("SDL_GL_GetProcAddress") fn SDL_GL_GetProcAddress( - proc: *const char) *void; + proc: *const c::char) *void; export @symbol("SDL_GL_SetAttribute") fn SDL_GL_SetAttribute( attr: SDL_GLattr, value: int) *void; export @symbol("SDL_GL_SwapWindow") fn SDL_GL_SwapWindow(window: *SDL_Window) void; diff --git a/sdl2/image/image.ha b/sdl2/image/image.ha index 8684f83..32f8f3d 100644 --- a/sdl2/image/image.ha +++ b/sdl2/image/image.ha @@ -1,7 +1,7 @@ // TODO: Flesh me out // TODO: SDL_RWops use sdl2; -use strings; +use types::c; // Flags for [[IMG_Init]]. export type IMG_InitFlags = enum int { @@ -23,24 +23,24 @@ export fn IMG_Init(flags: IMG_InitFlags) (void | sdl2::error) = { // Unloads libraries loaded with [[IMG_Init]] export @symbol("IMG_Quit") fn IMG_Quit() void; -@symbol("IMG_Load") fn _IMG_Load(file: const *char) nullable *sdl2::SDL_Surface; +@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 = strings::to_c(file); + 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 *char) nullable *sdl2::SDL_Texture; + 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 = strings::to_c(file); + const file = c::fromstr(file); defer free(file); return sdl2::wrapptr(_IMG_LoadTexture(SDL_Renderer, file))?: *sdl2::SDL_Texture; }; diff --git a/sdl2/keyboard.ha b/sdl2/keyboard.ha index eb38afd..d42fa8a 100644 --- a/sdl2/keyboard.ha +++ b/sdl2/keyboard.ha @@ -1,4 +1,4 @@ -use strings; +use types::c; export type SDL_Scancode = enum uint { UNKNOWN = 0, @@ -632,14 +632,14 @@ export type SDL_Keysym = struct { unused: u32, }; -@symbol("SDL_GetKeyFromName") fn _SDL_GetKeyFromName(name: *const char) SDL_Keycode; +@symbol("SDL_GetKeyFromName") fn _SDL_GetKeyFromName(name: *const c::char) SDL_Keycode; export fn SDL_GetKeyFromName(name: str) (SDL_Keycode | error) = { - const name = strings::to_c(name); + const name = c::fromstr(name); defer free(name); const sym = _SDL_GetKeyFromName(name); if (sym == SDL_Keycode::UNKNOWN) { - return strings::fromc(SDL_GetError()): error; + return c::tostr(SDL_GetError()): error; }; return sym; }; diff --git a/sdl2/rwops.ha b/sdl2/rwops.ha index ec961a2..9b9a190 100644 --- a/sdl2/rwops.ha +++ b/sdl2/rwops.ha @@ -1,5 +1,5 @@ use io; -use strings; +use types::c; // RWops types export type rwops_type = enum u32 { @@ -39,8 +39,8 @@ export type SDL_RWops = struct { }; @symbol("SDL_RWFromFile") fn _rw_from_file( - file: const *char, - mode: const *char, + file: const *c::char, + mode: const *c::char, ) *SDL_RWops; // Returns the size of an [[SDL_RWops]], or 0 if unknown or error. diff --git a/sdl2/video.ha b/sdl2/video.ha index bfcb3d0..f60d915 100644 --- a/sdl2/video.ha +++ b/sdl2/video.ha @@ -1,5 +1,5 @@ // TODO: Flesh me out -use strings; +use types::c; // The type used to identify a window. (Opaque) export type SDL_Window = void; @@ -33,12 +33,12 @@ export type SDL_WindowFlags = enum u32 { export def SDL_WINDOWPOS_UNDEFINED: int = 0x1FFF0000; export def SDL_WINDOWPOS_CENTERED: int = 0x2FFF0000; -@symbol("SDL_CreateWindow") fn _SDL_CreateWindow(title: const *char, +@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 [[strings::to_c]] +// '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 @@ -78,7 +78,7 @@ export fn SDL_CreateWindow( h: int, flags: SDL_WindowFlags, ) (*SDL_Window | error) = { - let title = strings::to_c(title); + let title = c::fromstr(title); defer free(title); return wrapptr(_SDL_CreateWindow(title, x, y, w, h, flags))?: *SDL_Window; }; -- cgit v1.2.3 From 93cf66cf5eec566960290da42f12bcff93c68025 Mon Sep 17 00:00:00 2001 From: Autumn! Date: Wed, 24 May 2023 20:37:01 +0000 Subject: rwops.ha: make more rigorous in order to fix various bugs Signed-off-by: Autumn! --- sdl2/mixer/samples.ha | 3 +-- sdl2/rwops.ha | 20 +++++++++++++------- 2 files changed, 14 insertions(+), 9 deletions(-) diff --git a/sdl2/mixer/samples.ha b/sdl2/mixer/samples.ha index 0a45151..ad1ecc1 100644 --- a/sdl2/mixer/samples.ha +++ b/sdl2/mixer/samples.ha @@ -13,10 +13,9 @@ export type Mix_Chunk = struct { @symbol("Mix_LoadWAV_RW") fn _Mix_LoadWAV_RW(src: *sdl2::SDL_RWops, freesrc: int) nullable *Mix_Chunk; -// Loads a sample from an [[io::handle]]. The stream will not be closed for you. +// 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); - defer sdl2::SDL_RWclose(rw); return sdl2::wrapptr(_Mix_LoadWAV_RW(rw, 0))?: *Mix_Chunk; }; diff --git a/sdl2/rwops.ha b/sdl2/rwops.ha index 9b9a190..4c9077b 100644 --- a/sdl2/rwops.ha +++ b/sdl2/rwops.ha @@ -16,8 +16,8 @@ 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: *void, sz: size, maxnum: size) size, - write: *fn(ctx: *SDL_RWops, ptr: *void, sz: size, num: size) size, - close: *fn(ctx: *SDL_RWops) void, + write: *fn(ctx: *SDL_RWops, ptr: *const void, sz: size, num: size) size, + close: *fn(ctx: *SDL_RWops) int, type_: rwops_type, // XXX: This union is platform-specific @@ -105,24 +105,30 @@ fn stream_read(ctx: *SDL_RWops, ptr: *void, sz: size, maxnum: size) size = { let buf = ptr: *[*]u8; match (io::readall(handle, buf[..sz * maxnum])) { case let n: size => - return n; + return n / sz; + case io::EOF => + return 0; case io::error => return 0; }; }; -fn stream_write(ctx: *SDL_RWops, ptr: *void, sz: size, num: size) size = { +fn stream_write(ctx: *SDL_RWops, ptr: *const void, sz: size, num: size) size = { const handle = *(&ctx.hidden.unknown.data1: *io::handle); - let buf = ptr: *[*]u8; + let buf = ptr: *[*]const u8; match (io::writeall(handle, buf[..sz * num])) { case let n: size => - return n; + return n / sz; case io::error => return 0; }; }; -fn stream_close(ctx: *SDL_RWops) void = { +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; + }; }; -- cgit v1.2.3 From 5874e403e14eabaf9c6596d2df5b6db6dd4acdcf Mon Sep 17 00:00:00 2001 From: Autumn! Date: Wed, 24 May 2023 20:37:02 +0000 Subject: Correct return type wrapping of Mix_Init() Signed-off-by: Autumn! --- sdl2/mixer/general.ha | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/sdl2/mixer/general.ha b/sdl2/mixer/general.ha index 4f819bf..87a729f 100644 --- a/sdl2/mixer/general.ha +++ b/sdl2/mixer/general.ha @@ -29,7 +29,9 @@ export def MIX_DEFAULT_FORMAT: sdl2::SDL_AudioFormat = sdl2::AUDIO_S16LSB; // 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) = { - return sdl2::wrapvoid(_Mix_Init(flags)); + if (flags & _Mix_Init(flags) != flags) { + return "Mixer flags not initialized": sdl2::error; + }; }; // Unloads libraries loaded with [[Mix_Init]]. -- cgit v1.2.3 From d738255b695ace281c3437d1fefe831427525daa Mon Sep 17 00:00:00 2001 From: Autumn! Date: Wed, 24 May 2023 20:37:03 +0000 Subject: correct/simplify .gitignore Signed-off-by: Autumn! --- .gitignore | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/.gitignore b/.gitignore index 7568da1..c090245 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,2 @@ -docs/ -demo -!./cmd/demo/ +/docs/ +/demo -- cgit v1.2.3 From 0c96e49946914c10767939cb29b259c7a91e1536 Mon Sep 17 00:00:00 2001 From: Autumn! Date: Wed, 24 May 2023 20:37:04 +0000 Subject: cmd/demo: fix call to fmt::fatal() Signed-off-by: Autumn! --- cmd/demo/main.ha | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/cmd/demo/main.ha b/cmd/demo/main.ha index 82de229..3ba1b1c 100644 --- a/cmd/demo/main.ha +++ b/cmd/demo/main.ha @@ -25,9 +25,9 @@ type state = struct { export fn main() void = { match (run()) { case let err: sdl2::error => - fmt::fatal("SDL2 error: {}", sdl2::strerror(err)); + fmt::fatal("SDL2 error:", sdl2::strerror(err)); case let err: fs::error => - fmt::fatal("Error: {}", fs::strerror(err)); + fmt::fatal("Error:", fs::strerror(err)); case void => void; }; }; -- cgit v1.2.3 From 2095913461ae7e6d65848948c55d2d979e665621 Mon Sep 17 00:00:00 2001 From: francorbacho Date: Sat, 12 Aug 2023 12:05:05 +0000 Subject: Add SDL_CreateTextureFromSurface() Signed-off-by: francorbacho --- sdl2/render.ha | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/sdl2/render.ha b/sdl2/render.ha index 545aae5..66571b1 100644 --- a/sdl2/render.ha +++ b/sdl2/render.ha @@ -315,6 +315,17 @@ export fn SDL_CreateTexture( )?: *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 *void, pitch: int) int; -- cgit v1.2.3 From 260b9effb19fe85604f05ccf0be18795fd2bc782 Mon Sep 17 00:00:00 2001 From: Drew DeVault Date: Fri, 22 Sep 2023 14:27:12 +0200 Subject: all: fix build errors --- sdl2/errors.ha | 4 ++-- sdl2/events.ha | 6 +++--- sdl2/gamecontroller.ha | 2 +- sdl2/gl.ha | 6 +++--- sdl2/render.ha | 14 +++++++------- sdl2/rwops.ha | 14 +++++++------- sdl2/surface.ha | 8 ++++---- sdl2/video.ha | 2 +- 8 files changed, 28 insertions(+), 28 deletions(-) diff --git a/sdl2/errors.ha b/sdl2/errors.ha index b386ebe..a848667 100644 --- a/sdl2/errors.ha +++ b/sdl2/errors.ha @@ -21,9 +21,9 @@ export fn wrapint(ret: int) (int | error) = { return ret; }; -export fn wrapptr(ret: nullable *void) (*void | error) = { +export fn wrapptr(ret: nullable *opaque) (*opaque | error) = { match (ret) { - case let v: *void => + case let v: *opaque => return v; case null => return c::tostr(SDL_GetError()): error; diff --git a/sdl2/events.ha b/sdl2/events.ha index beb1343..55a0a63 100644 --- a/sdl2/events.ha +++ b/sdl2/events.ha @@ -322,15 +322,15 @@ export type SDL_UserEvent = struct { SDL_CommonEvent, window_id: u32, code: i32, - data1: *void, - data2: *void, + 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: *void, // TODO + msg: *opaque, // TODO }; // General event structure diff --git a/sdl2/gamecontroller.ha b/sdl2/gamecontroller.ha index 1ce9384..4cab9ce 100644 --- a/sdl2/gamecontroller.ha +++ b/sdl2/gamecontroller.ha @@ -2,7 +2,7 @@ // The SDL_GameController structure used to identify an SDL game controller. // (Opaque) -export type SDL_GameController = void; +export type SDL_GameController = opaque; // The list of axes available from a controller // diff --git a/sdl2/gl.ha b/sdl2/gl.ha index 6599da8..9e3c163 100644 --- a/sdl2/gl.ha +++ b/sdl2/gl.ha @@ -1,6 +1,6 @@ use types::c; -export type SDL_GLContext = void; +export type SDL_GLContext = opaque; export type SDL_GLprofile = enum int { GL_CONTEXT_PROFILE_CORE = 0x0001, @@ -41,7 +41,7 @@ export type SDL_GLattr = enum { export @symbol("SDL_GL_CreateContext") fn SDL_GL_CreateContext( window: *SDL_Window) *SDL_GLContext; export @symbol("SDL_GL_GetProcAddress") fn SDL_GL_GetProcAddress( - proc: *const c::char) *void; + proc: *const c::char) *opaque; export @symbol("SDL_GL_SetAttribute") fn SDL_GL_SetAttribute( - attr: SDL_GLattr, value: int) *void; + attr: SDL_GLattr, value: int) *opaque; export @symbol("SDL_GL_SwapWindow") fn SDL_GL_SwapWindow(window: *SDL_Window) void; diff --git a/sdl2/render.ha b/sdl2/render.ha index 66571b1..1366ae4 100644 --- a/sdl2/render.ha +++ b/sdl2/render.ha @@ -1,10 +1,10 @@ // TODO: Flesh me out // A structure representing rendering state. (Opaque) -export type SDL_Renderer = void; +export type SDL_Renderer = opaque; // An efficient driver-specific representation of pixel data. (Opaque) -export type SDL_Texture = void; +export type SDL_Texture = opaque; export type SDLPixelFormatValues = enum u32 { SDL_PIXELFORMAT_UNKNOWN, @@ -327,21 +327,21 @@ export fn SDL_CreateTextureFromSurface( }; @symbol("SDL_UpdateTexture") fn _SDL_UpdateTexture(texture: *SDL_Texture, - rect: const nullable *SDL_Rect, pixels: const nullable *void, pitch: int) int; + 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 *void, pitch: int) + 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 *void, pitch: *int) int; + 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 *void, pitch: *int) + rect: const nullable *SDL_Rect, pixels: nullable * nullable *opaque, pitch: *int) (int | error) = { return wrapint(_SDL_LockTexture(texture, rect, pixels, pitch))?: int; }; @@ -359,4 +359,4 @@ export fn SDL_RenderSetScale( scaleY: f32, ) (void | error) = { return wrapvoid(_SDL_RenderSetScale(renderer, scaleX, scaleY)); -}; \ No newline at end of file +}; diff --git a/sdl2/rwops.ha b/sdl2/rwops.ha index 4c9077b..4605a3a 100644 --- a/sdl2/rwops.ha +++ b/sdl2/rwops.ha @@ -15,8 +15,8 @@ export type rwops_type = enum u32 { 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: *void, sz: size, maxnum: size) size, - write: *fn(ctx: *SDL_RWops, ptr: *const void, sz: size, num: size) size, + 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, @@ -24,7 +24,7 @@ export type SDL_RWops = struct { hidden: union { stdio: struct { autoclose: bool, - fp: nullable *void, // FILE * + fp: nullable *opaque, // FILE * }, mem: struct { base: nullable *u8, @@ -32,8 +32,8 @@ export type SDL_RWops = struct { stop: nullable *u8, }, unknown: struct { - data1: nullable *void, - data2: nullable *void, + data1: nullable *opaque, + data2: nullable *opaque, }, }, }; @@ -100,7 +100,7 @@ fn stream_seek(ctx: *SDL_RWops, offs: i64, whence: int) i64 = { }; }; -fn stream_read(ctx: *SDL_RWops, ptr: *void, sz: size, maxnum: size) size = { +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])) { @@ -113,7 +113,7 @@ fn stream_read(ctx: *SDL_RWops, ptr: *void, sz: size, maxnum: size) size = { }; }; -fn stream_write(ctx: *SDL_RWops, ptr: *const void, sz: size, num: size) size = { +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])) { diff --git a/sdl2/surface.ha b/sdl2/surface.ha index 572bdcc..24153c3 100644 --- a/sdl2/surface.ha +++ b/sdl2/surface.ha @@ -8,12 +8,12 @@ export type SDL_Surface = struct { w: int, h: int, pitch: int, - pixels: nullable *void, + pixels: nullable *opaque, - userdata: *void, + userdata: *opaque, locked: int, - lock_data: *void, + lock_data: *opaque, clip_rect: SDL_Rect, @@ -22,7 +22,7 @@ export type SDL_Surface = struct { refcount: int, }; -export type SDL_BlitMap = void; +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, diff --git a/sdl2/video.ha b/sdl2/video.ha index f60d915..466052e 100644 --- a/sdl2/video.ha +++ b/sdl2/video.ha @@ -2,7 +2,7 @@ use types::c; // The type used to identify a window. (Opaque) -export type SDL_Window = void; +export type SDL_Window = opaque; // The flags on a window export type SDL_WindowFlags = enum u32 { -- cgit v1.2.3 From 6d7c5bf0273094dc7c3670ec26d065a816d7dce2 Mon Sep 17 00:00:00 2001 From: Joe Finney Date: Fri, 29 Dec 2023 11:51:32 +0000 Subject: Add SDL_GetRendererOutputSize. Signed-off-by: Joe Finney --- sdl2/render.ha | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/sdl2/render.ha b/sdl2/render.ha index 1366ae4..192d608 100644 --- a/sdl2/render.ha +++ b/sdl2/render.ha @@ -104,6 +104,15 @@ export fn SDL_CreateRenderer( // 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; -- cgit v1.2.3 From f2e40ecffec519e1094ed829f8735309ae67997f Mon Sep 17 00:00:00 2001 From: ubq323 Date: Sat, 13 Apr 2024 16:30:46 +0100 Subject: add a few functions these are some sdl functions i needed for a project. there is not much structure beyond that. --- sdl2/keyboard.ha | 10 ++++++++++ sdl2/pixels.ha | 15 +++++++++++++++ sdl2/surface.ha | 9 +++++++++ sdl2/video.ha | 11 ++++++++++- 4 files changed, 44 insertions(+), 1 deletion(-) diff --git a/sdl2/keyboard.ha b/sdl2/keyboard.ha index d42fa8a..cc137d2 100644 --- a/sdl2/keyboard.ha +++ b/sdl2/keyboard.ha @@ -643,3 +643,13 @@ export fn SDL_GetKeyFromName(name: str) (SDL_Keycode | 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/pixels.ha b/sdl2/pixels.ha index 75ccb99..7aa8733 100644 --- a/sdl2/pixels.ha +++ b/sdl2/pixels.ha @@ -1,4 +1,5 @@ // TODO: Flesh me out +use types::c; export type SDL_Color = struct { r: u8, @@ -38,3 +39,17 @@ export type SDL_PixelFormat = struct { }; 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/surface.ha b/sdl2/surface.ha index 24153c3..7b6438e 100644 --- a/sdl2/surface.ha +++ b/sdl2/surface.ha @@ -35,3 +35,12 @@ export fn SDL_CreateRGBSurface(flags: u32, return wrapptr(_SDL_CreateRGBSurface(flags, width, height, depth, Rmask, Gmask, Bmask, Amask))?: *SDL_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/video.ha b/sdl2/video.ha index 466052e..2627b48 100644 --- a/sdl2/video.ha +++ b/sdl2/video.ha @@ -99,10 +99,19 @@ export @symbol("SDL_DestroyWindow") fn SDL_DestroyWindow(window: *SDL_Window) vo export @symbol("SDL_GetWindowSize") fn SDL_GetWindowSize(window: *SDL_Window, w: nullable *int, h: nullable *int) void; -// Get the SDL surface associated with the window. @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)); +}; + -- cgit v1.2.3 From 27476717c866a40937c2a20ecc906cf0e8d77303 Mon Sep 17 00:00:00 2001 From: ubq323 Date: Sat, 27 Apr 2024 20:02:27 +0100 Subject: add SDL_FreeSurface --- sdl2/surface.ha | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/sdl2/surface.ha b/sdl2/surface.ha index 7b6438e..afca40c 100644 --- a/sdl2/surface.ha +++ b/sdl2/surface.ha @@ -36,6 +36,13 @@ export fn SDL_CreateRGBSurface(flags: u32, 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; -- cgit v1.2.3 From 1b70cc8b74aa7669c1af908fd3cf7d275377d2e0 Mon Sep 17 00:00:00 2001 From: Drew DeVault Date: Fri, 25 Oct 2024 19:38:12 +0200 Subject: sdl2: add (some) mouse functionality --- sdl2/mouse.ha | 49 +++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 49 insertions(+) create mode 100644 sdl2/mouse.ha diff --git a/sdl2/mouse.ha b/sdl2/mouse.ha new file mode 100644 index 0000000..53167ff --- /dev/null +++ b/sdl2/mouse.ha @@ -0,0 +1,49 @@ +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; + +// Set relative mouse mode. +export @symbol("SDL_SetRelativeMouseMode") fn SDL_SetRelativeMouseMode(enabled: bool) int; + +// 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; -- cgit v1.2.3 From ce0d3fc291089ac22a2cba914787620a95ea999e Mon Sep 17 00:00:00 2001 From: Drew DeVault Date: Sat, 26 Oct 2024 15:09:59 +0200 Subject: Add SDL_GL_SetSwapInterval --- sdl2/gl.ha | 1 + 1 file changed, 1 insertion(+) diff --git a/sdl2/gl.ha b/sdl2/gl.ha index 9e3c163..b49ecf0 100644 --- a/sdl2/gl.ha +++ b/sdl2/gl.ha @@ -45,3 +45,4 @@ export @symbol("SDL_GL_GetProcAddress") fn SDL_GL_GetProcAddress( export @symbol("SDL_GL_SetAttribute") fn SDL_GL_SetAttribute( attr: SDL_GLattr, value: int) *opaque; export @symbol("SDL_GL_SwapWindow") fn SDL_GL_SwapWindow(window: *SDL_Window) void; +export @symbol("SDL_GL_SetSwapInterval") fn SDL_GL_SetSwapInterval(interval: int) bool; -- cgit v1.2.3 From e39a190e8f659d92e20840693e12311488774329 Mon Sep 17 00:00:00 2001 From: Drew DeVault Date: Sun, 3 Nov 2024 09:01:17 +0100 Subject: Add SDL_GL_GetDrawableSize --- sdl2/gl.ha | 1 + 1 file changed, 1 insertion(+) diff --git a/sdl2/gl.ha b/sdl2/gl.ha index b49ecf0..b2295f6 100644 --- a/sdl2/gl.ha +++ b/sdl2/gl.ha @@ -46,3 +46,4 @@ export @symbol("SDL_GL_SetAttribute") fn SDL_GL_SetAttribute( attr: SDL_GLattr, value: int) *opaque; export @symbol("SDL_GL_SwapWindow") fn SDL_GL_SwapWindow(window: *SDL_Window) void; export @symbol("SDL_GL_SetSwapInterval") fn SDL_GL_SetSwapInterval(interval: int) bool; +export @symbol("SDL_GL_GetDrawableSize") fn SDL_GL_GetDrawableSize(window: *SDL_Window, w: *int, h: *int) void; -- cgit v1.2.3 From 5ae3aca9f64a2a3b7b1ec12038c79755b58502fa Mon Sep 17 00:00:00 2001 From: Drew DeVault Date: Mon, 18 Nov 2024 17:58:43 +0100 Subject: Add SDL text input wrappers --- sdl2/keyboard.ha | 2 ++ 1 file changed, 2 insertions(+) diff --git a/sdl2/keyboard.ha b/sdl2/keyboard.ha index cc137d2..b9759dd 100644 --- a/sdl2/keyboard.ha +++ b/sdl2/keyboard.ha @@ -653,3 +653,5 @@ export fn SDL_GetKeyboardState() []bool = { return arr; }; +export @symbol("SDL_StartTextInput") fn SDL_StartTextInput(win: *SDL_Window) bool; +export @symbol("SDL_StopTextInput") fn SDL_StopTextInput(win: *SDL_Window) bool; -- cgit v1.2.3 From 304d7203d19f71efac49422b5b72f1b5e6f89ff8 Mon Sep 17 00:00:00 2001 From: Drew DeVault Date: Mon, 13 Jan 2025 11:03:19 +0100 Subject: sdl2/rwops: assert on allocation failure --- sdl2/rwops.ha | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sdl2/rwops.ha b/sdl2/rwops.ha index 4605a3a..da5d83d 100644 --- a/sdl2/rwops.ha +++ b/sdl2/rwops.ha @@ -67,7 +67,7 @@ export fn rw_from_handle(in: io::handle) *SDL_RWops = { 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; -- cgit v1.2.3 From fb6008be0b79a2a24b1ac960316a83f7873b4f39 Mon Sep 17 00:00:00 2001 From: "Haelwenn (lanodan) Monnier" Date: Mon, 20 Oct 2025 19:44:46 +0200 Subject: Add ! after c::fromstr calls to handle nomem Lazy way out, might be better to change API either by returning nomem or using `*char` as parameter so it's caller controlled instead of `str`. --- sdl2/image/image.ha | 4 ++-- sdl2/keyboard.ha | 2 +- sdl2/video.ha | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/sdl2/image/image.ha b/sdl2/image/image.ha index 32f8f3d..b4af99e 100644 --- a/sdl2/image/image.ha +++ b/sdl2/image/image.ha @@ -27,7 +27,7 @@ export @symbol("IMG_Quit") fn IMG_Quit() void; // Load an image from a file path. export fn IMG_Load(file: str) (*sdl2::SDL_Surface | sdl2::error) = { - const file = c::fromstr(file); + const file = c::fromstr(file)!; defer free(file); return sdl2::wrapptr(_IMG_Load(file))?: *sdl2::SDL_Surface; }; @@ -40,7 +40,7 @@ export fn IMG_LoadTexture( SDL_Renderer: *sdl2::SDL_Renderer, file: str, ) (*sdl2::SDL_Texture | sdl2::error) = { - const file = c::fromstr(file); + const file = c::fromstr(file)!; defer free(file); return sdl2::wrapptr(_IMG_LoadTexture(SDL_Renderer, file))?: *sdl2::SDL_Texture; }; diff --git a/sdl2/keyboard.ha b/sdl2/keyboard.ha index b9759dd..02cedae 100644 --- a/sdl2/keyboard.ha +++ b/sdl2/keyboard.ha @@ -635,7 +635,7 @@ export type SDL_Keysym = struct { @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); + const name = c::fromstr(name)!; defer free(name); const sym = _SDL_GetKeyFromName(name); if (sym == SDL_Keycode::UNKNOWN) { diff --git a/sdl2/video.ha b/sdl2/video.ha index 2627b48..72ed96f 100644 --- a/sdl2/video.ha +++ b/sdl2/video.ha @@ -78,7 +78,7 @@ export fn SDL_CreateWindow( h: int, flags: SDL_WindowFlags, ) (*SDL_Window | error) = { - let title = c::fromstr(title); + let title = c::fromstr(title)!; defer free(title); return wrapptr(_SDL_CreateWindow(title, x, y, w, h, flags))?: *SDL_Window; }; -- cgit v1.2.3