diff --git a/.github/workflows/publish.yml b/.github/workflows/publish.yml
index 17e16913..6e685dba 100644
--- a/.github/workflows/publish.yml
+++ b/.github/workflows/publish.yml
@@ -13,14 +13,17 @@ jobs:
uses: actions/setup-java@v3
with:
distribution: 'temurin'
- java-version: 17
+ java-version: 21
cache: 'gradle'
- name: Build and publish with Gradle
run: |
cd ./klang
- ./gradlew build publish --info
+ ./gradlew publishAll --info
env:
VERSION: ${{ github.event.release.tag_name }}
- URL: ${{ vars.GITLAB_URL }}
- TOKEN: ${{ secrets.GITLAB_TOKEN }}
+ SONATYPE_LOGIN: ${{ secrets.SONATYPE_LOGIN }}
+ SONATYPE_PASSWORD: ${{ secrets.SONATYPE_PASSWORD }}
+ PGP_PUBLIC: ${{ secrets.PGP_PUBLIC }}
+ PGP_PRIVATE: ${{ secrets.PGP_PRIVATE }}
+ PGP_PASSPHRASE: ${{ secrets.PGP_PASSPHRASE }}
diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml
index 94f32a35..4aed950f 100644
--- a/.github/workflows/test.yml
+++ b/.github/workflows/test.yml
@@ -13,16 +13,19 @@ concurrency:
jobs:
tests:
strategy:
+ fail-fast: false
matrix:
- os: [ubuntu-latest, macos-latest]
+ os: [macos-14, ubuntu-latest]
runs-on: ${{ matrix.os }}
steps:
+ - name: print architecture
+ run: uname -m
- uses: actions/checkout@v3
- name: Set up JDK
uses: actions/setup-java@v3
with:
distribution: 'temurin'
- java-version: 17
+ java-version: 21
cache: 'gradle'
- name: Cache Gradle packages
uses: actions/cache@v3
@@ -30,7 +33,15 @@ jobs:
path: ~/.gradle/caches
key: ${{ runner.os }}-gradle-${{ hashFiles('**/*.gradle') }}
restore-keys: ${{ runner.os }}-gradle
- - name: Build & test klang
+ - name: Build & test klang macos
+ if: matrix.os == 'macos-14'
+ run: |
+ cd ./klang
+ ./gradlew test
+ - name: Build & test klang ubuntu
+ if: matrix.os == 'ubuntu-latest'
+ env:
+ LIBCLANG_PATH: "/usr/lib/llvm-15/lib/libclang-15.so.1"
run: |
cd ./klang
./gradlew test
diff --git a/.gitignore b/.gitignore
index 22540597..8694bc9b 100644
--- a/.gitignore
+++ b/.gitignore
@@ -21,3 +21,9 @@ gradle-app.setting
.classpath
/.idea/
/toolkit/*.log
+
+# Ignore native libraries
+*.dll
+*.dylib
+*.so
+*.jar
diff --git a/.run/generate binding.run.xml b/.run/generate binding.run.xml
deleted file mode 100644
index 6319132d..00000000
--- a/.run/generate binding.run.xml
+++ /dev/null
@@ -1,26 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
- true
- true
- false
- false
-
-
-
-
-
\ No newline at end of file
diff --git a/.run/run integration test.run.xml b/.run/run integration test.run.xml
deleted file mode 100644
index ad27f438..00000000
--- a/.run/run integration test.run.xml
+++ /dev/null
@@ -1,31 +0,0 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- false
- true
- false
- true
-
-
-
\ No newline at end of file
diff --git a/README.md b/README.md
index ded46d61..d037a3c9 100644
--- a/README.md
+++ b/README.md
@@ -1 +1,42 @@
-Experimental toolkit to auto generate binding from C/C++/Objective C library to Kotlin
\ No newline at end of file
+# Klang Toolkit
+
+*Experimental toolkit to generate bindings from C/C++/Objective-C library to Kotlin using Clang.*
+
+## Status Overview
+
+Currently, we are in the experimental phase of parsing headers. We have two main approaches:
+
+### Approach 1: Standalone LibClang 15 Library
+
+- **Advantages**
+ - More accurate header parsing.
+- **Disadvantages**
+ - LibClang is part of the LLVM toolchain.
+
+### Approach 2: Clang 15 from Docker for JSON AST Generation
+
+- **Advantages**
+ - Easier to use.
+- **Disadvantages**
+ - Limited information on JSON AST.
+ - Requires Docker on host for JSON AST generation.
+ - Hard to use OS-specific headers.
+
+We can generate a good enough binding with JNA on a C library. Check the `bindings` folder for examples.
+
+## Known Issues
+
+Currently, with Gradle, the native library is loaded multiple times on the daemon. Therefore, the Klang plugin does not
+support the Gradle daemon.
+
+## Additional Information
+
+The `Jextract` code is embedded almost as is, and the license may differ from Klang toolkit.
+
+This project embeds C headers from different sources; namely:
+
+1. `/klang/src/main/resource/darwin-headers.zip` is obtained from XCode. Refer to `/usr/bin/xcrun --show-sdk-path`.
+2. `/klang/src/main/resource/c-headers.zip` is obtained from Clang 15 headers.
+
+Clang dynamic libraries (version 15) are embedded. These are fetched
+from [prebuilt version on GitHub](https://github.com/klang-toolkit/libclang-binary/releases/tag/15).
\ No newline at end of file
diff --git a/bindings/angle/binaries/build.gradle.kts b/bindings/angle/binaries/build.gradle.kts
new file mode 100644
index 00000000..f75408d9
--- /dev/null
+++ b/bindings/angle/binaries/build.gradle.kts
@@ -0,0 +1,34 @@
+import org.jetbrains.kotlin.de.undercouch.gradle.tasks.download.Download
+
+plugins {
+ kotlin("jvm") version libs.versions.kotlin
+ `maven-publish`
+}
+
+publishing {
+ publications {
+ create("mavenJava") { from(components["java"]) }
+ }
+}
+version = "chrome-122.0.6261"
+
+val directory = project.file("src/main/resources")
+val baseUrl = "https://github.com/klang-toolkit/ANGLE-binary/releases/download/$version/"
+val fileToDownload = listOf(
+ "libEGL.dylib" to directory.resolve("darwin").resolve("libEGL.dylib"),
+ "libGLESv2.dylib" to directory.resolve("darwin").resolve("libGLESv2.dylib"),
+ "libEGL.dll" to directory.resolve("win32").resolve("libEGL.dylib"),
+ "libGLESv2.dll" to directory.resolve("win32").resolve("libGLESv2.dylib"),
+).forEach { (fileName, target) ->
+ val url = "$baseUrl$fileName"
+ val taskName = "downloadFile-$fileName"
+ tasks.register(taskName) {
+ onlyIf { !target.exists() }
+ src(url)
+ dest(target)
+ }
+
+ tasks.named("processResources") {
+ dependsOn(taskName)
+ }
+}
\ No newline at end of file
diff --git a/bindings/angle/build.gradle.kts b/bindings/angle/build.gradle.kts
index 636afdab..eb2f7901 100644
--- a/bindings/angle/build.gradle.kts
+++ b/bindings/angle/build.gradle.kts
@@ -1,7 +1,19 @@
+plugins {
+ kotlin("jvm") version libs.versions.kotlin
+ id("com.gradle.plugin-publish") version "1.0.0"
+}
+
+repositories {
+ mavenCentral()
+}
+group = "io.ygdrasil"
+version = "1.0.0-SNAPSHOT"
-allprojects {
+subprojects {
+ apply(plugin = "maven-publish")
+ apply(plugin = "org.jetbrains.kotlin.jvm")
repositories {
mavenCentral()
@@ -9,6 +21,39 @@ allprojects {
group = "io.ygdrasil"
version = "1.0.0-SNAPSHOT"
+
+ publishing {
+
+ publications {
+ create("maven") {
+ from(components["java"])
+
+ pom {
+ name = "Klang-${project.name}"
+ description = "Angle binding"
+ url = "https://ygdrasil.io/"
+ licenses {
+ license {
+ name = "MIT"
+ url = "https://opensource.org/license/mit/"
+ }
+ }
+ developers {
+ developer {
+ id = "alexandremo"
+ name = "Alexandre Mommers"
+ email = "alexandre dot mommers at gmail do com"
+ }
+ }
+ scm {
+ connection = "scm:git:git://github.com/ygdrasil-io/klang.git"
+ developerConnection = "scm:git:ssh//git@github.com:ygdrasil-io/klang.git"
+ url = "https://github.com/ygdrasil-io/klang"
+ }
+ }
+ }
+ }
+ }
}
diff --git a/bindings/angle/example/build.gradle.kts b/bindings/angle/example/build.gradle.kts
index 9fd1eedf..eb3203fc 100644
--- a/bindings/angle/example/build.gradle.kts
+++ b/bindings/angle/example/build.gradle.kts
@@ -1,6 +1,6 @@
plugins {
- kotlin("jvm") version "1.9.10"
+ kotlin("jvm") version libs.versions.kotlin
}
dependencies {
diff --git a/bindings/angle/example/src/main/kotlin/example/HelloTriangle.kt b/bindings/angle/example/src/main/kotlin/example/HelloTriangle.kt
index cd04e424..f9e2f9ee 100644
--- a/bindings/angle/example/src/main/kotlin/example/HelloTriangle.kt
+++ b/bindings/angle/example/src/main/kotlin/example/HelloTriangle.kt
@@ -52,16 +52,16 @@ class HelloTriangle : SampleApplication("HelloTriangle") {
libGLESv2Library.glViewport(0, 0, window.width, window.height)
// Clear the color buffer
- libGLESv2Library.glClear(GL_COLOR_BUFFER_BIT)
+ libGLESv2Library.glClear(GL_COLOR_BUFFER_BIT.toInt())
// Use the program object
libGLESv2Library.glUseProgram(mProgram)
// Load the vertex data
- libGLESv2Library.glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE.toByte(), 0, verticesBuffer)
+ libGLESv2Library.glVertexAttribPointer(0, 3, GL_FLOAT.toInt(), GL_FALSE.toByte(), 0, verticesBuffer)
libGLESv2Library.glEnableVertexAttribArray(0)
- libGLESv2Library.glDrawArrays(GL_TRIANGLES, 0, 3)
+ libGLESv2Library.glDrawArrays(GL_TRIANGLES.toInt(), 0, 3)
}
}
diff --git a/bindings/angle/example/src/main/kotlin/example/toolkit/EGLPlatformParameters.kt b/bindings/angle/example/src/main/kotlin/example/toolkit/EGLPlatformParameters.kt
index 9e62e0bb..796d69f7 100644
--- a/bindings/angle/example/src/main/kotlin/example/toolkit/EGLPlatformParameters.kt
+++ b/bindings/angle/example/src/main/kotlin/example/toolkit/EGLPlatformParameters.kt
@@ -1,28 +1,23 @@
package example.toolkit
-import libangle.EGL_DONT_CARE
-import libangle.EGL_PLATFORM_ANGLE_DEVICE_TYPE_HARDWARE_ANGLE
-import libangle.EGL_PLATFORM_ANGLE_TYPE_DEFAULT_ANGLE
-import libangle.Feature
+import libangle.*
import java.util.*
class PlatformMethods
class EGLPlatformParameters {
var renderer: Int = EGL_PLATFORM_ANGLE_TYPE_DEFAULT_ANGLE
- var majorVersion: Int = EGL_DONT_CARE
- var minorVersion: Int = EGL_DONT_CARE
+ var majorVersion: Int = EGL_DONT_CARE.toInt()
+ var minorVersion: Int = EGL_DONT_CARE.toInt()
var deviceType: Int = EGL_PLATFORM_ANGLE_DEVICE_TYPE_HARDWARE_ANGLE
- var presentPath: Int = EGL_DONT_CARE
- var debugLayersEnabled: Int = EGL_DONT_CARE
- var robustness: Int = EGL_DONT_CARE
- var displayPowerPreference: Int = EGL_DONT_CARE
+ var presentPath: Int = EGL_DONT_CARE.toInt()
+ var debugLayersEnabled: Int = EGL_DONT_CARE.toInt()
+ var robustness: Int = EGL_DONT_CARE.toInt()
+ var displayPowerPreference: Int = EGL_DONT_CARE.toInt()
var enabledFeatureOverrides: MutableList = ArrayList()
var disabledFeatureOverrides: MutableList = ArrayList()
var platformMethods: PlatformMethods? = null
-
constructor() // Constructor por defecto
-
constructor(renderer: Int) {
this.renderer = renderer
}
diff --git a/bindings/angle/example/src/main/kotlin/example/toolkit/EGLWindow.kt b/bindings/angle/example/src/main/kotlin/example/toolkit/EGLWindow.kt
index f7e3ef39..e51195c1 100644
--- a/bindings/angle/example/src/main/kotlin/example/toolkit/EGLWindow.kt
+++ b/bindings/angle/example/src/main/kotlin/example/toolkit/EGLWindow.kt
@@ -31,28 +31,7 @@ class EGLWindow(window: OSWindow) {
}
fun initializeDisplay(osWindow: OSWindow, glWindowingLibrary: Library, driverType: GLESDriverType, params: EGLPlatformParameters): Boolean {
- if (driverType == GLESDriverType.ZinkEGL) {
- val driDirStream = StringBuilder()
- val s = GetPathSeparator()
- driDirStream.append(GetModuleDirectory()).append("mesa").append(s).append("src").append(s).append("gallium").append(s).append("targets").append(s).append("dri")
- val driDir = driDirStream.toString()
-
- SetEnvironmentVar("MESA_LOADER_DRIVER_OVERRIDE", "zink")
- SetEnvironmentVar("LIBGL_DRIVERS_PATH", driDir)
- }
-
- if (ANGLE_USE_UTIL_LOADER) {
- var getProcAddress: PFNEGLGETPROCADDRESSPROC
- glWindowingLibrary.getAs("eglGetProcAddress", getProcAddress)
- if (getProcAddress == null) {
- println("Cannot load eglGetProcAddress")
- return false
- }
-
- // Likely we will need to use a fallback to Library::getAs on non-ANGLE platforms.
- LoadUtilEGL(getProcAddress)
- }
// EGL_NO_DISPLAY + EGL_EXTENSIONS returns NULL before Android 10
val extensionString = eglQueryString(EGL_NO_DISPLAY, EGL_EXTENSIONS) as String?
@@ -210,7 +189,6 @@ enum class GLESDriverType {
AngleVulkanSecondariesEGL,
SystemEGL,
SystemWGL,
- ZinkEGL,
}
enum class GLWindowResult {
diff --git a/bindings/angle/libangle/src/main/kotlin/libangle/Feature.kt b/bindings/angle/example/src/main/kotlin/example/toolkit/Feature.kt
similarity index 93%
rename from bindings/angle/libangle/src/main/kotlin/libangle/Feature.kt
rename to bindings/angle/example/src/main/kotlin/example/toolkit/Feature.kt
index 89713000..15df630d 100644
--- a/bindings/angle/libangle/src/main/kotlin/libangle/Feature.kt
+++ b/bindings/angle/example/src/main/kotlin/example/toolkit/Feature.kt
@@ -1,8 +1,10 @@
-package libangle
+package example.toolkit
-enum class Feature {
+enum class Feature
+{
AddAndTrueToLoopCondition,
AddMockTextureNoRenderTarget,
+ AdjustClearColorPrecision,
AdjustSrcDstRegionForBlitFramebuffer,
AllocateNonZeroMemory,
AllowAstcFormats,
@@ -25,6 +27,8 @@ enum class Feature {
AllowTranslateUniformBlockToStructuredBuffer,
AlwaysCallUseProgramAfterLink,
AlwaysPreferStagedTextureUploads,
+ AlwaysResolveMultisampleRenderBuffers,
+ AlwaysRunLinkSubJobsThreaded,
AlwaysUnbindFramebufferTexture2D,
AlwaysUseManagedStorageModeForBuffers,
AlwaysUseSharedStorageModeForBuffers,
@@ -33,6 +37,7 @@ enum class Feature {
AsyncCommandBufferReset,
AsyncCommandQueue,
Avoid1BitAlphaTextureFormats,
+ AvoidOpSelectWithMismatchingRelaxedPrecision,
AvoidStencilTextureSwizzle,
BindCompleteFramebufferForTimerQueries,
BindTransformFeedbackBufferBeforeBindBufferRange,
@@ -47,10 +52,12 @@ enum class Feature {
ClampPointSize,
ClearToZeroOrOneBroken,
ClipSrcRegionForBlitFramebuffer,
+ CompileJobIsThreadSafe,
CompileMetalShaders,
CompressVertexData,
CopyIOSurfaceToNonIOSurfaceForReadOptimization,
CopyTextureToBufferForReadOptimization,
+ CorruptProgramBinaryForTesting,
DecodeEncodeSRGBForGenerateMipmap,
DeferFlushUntilEndRenderPass,
DepthStencilBlitExtraCopy,
@@ -65,6 +72,7 @@ enum class Feature {
DisableMetalOnNvidia,
DisableMultisampledRenderToTexture,
DisableNativeParallelCompile,
+ DisablePipelineCacheLoadForTesting,
DisableProgramBinary,
DisableProgramCaching,
DisableProgramCachingForTransformFeedback,
@@ -74,6 +82,7 @@ enum class Feature {
DisableRenderSnorm,
DisableRWTextureTier2Support,
DisableSemaphoreFd,
+ DisableSeparateShaderObjects,
DisableStagedInitializationOfPackedTextureFormats,
DisableSyncControlSupport,
DisableTextureClampToBorder,
@@ -93,6 +102,7 @@ enum class Feature {
EmulateAlphaToCoverage,
EmulateAtan2Float,
EmulateClipDistanceState,
+ EmulateClipOrigin,
EmulateCopyTexImage2D,
EmulateCopyTexImage2DFromRenderbuffers,
EmulateDithering,
@@ -146,10 +156,12 @@ enum class Feature {
ForceGlErrorChecking,
ForceInitShaderVariables,
ForceMaxUniformBufferSize16KB,
+ ForceMinimumMaxVertexAttributes,
ForceNearestFiltering,
ForceNearestMipFiltering,
ForceNonCSBaseMipmapGeneration,
ForceRobustResourceInit,
+ ForceSampleUsageForAhbBackedImages,
ForceSubmitImmutableTextureUpdates,
ForceTextureLodOffset1,
ForceTextureLodOffset2,
@@ -170,6 +182,7 @@ enum class Feature {
HasTextureSwizzle,
InitFragmentOutputVariables,
InitializeCurrentVertexAttributes,
+ InjectAsmStatementIntoLoopBodies,
IntelDisableFastMath,
IntelExplicitBoolCastWorkaround,
KeepBufferShadowCopy,
@@ -179,7 +192,7 @@ enum class Feature {
LimitMaxMSAASamplesTo4,
LimitSampleCountTo2,
LimitWebglMaxTextureSizeTo4096,
- LinkJobIsNotThreadSafe,
+ LinkJobIsThreadSafe,
LoadMetalShadersFromBlobCache,
LogMemoryReportCallbacks,
LogMemoryReportStats,
@@ -205,11 +218,13 @@ enum class Feature {
PreferDeviceLocalMemoryHostVisible,
PreferDrawClearOverVkCmdClearAttachments,
PreferDriverUniformOverSpecConst,
+ PreferHostCachedForNonStaticBufferUsage,
PreferLinearFilterForYUV,
PreferMonolithicPipelinesOverLibraries,
PreferSkippingInvalidateForEmulatedFormats,
PreferSubmitAtFBOBoundary,
PreferSubmitOnAnySamplesPassedQueryEnd,
+ PreTransformTextureCubeGradDerivatives,
PrintMetalShaders,
PromotePackedFormatsTo8BitPerChannel,
ProvokingVertex,
@@ -219,10 +234,12 @@ enum class Feature {
RegenerateStructNames,
RemoveDynamicIndexingOfSwizzledVector,
RemoveInvariantAndCentroidForESSL3,
+ RequireCachedBitForStagingBuffer,
RequireGpuFamily2,
RequireMsl21,
RescopeGlobalVariables,
ResetTexImage2DBaseLevel,
+ ResyncDepthRangeOnClipControl,
RetainSPIRVDebugInfo,
RewriteFloatUnaryMinusOperator,
RewriteRepeatedAssignToSwizzled,
@@ -257,6 +274,7 @@ enum class Feature {
SupportsExtendedDynamicState2,
SupportsExternalFenceCapabilities,
SupportsExternalFenceFd,
+ SupportsExternalFormatResolve,
SupportsExternalMemoryDmaBufAndModifiers,
SupportsExternalMemoryFd,
SupportsExternalMemoryFuchsia,
@@ -264,7 +282,6 @@ enum class Feature {
SupportsExternalSemaphoreCapabilities,
SupportsExternalSemaphoreFd,
SupportsExternalSemaphoreFuchsia,
- SupportsFilteringPrecision,
SupportsFormatFeatureFlags2,
SupportsFragmentShaderInterlockARB,
SupportsFragmentShaderInterlockNV,
@@ -293,6 +310,7 @@ enum class Feature {
SupportsMultisampledRenderToSingleSampled,
SupportsMultisampledRenderToSingleSampledGOOGLEX,
SupportsMultiview,
+ SupportsNonConstantLoopIndexing,
SupportsPipelineCreationCacheControl,
SupportsPipelineCreationFeedback,
SupportsPipelineProtectedAccess,
@@ -346,6 +364,7 @@ enum class Feature {
UseDepthWriteEnableDynamicState,
UseFrontFaceDynamicState,
UseInstancedPointSpriteEmulation,
+ UseIntermediateTextureForGenerateMipmap,
UseMultipleDescriptorsForExternalFormats,
UseNonZeroStencilWriteMaskStaticState,
UsePrimitiveRestartEnableDynamicState,
@@ -362,7 +381,9 @@ enum class Feature {
VertexIDDoesNotIncludeBaseVertex,
WaitIdleBeforeSwapchainRecreation,
WarmUpPipelineCacheAtLink,
+ WriteHelperSampleMask,
ZeroMaxLodWorkaround,
InvalidEnum,
-}
\ No newline at end of file
+ //EnumCount = InvalidEnum,
+};
\ No newline at end of file
diff --git a/bindings/angle/gradle.properties b/bindings/angle/gradle.properties
new file mode 100644
index 00000000..1a9f3845
--- /dev/null
+++ b/bindings/angle/gradle.properties
@@ -0,0 +1,3 @@
+# Enable to use panama class on klang gradle plugin
+org.gradle.jvmargs=--enable-preview
+org.gradle.daemon=false
\ No newline at end of file
diff --git a/bindings/angle/gradle/libs.versions.toml b/bindings/angle/gradle/libs.versions.toml
index 12809027..849f8965 100644
--- a/bindings/angle/gradle/libs.versions.toml
+++ b/bindings/angle/gradle/libs.versions.toml
@@ -2,6 +2,7 @@
kotest = "5.6.1"
klang = "0.0.0"
jna = "5.13.0"
+kotlin = "1.9.22"
[libraries]
kotest = { module = "io.kotest:kotest-runner-junit5-jvm", version.ref = "kotest" }
diff --git a/bindings/angle/gradle/wrapper/gradle-wrapper.jar b/bindings/angle/gradle/wrapper/gradle-wrapper.jar
index c1962a79..7f93135c 100644
Binary files a/bindings/angle/gradle/wrapper/gradle-wrapper.jar and b/bindings/angle/gradle/wrapper/gradle-wrapper.jar differ
diff --git a/bindings/angle/gradle/wrapper/gradle-wrapper.properties b/bindings/angle/gradle/wrapper/gradle-wrapper.properties
index c30b486a..a80b22ce 100644
--- a/bindings/angle/gradle/wrapper/gradle-wrapper.properties
+++ b/bindings/angle/gradle/wrapper/gradle-wrapper.properties
@@ -1,6 +1,7 @@
distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
-distributionUrl=https\://services.gradle.org/distributions/gradle-8.3-bin.zip
+distributionUrl=https\://services.gradle.org/distributions/gradle-8.6-bin.zip
networkTimeout=10000
+validateDistributionUrl=true
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists
diff --git a/bindings/angle/gradlew b/bindings/angle/gradlew
index aeb74cbb..0adc8e1a 100755
--- a/bindings/angle/gradlew
+++ b/bindings/angle/gradlew
@@ -83,7 +83,8 @@ done
# This is normally unused
# shellcheck disable=SC2034
APP_BASE_NAME=${0##*/}
-APP_HOME=$( cd "${APP_HOME:-./}" && pwd -P ) || exit
+# Discard cd standard output in case $CDPATH is set (https://github.com/gradle/gradle/issues/25036)
+APP_HOME=$( cd "${APP_HOME:-./}" > /dev/null && pwd -P ) || exit
# Use the maximum available, or set MAX_FD != -1 to use that value.
MAX_FD=maximum
@@ -130,10 +131,13 @@ location of your Java installation."
fi
else
JAVACMD=java
- which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
+ if ! command -v java >/dev/null 2>&1
+ then
+ die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
Please set the JAVA_HOME variable in your environment to match the
location of your Java installation."
+ fi
fi
# Increase the maximum file descriptors if we can.
diff --git a/bindings/angle/libangle/build.gradle.kts b/bindings/angle/libangle/build.gradle.kts
index 4fe64dee..78a5a796 100644
--- a/bindings/angle/libangle/build.gradle.kts
+++ b/bindings/angle/libangle/build.gradle.kts
@@ -1,6 +1,8 @@
+import io.ygdrasil.ParsingMethod
import org.gradle.api.tasks.testing.logging.TestExceptionFormat
import org.gradle.api.tasks.testing.logging.TestLogEvent
-import java.net.URL
+import java.net.URI
+import io.ygdrasil.noMacros
buildscript {
dependencies {
@@ -14,7 +16,7 @@ buildscript {
}
plugins {
- kotlin("jvm") version "1.9.10"
+ kotlin("jvm") version libs.versions.kotlin
alias(libs.plugins.klang)
}
@@ -49,12 +51,16 @@ sourceSets.main {
java.srcDirs(buildDir)
}
-val headerUrl = URL("https://github.com/klang-toolkit/ANGLE-binary/releases/download/2-beta/headers.zip")
+val headerUrl = URI("https://github.com/klang-toolkit/ANGLE-binary/releases/download/2-beta/headers.zip")
+ .toURL()
klang {
+
+ parsingMethod = ParsingMethod.Libclang
+
download(headerUrl)
.let(::unpack)
- .let { parse(fileToParse = "EGL/egl.h", at = it) { } }
+ .let { parse(fileToParse = "EGL/egl.h", at = it, noMacros) { } }
generateBinding("libangle", "EGL")
}
diff --git a/bindings/angle/libangle/src/main/kotlin/libangle/Constants.kt b/bindings/angle/libangle/src/main/kotlin/libangle/Constants.kt
deleted file mode 100644
index 99a3d169..00000000
--- a/bindings/angle/libangle/src/main/kotlin/libangle/Constants.kt
+++ /dev/null
@@ -1,111 +0,0 @@
-package libangle
-
-const val EGL_COLOR_COMPONENT_TYPE_EXT = 0x3339
-const val EGL_COLOR_COMPONENT_TYPE_FIXED_EXT = 0x333A
-const val EGL_COLOR_COMPONENT_TYPE_FLOAT_EXT = 0x333B
-
-const val EGL_CONTEXT_OPENGL_ROBUST_ACCESS_EXT = 0x30BF
-const val EGL_CONTEXT_OPENGL_RESET_NOTIFICATION_STRATEGY_EXT = 0x3138
-const val EGL_NO_RESET_NOTIFICATION_EXT = 0x31BE
-const val EGL_LOSE_CONTEXT_ON_RESET_EXT = 0x31BF
-
-const val EGL_ALPHA_FORMAT = 0x3088
-const val EGL_ALPHA_FORMAT_NONPRE = 0x308B
-const val EGL_ALPHA_FORMAT_PRE = 0x308C
-const val EGL_ALPHA_MASK_SIZE = 0x303E
-const val EGL_BUFFER_PRESERVED = 0x3094
-const val EGL_BUFFER_DESTROYED = 0x3095
-const val EGL_CLIENT_APIS = 0x308D
-const val EGL_COLORSPACE = 0x3087
-const val EGL_COLORSPACE_sRGB = 0x3089
-const val EGL_COLORSPACE_LINEAR = 0x308A
-const val EGL_COLOR_BUFFER_TYPE = 0x303F
-const val EGL_CONTEXT_CLIENT_TYPE = 0x3097
-const val EGL_DISPLAY_SCALING = 10000
-const val EGL_HORIZONTAL_RESOLUTION = 0x3090
-const val EGL_LUMINANCE_BUFFER = 0x308F
-const val EGL_LUMINANCE_SIZE = 0x303D
-const val EGL_OPENGL_ES_BIT = 0x0001
-const val EGL_OPENVG_BIT = 0x0002
-const val EGL_OPENGL_ES_API = 0x30A0
-const val EGL_OPENVG_API = 0x30A1
-const val EGL_OPENVG_IMAGE = 0x3096
-const val EGL_PIXEL_ASPECT_RATIO = 0x3092
-const val EGL_RENDERABLE_TYPE = 0x3040
-const val EGL_RENDER_BUFFER = 0x3086
-const val EGL_RGB_BUFFER = 0x308E
-const val EGL_SINGLE_BUFFER = 0x3085
-const val EGL_SWAP_BEHAVIOR = 0x3093
-const val EGL_UNKNOWN = -1
-const val EGL_VERTICAL_RESOLUTION = 0x3091
-
-const val EGL_PLATFORM_ANGLE_ANGLE = 0x3202
-const val EGL_PLATFORM_ANGLE_TYPE_ANGLE = 0x3203
-const val EGL_PLATFORM_ANGLE_MAX_VERSION_MAJOR_ANGLE = 0x3204
-const val EGL_PLATFORM_ANGLE_MAX_VERSION_MINOR_ANGLE = 0x3205
-const val EGL_PLATFORM_ANGLE_TYPE_DEFAULT_ANGLE = 0x3206
-const val EGL_PLATFORM_ANGLE_DEBUG_LAYERS_ENABLED_ANGLE = 0x3451
-const val EGL_PLATFORM_ANGLE_DEVICE_TYPE_ANGLE = 0x3209
-const val EGL_PLATFORM_ANGLE_DEVICE_TYPE_HARDWARE_ANGLE = 0x320A
-const val EGL_PLATFORM_ANGLE_DEVICE_TYPE_NULL_ANGLE = 0x345E
-const val EGL_PLATFORM_ANGLE_NATIVE_PLATFORM_TYPE_ANGLE = 0x348F
-
-const val EGL_ALPHA_SIZE = 0x3021
-const val EGL_BAD_ACCESS = 0x3002
-const val EGL_BAD_ALLOC = 0x3003
-const val EGL_BAD_ATTRIBUTE = 0x3004
-const val EGL_BAD_CONFIG = 0x3005
-const val EGL_BAD_CONTEXT = 0x3006
-const val EGL_BAD_CURRENT_SURFACE = 0x3007
-const val EGL_BAD_DISPLAY = 0x3008
-const val EGL_BAD_MATCH = 0x3009
-const val EGL_BAD_NATIVE_PIXMAP = 0x300A
-const val EGL_BAD_NATIVE_WINDOW = 0x300B
-const val EGL_BAD_PARAMETER = 0x300C
-const val EGL_BAD_SURFACE = 0x300D
-const val EGL_BLUE_SIZE = 0x3022
-const val EGL_BUFFER_SIZE = 0x3020
-const val EGL_CONFIG_CAVEAT = 0x3027
-const val EGL_CONFIG_ID = 0x3028
-const val EGL_CORE_NATIVE_ENGINE = 0x305B
-const val EGL_DEPTH_SIZE = 0x3025
-const val EGL_DONT_CARE = -1
-const val EGL_DRAW = 0x3059
-const val EGL_EXTENSIONS = 0x3055
-const val EGL_FALSE = 0
-const val EGL_GREEN_SIZE = 0x3023
-const val EGL_HEIGHT = 0x3056
-const val EGL_LARGEST_PBUFFER = 0x3058
-const val EGL_LEVEL = 0x3029
-const val EGL_MAX_PBUFFER_HEIGHT = 0x302A
-const val EGL_MAX_PBUFFER_PIXELS = 0x302B
-const val EGL_MAX_PBUFFER_WIDTH = 0x302C
-const val EGL_NATIVE_RENDERABLE = 0x302D
-const val EGL_NATIVE_VISUAL_ID = 0x302E
-const val EGL_NATIVE_VISUAL_TYPE = 0x302F
-const val EGL_NONE = 0x3038
-const val EGL_NON_CONFORMANT_CONFIG = 0x3051
-const val EGL_NOT_INITIALIZED = 0x3001
-const val EGL_NO_CONTEXT: EGLContext? = null
-const val EGL_NO_DISPLAY: EGLDisplay? = null
-const val EGL_NO_SURFACE: EGLSurface? = null
-const val EGL_PBUFFER_BIT = 0x0001
-const val EGL_PIXMAP_BIT = 0x0002
-const val EGL_READ = 0x305A
-const val EGL_RED_SIZE = 0x3024
-const val EGL_SAMPLES = 0x3031
-const val EGL_SAMPLE_BUFFERS = 0x3032
-const val EGL_SLOW_CONFIG = 0x3050
-const val EGL_STENCIL_SIZE = 0x3026
-const val EGL_SUCCESS = 0x3000
-const val EGL_SURFACE_TYPE = 0x3033
-const val EGL_TRANSPARENT_BLUE_VALUE = 0x3035
-const val EGL_TRANSPARENT_GREEN_VALUE = 0x3036
-const val EGL_TRANSPARENT_RED_VALUE = 0x3037
-const val EGL_TRANSPARENT_RGB = 0x3052
-const val EGL_TRANSPARENT_TYPE = 0x3034
-const val EGL_TRUE = 1
-const val EGL_VENDOR = 0x3053
-const val EGL_VERSION = 0x3054
-const val EGL_WIDTH = 0x3057
-const val EGL_WINDOW_BIT = 0x0004
diff --git a/bindings/angle/libangle/src/main/kotlin/libangle/FixTypeAlias.kt b/bindings/angle/libangle/src/main/kotlin/libangle/FixTypeAlias.kt
deleted file mode 100644
index 6465de2f..00000000
--- a/bindings/angle/libangle/src/main/kotlin/libangle/FixTypeAlias.kt
+++ /dev/null
@@ -1,4 +0,0 @@
-package libangle
-
-
-typealias GLuint = Int
\ No newline at end of file
diff --git a/bindings/angle/libangle/src/main/kotlin/libangle/Library.kt b/bindings/angle/libangle/src/main/kotlin/libangle/Library.kt
deleted file mode 100644
index 84884ce3..00000000
--- a/bindings/angle/libangle/src/main/kotlin/libangle/Library.kt
+++ /dev/null
@@ -1,4 +0,0 @@
-package libangle
-
-class Library {
-}
\ No newline at end of file
diff --git a/bindings/angle/libangle/src/main/kotlin/libangle/UnionDelegate.kt b/bindings/angle/libangle/src/main/kotlin/libangle/UnionDelegate.kt
deleted file mode 100644
index 5f1d44fa..00000000
--- a/bindings/angle/libangle/src/main/kotlin/libangle/UnionDelegate.kt
+++ /dev/null
@@ -1 +0,0 @@
-package libangle
diff --git a/bindings/angle/libangle/src/main/kotlin/main.kt b/bindings/angle/libangle/src/main/kotlin/main.kt
deleted file mode 100644
index e82bfd5c..00000000
--- a/bindings/angle/libangle/src/main/kotlin/main.kt
+++ /dev/null
@@ -1,49 +0,0 @@
-import com.sun.jna.Native
-import com.sun.jna.ptr.IntByReference
-import libangle.EGLDisplay
-import libangle.EGLSurface
-import libangle.libEGLLibrary
-import java.awt.Component
-import java.lang.reflect.Field
-import javax.swing.JFrame
-
-
-fun main() {
- val frame = JFrame("test").apply {
- setSize(800, 600)
- pack()
- isVisible = true
- }
- val windowId = Native.getComponentID(frame)
- println("windowId: $windowId")
- val field: Field = Component::class.java.getDeclaredField("peer")
- field.setAccessible(true)
- val peer = field.get(frame)
- println("peer: $peer")
- //frame.peer
- //val context = Context(frame)
-
-}
-
-
-class Window : JFrame("test") {
-
-}
-
-
-class Context(val mDisplay: EGLDisplay) {
-
- lateinit var mSurface: EGLSurface
-
- init {
- val majorVersion = IntByReference()
- majorVersion.value = 3
- val minorVersion = IntByReference()
- majorVersion.value = 2
- libEGLLibrary.eglInitialize(mDisplay, majorVersion.pointer, minorVersion.pointer)
- }
-
- fun swap() {
- libEGLLibrary.eglSwapBuffers(mDisplay, mSurface)
- }
-}
\ No newline at end of file
diff --git a/bindings/angle/libgles/build.gradle.kts b/bindings/angle/libgles/build.gradle.kts
index 38d25e1e..5f86ff0c 100644
--- a/bindings/angle/libgles/build.gradle.kts
+++ b/bindings/angle/libgles/build.gradle.kts
@@ -1,8 +1,10 @@
+import io.ygdrasil.ParsingMethod
import klang.domain.typeOf
import klang.domain.unchecked
import org.gradle.api.tasks.testing.logging.TestExceptionFormat
import org.gradle.api.tasks.testing.logging.TestLogEvent
-import java.net.URL
+import java.net.URI
+import io.ygdrasil.noMacros
buildscript {
dependencies {
@@ -16,7 +18,7 @@ buildscript {
}
plugins {
- kotlin("jvm") version "1.9.10"
+ kotlin("jvm") version libs.versions.kotlin
alias(libs.plugins.klang)
}
@@ -50,15 +52,19 @@ sourceSets.main {
java.srcDirs(buildDir)
}
-val headerUrl = URL("https://github.com/klang-toolkit/ANGLE-binary/releases/download/2-beta/headers.zip")
+val headerUrl = URI("https://github.com/klang-toolkit/ANGLE-binary/releases/download/2-beta/headers.zip")
+ .toURL()
klang {
+
+ parsingMethod = ParsingMethod.Libclang
+
download(headerUrl)
.let(::unpack)
.let {
- parse(fileToParse = "GLES3/gl3.h", at = it) {
+ parse(fileToParse = "GLES3/gl3.h", at = it, noMacros) {
findFunctionByName("glShaderSource")?.let { function ->
- function.arguments.first { it.name == "string" }.apply {
+ function.arguments.first { it.name?.value == "string" }.apply {
type = typeOf("char *").unchecked()
}
}
diff --git a/bindings/angle/libgles/src/main/kotlin/libgles/Constants.kt b/bindings/angle/libgles/src/main/kotlin/libgles/Constants.kt
deleted file mode 100644
index 256220b8..00000000
--- a/bindings/angle/libgles/src/main/kotlin/libgles/Constants.kt
+++ /dev/null
@@ -1,382 +0,0 @@
-package libgles
-
-
-const val GL_DEPTH_BUFFER_BIT = 0x00000100
-const val GL_STENCIL_BUFFER_BIT = 0x00000400
-const val GL_COLOR_BUFFER_BIT = 0x00004000
-const val GL_FALSE = 0
-const val GL_TRUE = 1
-const val GL_POINTS = 0x0000
-const val GL_LINES = 0x0001
-const val GL_LINE_LOOP = 0x0002
-const val GL_LINE_STRIP = 0x0003
-const val GL_TRIANGLES = 0x0004
-const val GL_TRIANGLE_STRIP = 0x0005
-const val GL_TRIANGLE_FAN = 0x0006
-const val GL_ZERO = 0
-const val GL_ONE = 1
-const val GL_SRC_COLOR = 0x0300
-const val GL_ONE_MINUS_SRC_COLOR = 0x0301
-const val GL_SRC_ALPHA = 0x0302
-const val GL_ONE_MINUS_SRC_ALPHA = 0x0303
-const val GL_DST_ALPHA = 0x0304
-const val GL_ONE_MINUS_DST_ALPHA = 0x0305
-const val GL_DST_COLOR = 0x0306
-const val GL_ONE_MINUS_DST_COLOR = 0x0307
-const val GL_SRC_ALPHA_SATURATE = 0x0308
-const val GL_FUNC_ADD = 0x8006
-const val GL_BLEND_EQUATION = 0x8009
-const val GL_BLEND_EQUATION_RGB = 0x8009
-const val GL_BLEND_EQUATION_ALPHA = 0x883D
-const val GL_FUNC_SUBTRACT = 0x800A
-const val GL_FUNC_REVERSE_SUBTRACT = 0x800B
-const val GL_BLEND_DST_RGB = 0x80C8
-const val GL_BLEND_SRC_RGB = 0x80C9
-const val GL_BLEND_DST_ALPHA = 0x80CA
-const val GL_BLEND_SRC_ALPHA = 0x80CB
-const val GL_CONSTANT_COLOR = 0x8001
-const val GL_ONE_MINUS_CONSTANT_COLOR = 0x8002
-const val GL_CONSTANT_ALPHA = 0x8003
-const val GL_ONE_MINUS_CONSTANT_ALPHA = 0x8004
-const val GL_BLEND_COLOR = 0x8005
-const val GL_ARRAY_BUFFER = 0x8892
-const val GL_ELEMENT_ARRAY_BUFFER = 0x8893
-const val GL_ARRAY_BUFFER_BINDING = 0x8894
-const val GL_ELEMENT_ARRAY_BUFFER_BINDING = 0x8895
-const val GL_STREAM_DRAW = 0x88E0
-const val GL_STATIC_DRAW = 0x88E4
-const val GL_DYNAMIC_DRAW = 0x88E8
-const val GL_BUFFER_SIZE = 0x8764
-const val GL_BUFFER_USAGE = 0x8765
-const val GL_CURRENT_VERTEX_ATTRIB = 0x8626
-const val GL_FRONT = 0x0404
-const val GL_BACK = 0x0405
-const val GL_FRONT_AND_BACK = 0x0408
-const val GL_TEXTURE_2D = 0x0DE1
-const val GL_CULL_FACE = 0x0B44
-const val GL_BLEND = 0x0BE2
-const val GL_DITHER = 0x0BD0
-const val GL_STENCIL_TEST = 0x0B90
-const val GL_DEPTH_TEST = 0x0B71
-const val GL_SCISSOR_TEST = 0x0C11
-const val GL_POLYGON_OFFSET_FILL = 0x8037
-const val GL_SAMPLE_ALPHA_TO_COVERAGE = 0x809E
-const val GL_SAMPLE_COVERAGE = 0x80A0
-const val GL_NO_ERROR = 0
-const val GL_INVALID_ENUM = 0x0500
-const val GL_INVALID_VALUE = 0x0501
-const val GL_INVALID_OPERATION = 0x0502
-const val GL_OUT_OF_MEMORY = 0x0505
-const val GL_CW = 0x0900
-const val GL_CCW = 0x0901
-const val GL_LINE_WIDTH = 0x0B21
-const val GL_ALIASED_POINT_SIZE_RANGE = 0x846D
-const val GL_ALIASED_LINE_WIDTH_RANGE = 0x846E
-const val GL_CULL_FACE_MODE = 0x0B45
-const val GL_FRONT_FACE = 0x0B46
-const val GL_DEPTH_RANGE = 0x0B70
-const val GL_DEPTH_WRITEMASK = 0x0B72
-const val GL_DEPTH_CLEAR_VALUE = 0x0B73
-const val GL_DEPTH_FUNC = 0x0B74
-const val GL_STENCIL_CLEAR_VALUE = 0x0B91
-const val GL_STENCIL_FUNC = 0x0B92
-const val GL_STENCIL_FAIL = 0x0B94
-const val GL_STENCIL_PASS_DEPTH_FAIL = 0x0B95
-const val GL_STENCIL_PASS_DEPTH_PASS = 0x0B96
-const val GL_STENCIL_REF = 0x0B97
-const val GL_STENCIL_VALUE_MASK = 0x0B93
-const val GL_STENCIL_WRITEMASK = 0x0B98
-const val GL_STENCIL_BACK_FUNC = 0x8800
-const val GL_STENCIL_BACK_FAIL = 0x8801
-const val GL_STENCIL_BACK_PASS_DEPTH_FAIL = 0x8802
-const val GL_STENCIL_BACK_PASS_DEPTH_PASS = 0x8803
-const val GL_STENCIL_BACK_REF = 0x8CA3
-const val GL_STENCIL_BACK_VALUE_MASK = 0x8CA4
-const val GL_STENCIL_BACK_WRITEMASK = 0x8CA5
-const val GL_VIEWPORT = 0x0BA2
-const val GL_SCISSOR_BOX = 0x0C10
-const val GL_COLOR_CLEAR_VALUE = 0x0C22
-const val GL_COLOR_WRITEMASK = 0x0C23
-const val GL_UNPACK_ALIGNMENT = 0x0CF5
-const val GL_PACK_ALIGNMENT = 0x0D05
-const val GL_MAX_TEXTURE_SIZE = 0x0D33
-const val GL_MAX_VIEWPORT_DIMS = 0x0D3A
-const val GL_SUBPIXEL_BITS = 0x0D50
-const val GL_RED_BITS = 0x0D52
-const val GL_GREEN_BITS = 0x0D53
-const val GL_BLUE_BITS = 0x0D54
-const val GL_ALPHA_BITS = 0x0D55
-const val GL_DEPTH_BITS = 0x0D56
-const val GL_STENCIL_BITS = 0x0D57
-const val GL_POLYGON_OFFSET_UNITS = 0x2A00
-const val GL_POLYGON_OFFSET_FACTOR = 0x8038
-const val GL_TEXTURE_BINDING_2D = 0x8069
-const val GL_SAMPLE_BUFFERS = 0x80A8
-const val GL_SAMPLES = 0x80A9
-const val GL_SAMPLE_COVERAGE_VALUE = 0x80AA
-const val GL_SAMPLE_COVERAGE_INVERT = 0x80
-const val GL_NUM_COMPRESSED_TEXTURE_FORMATS = 0x86A2
-const val GL_COMPRESSED_TEXTURE_FORMATS = 0x86A3
-const val GL_DONT_CARE = 0x1100
-const val GL_FASTEST = 0x1101
-const val GL_NICEST = 0x1102
-const val GL_GENERATE_MIPMAP_HINT = 0x8192
-const val GL_BYTE = 0x1400
-const val GL_UNSIGNED_BYTE = 0x1401
-const val GL_SHORT = 0x1402
-const val GL_UNSIGNED_SHORT = 0x1403
-const val GL_INT = 0x1404
-const val GL_UNSIGNED_INT = 0x1405
-const val GL_FLOAT = 0x1406
-const val GL_FIXED = 0x140C
-const val GL_DEPTH_COMPONENT = 0x1902
-const val GL_ALPHA = 0x1906
-const val GL_RGB = 0x1907
-const val GL_RGBA = 0x1908
-const val GL_LUMINANCE = 0x1909
-const val GL_LUMINANCE_ALPHA = 0x190A
-const val GL_UNSIGNED_SHORT_4_4_4_4 = 0x8033
-const val GL_UNSIGNED_SHORT_5_5_5_1 = 0x8034
-const val GL_UNSIGNED_SHORT_5_6_5 = 0x8363
-const val GL_FRAGMENT_SHADER = 0x8B30
-const val GL_VERTEX_SHADER = 0x8B31
-const val GL_MAX_VERTEX_ATTRIBS = 0x8869
-const val GL_MAX_VERTEX_UNIFORM_VECTORS = 0x8DFB
-const val GL_MAX_VARYING_VECTORS = 0x8DFC
-const val GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS = 0x8B4D
-const val GL_MAX_VERTEX_TEXTURE_IMAGE_UNITS = 0x8B4C
-const val GL_MAX_TEXTURE_IMAGE_UNITS = 0x8872
-const val GL_MAX_FRAGMENT_UNIFORM_VECTORS = 0x8DFD
-const val GL_SHADER_TYPE = 0x8B4F
-const val GL_DELETE_STATUS = 0x8B80
-const val GL_LINK_STATUS = 0x8B82
-const val GL_VALIDATE_STATUS = 0x8B83
-const val GL_ATTACHED_SHADERS = 0x8B85
-const val GL_ACTIVE_UNIFORMS = 0x8B86
-const val GL_ACTIVE_UNIFORM_MAX_LENGTH = 0x8B87
-const val GL_ACTIVE_ATTRIBUTES = 0x8B89
-const val GL_ACTIVE_ATTRIBUTE_MAX_LENGTH = 0x8B8A
-const val GL_SHADING_LANGUAGE_VERSION = 0x8B8C
-const val GL_CURRENT_PROGRAM = 0x8B8D
-const val GL_NEVER = 0x0200
-const val GL_LESS = 0x0201
-const val GL_EQUAL = 0x0202
-const val GL_LEQUAL = 0x0203
-const val GL_GREATER = 0x0204
-const val GL_NOTEQUAL = 0x0205
-const val GL_GEQUAL = 0x0206
-const val GL_ALWAYS = 0x0207
-const val GL_KEEP = 0x1E00
-const val GL_REPLACE = 0x1E01
-const val GL_INCR = 0x1E02
-const val GL_DECR = 0x1E03
-const val GL_INVERT = 0x150A
-const val GL_INCR_WRAP = 0x8507
-const val GL_DECR_WRAP = 0x8508
-const val GL_VENDOR = 0x1F00
-const val GL_RENDERER = 0x1F01
-const val GL_VERSION = 0x1F02
-const val GL_EXTENSIONS = 0x1F03
-const val GL_NEAREST = 0x2600
-const val GL_LINEAR = 0x2601
-const val GL_NEAREST_MIPMAP_NEAREST = 0x2700
-const val GL_LINEAR_MIPMAP_NEAREST = 0x2701
-const val GL_NEAREST_MIPMAP_LINEAR = 0x2702
-const val GL_LINEAR_MIPMAP_LINEAR = 0x2703
-const val GL_TEXTURE_MAG_FILTER = 0x2800
-const val GL_TEXTURE_MIN_FILTER = 0x2801
-const val GL_TEXTURE_WRAP_S = 0x2802
-const val GL_TEXTURE_WRAP_T = 0x2803
-const val GL_TEXTURE = 0x1702
-const val GL_TEXTURE_CUBE_MAP = 0x8513
-const val GL_TEXTURE_BINDING_CUBE_MAP = 0x8514
-const val GL_TEXTURE_CUBE_MAP_POSITIVE_X = 0x8515
-const val GL_TEXTURE_CUBE_MAP_NEGATIVE_X = 0x8516
-const val GL_TEXTURE_CUBE_MAP_POSITIVE_Y = 0x8517
-const val GL_TEXTURE_CUBE_MAP_NEGATIVE_Y = 0x8518
-const val GL_TEXTURE_CUBE_MAP_POSITIVE_Z = 0x8519
-const val GL_TEXTURE_CUBE_MAP_NEGATIVE_Z = 0x851A
-const val GL_MAX_CUBE_MAP_TEXTURE_SIZE = 0x851C
-const val GL_TEXTURE0 = 0x84C0
-const val GL_TEXTURE1 = 0x84C1
-const val GL_TEXTURE2 = 0x84C2
-const val GL_TEXTURE3 = 0x84C3
-const val GL_TEXTURE4 = 0x84C4
-const val GL_TEXTURE5 = 0x84C5
-const val GL_TEXTURE6 = 0x84C6
-const val GL_TEXTURE7 = 0x84C7
-const val GL_TEXTURE8 = 0x84C8
-const val GL_TEXTURE9 = 0x84C9
-const val GL_TEXTURE10 = 0x84CA
-const val GL_TEXTURE11 = 0x84CB
-const val GL_TEXTURE12 = 0x84CC
-const val GL_TEXTURE13 = 0x84CD
-const val GL_TEXTURE14 = 0x84CE
-const val GL_TEXTURE15 = 0x84CF
-const val GL_TEXTURE16 = 0x84D0
-const val GL_TEXTURE17 = 0x84D1
-const val GL_TEXTURE18 = 0x84D2
-const val GL_TEXTURE19 = 0x84D3
-const val GL_TEXTURE20 = 0x84D4
-const val GL_TEXTURE21 = 0x84D5
-const val GL_TEXTURE22 = 0x84D6
-const val GL_TEXTURE23 = 0x84D7
-const val GL_TEXTURE24 = 0x84D8
-const val GL_TEXTURE25 = 0x84D9
-const val GL_TEXTURE26 = 0x84DA
-const val GL_TEXTURE27 = 0x84DB
-const val GL_TEXTURE28 = 0x84DC
-const val GL_TEXTURE29 = 0x84DD
-const val GL_TEXTURE30 = 0x84DE
-const val GL_TEXTURE31 = 0x84DF
-const val GL_ACTIVE_TEXTURE = 0x84E0
-const val GL_REPEAT = 0x2901
-const val GL_CLAMP_TO_EDGE = 0x812F
-const val GL_MIRRORED_REPEAT = 0x8370
-const val GL_FLOAT_VEC2 = 0x8B50
-const val GL_FLOAT_VEC3 = 0x8B51
-const val GL_FLOAT_VEC4 = 0x8B52
-const val GL_INT_VEC2 = 0x8B53
-const val GL_INT_VEC3 = 0x8B54
-const val GL_INT_VEC4 = 0x8B55
-const val GL_BOOL = 0x8B56
-const val GL_BOOL_VEC2 = 0x8B57
-const val GL_BOOL_VEC3 = 0x8B58
-const val GL_BOOL_VEC4 = 0x8B59
-const val GL_FLOAT_MAT2 = 0x8B5A
-const val GL_FLOAT_MAT3 = 0x8B5B
-const val GL_FLOAT_MAT4 = 0x8B5C
-const val GL_SAMPLER_2D = 0x8B5E
-const val GL_SAMPLER_CUBE = 0x8B60
-const val GL_VERTEX_ATTRIB_ARRAY_ENABLED = 0x8622
-const val GL_VERTEX_ATTRIB_ARRAY_SIZE = 0x8623
-const val GL_VERTEX_ATTRIB_ARRAY_STRIDE = 0x8624
-const val GL_VERTEX_ATTRIB_ARRAY_TYPE = 0x8625
-const val GL_VERTEX_ATTRIB_ARRAY_NORMALIZED = 0x886A
-const val GL_VERTEX_ATTRIB_ARRAY_POINTER = 0x8645
-const val GL_VERTEX_ATTRIB_ARRAY_BUFFER_BINDING = 0x889F
-const val GL_IMPLEMENTATION_COLOR_READ_TYPE = 0x8B9A
-const val GL_IMPLEMENTATION_COLOR_READ_FORMAT = 0x8B9B
-const val GL_COMPILE_STATUS = 0x8B81
-const val GL_INFO_LOG_LENGTH = 0x8B84
-const val GL_SHADER_SOURCE_LENGTH = 0x8B88
-const val GL_SHADER_COMPILER = 0x8DFA
-const val GL_SHADER_BINARY_FORMATS = 0x8DF8
-const val GL_NUM_SHADER_BINARY_FORMATS = 0x8DF9
-const val GL_LOW_FLOAT = 0x8DF0
-const val GL_MEDIUM_FLOAT = 0x8DF1
-const val GL_HIGH_FLOAT = 0x8DF2
-const val GL_LOW_INT = 0x8DF3
-const val GL_MEDIUM_INT = 0x8DF4
-const val GL_HIGH_INT = 0x8DF5
-const val GL_FRAMEBUFFER = 0x8D40
-const val GL_RENDERBUFFER = 0x8D41
-const val GL_RGBA4 = 0x8056
-const val GL_RGB5_A1 = 0x8057
-const val GL_RGB565 = 0x8D62
-const val GL_DEPTH_COMPONENT16 = 0x81A5
-const val GL_STENCIL_INDEX8 = 0x8D48
-const val GL_RENDERBUFFER_WIDTH = 0x8D42
-const val GL_RENDERBUFFER_HEIGHT = 0x8D43
-const val GL_RENDERBUFFER_INTERNAL_FORMAT = 0x8D44
-const val GL_RENDERBUFFER_RED_SIZE = 0x8D50
-const val GL_RENDERBUFFER_GREEN_SIZE = 0x8D51
-const val GL_RENDERBUFFER_BLUE_SIZE = 0x8D52
-const val GL_RENDERBUFFER_ALPHA_SIZE = 0x8D53
-const val GL_RENDERBUFFER_DEPTH_SIZE = 0x8D54
-const val GL_RENDERBUFFER_STENCIL_SIZE = 0x8D55
-const val GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE = 0x8CD0
-const val GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME = 0x8CD1
-const val GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LEVEL = 0x8CD2
-const val GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_CUBE_MAP_FACE = 0x8CD3
-const val GL_COLOR_ATTACHMENT0 = 0x8CE0
-const val GL_DEPTH_ATTACHMENT = 0x8D00
-const val GL_STENCIL_ATTACHMENT = 0x8D20
-const val GL_NONE = 0
-const val GL_FRAMEBUFFER_COMPLETE = 0x8CD5
-const val GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT = 0x8CD6
-const val GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT = 0x8CD7
-const val GL_FRAMEBUFFER_INCOMPLETE_DIMENSIONS = 0x8CD9
-const val GL_FRAMEBUFFER_UNSUPPORTED = 0x8CDD
-const val GL_FRAMEBUFFER_BINDING = 0x8CA6
-const val GL_RENDERBUFFER_BINDING = 0x8CA7
-const val GL_MAX_RENDERBUFFER_SIZE = 0x84E8
-const val GL_INVALID_FRAMEBUFFER_OPERATION = 0x0506
-
-const val GL_GEOMETRY_SHADER_EXT = 0x8DD9
-const val GL_GEOMETRY_SHADER_BIT_EXT = 0x00000004
-const val GL_GEOMETRY_LINKED_VERTICES_OUT_EXT = 0x8916
-const val GL_GEOMETRY_LINKED_INPUT_TYPE_EXT = 0x8917
-const val GL_GEOMETRY_LINKED_OUTPUT_TYPE_EXT = 0x8918
-const val GL_GEOMETRY_SHADER_INVOCATIONS_EXT = 0x887F
-const val GL_LAYER_PROVOKING_VERTEX_EXT = 0x825E
-const val GL_LINES_ADJACENCY_EXT = 0x000A
-const val GL_LINE_STRIP_ADJACENCY_EXT = 0x000B
-const val GL_TRIANGLES_ADJACENCY_EXT = 0x000C
-const val GL_TRIANGLE_STRIP_ADJACENCY_EXT = 0x000D
-const val GL_MAX_GEOMETRY_UNIFORM_COMPONENTS_EXT = 0x8DDF
-const val GL_MAX_GEOMETRY_UNIFORM_BLOCKS_EXT = 0x8A2C
-const val GL_MAX_COMBINED_GEOMETRY_UNIFORM_COMPONENTS_EXT = 0x8A32
-const val GL_MAX_GEOMETRY_INPUT_COMPONENTS_EXT = 0x9123
-const val GL_MAX_GEOMETRY_OUTPUT_COMPONENTS_EXT = 0x9124
-const val GL_MAX_GEOMETRY_OUTPUT_VERTICES_EXT = 0x8DE0
-const val GL_MAX_GEOMETRY_TOTAL_OUTPUT_COMPONENTS_EXT = 0x8DE1
-const val GL_MAX_GEOMETRY_SHADER_INVOCATIONS_EXT = 0x8E5A
-const val GL_MAX_GEOMETRY_TEXTURE_IMAGE_UNITS_EXT = 0x8C29
-const val GL_MAX_GEOMETRY_ATOMIC_COUNTER_BUFFERS_EXT = 0x92CF
-const val GL_MAX_GEOMETRY_ATOMIC_COUNTERS_EXT = 0x92D5
-const val GL_MAX_GEOMETRY_IMAGE_UNIFORMS_EXT = 0x90CD
-const val GL_MAX_GEOMETRY_SHADER_STORAGE_BLOCKS_EXT = 0x90D7
-const val GL_FIRST_VERTEX_CONVENTION_EXT = 0x8E4D
-const val GL_LAST_VERTEX_CONVENTION_EXT = 0x8E4E
-const val GL_UNDEFINED_VERTEX_EXT = 0x8260
-const val GL_PRIMITIVES_GENERATED_EXT = 0x8C87
-const val GL_FRAMEBUFFER_DEFAULT_LAYERS_EXT = 0x9312
-const val GL_MAX_FRAMEBUFFER_LAYERS_EXT = 0x9317
-const val GL_FRAMEBUFFER_INCOMPLETE_LAYER_TARGETS_EXT = 0x8DA8
-const val GL_FRAMEBUFFER_ATTACHMENT_LAYERED_EXT = 0x8DA7
-const val GL_REFERENCED_BY_GEOMETRY_SHADER_EXT = 0x9309
-
-const val GL_PATCHES_EXT = 0x000E
-const val GL_PATCH_VERTICES_EXT = 0x8E72
-const val GL_TESS_CONTROL_OUTPUT_VERTICES_EXT = 0x8E75
-const val GL_TESS_GEN_MODE_EXT = 0x8E76
-const val GL_TESS_GEN_SPACING_EXT = 0x8E77
-const val GL_TESS_GEN_VERTEX_ORDER_EXT = 0x8E78
-const val GL_TESS_GEN_POINT_MODE_EXT = 0x8E79
-const val GL_ISOLINES_EXT = 0x8E7A
-const val GL_QUADS_EXT = 0x0007
-const val GL_FRACTIONAL_ODD_EXT = 0x8E7B
-const val GL_FRACTIONAL_EVEN_EXT = 0x8E7C
-const val GL_MAX_PATCH_VERTICES_EXT = 0x8E7D
-const val GL_MAX_TESS_GEN_LEVEL_EXT = 0x8E7E
-const val GL_MAX_TESS_CONTROL_UNIFORM_COMPONENTS_EXT = 0x8E7F
-const val GL_MAX_TESS_EVALUATION_UNIFORM_COMPONENTS_EXT = 0x8E80
-const val GL_MAX_TESS_CONTROL_TEXTURE_IMAGE_UNITS_EXT = 0x8E81
-const val GL_MAX_TESS_EVALUATION_TEXTURE_IMAGE_UNITS_EXT = 0x8E82
-const val GL_MAX_TESS_CONTROL_OUTPUT_COMPONENTS_EXT = 0x8E83
-const val GL_MAX_TESS_PATCH_COMPONENTS_EXT = 0x8E84
-const val GL_MAX_TESS_CONTROL_TOTAL_OUTPUT_COMPONENTS_EXT = 0x8E85
-const val GL_MAX_TESS_EVALUATION_OUTPUT_COMPONENTS_EXT = 0x8E86
-const val GL_MAX_TESS_CONTROL_UNIFORM_BLOCKS_EXT = 0x8E89
-const val GL_MAX_TESS_EVALUATION_UNIFORM_BLOCKS_EXT = 0x8E8A
-const val GL_MAX_TESS_CONTROL_INPUT_COMPONENTS_EXT = 0x886C
-const val GL_MAX_TESS_EVALUATION_INPUT_COMPONENTS_EXT = 0x886D
-const val GL_MAX_COMBINED_TESS_CONTROL_UNIFORM_COMPONENTS_EXT = 0x8E1E
-const val GL_MAX_COMBINED_TESS_EVALUATION_UNIFORM_COMPONENTS_EXT = 0x8E1F
-const val GL_MAX_TESS_CONTROL_ATOMIC_COUNTER_BUFFERS_EXT = 0x92CD
-const val GL_MAX_TESS_EVALUATION_ATOMIC_COUNTER_BUFFERS_EXT = 0x92CE
-const val GL_MAX_TESS_CONTROL_ATOMIC_COUNTERS_EXT = 0x92D3
-const val GL_MAX_TESS_EVALUATION_ATOMIC_COUNTERS_EXT = 0x92D4
-const val GL_MAX_TESS_CONTROL_IMAGE_UNIFORMS_EXT = 0x90CB
-const val GL_MAX_TESS_EVALUATION_IMAGE_UNIFORMS_EXT = 0x90CC
-const val GL_MAX_TESS_CONTROL_SHADER_STORAGE_BLOCKS_EXT = 0x90D8
-const val GL_MAX_TESS_EVALUATION_SHADER_STORAGE_BLOCKS_EXT = 0x90D9
-const val GL_PRIMITIVE_RESTART_FOR_PATCHES_SUPPORTED = 0x8221
-const val GL_IS_PER_PATCH_EXT = 0x92E7
-const val GL_REFERENCED_BY_TESS_CONTROL_SHADER_EXT = 0x9307
-const val GL_REFERENCED_BY_TESS_EVALUATION_SHADER_EXT = 0x9308
-const val GL_TESS_CONTROL_SHADER_EXT = 0x8E88
-const val GL_TESS_EVALUATION_SHADER_EXT = 0x8E87
-const val GL_TESS_CONTROL_SHADER_BIT_EXT = 0x00000008
-const val GL_TESS_EVALUATION_SHADER_BIT_EXT = 0x00000010
\ No newline at end of file
diff --git a/bindings/angle/libgles/src/main/kotlin/libgles/FixTypeAlias.kt b/bindings/angle/libgles/src/main/kotlin/libgles/FixTypeAlias.kt
deleted file mode 100644
index fecfe574..00000000
--- a/bindings/angle/libgles/src/main/kotlin/libgles/FixTypeAlias.kt
+++ /dev/null
@@ -1,2 +0,0 @@
-package libges
-
diff --git a/bindings/angle/libgles/src/main/kotlin/libgles/UnionDelegate.kt b/bindings/angle/libgles/src/main/kotlin/libgles/UnionDelegate.kt
deleted file mode 100644
index fa8630c9..00000000
--- a/bindings/angle/libgles/src/main/kotlin/libgles/UnionDelegate.kt
+++ /dev/null
@@ -1 +0,0 @@
-package libgles
diff --git a/bindings/angle/libgles/src/main/kotlin/main.kt b/bindings/angle/libgles/src/main/kotlin/main.kt
deleted file mode 100644
index e82bfd5c..00000000
--- a/bindings/angle/libgles/src/main/kotlin/main.kt
+++ /dev/null
@@ -1,49 +0,0 @@
-import com.sun.jna.Native
-import com.sun.jna.ptr.IntByReference
-import libangle.EGLDisplay
-import libangle.EGLSurface
-import libangle.libEGLLibrary
-import java.awt.Component
-import java.lang.reflect.Field
-import javax.swing.JFrame
-
-
-fun main() {
- val frame = JFrame("test").apply {
- setSize(800, 600)
- pack()
- isVisible = true
- }
- val windowId = Native.getComponentID(frame)
- println("windowId: $windowId")
- val field: Field = Component::class.java.getDeclaredField("peer")
- field.setAccessible(true)
- val peer = field.get(frame)
- println("peer: $peer")
- //frame.peer
- //val context = Context(frame)
-
-}
-
-
-class Window : JFrame("test") {
-
-}
-
-
-class Context(val mDisplay: EGLDisplay) {
-
- lateinit var mSurface: EGLSurface
-
- init {
- val majorVersion = IntByReference()
- majorVersion.value = 3
- val minorVersion = IntByReference()
- majorVersion.value = 2
- libEGLLibrary.eglInitialize(mDisplay, majorVersion.pointer, minorVersion.pointer)
- }
-
- fun swap() {
- libEGLLibrary.eglSwapBuffers(mDisplay, mSurface)
- }
-}
\ No newline at end of file
diff --git a/bindings/angle/settings.gradle.kts b/bindings/angle/settings.gradle.kts
index 3e7005ca..168f462b 100644
--- a/bindings/angle/settings.gradle.kts
+++ b/bindings/angle/settings.gradle.kts
@@ -8,7 +8,7 @@ pluginManagement {
}
}
-include(":libgles")
-include(":libangle")
+include(":libgles", ":libangle", ":binaries")
findProject(":libangle")?.name = "angle4k"
+findProject(":binaries")?.name = "angle-binaries"
include("example")
diff --git a/bindings/clang/gradle/wrapper/gradle-wrapper.properties b/bindings/clang/gradle/wrapper/gradle-wrapper.properties
index 17a8ddce..3499ded5 100644
--- a/bindings/clang/gradle/wrapper/gradle-wrapper.properties
+++ b/bindings/clang/gradle/wrapper/gradle-wrapper.properties
@@ -1,6 +1,6 @@
distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
-distributionUrl=https\://services.gradle.org/distributions/gradle-8.2.1-bin.zip
+distributionUrl=https\://services.gradle.org/distributions/gradle-8.5-bin.zip
networkTimeout=10000
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists
diff --git a/bindings/darwin/darwin/foundation/.gitignore b/bindings/darwin/darwin/foundation/.gitignore
index b63da455..2fa99da5 100644
--- a/bindings/darwin/darwin/foundation/.gitignore
+++ b/bindings/darwin/darwin/foundation/.gitignore
@@ -39,4 +39,7 @@ bin/
.vscode/
### Mac OS ###
-.DS_Store
\ No newline at end of file
+.DS_Store
+
+
+*.jar
diff --git a/bindings/darwin/darwin/foundation/build.gradle.kts b/bindings/darwin/darwin/foundation/build.gradle.kts
index fe17730e..2f47f8d6 100644
--- a/bindings/darwin/darwin/foundation/build.gradle.kts
+++ b/bindings/darwin/darwin/foundation/build.gradle.kts
@@ -2,12 +2,20 @@ import org.gradle.api.tasks.testing.logging.TestExceptionFormat
import org.gradle.api.tasks.testing.logging.TestLogEvent
plugins {
- kotlin("jvm")
+ kotlin("jvm") version libs.versions.kotlin
}
+repositories {
+ mavenLocal()
+ mavenCentral()
+}
+
+group = "io.ygdrasil"
+version = "0.0.0"
+
dependencies {
api ("net.java.dev.jna:jna:5.13.0")
- implementation(project(":klang"))
+ api("$group:klang:$version")
testImplementation("org.junit.jupiter:junit-jupiter")
testImplementation(libs.kotest)
}
@@ -31,3 +39,17 @@ tasks.test {
sourceSets.main {
//java.srcDirs("src/main/generated")
}
+
+kotlin {
+ jvmToolchain(21)
+
+ sourceSets.all {
+ languageSettings {
+ java {
+ sourceCompatibility = JavaVersion.VERSION_21
+ targetCompatibility = JavaVersion.VERSION_21
+ }
+ languageVersion = "2.0"
+ }
+ }
+}
diff --git a/bindings/darwin/darwin/foundation/gradle/libs.versions.toml b/bindings/darwin/darwin/foundation/gradle/libs.versions.toml
new file mode 100644
index 00000000..3678e8bf
--- /dev/null
+++ b/bindings/darwin/darwin/foundation/gradle/libs.versions.toml
@@ -0,0 +1,11 @@
+[versions]
+arrow = "1.2.0"
+kotest = "5.6.1"
+kotlinpoet = "1.14.2"
+kotlin = "1.9.22"
+
+[libraries]
+arrow-core = { module = "io.arrow-kt:arrow-core", version.ref = "arrow" }
+arrow-fx-coroutines = { module = "io.arrow-kt:arrow-fx-coroutines", version.ref = "arrow" }
+kotest = { module = "io.kotest:kotest-runner-junit5-jvm", version.ref = "kotest" }
+kotlinpoet = { module = "com.squareup:kotlinpoet", version.ref = "kotlinpoet" }
\ No newline at end of file
diff --git a/bindings/darwin/darwin/foundation/gradle/wrapper/gradle-wrapper.properties b/bindings/darwin/darwin/foundation/gradle/wrapper/gradle-wrapper.properties
new file mode 100644
index 00000000..1af9e093
--- /dev/null
+++ b/bindings/darwin/darwin/foundation/gradle/wrapper/gradle-wrapper.properties
@@ -0,0 +1,7 @@
+distributionBase=GRADLE_USER_HOME
+distributionPath=wrapper/dists
+distributionUrl=https\://services.gradle.org/distributions/gradle-8.5-bin.zip
+networkTimeout=10000
+validateDistributionUrl=true
+zipStoreBase=GRADLE_USER_HOME
+zipStorePath=wrapper/dists
diff --git a/bindings/darwin/darwin/foundation/gradlew b/bindings/darwin/darwin/foundation/gradlew
new file mode 100755
index 00000000..1aa94a42
--- /dev/null
+++ b/bindings/darwin/darwin/foundation/gradlew
@@ -0,0 +1,249 @@
+#!/bin/sh
+
+#
+# Copyright © 2015-2021 the original authors.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# https://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+
+##############################################################################
+#
+# Gradle start up script for POSIX generated by Gradle.
+#
+# Important for running:
+#
+# (1) You need a POSIX-compliant shell to run this script. If your /bin/sh is
+# noncompliant, but you have some other compliant shell such as ksh or
+# bash, then to run this script, type that shell name before the whole
+# command line, like:
+#
+# ksh Gradle
+#
+# Busybox and similar reduced shells will NOT work, because this script
+# requires all of these POSIX shell features:
+# * functions;
+# * expansions «$var», «${var}», «${var:-default}», «${var+SET}»,
+# «${var#prefix}», «${var%suffix}», and «$( cmd )»;
+# * compound commands having a testable exit status, especially «case»;
+# * various built-in commands including «command», «set», and «ulimit».
+#
+# Important for patching:
+#
+# (2) This script targets any POSIX shell, so it avoids extensions provided
+# by Bash, Ksh, etc; in particular arrays are avoided.
+#
+# The "traditional" practice of packing multiple parameters into a
+# space-separated string is a well documented source of bugs and security
+# problems, so this is (mostly) avoided, by progressively accumulating
+# options in "$@", and eventually passing that to Java.
+#
+# Where the inherited environment variables (DEFAULT_JVM_OPTS, JAVA_OPTS,
+# and GRADLE_OPTS) rely on word-splitting, this is performed explicitly;
+# see the in-line comments for details.
+#
+# There are tweaks for specific operating systems such as AIX, CygWin,
+# Darwin, MinGW, and NonStop.
+#
+# (3) This script is generated from the Groovy template
+# https://github.com/gradle/gradle/blob/HEAD/subprojects/plugins/src/main/resources/org/gradle/api/internal/plugins/unixStartScript.txt
+# within the Gradle project.
+#
+# You can find Gradle at https://github.com/gradle/gradle/.
+#
+##############################################################################
+
+# Attempt to set APP_HOME
+
+# Resolve links: $0 may be a link
+app_path=$0
+
+# Need this for daisy-chained symlinks.
+while
+ APP_HOME=${app_path%"${app_path##*/}"} # leaves a trailing /; empty if no leading path
+ [ -h "$app_path" ]
+do
+ ls=$( ls -ld "$app_path" )
+ link=${ls#*' -> '}
+ case $link in #(
+ /*) app_path=$link ;; #(
+ *) app_path=$APP_HOME$link ;;
+ esac
+done
+
+# This is normally unused
+# shellcheck disable=SC2034
+APP_BASE_NAME=${0##*/}
+# Discard cd standard output in case $CDPATH is set (https://github.com/gradle/gradle/issues/25036)
+APP_HOME=$( cd "${APP_HOME:-./}" > /dev/null && pwd -P ) || exit
+
+# Use the maximum available, or set MAX_FD != -1 to use that value.
+MAX_FD=maximum
+
+warn () {
+ echo "$*"
+} >&2
+
+die () {
+ echo
+ echo "$*"
+ echo
+ exit 1
+} >&2
+
+# OS specific support (must be 'true' or 'false').
+cygwin=false
+msys=false
+darwin=false
+nonstop=false
+case "$( uname )" in #(
+ CYGWIN* ) cygwin=true ;; #(
+ Darwin* ) darwin=true ;; #(
+ MSYS* | MINGW* ) msys=true ;; #(
+ NONSTOP* ) nonstop=true ;;
+esac
+
+CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar
+
+
+# Determine the Java command to use to start the JVM.
+if [ -n "$JAVA_HOME" ] ; then
+ if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
+ # IBM's JDK on AIX uses strange locations for the executables
+ JAVACMD=$JAVA_HOME/jre/sh/java
+ else
+ JAVACMD=$JAVA_HOME/bin/java
+ fi
+ if [ ! -x "$JAVACMD" ] ; then
+ die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME
+
+Please set the JAVA_HOME variable in your environment to match the
+location of your Java installation."
+ fi
+else
+ JAVACMD=java
+ if ! command -v java >/dev/null 2>&1
+ then
+ die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
+
+Please set the JAVA_HOME variable in your environment to match the
+location of your Java installation."
+ fi
+fi
+
+# Increase the maximum file descriptors if we can.
+if ! "$cygwin" && ! "$darwin" && ! "$nonstop" ; then
+ case $MAX_FD in #(
+ max*)
+ # In POSIX sh, ulimit -H is undefined. That's why the result is checked to see if it worked.
+ # shellcheck disable=SC2039,SC3045
+ MAX_FD=$( ulimit -H -n ) ||
+ warn "Could not query maximum file descriptor limit"
+ esac
+ case $MAX_FD in #(
+ '' | soft) :;; #(
+ *)
+ # In POSIX sh, ulimit -n is undefined. That's why the result is checked to see if it worked.
+ # shellcheck disable=SC2039,SC3045
+ ulimit -n "$MAX_FD" ||
+ warn "Could not set maximum file descriptor limit to $MAX_FD"
+ esac
+fi
+
+# Collect all arguments for the java command, stacking in reverse order:
+# * args from the command line
+# * the main class name
+# * -classpath
+# * -D...appname settings
+# * --module-path (only if needed)
+# * DEFAULT_JVM_OPTS, JAVA_OPTS, and GRADLE_OPTS environment variables.
+
+# For Cygwin or MSYS, switch paths to Windows format before running java
+if "$cygwin" || "$msys" ; then
+ APP_HOME=$( cygpath --path --mixed "$APP_HOME" )
+ CLASSPATH=$( cygpath --path --mixed "$CLASSPATH" )
+
+ JAVACMD=$( cygpath --unix "$JAVACMD" )
+
+ # Now convert the arguments - kludge to limit ourselves to /bin/sh
+ for arg do
+ if
+ case $arg in #(
+ -*) false ;; # don't mess with options #(
+ /?*) t=${arg#/} t=/${t%%/*} # looks like a POSIX filepath
+ [ -e "$t" ] ;; #(
+ *) false ;;
+ esac
+ then
+ arg=$( cygpath --path --ignore --mixed "$arg" )
+ fi
+ # Roll the args list around exactly as many times as the number of
+ # args, so each arg winds up back in the position where it started, but
+ # possibly modified.
+ #
+ # NB: a `for` loop captures its iteration list before it begins, so
+ # changing the positional parameters here affects neither the number of
+ # iterations, nor the values presented in `arg`.
+ shift # remove old arg
+ set -- "$@" "$arg" # push replacement arg
+ done
+fi
+
+
+# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
+DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"'
+
+# Collect all arguments for the java command:
+# * DEFAULT_JVM_OPTS, JAVA_OPTS, JAVA_OPTS, and optsEnvironmentVar are not allowed to contain shell fragments,
+# and any embedded shellness will be escaped.
+# * For example: A user cannot expect ${Hostname} to be expanded, as it is an environment variable and will be
+# treated as '${Hostname}' itself on the command line.
+
+set -- \
+ "-Dorg.gradle.appname=$APP_BASE_NAME" \
+ -classpath "$CLASSPATH" \
+ org.gradle.wrapper.GradleWrapperMain \
+ "$@"
+
+# Stop when "xargs" is not available.
+if ! command -v xargs >/dev/null 2>&1
+then
+ die "xargs is not available"
+fi
+
+# Use "xargs" to parse quoted args.
+#
+# With -n1 it outputs one arg per line, with the quotes and backslashes removed.
+#
+# In Bash we could simply go:
+#
+# readarray ARGS < <( xargs -n1 <<<"$var" ) &&
+# set -- "${ARGS[@]}" "$@"
+#
+# but POSIX shell has neither arrays nor command substitution, so instead we
+# post-process each arg (as a line of input to sed) to backslash-escape any
+# character that might be a shell metacharacter, then use eval to reverse
+# that process (while maintaining the separation between arguments), and wrap
+# the whole thing up as a single "set" statement.
+#
+# This will of course break if any of these variables contains a newline or
+# an unmatched quote.
+#
+
+eval "set -- $(
+ printf '%s\n' "$DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS" |
+ xargs -n1 |
+ sed ' s~[^-[:alnum:]+,./:=@_]~\\&~g; ' |
+ tr '\n' ' '
+ )" '"$@"'
+
+exec "$JAVACMD" "$@"
diff --git a/bindings/darwin/darwin/foundation/gradlew.bat b/bindings/darwin/darwin/foundation/gradlew.bat
new file mode 100644
index 00000000..93e3f59f
--- /dev/null
+++ b/bindings/darwin/darwin/foundation/gradlew.bat
@@ -0,0 +1,92 @@
+@rem
+@rem Copyright 2015 the original author or authors.
+@rem
+@rem Licensed under the Apache License, Version 2.0 (the "License");
+@rem you may not use this file except in compliance with the License.
+@rem You may obtain a copy of the License at
+@rem
+@rem https://www.apache.org/licenses/LICENSE-2.0
+@rem
+@rem Unless required by applicable law or agreed to in writing, software
+@rem distributed under the License is distributed on an "AS IS" BASIS,
+@rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+@rem See the License for the specific language governing permissions and
+@rem limitations under the License.
+@rem
+
+@if "%DEBUG%"=="" @echo off
+@rem ##########################################################################
+@rem
+@rem Gradle startup script for Windows
+@rem
+@rem ##########################################################################
+
+@rem Set local scope for the variables with windows NT shell
+if "%OS%"=="Windows_NT" setlocal
+
+set DIRNAME=%~dp0
+if "%DIRNAME%"=="" set DIRNAME=.
+@rem This is normally unused
+set APP_BASE_NAME=%~n0
+set APP_HOME=%DIRNAME%
+
+@rem Resolve any "." and ".." in APP_HOME to make it shorter.
+for %%i in ("%APP_HOME%") do set APP_HOME=%%~fi
+
+@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
+set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m"
+
+@rem Find java.exe
+if defined JAVA_HOME goto findJavaFromJavaHome
+
+set JAVA_EXE=java.exe
+%JAVA_EXE% -version >NUL 2>&1
+if %ERRORLEVEL% equ 0 goto execute
+
+echo.
+echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
+echo.
+echo Please set the JAVA_HOME variable in your environment to match the
+echo location of your Java installation.
+
+goto fail
+
+:findJavaFromJavaHome
+set JAVA_HOME=%JAVA_HOME:"=%
+set JAVA_EXE=%JAVA_HOME%/bin/java.exe
+
+if exist "%JAVA_EXE%" goto execute
+
+echo.
+echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%
+echo.
+echo Please set the JAVA_HOME variable in your environment to match the
+echo location of your Java installation.
+
+goto fail
+
+:execute
+@rem Setup the command line
+
+set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar
+
+
+@rem Execute Gradle
+"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %*
+
+:end
+@rem End local scope for the variables with windows NT shell
+if %ERRORLEVEL% equ 0 goto mainEnd
+
+:fail
+rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of
+rem the _cmd.exe /c_ return code!
+set EXIT_CODE=%ERRORLEVEL%
+if %EXIT_CODE% equ 0 set EXIT_CODE=1
+if not ""=="%GRADLE_EXIT_CONSOLE%" exit %EXIT_CODE%
+exit /b %EXIT_CODE%
+
+:mainEnd
+if "%OS%"=="Windows_NT" endlocal
+
+:omega
diff --git a/bindings/darwin/darwin/foundation/settings.gradle.kts b/bindings/darwin/darwin/foundation/settings.gradle.kts
new file mode 100644
index 00000000..99baa252
--- /dev/null
+++ b/bindings/darwin/darwin/foundation/settings.gradle.kts
@@ -0,0 +1 @@
+rootProject.name = "darwin-foundation"
diff --git a/bindings/darwin/darwin/foundation/src/main/kotlin/generation/Generate.kt b/bindings/darwin/darwin/foundation/src/main/kotlin/generation/Generate.kt
index ca6a6083..35b3d5ed 100644
--- a/bindings/darwin/darwin/foundation/src/main/kotlin/generation/Generate.kt
+++ b/bindings/darwin/darwin/foundation/src/main/kotlin/generation/Generate.kt
@@ -5,12 +5,13 @@ import klang.domain.NativeDeclaration
import klang.domain.NativeEnumeration
import klang.domain.ObjectiveCClass
import klang.findDeclarationByName
+import klang.generator.JnaBindingGenerator
import klang.generator.generateKotlinFile
import klang.parser.json.ParserRepository
import klang.parser.json.parseAstJson
import java.io.File
-const val baseDirectory = "binding/darwin/foundation/"
+const val baseDirectory = "binding/darwin/darwin/foundation/"
const val astPath = "${baseDirectory}src/main/objective-c/cocoa.m.ast.json"
const val outputDirectory = "${baseDirectory}src/main/generated/"
@@ -35,13 +36,16 @@ fun main() {
cleanupTargetPath()
+ with(JnaBindingGenerator) {
+ generateKotlinFiles(File(outputDirectory), "darwin", "na")
+ }
+
declarations
.filterIsInstance()
- .filter { it.name != "NSString" }
- .filter { it.name == "NSWindow" || it is NativeEnumeration }
+ .filter { it.name.toString() != "NSString" }
+ .filter { it.name.toString() == "NSWindow" || it is NativeEnumeration }
.forEach(::generateKotlinFile)
-
}
@@ -50,7 +54,7 @@ fun main() {
private fun generateKotlinFile(declaration: NativeDeclaration) {
when (declaration) {
is ObjectiveCClass -> declaration.generateKotlinFile("${outputDirectory}darwin/")
- is NativeEnumeration -> declaration.generateKotlinFile(outputDirectory)
+ //is NativeEnumeration -> declaration.toSpecAsEnumeration("darwin")//outputDirectory)
else -> println("Not implemented: $declaration")
}
}
diff --git a/bindings/darwin/darwin/foundation/src/main/kotlin/generation/TypeRefToKotlinType.kt b/bindings/darwin/darwin/foundation/src/main/kotlin/generation/TypeRefToKotlinType.kt
index 66c237d1..46ae5bfe 100644
--- a/bindings/darwin/darwin/foundation/src/main/kotlin/generation/TypeRefToKotlinType.kt
+++ b/bindings/darwin/darwin/foundation/src/main/kotlin/generation/TypeRefToKotlinType.kt
@@ -9,7 +9,7 @@ internal fun TypeRef.toKotlinType(): String = when (this) {
is ResolvedTypeRef -> toKotlinType()
}
-private fun ResolvedTypeRef.toKotlinType(): String = typeName
+private fun ResolvedTypeRef.toKotlinType(): String = typeName.toString()
private fun UnresolvedTypeRef.toKotlinType(): String = when (referenceAsString) {
"void" -> "Unit"
diff --git a/bindings/darwin/darwin/foundation/src/main/kotlin/klang/generator/NativeEnumeration.kt b/bindings/darwin/darwin/foundation/src/main/kotlin/klang/generator/NativeEnumeration.kt
deleted file mode 100644
index 3c33aee7..00000000
--- a/bindings/darwin/darwin/foundation/src/main/kotlin/klang/generator/NativeEnumeration.kt
+++ /dev/null
@@ -1,13 +0,0 @@
-package klang.generator
-
-import com.squareup.kotlinpoet.FileSpec
-import klang.domain.NativeEnumeration
-import klang.mapper.toSpec
-import java.io.File
-
-internal fun NativeEnumeration.generateKotlinFile(outputDirectory: String) {
- FileSpec.builder("darwin", "${name}NativeEnumeration")
- .addType(this.toSpec())
- .build()
- .writeTo(File(outputDirectory))
-}
\ No newline at end of file
diff --git a/bindings/darwin/darwin/foundation/src/main/kotlin/klang/generator/ObjectiveCClass.kt b/bindings/darwin/darwin/foundation/src/main/kotlin/klang/generator/ObjectiveCClass.kt
index 0df77502..4a229e6c 100644
--- a/bindings/darwin/darwin/foundation/src/main/kotlin/klang/generator/ObjectiveCClass.kt
+++ b/bindings/darwin/darwin/foundation/src/main/kotlin/klang/generator/ObjectiveCClass.kt
@@ -1,6 +1,7 @@
package klang.generator
import generation.toKotlinType
+import klang.domain.NotBlankString
import klang.domain.ObjectiveCClass
import java.io.File
@@ -40,5 +41,5 @@ private fun ObjectiveCClass.Method.generateMethod(): String {
return "\tfun ${name.toMethodName()}(${arguments.joinToString { "${it.name}: ${it.type.toKotlinType()}" }}): ${returnType.toKotlinType()} = ObjectiveC.objc_msgSend(id, sel(\"${name}\"), ${arguments.joinToString { it.name }})"
}
-private fun String.toMethodName(): String
+private fun NotBlankString.toMethodName(): String
= split(":").first()
diff --git a/bindings/sdl/binaries/build.gradle.kts b/bindings/sdl/binaries/build.gradle.kts
new file mode 100644
index 00000000..b7b2173a
--- /dev/null
+++ b/bindings/sdl/binaries/build.gradle.kts
@@ -0,0 +1,27 @@
+import org.jetbrains.kotlin.de.undercouch.gradle.tasks.download.Download
+
+plugins {
+ kotlin("jvm") version libs.versions.kotlin
+}
+
+
+
+val directory = project.file("src/main/resources")
+val baseUrl = "https://github.com/klang-toolkit/SDL-binary/releases/download/2.30.0/"
+val fileToDownload = listOf(
+ "libSDL2-aarch64.dylib" to directory.resolve("darwin-aarch64").resolve("libSDL2.dylib"),
+ "libSDL2-amd64.dylib" to directory.resolve("darwin-amd64").resolve("libSDL2.dylib"),
+ "libSDL2.dll" to directory.resolve("win32").resolve("libSDL2.dll"),
+).forEach { (fileName, target) ->
+ val url = "$baseUrl$fileName"
+ val taskName = "downloadFile-$fileName"
+ tasks.register(taskName) {
+ onlyIf { !target.exists() }
+ src(url)
+ dest(target)
+ }
+
+ tasks.named("processResources") {
+ dependsOn(taskName)
+ }
+}
\ No newline at end of file
diff --git a/bindings/sdl/build.gradle.kts b/bindings/sdl/build.gradle.kts
index 636afdab..718c42f9 100644
--- a/bindings/sdl/build.gradle.kts
+++ b/bindings/sdl/build.gradle.kts
@@ -1,14 +1,60 @@
+plugins {
+ kotlin("jvm") version libs.versions.kotlin
+ id("com.gradle.plugin-publish") version "1.0.0"
+}
+
+repositories {
+ mavenCentral()
+}
+
+group = "io.ygdrasil"
+version = "1.0.0-SNAPSHOT"
-allprojects {
+subprojects {
+ apply(plugin = "maven-publish")
+ apply(plugin = "org.jetbrains.kotlin.jvm")
- repositories {
- mavenCentral()
- }
+ repositories {
+ mavenCentral()
+ }
group = "io.ygdrasil"
version = "1.0.0-SNAPSHOT"
+
+ publishing {
+
+ publications {
+ create("maven") {
+ from(components["java"])
+
+ pom {
+ name = "Klang-${project.name}"
+ description = "SDL2 binding"
+ url = "https://ygdrasil.io/"
+ licenses {
+ license {
+ name = "MIT"
+ url = "https://opensource.org/license/mit/"
+ }
+ }
+ developers {
+ developer {
+ id = "alexandremo"
+ name = "Alexandre Mommers"
+ email = "alexandre dot mommers at gmail do com"
+ }
+ }
+ scm {
+ connection = "scm:git:git://github.com/ygdrasil-io/klang.git"
+ developerConnection = "scm:git:ssh//git@github.com:ygdrasil-io/klang.git"
+ url = "https://github.com/ygdrasil-io/klang"
+ }
+ }
+ }
+ }
+ }
}
diff --git a/bindings/sdl/examples/snake/build.gradle.kts b/bindings/sdl/examples/snake/build.gradle.kts
new file mode 100644
index 00000000..12fbb434
--- /dev/null
+++ b/bindings/sdl/examples/snake/build.gradle.kts
@@ -0,0 +1,39 @@
+
+plugins {
+ kotlin("jvm") version libs.versions.kotlin
+ application
+ id("org.beryx.jlink") version "3.0.1"
+}
+
+version = "1.0.0"
+
+dependencies {
+ api(project(":sdl2-4k"))
+ api(project(":sdl2-binaries"))
+ testImplementation("org.junit.jupiter:junit-jupiter")
+ testImplementation(libs.kotest)
+}
+
+application {
+ mainModule = "io.ygdrasil"
+ mainClass.set("io.ygdrasil.snake.MainKt")
+ applicationDefaultJvmArgs += "-XstartOnFirstThread"
+ //tasks.run.get().workingDir = project.projectDir.resolve("src").resolve("main").resolve("resources")
+}
+
+jlink {
+ addOptions("--strip-debug", "--compress", "2", "--no-header-files", "--no-man-pages")
+ launcher{
+ moduleName = "io.ygdrasil"
+ //name = "Snake"
+ jvmArgs = listOf("-XstartOnFirstThread")
+ }
+}
+
+
+tasks.named("compileJava", JavaCompile::class.java) {
+ options.compilerArgumentProviders.add(CommandLineArgumentProvider {
+ // Provide compiled Kotlin classes to javac – needed for Java/Kotlin mixed sources to work
+ listOf("--patch-module", "io.ygdrasil=${sourceSets["main"].output.asPath}")
+ })
+}
\ No newline at end of file
diff --git a/bindings/sdl/examples/snake/src/main/java/module-info.java b/bindings/sdl/examples/snake/src/main/java/module-info.java
new file mode 100644
index 00000000..2eee13a8
--- /dev/null
+++ b/bindings/sdl/examples/snake/src/main/java/module-info.java
@@ -0,0 +1,5 @@
+module io.ygdrasil {
+ requires kotlin.stdlib;
+ requires com.sun.jna;
+ requires io.ygdrasil.libsdl;
+}
\ No newline at end of file
diff --git a/bindings/sdl/examples/snake/src/main/kotlin/io/ygdrasil/sdl/App.kt b/bindings/sdl/examples/snake/src/main/kotlin/io/ygdrasil/sdl/App.kt
new file mode 100644
index 00000000..9e4c2266
--- /dev/null
+++ b/bindings/sdl/examples/snake/src/main/kotlin/io/ygdrasil/sdl/App.kt
@@ -0,0 +1,55 @@
+package io.ygdrasil.sdl
+
+import com.sun.jna.Library
+import io.ygdrasil.libsdl.*
+
+private class App : AutoCloseable, AppContext {
+
+ override val window: SDL_Window = createWindow()
+ override val renderer: SDL_Renderer = createRenderer()
+ override val textures = mutableListOf()
+ override val controllers: List = findControllers()
+
+ override fun addTexture(filename: String) = renderer.loadTexture(filename)
+ .also(textures::add)
+
+ override fun removeTexture(texture: SDL_Texture) {
+ if (textures.remove(texture)) {
+ SDL_DestroyTexture(texture)
+ }
+ }
+
+ override fun close() {
+ textures.forEach(::SDL_DestroyTexture)
+ controllers.forEach(::SDL_GameControllerClose)
+ SDL_DestroyRenderer(renderer)
+ SDL_DestroyWindow(window)
+ SDL_Quit()
+ }
+
+ private fun createWindow() = SDL_CreateWindow(
+ "", SDL_WINDOWPOS_CENTERED.toInt(),
+ SDL_WINDOWPOS_CENTERED.toInt(), 1, 1,
+ SDL_WindowFlags.SDL_WINDOW_SHOWN.value
+ ) ?: error("fail to create window ${SDL_GetError()}")
+
+ private fun createRenderer() = SDL_CreateRenderer(
+ window, -1, SDL_RendererFlags.SDL_RENDERER_ACCELERATED or SDL_RendererFlags.SDL_RENDERER_PRESENTVSYNC
+ ) ?: error("fail to create renderer")
+
+ private fun findControllers() = (0 until SDL_NumJoysticks()).mapNotNull { index ->
+ SDL_GameControllerOpen(index).also { if (it == null) println("fail to get controller at index $index") }
+ }
+
+}
+
+fun app(
+ block: AppContext.() -> Unit
+) {
+
+ if (SDL_Init(SDL_INIT_EVERYTHING.toInt()) != 0) {
+ error("SDL_Init Error: ${SDL_GetError()}")
+ }
+
+ App().use(block)
+}
\ No newline at end of file
diff --git a/bindings/sdl/examples/snake/src/main/kotlin/io/ygdrasil/sdl/Context.kt b/bindings/sdl/examples/snake/src/main/kotlin/io/ygdrasil/sdl/Context.kt
new file mode 100644
index 00000000..6414afb9
--- /dev/null
+++ b/bindings/sdl/examples/snake/src/main/kotlin/io/ygdrasil/sdl/Context.kt
@@ -0,0 +1,14 @@
+package io.ygdrasil.sdl
+
+import io.ygdrasil.libsdl.*
+
+interface AppContext {
+ val window: SDL_Window
+ val renderer: SDL_Renderer
+ val textures: MutableList
+ val controllers: List
+
+ fun addTexture(filename: String): SDL_Texture
+ fun removeTexture(texture: SDL_Texture)
+}
+
diff --git a/bindings/sdl/examples/snake/src/main/kotlin/io/ygdrasil/sdl/Rect.kt b/bindings/sdl/examples/snake/src/main/kotlin/io/ygdrasil/sdl/Rect.kt
new file mode 100644
index 00000000..a1a750df
--- /dev/null
+++ b/bindings/sdl/examples/snake/src/main/kotlin/io/ygdrasil/sdl/Rect.kt
@@ -0,0 +1,10 @@
+package io.ygdrasil.sdl
+
+import io.ygdrasil.libsdl.SDL_Rect
+
+fun rect(x: Int, y: Int, w: Int, h: Int) = SDL_Rect().also {
+ it.x = x
+ it.y = y
+ it.w = w
+ it.h = h
+}
\ No newline at end of file
diff --git a/bindings/sdl/examples/snake/src/main/kotlin/io/ygdrasil/sdl/Texture.kt b/bindings/sdl/examples/snake/src/main/kotlin/io/ygdrasil/sdl/Texture.kt
new file mode 100644
index 00000000..f994f861
--- /dev/null
+++ b/bindings/sdl/examples/snake/src/main/kotlin/io/ygdrasil/sdl/Texture.kt
@@ -0,0 +1,29 @@
+package io.ygdrasil.sdl
+
+import com.sun.jna.Native
+import io.ygdrasil.libsdl.*
+import java.io.InputStream
+import java.nio.ByteBuffer
+
+internal fun SDL_Renderer.loadTexture(fileName: String): SDL_Texture {
+ println("load texture $fileName")
+ val resourceStream = findClassPathResource(fileName) ?: error("fail to find resource with name filename")
+ val (buffer, bufferSize) = resourceStream.toBuffer()
+ val bufferPointer = Native.getDirectBufferPointer(buffer)
+ val res = SDL_RWFromMem(bufferPointer, bufferSize)
+ val image = SDL_LoadBMP_RW(res, 1)
+ val texture = SDL_CreateTextureFromSurface(this, image) ?: error("fail to create texture from filename $fileName")
+ SDL_FreeSurface(image)
+ return texture
+}
+
+private fun InputStream.toBuffer(): Pair {
+ val resourceBytes = readAllBytes()
+ val buffer = ByteBuffer.allocateDirect(resourceBytes.size)
+ buffer.put(resourceBytes)
+ val bufferSize = resourceBytes.size
+ return Pair(buffer, bufferSize)
+}
+
+private fun findClassPathResource(fileName: String): InputStream? =
+ AppContext::class.java.classLoader.getResourceAsStream(fileName)
\ No newline at end of file
diff --git a/bindings/sdl/examples/snake/src/main/kotlin/io/ygdrasil/snake/SnakeView.kt b/bindings/sdl/examples/snake/src/main/kotlin/io/ygdrasil/snake/SnakeView.kt
new file mode 100644
index 00000000..b7846299
--- /dev/null
+++ b/bindings/sdl/examples/snake/src/main/kotlin/io/ygdrasil/snake/SnakeView.kt
@@ -0,0 +1,312 @@
+package io.ygdrasil.snake
+
+import com.sun.jna.ptr.IntByReference
+import com.sun.jna.ptr.PointerByReference
+import io.ygdrasil.libsdl.*
+import io.ygdrasil.sdl.AppContext
+import io.ygdrasil.sdl.rect
+import java.io.File
+
+class SnakeView(
+ context: AppContext
+) : AutoCloseable, AppContext by context {
+
+ var game = initialGameState
+ var ticks = 0
+ val speed = 10
+
+ private val font = Font()
+ private val sprites = Sprites()
+ private val pixelWidth = game.width * sprites.w
+ private val pixelHeight = game.height * sprites.h
+
+ init {
+ SDL_SetWindowSize(window, pixelWidth, pixelHeight)
+ SDL_SetWindowTitle(window, "io/ygdrasil/snake")
+
+ //playMusic()
+ }
+
+ fun draw(game: Game) {
+ SDL_RenderClear(renderer)
+ SDL_SetRenderDrawColor(
+ renderer,
+ (200 / 2).toByte(),
+ (230 / 2).toByte(),
+ (151 / 2).toByte(),
+ SDL_ALPHA_OPAQUE.toByte()
+ )
+
+ val grassW = 256
+ val grassScaledW = 400 // scale grass up to reduce its resolution so that it's similar to snake sprites
+ 0.until(pixelWidth / grassW + 1).forEach { x ->
+ 0.until(pixelHeight / grassW + 1).forEach { y ->
+ sprites.render(sprites.grassRect, rect(x * grassW, y * grassW, grassScaledW, grassScaledW))
+ }
+ }
+
+ game.apples.cells.forEach {
+ sprites.render(sprites.appleRect, cellRect(it))
+ }
+
+ game.snake.tail.dropLast(1).forEachIndexed { i, it ->
+ val index = i + 1
+ val direction = direction(from = game.snake.cells[index - 1], to = it)
+ val nextDirection = direction(from = it, to = game.snake.cells[index + 1])
+
+ val srcRect = if (direction == nextDirection) {
+ when (direction) {
+ Direction.right, Direction.left -> sprites.bodyHorRect
+ Direction.up, Direction.down -> sprites.bodyVertRect
+ }
+ } else if ((direction == Direction.left && nextDirection == Direction.down) || (direction == Direction.up && nextDirection == Direction.right)) {
+ sprites.bodyLeftDownRect
+ } else if ((direction == Direction.left && nextDirection == Direction.up) || (direction == Direction.down && nextDirection == Direction.right)) {
+ sprites.bodyLeftUpRect
+ } else if ((direction == Direction.right && nextDirection == Direction.down) || (direction == Direction.up && nextDirection == Direction.left)) {
+ sprites.bodyRightDownRect
+ } else if ((direction == Direction.right && nextDirection == Direction.up) || (direction == Direction.down && nextDirection == Direction.left)) {
+ sprites.bodyRightUpRect
+ } else {
+ sprites.emptyRect
+ }
+ sprites.render(srcRect, cellRect(it))
+ }
+
+ val tipRect = when (game.snake.cells.let { direction(from = it.last(), to = it[it.size - 2]) }) {
+ Direction.up -> sprites.tipUpRect
+ Direction.down -> sprites.tipDownRect
+ Direction.left -> sprites.tipLeftRect
+ Direction.right -> sprites.tipRightRect
+ }
+ sprites.render(tipRect, cellRect(game.snake.tail.last()))
+
+ val headRect = when (game.snake.direction) {
+ Direction.up -> sprites.headUpRect
+ Direction.down -> sprites.headDownRect
+ Direction.left -> sprites.headLeftRect
+ Direction.right -> sprites.headRightRect
+ }
+ sprites.render(headRect, cellRect(game.snake.head))
+
+ if (game.isOver) {
+ renderStringCentered(3, game.width, "game over")
+ renderStringCentered(5, game.width, "your score is ${game.score}")
+ }
+
+ SDL_RenderPresent(renderer)
+
+ }
+
+ fun delay(timeMs: Int) {
+ SDL_Delay(timeMs)
+ }
+
+ fun readCommands(): List {
+ val result = ArrayList()
+ val event = SDL_Event()
+ while (SDL_PollEvent(event) != 0) {
+ event.read()
+ println("event(${event.type}): ${SDL_EventType.of(event.type)}")
+ when (SDL_EventType.of(event.type)) {
+ SDL_EventType.SDL_WINDOWEVENT -> {
+ val windowEvent = SDL_WindowEventID.of(event.window.event.toInt())
+ println("controllerButtonEvent(${windowEvent})")
+
+ if (windowEvent == SDL_WindowEventID.SDL_WINDOWEVENT_SHOWN) {
+ //playMusic()
+ }
+ }
+
+ SDL_EventType.SDL_QUIT -> result.add(UserCommand.quit)
+ SDL_EventType.SDL_CONTROLLERBUTTONDOWN -> {
+ val controllerButtonEvent = event.cbutton
+ val button = controllerButtonEvent.button.toInt()
+ println("controllerButtonEvent($button): ${SDL_GameControllerButton.of(button)}")
+ val command = when (SDL_GameControllerButton.of(button)) {
+ SDL_GameControllerButton.SDL_CONTROLLER_BUTTON_DPAD_UP -> UserCommand.up
+ SDL_GameControllerButton.SDL_CONTROLLER_BUTTON_DPAD_DOWN -> UserCommand.down
+ SDL_GameControllerButton.SDL_CONTROLLER_BUTTON_DPAD_LEFT -> UserCommand.left
+ SDL_GameControllerButton.SDL_CONTROLLER_BUTTON_DPAD_RIGHT -> UserCommand.right
+ SDL_GameControllerButton.SDL_CONTROLLER_BUTTON_START -> UserCommand.restart
+ SDL_GameControllerButton.SDL_CONTROLLER_BUTTON_BACK -> UserCommand.quit
+ else -> null
+ }
+ if (command != null) result.add(command)
+ }
+
+ SDL_EventType.SDL_KEYDOWN -> {
+ val keyboardEvent = event.key
+ val keysym = keyboardEvent.keysym
+ println("keyboardEvent(${keysym.scancode}): ${SDL_Scancode.of(keysym.scancode)}")
+ val command = when (SDL_Scancode.of(keysym.scancode)) {
+ SDL_Scancode.SDL_SCANCODE_I -> UserCommand.up
+ SDL_Scancode.SDL_SCANCODE_J -> UserCommand.left
+ SDL_Scancode.SDL_SCANCODE_K -> UserCommand.down
+ SDL_Scancode.SDL_SCANCODE_L -> UserCommand.right
+ SDL_Scancode.SDL_SCANCODE_R -> UserCommand.restart
+ SDL_Scancode.SDL_SCANCODE_Q -> UserCommand.quit
+ else -> null
+ }
+ if (command != null) result.add(command)
+ }
+
+ else -> Unit
+ }
+ }
+ return result
+ }
+
+ private fun playMusic() {
+ val fileName = "Crowander-Stop-on-a-Bench.wav"
+ val paths = listOf(fileName, "resources/$fileName", "../resources/$fileName")
+ val filePath = paths.find { File(it).canRead() } ?: error("Can't find sound file.")
+ val audioFile = SDL_RWFromFile(filePath, "rb")
+ val audio_spec = SDL_AudioSpec()
+ val audio_buf = PointerByReference()
+ val audio_len = IntByReference()
+ SDL_LoadWAV_RW(
+ src = audioFile,
+ freesrc = 1,
+ spec = audio_spec,
+ audio_buf.pointer,
+ audio_len.pointer
+ )
+
+ val deviceName = SDL_GetAudioDeviceName(0, 0)
+ val device_id = SDL_OpenAudioDevice(deviceName, 0, audio_spec, SDL_AudioSpec(), 0)
+ SDL_QueueAudio(device_id, audio_buf.value, audio_len.value)
+ SDL_PauseAudioDevice(device_id, 0)
+ }
+
+ private fun direction(from: Cell, to: Cell): Direction = when {
+ from.x == to.x && from.y > to.y -> Direction.up
+ from.x == to.x && from.y < to.y -> Direction.down
+ from.x > to.x && from.y == to.y -> Direction.left
+ from.x < to.x && from.y == to.y -> Direction.right
+ else -> error("")
+ }
+
+ private fun cellRect(cell: Cell): SDL_Rect {
+ val x = cell.x * sprites.w
+ val y = cell.y * sprites.h
+ return rect(x, y, sprites.w, sprites.h)
+ }
+
+ private fun renderStringCentered(y: Int, width: Int, s: String) {
+ var x = (width / 2) - (s.length / 2)
+ if (x.rem(2) != 0) x--
+ renderString(Cell(x, y), s)
+ }
+
+ private fun renderString(atCell: Cell, s: String) {
+ s.toCharArray().forEachIndexed { i, c ->
+ font.render(c, cellRect(atCell.copy(x = atCell.x + i)))
+ }
+ }
+
+ enum class UserCommand {
+ up, down, left, right, restart, quit
+ }
+
+
+ private inner class Font {
+ val w = 48
+ val h = 46
+
+ val texture = addTexture("Font16_42_Normal4_sheet.bmp")
+ private val letters = mapOf(
+ 'A' to textureRect(0, 0, -7),
+ 'B' to textureRect(1, 0),
+ 'C' to textureRect(2, 0, -9),
+ 'D' to textureRect(3, 0),
+ 'E' to textureRect(4, 0, -5),
+ 'F' to textureRect(5, 0, -5),
+ 'G' to textureRect(6, 0),
+ 'H' to textureRect(7, 0, -7),
+ 'I' to textureRect(8, 0, -15),
+ 'J' to textureRect(9, 0, -5),
+ 'K' to textureRect(0, 1, -10),
+ 'L' to textureRect(1, 1, -5),
+ 'M' to textureRect(2, 1),
+ 'N' to textureRect(3, 1),
+ 'O' to textureRect(4, 1, -7),
+ 'P' to textureRect(5, 1, -7),
+ 'Q' to textureRect(6, 1),
+ 'R' to textureRect(7, 1),
+ 'S' to textureRect(8, 1),
+ 'T' to textureRect(9, 1),
+ 'U' to textureRect(0, 2, -13),
+ 'V' to textureRect(1, 2, -10),
+ 'W' to textureRect(2, 2),
+ 'X' to textureRect(3, 2),
+ 'Y' to textureRect(4, 2, -5),
+ 'Z' to textureRect(5, 2),
+ '0' to textureRect(2, 5),
+ '1' to textureRect(3, 5, -15),
+ '2' to textureRect(4, 5),
+ '3' to textureRect(5, 5),
+ '4' to textureRect(6, 5),
+ '5' to textureRect(7, 5),
+ '6' to textureRect(8, 5),
+ '7' to textureRect(9, 5),
+ '8' to textureRect(0, 6),
+ '9' to textureRect(1, 6),
+ ' ' to rect(0, 0, 0, 0)
+ )
+
+ fun render(char: Char, cellRect: SDL_Rect) {
+ val charRect = letters[char.uppercaseChar()] ?: (letters[' '] ?: error(""))
+ SDL_RenderCopy(renderer, texture, charRect, cellRect)
+ }
+
+ private fun textureRect(x: Int, y: Int, wAdjust: Int = 0): SDL_Rect {
+ val xShift = x * w
+ val yShift = y * h
+ return rect(xShift, yShift, w + wAdjust, h)
+ }
+ }
+
+ private inner class Sprites {
+ val w = 64
+ val h = 64
+
+ val texture = addTexture("snake-graphics.bmp")
+ val grassTexture = addTexture("grass.bmp")
+
+ val headUpRect = textureRect(3, 0)
+ val headRightRect = textureRect(4, 0)
+ val headLeftRect = textureRect(3, 1)
+ val headDownRect = textureRect(4, 1)
+
+ val tipUpRect = textureRect(3, 2)
+ val tipRightRect = textureRect(4, 2)
+ val tipLeftRect = textureRect(3, 3)
+ val tipDownRect = textureRect(4, 3)
+
+ val bodyHorRect = textureRect(1, 0)
+ val bodyVertRect = textureRect(2, 1)
+ val bodyLeftDownRect = textureRect(0, 0)
+ val bodyLeftUpRect = textureRect(0, 1)
+ val bodyRightDownRect = textureRect(2, 0)
+ val bodyRightUpRect = textureRect(2, 2)
+
+ val appleRect = textureRect(0, 3)
+ val emptyRect = textureRect(0, 2)
+
+ val grassRect = rect(0, 0, 256, 256)
+
+ private fun textureRect(x: Int, y: Int) = rect(x * w, y * h, w, h)
+
+ fun render(srcRect: SDL_Rect, dstRect: SDL_Rect) {
+ if (srcRect == grassRect) SDL_RenderCopy(renderer, grassTexture, srcRect, dstRect)
+ else SDL_RenderCopy(renderer, texture, srcRect, dstRect)
+ }
+ }
+
+ override fun close() {
+ removeTexture(sprites.texture)
+ removeTexture(sprites.grassTexture)
+ removeTexture(font.texture)
+ }
+}
diff --git a/bindings/sdl/examples/snake/src/main/kotlin/io/ygdrasil/snake/domain.kt b/bindings/sdl/examples/snake/src/main/kotlin/io/ygdrasil/snake/domain.kt
new file mode 100644
index 00000000..ff3ebeaa
--- /dev/null
+++ b/bindings/sdl/examples/snake/src/main/kotlin/io/ygdrasil/snake/domain.kt
@@ -0,0 +1,86 @@
+package io.ygdrasil.snake
+
+import kotlin.math.max
+import kotlin.random.Random
+
+data class Game(
+ val width: Int,
+ val height: Int,
+ val snake: Snake,
+ val apples: Apples = Apples(width, height)
+) {
+ val isOver =
+ snake.tail.contains(snake.head) ||
+ snake.cells.any { it.x < 0 || it.x >= width || it.y < 0 || it.y >= height }
+
+ val score = snake.cells.size
+
+ fun update(direction: Direction? = null): Game {
+ if (isOver) return this
+ val (newSnake, newApples) = snake.turn(direction).move().eat(apples.grow())
+ return copy(snake = newSnake, apples = newApples)
+ }
+}
+
+val initialGameState = Game(
+ width = 20,
+ height = 10,
+ snake = Snake(
+ cells = listOf(Cell(4, 4), Cell(3, 4), Cell(2, 4), Cell(1, 4), Cell(0, 4)),
+ direction = Direction.right
+ )
+)
+
+data class Snake(
+ val cells: List,
+ val direction: Direction,
+ val eatenApples: Int = 0
+) {
+ val head = cells.first()
+ val tail = cells.subList(1, cells.size)
+
+ fun move(): Snake {
+ val newHead = head.move(direction)
+ val newTail = if (eatenApples == 0) cells.dropLast(1) else cells
+ return copy(
+ cells = listOf(newHead) + newTail,
+ eatenApples = max(eatenApples - 1, 0)
+ )
+ }
+
+ fun turn(newDirection: Direction?): Snake {
+ if (newDirection == null || newDirection.isOpposite(direction)) return this
+ return copy(direction = newDirection)
+ }
+
+ fun eat(apples: Apples): Pair {
+ if (!apples.cells.contains(head)) return Pair(this, apples)
+ return Pair(
+ copy(eatenApples = eatenApples + 1),
+ apples.copy(cells = apples.cells - head)
+ )
+ }
+}
+
+data class Apples(
+ val fieldWidth: Int,
+ val fieldHeight: Int,
+ val cells: Set = emptySet(),
+ val growthSpeed: Int = 3,
+ val random: Random = Random
+) {
+ fun grow(): Apples {
+ if (random.nextInt(growthSpeed) != 0) return this
+ return copy(cells = cells + Cell(random.nextInt(fieldWidth), random.nextInt(fieldHeight)))
+ }
+}
+
+data class Cell(val x: Int, val y: Int) {
+ fun move(direction: Direction) = Cell(x + direction.dx, y + direction.dy)
+}
+
+enum class Direction(val dx: Int, val dy: Int) {
+ up(0, -1), down(0, 1), left(-1, 0), right(1, 0);
+
+ fun isOpposite(that: Direction) = dx + that.dx == 0 && dy + that.dy == 0
+}
\ No newline at end of file
diff --git a/bindings/sdl/examples/snake/src/main/kotlin/io/ygdrasil/snake/main.kt b/bindings/sdl/examples/snake/src/main/kotlin/io/ygdrasil/snake/main.kt
new file mode 100644
index 00000000..dfc53c9c
--- /dev/null
+++ b/bindings/sdl/examples/snake/src/main/kotlin/io/ygdrasil/snake/main.kt
@@ -0,0 +1,35 @@
+package io.ygdrasil.snake
+
+import io.ygdrasil.sdl.app
+
+fun main() = app {
+
+ SnakeView(this).use { view ->
+
+ while (true) {
+
+ view.draw(view.game)
+
+ view.delay(1000 / 60)
+ view.ticks++
+ if (view.ticks >= view.speed) {
+ view.game = view.game.update()
+ view.ticks = 0
+ }
+
+ view.readCommands().forEach { command ->
+ var direction: Direction? = null
+ when (command) {
+ SnakeView.UserCommand.up -> direction = Direction.up
+ SnakeView.UserCommand.down -> direction = Direction.down
+ SnakeView.UserCommand.left -> direction = Direction.left
+ SnakeView.UserCommand.right -> direction = Direction.right
+ SnakeView.UserCommand.restart -> view.game = initialGameState
+ SnakeView.UserCommand.quit -> return@app
+ }
+ view.game = view.game.update(direction)
+ view.draw(view.game)
+ }
+ }
+ }
+}
diff --git a/bindings/sdl/examples/snake/src/main/kotlin/io/ygdrasil/tetris/SDLView.kt b/bindings/sdl/examples/snake/src/main/kotlin/io/ygdrasil/tetris/SDLView.kt
new file mode 100644
index 00000000..34ef8bfa
--- /dev/null
+++ b/bindings/sdl/examples/snake/src/main/kotlin/io/ygdrasil/tetris/SDLView.kt
@@ -0,0 +1,465 @@
+package io.ygdrasil.tetris
+
+import com.sun.jna.ptr.IntByReference
+import io.ygdrasil.libsdl.*
+
+class SDLView(private val width: Int, private val height: Int) : GameFieldVisualizer, UserInput {
+
+ fun error(message: Any): Nothing {
+ if (this::renderer.isInitialized) SDL_DestroyRenderer(renderer)
+ if (this::window.isInitialized) SDL_DestroyWindow(window)
+ println("$message: ${SDL_GetError()}")
+ SDL_Quit()
+ throw IllegalStateException()
+ }
+
+ private val CELL_SIZE = 20
+ private val COLORS = 10
+ private val CELLS_WIDTH = COLORS * CELL_SIZE
+ private val CELLS_HEIGHT = 3 * CELL_SIZE
+ private val SYMBOL_SIZE = 21
+ private val INFO_MARGIN = 10
+ private val MARGIN = 2
+ private val BORDER_WIDTH = 18
+ private val INFO_SPACE_WIDTH = SYMBOL_SIZE * (2 + 8)
+ private val LINES_LABEL_WIDTH = 104
+ private val SCORE_LABEL_WIDTH = 107
+ private val LEVEL_LABEL_WIDTH = 103
+ private val NEXT_LABEL_WIDTH = 85
+ private val TETRISES_LABEL_WIDTH = 162
+
+ private var ratio: Float
+
+ private fun stretch(value: Int) = (value.toFloat() * ratio + 0.5).toInt()
+
+ inner class GamePadButtons(width: Int, height: Int, gamePadHeight: Int) {
+ val MOVE_BUTTON_SIZE = 50
+ val ROTATE_BUTTON_SIZE = 80
+ val BUTTONS_MARGIN = 25
+
+ val leftRect: SDL_Rect
+ val rightRect: SDL_Rect
+ val downRect: SDL_Rect
+ val dropRect: SDL_Rect
+ val rotateRect: SDL_Rect
+
+ init {
+ val moveButtonsWidth = 3 * MOVE_BUTTON_SIZE + 2 * BUTTONS_MARGIN + BUTTONS_MARGIN
+ val x = (width - moveButtonsWidth - ROTATE_BUTTON_SIZE) / 2 - MOVE_BUTTON_SIZE
+ val y2 = (gamePadHeight - 2 * MOVE_BUTTON_SIZE - BUTTONS_MARGIN) / 2
+ leftRect = SDL_Rect()
+ leftRect.w = MOVE_BUTTON_SIZE
+ leftRect.h = MOVE_BUTTON_SIZE
+ leftRect.x = x
+ leftRect.y = height - gamePadHeight + y2 + MOVE_BUTTON_SIZE + BUTTONS_MARGIN
+
+ downRect = SDL_Rect()
+ downRect.w = MOVE_BUTTON_SIZE
+ downRect.h = MOVE_BUTTON_SIZE
+ downRect.x = x + MOVE_BUTTON_SIZE + BUTTONS_MARGIN
+ downRect.y = leftRect.y
+
+ dropRect = SDL_Rect().apply {
+ this.x = MOVE_BUTTON_SIZE
+ y = MOVE_BUTTON_SIZE
+ h = downRect.x
+ w =height - gamePadHeight + y2
+ }
+
+ rightRect = SDL_Rect()
+ rightRect.w = MOVE_BUTTON_SIZE
+ rightRect.h = MOVE_BUTTON_SIZE
+ rightRect.x = x + 2 * MOVE_BUTTON_SIZE + 2 * BUTTONS_MARGIN
+ rightRect.y = height - gamePadHeight + y2 + MOVE_BUTTON_SIZE + BUTTONS_MARGIN
+
+ rotateRect = SDL_Rect()
+ rotateRect.w = ROTATE_BUTTON_SIZE
+ rotateRect.h = ROTATE_BUTTON_SIZE
+ rotateRect.x = x + moveButtonsWidth
+ rotateRect.y = height - gamePadHeight + y2 - BUTTONS_MARGIN
+ }
+
+ fun getCommandAt(x: Int, y: Int): UserCommand? {
+ return when {
+ inside(leftRect, x, y) -> UserCommand.LEFT
+ inside(rightRect, x, y) -> UserCommand.RIGHT
+ inside(downRect, x, y) -> UserCommand.DOWN
+ inside(dropRect, x, y) -> UserCommand.DROP
+ inside(rotateRect, x, y) -> UserCommand.ROTATE
+ else -> null
+ }
+ }
+
+ private fun inside(rect: SDL_Rect, x: Int, y: Int): Boolean {
+ return x >= stretch(rect.x) && x <= stretch(rect.x + rect.w)
+ && y >= stretch(rect.y) && y <= stretch(rect.y + rect.h)
+ }
+
+ }
+
+ private val field: Field = Array(height) { ByteArray(width) }
+ private val nextPieceField: Field = Array(4) { ByteArray(4) }
+ private var linesCleared: Int = 0
+ private var level: Int = 0
+ private var score: Int = 0
+ private var tetrises: Int = 0
+
+ private var displayWidth: Int = 0
+ private var displayHeight: Int = 0
+ private val fieldWidth: Int
+ private val fieldHeight: Int
+ private var windowX: Int
+ private var windowY: Int
+ private lateinit var window: SDL_Window
+ private lateinit var renderer: SDL_Renderer
+ private val texture: SDL_Texture
+ private val gamePadButtons: GamePadButtons?
+
+ init {
+ if (SDL_Init(SDL_INIT_EVERYTHING.toInt()) != 0) {
+ throw Error("SDL_Init Error: ${SDL_GetError()}")
+ }
+
+ val platform: String = SDL_GetPlatform() ?: error("fail to get platform")
+
+ val displayMode = SDL_DisplayMode()
+ if (SDL_GetCurrentDisplayMode(0, displayMode) != 0) {
+ println("SDL_GetCurrentDisplayMode Error: ${SDL_GetError()}")
+ SDL_Quit()
+ throw Error()
+ }
+ displayWidth = displayMode.w
+ displayHeight = displayMode.h
+ fieldWidth = width * (CELL_SIZE + MARGIN) + MARGIN + BORDER_WIDTH * 2
+ fieldHeight = height * (CELL_SIZE + MARGIN) + MARGIN + BORDER_WIDTH * 2
+ var windowWidth = fieldWidth + INFO_SPACE_WIDTH
+ var windowHeight: Int
+ if (platform == "iOS") {
+ val gamePadHeight = (displayHeight * windowWidth - fieldHeight * displayWidth) / displayWidth
+ windowHeight = fieldHeight + gamePadHeight
+ gamePadButtons = GamePadButtons(windowWidth, windowHeight, gamePadHeight)
+ windowX = 0
+ windowY = 0
+ ratio = displayHeight.toFloat() / windowHeight
+ windowWidth = displayWidth
+ windowHeight = displayHeight
+ } else {
+ windowHeight = fieldHeight
+ gamePadButtons = null
+ windowX = (displayWidth - windowWidth) / 2
+ windowY = (displayHeight - windowHeight) / 2
+ ratio = 1.0f
+ }
+
+ window = SDL_CreateWindow(
+ "Tetris", windowX, windowY, windowWidth, windowHeight,
+ SDL_WindowFlags.SDL_WINDOW_SHOWN or SDL_WindowFlags.SDL_WINDOW_ALLOW_HIGHDPI
+ ) ?: error("")
+
+ renderer = SDL_CreateRenderer(window, -1, SDL_RendererFlags.SDL_RENDERER_ACCELERATED or SDL_RendererFlags.SDL_RENDERER_PRESENTVSYNC)
+ ?: error("")
+
+ val realWidth = IntByReference()
+ val realHeight = IntByReference()
+ SDL_GetRendererOutputSize(renderer, realWidth.pointer, realHeight.pointer)
+ if (platform != "iOS" && windowHeight != realHeight.value) {
+ println("DPI differs ${realWidth} x ${realHeight} vs $windowWidth x $windowHeight")
+ ratio = realHeight.value.toFloat() / windowHeight
+ }
+
+ texture = loadImage(renderer, "tetris_all.bmp")
+ }
+
+ private fun loadImage(ren: SDL_Renderer, imagePath: String): SDL_Texture {
+ val bmp = SDL_LoadBMP_RW(SDL_RWFromFile(imagePath, "rb"), 1)
+
+ val tex = SDL_CreateTextureFromSurface(ren, bmp) ?: error("")
+ SDL_FreeSurface(bmp)
+ return tex
+ }
+
+ override fun drawCell(x: Int, y: Int, cell: Byte) {
+ field[x][y] = cell
+ }
+
+ override fun drawNextPieceCell(x: Int, y: Int, cell: Byte) {
+ nextPieceField[x][y] = cell
+ }
+
+ override fun setInfo(linesCleared: Int, level: Int, score: Int, tetrises: Int) {
+ this.linesCleared = linesCleared
+ this.level = level
+ this.score = score
+ this.tetrises = tetrises
+ }
+
+ override fun refresh() {
+ SDL_RenderClear(renderer)
+ drawField()
+ drawInfo()
+ drawNextPiece()
+ drawGamePad()
+ SDL_RenderPresent(renderer)
+ }
+
+ private fun drawBorder(topLeftX: Int, topLeftY: Int, width: Int, height: Int) {
+ // Upper-left corner.
+ var srcX = CELLS_WIDTH
+ var srcY = 0
+ var destX = topLeftX
+ var destY = topLeftY
+ copyRect(srcX, srcY, destX, destY, BORDER_WIDTH + MARGIN, BORDER_WIDTH)
+
+ // Upper margin.
+ srcX += BORDER_WIDTH + MARGIN
+ destX += BORDER_WIDTH + MARGIN
+ for (i in 0..width - 1) {
+ copyRect(srcX, srcY, destX, destY, CELL_SIZE + MARGIN, BORDER_WIDTH)
+ destX += CELL_SIZE + MARGIN
+ }
+
+ // Upper-right corner.
+ srcX += CELL_SIZE + MARGIN
+ copyRect(srcX, srcY, destX, destY, BORDER_WIDTH, BORDER_WIDTH + MARGIN)
+
+ // Right margin.
+ srcY += BORDER_WIDTH + MARGIN
+ destY += BORDER_WIDTH + MARGIN
+ for (j in 0..height - 1) {
+ copyRect(srcX, srcY, destX, destY, BORDER_WIDTH, CELL_SIZE + MARGIN)
+ destY += CELL_SIZE + MARGIN
+ }
+
+ // Left margin.
+ srcX = CELLS_WIDTH
+ srcY = BORDER_WIDTH
+ destX = topLeftX
+ destY = topLeftY + BORDER_WIDTH
+ for (j in 0..height - 1) {
+ copyRect(srcX, srcY, destX, destY, BORDER_WIDTH, CELL_SIZE + MARGIN)
+ destY += CELL_SIZE + MARGIN
+ }
+
+ // Left-down corner.
+ srcY += CELL_SIZE + MARGIN
+ copyRect(srcX, srcY, destX, destY, BORDER_WIDTH, BORDER_WIDTH + MARGIN)
+
+ // Down marign.
+ srcX += BORDER_WIDTH
+ srcY += MARGIN
+ destX += BORDER_WIDTH
+ destY += MARGIN
+ for (i in 0..width - 1) {
+ copyRect(srcX, srcY, destX, destY, CELL_SIZE + MARGIN, BORDER_WIDTH)
+ destX += CELL_SIZE + MARGIN
+
+ }
+ // Right-down corner.
+ srcX += CELL_SIZE + MARGIN
+ copyRect(srcX, srcY, destX, destY, BORDER_WIDTH + MARGIN, BORDER_WIDTH)
+ }
+
+ private fun drawField() {
+ drawField(
+ field = field,
+ topLeftX = 0,
+ topLeftY = 0,
+ width = width,
+ height = height
+ )
+ }
+
+ private fun drawNextPiece() {
+ drawInt(
+ labelSrcX = LEVEL_LABEL_WIDTH,
+ labelSrcY = CELLS_HEIGHT + SYMBOL_SIZE,
+ labelDestX = fieldWidth + SYMBOL_SIZE,
+ labelDestY = getInfoY(5),
+ labelWidth = NEXT_LABEL_WIDTH,
+ totalDigits = 0,
+ value = 0
+ )
+ drawField(
+ field = nextPieceField,
+ topLeftX = fieldWidth + SYMBOL_SIZE,
+ topLeftY = getInfoY(6),
+ width = 4,
+ height = 4
+ )
+ }
+
+ private fun drawField(field: Field, topLeftX: Int, topLeftY: Int, width: Int, height: Int) {
+ drawBorder(
+ topLeftX = topLeftX,
+ topLeftY = topLeftY,
+ width = width,
+ height = height
+ )
+ for (i in 0..height - 1)
+ for (j in 0..width - 1) {
+ val cell = field[i][j].toInt()
+ if (cell == 0) continue
+ copyRect(
+ srcX = (level % COLORS) * CELL_SIZE,
+ srcY = (3 - cell) * CELL_SIZE,
+ destX = topLeftX + BORDER_WIDTH + MARGIN + j * (CELL_SIZE + MARGIN),
+ destY = topLeftY + BORDER_WIDTH + MARGIN + i * (CELL_SIZE + MARGIN),
+ width = CELL_SIZE,
+ height = CELL_SIZE
+ )
+ }
+ }
+
+ private fun drawInfo() {
+ drawInt(
+ labelSrcX = LINES_LABEL_WIDTH,
+ labelSrcY = CELLS_HEIGHT,
+ labelDestX = fieldWidth + SYMBOL_SIZE,
+ labelDestY = getInfoY(0),
+ labelWidth = SCORE_LABEL_WIDTH,
+ totalDigits = 6,
+ value = score
+ )
+ drawInt(
+ labelSrcX = 0,
+ labelSrcY = CELLS_HEIGHT,
+ labelDestX = fieldWidth + SYMBOL_SIZE,
+ labelDestY = getInfoY(1),
+ labelWidth = LINES_LABEL_WIDTH,
+ totalDigits = 3,
+ value = linesCleared
+ )
+ drawInt(
+ labelSrcX = 0,
+ labelSrcY = CELLS_HEIGHT + SYMBOL_SIZE,
+ labelDestX = fieldWidth + SYMBOL_SIZE,
+ labelDestY = getInfoY(2),
+ labelWidth = LEVEL_LABEL_WIDTH,
+ totalDigits = 2,
+ value = level
+ )
+ drawInt(
+ labelSrcX = 0,
+ labelSrcY = CELLS_HEIGHT + SYMBOL_SIZE * 2,
+ labelDestX = fieldWidth + SYMBOL_SIZE,
+ labelDestY = getInfoY(3),
+ labelWidth = TETRISES_LABEL_WIDTH,
+ totalDigits = 2,
+ value = tetrises
+ )
+ }
+
+ private fun getInfoY(line: Int): Int {
+ return SYMBOL_SIZE * (2 * line + 1) + INFO_MARGIN * line
+ }
+
+ private fun drawInt(
+ labelSrcX: Int, labelSrcY: Int, labelDestX: Int, labelDestY: Int,
+ labelWidth: Int, totalDigits: Int, value: Int
+ ) {
+ copyRect(
+ srcX = labelSrcX,
+ srcY = labelSrcY,
+ destX = labelDestX,
+ destY = labelDestY,
+ width = labelWidth,
+ height = SYMBOL_SIZE
+ )
+ val digits = IntArray(totalDigits)
+ var x = value
+ for (i in 0..totalDigits - 1) {
+ digits[totalDigits - 1 - i] = x % 10
+ x = x / 10
+ }
+ for (i in 0..totalDigits - 1) {
+ copyRect(
+ srcX = digits[i] * SYMBOL_SIZE,
+ srcY = CELLS_HEIGHT + 3 * SYMBOL_SIZE,
+ destX = labelDestX + SYMBOL_SIZE + i * SYMBOL_SIZE,
+ destY = labelDestY + SYMBOL_SIZE,
+ width = SYMBOL_SIZE,
+ height = SYMBOL_SIZE
+ )
+ }
+ }
+
+ private fun drawGamePad() {
+ if (gamePadButtons == null) return
+ SDL_SetRenderDrawColor(renderer, 127, 127, 127, SDL_ALPHA_OPAQUE.toByte())
+ fillRect(gamePadButtons.leftRect)
+ fillRect(gamePadButtons.downRect)
+ fillRect(gamePadButtons.dropRect)
+ fillRect(gamePadButtons.rightRect)
+ fillRect(gamePadButtons.rotateRect)
+ SDL_SetRenderDrawColor(renderer, 0, 0, 0, SDL_ALPHA_OPAQUE.toByte())
+ }
+
+ private fun fillRect(rect: SDL_Rect) {
+ val stretchedRect = SDL_Rect().apply {
+ w = stretch(rect.w)
+ h = stretch(rect.h)
+ x = stretch(rect.x)
+ y = stretch(rect.y)
+ }
+ SDL_RenderFillRect(renderer, stretchedRect)
+ }
+
+
+ private fun copyRect(srcX: Int, srcY: Int, destX: Int, destY: Int, width: Int, height: Int) {
+ val srcRect = SDL_Rect().apply {
+ w = width
+ h = height
+ x = srcX
+ y = srcY
+ }
+ val destRect = SDL_Rect().apply {
+ w = stretch(width)
+ h = stretch(height)
+ x = stretch(destX)
+ y = stretch(destY)
+ }
+ SDL_RenderCopy(renderer, texture, srcRect, destRect)
+ }
+
+ override fun readCommands(): List {
+ val commands = mutableListOf()
+ val event = SDL_Event()
+ SDL_PollEvent(event)
+ while (event != null) {
+ when (SDL_EventType.of(event.type)) {
+ SDL_EventType.SDL_QUIT -> commands.add(UserCommand.EXIT)
+ SDL_EventType.SDL_KEYDOWN -> {
+ val keyboardEvent = event.key
+ when (keyboardEvent.keysym.scancode.toInt()) {
+ SDL_Scancode.SDL_SCANCODE_LEFT.value -> commands.add(UserCommand.LEFT)
+ SDL_Scancode.SDL_SCANCODE_RIGHT.value -> commands.add(UserCommand.RIGHT)
+ SDL_Scancode.SDL_SCANCODE_DOWN.value -> commands.add(UserCommand.DOWN)
+ SDL_Scancode.SDL_SCANCODE_Z.value, SDL_Scancode.SDL_SCANCODE_SPACE.value -> commands.add(UserCommand.ROTATE)
+ SDL_Scancode.SDL_SCANCODE_UP.value -> commands.add(UserCommand.DROP)
+ SDL_Scancode.SDL_SCANCODE_ESCAPE.value -> commands.add(UserCommand.EXIT)
+ }
+ }
+ SDL_EventType.SDL_MOUSEBUTTONDOWN -> if (gamePadButtons != null) {
+ val mouseEvent = event as SDL_MouseButtonEvent
+ val x = mouseEvent.x
+ val y = mouseEvent.y
+ val command = gamePadButtons.getCommandAt(x, y)
+ if (command != null)
+ commands.add(command)
+ }
+
+ else -> { }
+ }
+
+ SDL_PollEvent(event)
+ }
+ return commands
+ }
+
+ fun destroy() {
+ SDL_DestroyTexture(texture)
+ SDL_DestroyRenderer(renderer)
+ SDL_DestroyWindow(window)
+ SDL_Quit()
+ }
+}
diff --git a/bindings/sdl/examples/snake/src/main/kotlin/io/ygdrasil/tetris/Tetris.kt b/bindings/sdl/examples/snake/src/main/kotlin/io/ygdrasil/tetris/Tetris.kt
new file mode 100644
index 00000000..b56b40bc
--- /dev/null
+++ b/bindings/sdl/examples/snake/src/main/kotlin/io/ygdrasil/tetris/Tetris.kt
@@ -0,0 +1,489 @@
+package io.ygdrasil.tetris
+
+import io.ygdrasil.libsdl.SDL_Delay
+import kotlin.random.Random
+
+typealias Field = Array
+
+enum class Move {
+ LEFT,
+ RIGHT,
+ DOWN,
+ ROTATE
+}
+
+enum class PlacementResult(val linesCleared: Int = 0, val bonus: Int = 0) {
+ NOTHING,
+ GAMEOVER,
+ // For values of bonuses see https://tetris.wiki/Scoring
+ SINGLE(1, 40),
+ DOUBLE(2, 100),
+ TRIPLE(3, 300),
+ TETRIS(4, 1200)
+}
+
+const val EMPTY: Byte = 0
+const val CELL1: Byte = 1
+const val CELL2: Byte = 2
+const val CELL3: Byte = 3
+const val BRICK: Byte = -1
+
+class Point(var x: Int, var y: Int)
+
+operator fun Point.plus(other: Point): Point {
+ return Point(x + other.x, y + other.y)
+}
+
+class PiecePosition(piece: Piece, private val origin: Point) {
+ private var p = piece.origin
+ val x get() = p.x + origin.x
+ val y get() = p.y + origin.y
+
+ var state: Int private set
+ val numberOfStates = piece.numberOfStates
+
+ init {
+ state = 0
+ }
+
+ fun makeMove(move: Move) {
+ when (move) {
+ Move.LEFT -> --p.y
+ Move.RIGHT -> ++p.y
+ Move.DOWN -> ++p.x
+ Move.ROTATE -> state = (state + 1) % numberOfStates
+ }
+ }
+
+ fun unMakeMove(move: Move) {
+ when (move) {
+ Move.LEFT -> ++p.y
+ Move.RIGHT -> --p.y
+ Move.DOWN -> --p.x
+ Move.ROTATE -> state = (state + numberOfStates - 1) % numberOfStates
+ }
+ }
+}
+
+/*
+ * We use Nintendo Rotation System, right-handed version.
+ * See https://tetris.wiki/Nintendo_Rotation_System
+ */
+enum class Piece(private val origin_: Point, private vararg val states: Field) {
+ T(
+ Point(-1, -2),
+ arrayOf(
+ byteArrayOf(EMPTY, EMPTY, EMPTY),
+ byteArrayOf(CELL1, CELL1, CELL1),
+ byteArrayOf(EMPTY, CELL1, EMPTY)),
+ arrayOf(
+ byteArrayOf(EMPTY, CELL1, EMPTY),
+ byteArrayOf(CELL1, CELL1, EMPTY),
+ byteArrayOf(EMPTY, CELL1, EMPTY)),
+ arrayOf(
+ byteArrayOf(EMPTY, CELL1, EMPTY),
+ byteArrayOf(CELL1, CELL1, CELL1),
+ byteArrayOf(EMPTY, EMPTY, EMPTY)),
+ arrayOf(
+ byteArrayOf(EMPTY, CELL1, EMPTY),
+ byteArrayOf(EMPTY, CELL1, CELL1),
+ byteArrayOf(EMPTY, CELL1, EMPTY))
+ ),
+ J(
+ Point(-1, -2),
+ arrayOf(
+ byteArrayOf(EMPTY, EMPTY, EMPTY),
+ byteArrayOf(CELL2, CELL2, CELL2),
+ byteArrayOf(EMPTY, EMPTY, CELL2)),
+ arrayOf(
+ byteArrayOf(EMPTY, CELL2, EMPTY),
+ byteArrayOf(EMPTY, CELL2, EMPTY),
+ byteArrayOf(CELL2, CELL2, EMPTY)),
+ arrayOf(
+ byteArrayOf(CELL2, EMPTY, EMPTY),
+ byteArrayOf(CELL2, CELL2, CELL2),
+ byteArrayOf(EMPTY, EMPTY, EMPTY)),
+ arrayOf(
+ byteArrayOf(EMPTY, CELL2, CELL2),
+ byteArrayOf(EMPTY, CELL2, EMPTY),
+ byteArrayOf(EMPTY, CELL2, EMPTY))
+ ),
+ Z(
+ Point(-1, -2),
+ arrayOf(
+ byteArrayOf(EMPTY, EMPTY, EMPTY),
+ byteArrayOf(CELL3, CELL3, EMPTY),
+ byteArrayOf(EMPTY, CELL3, CELL3)),
+ arrayOf(
+ byteArrayOf(EMPTY, EMPTY, CELL3),
+ byteArrayOf(EMPTY, CELL3, CELL3),
+ byteArrayOf(EMPTY, CELL3, EMPTY))
+ ),
+ O(
+ Point(0, -1),
+ arrayOf(
+ byteArrayOf(CELL1, CELL1),
+ byteArrayOf(CELL1, CELL1))
+ ),
+ S(
+ Point(-1, -2),
+ arrayOf(
+ byteArrayOf(EMPTY, EMPTY, EMPTY),
+ byteArrayOf(EMPTY, CELL2, CELL2),
+ byteArrayOf(CELL2, CELL2, EMPTY)),
+ arrayOf(
+ byteArrayOf(EMPTY, CELL2, EMPTY),
+ byteArrayOf(EMPTY, CELL2, CELL2),
+ byteArrayOf(EMPTY, EMPTY, CELL2))
+ ),
+ L(
+ Point(-1, -2),
+ arrayOf(
+ byteArrayOf(EMPTY, EMPTY, EMPTY),
+ byteArrayOf(CELL3, CELL3, CELL3),
+ byteArrayOf(CELL3, EMPTY, EMPTY)),
+ arrayOf(
+ byteArrayOf(CELL3, CELL3, EMPTY),
+ byteArrayOf(EMPTY, CELL3, EMPTY),
+ byteArrayOf(EMPTY, CELL3, EMPTY)),
+ arrayOf(
+ byteArrayOf(EMPTY, EMPTY, CELL3),
+ byteArrayOf(CELL3, CELL3, CELL3),
+ byteArrayOf(EMPTY, EMPTY, EMPTY)),
+ arrayOf(
+ byteArrayOf(EMPTY, CELL3, EMPTY),
+ byteArrayOf(EMPTY, CELL3, EMPTY),
+ byteArrayOf(EMPTY, CELL3, CELL3))
+ ),
+ I(
+ Point(-2, -2),
+ arrayOf(
+ byteArrayOf(EMPTY, EMPTY, EMPTY, EMPTY),
+ byteArrayOf(EMPTY, EMPTY, EMPTY, EMPTY),
+ byteArrayOf(CELL1, CELL1, CELL1, CELL1),
+ byteArrayOf(EMPTY, EMPTY, EMPTY, EMPTY)),
+ arrayOf(
+ byteArrayOf(EMPTY, EMPTY, CELL1, EMPTY),
+ byteArrayOf(EMPTY, EMPTY, CELL1, EMPTY),
+ byteArrayOf(EMPTY, EMPTY, CELL1, EMPTY),
+ byteArrayOf(EMPTY, EMPTY, CELL1, EMPTY))
+ );
+
+ val origin get() = Point(origin_.x, origin_.y)
+ val numberOfStates: Int = states.size
+
+ fun canBePlaced(field: Field, position: PiecePosition): Boolean {
+ val piece = states[position.state]
+ val x = position.x
+ val y = position.y
+ for (i in piece.indices) {
+ val pieceRow = piece[i]
+ val boardRow = field[x + i]
+ for (j in pieceRow.indices) {
+ if (pieceRow[j] != EMPTY && boardRow[y + j] != EMPTY)
+ return false
+ }
+ }
+ return true
+ }
+
+ fun place(field: Field, position: PiecePosition) {
+ val piece = states[position.state]
+ val x = position.x
+ val y = position.y
+ for (i in piece.indices) {
+ val pieceRow = piece[i]
+ for (j in pieceRow.indices) {
+ if (pieceRow[j] != EMPTY) field[x + i][y + j] = pieceRow[j]
+ }
+ }
+ }
+
+ fun unPlace(field: Field, position: PiecePosition) {
+ val piece = states[position.state]
+ val x = position.x
+ val y = position.y
+ for (i in piece.indices) {
+ val pieceRow = piece[i]
+ for (j in pieceRow.indices) {
+ if (pieceRow[j] != EMPTY) field[x + i][y + j] = EMPTY
+ }
+ }
+ }
+}
+
+interface GameFieldVisualizer {
+ fun drawCell(x: Int, y: Int, cell: Byte)
+ fun drawNextPieceCell(x: Int, y: Int, cell: Byte)
+ fun setInfo(linesCleared: Int, level: Int, score: Int, tetrises: Int)
+ fun refresh()
+}
+
+enum class UserCommand {
+ LEFT,
+ RIGHT,
+ DOWN,
+ DROP,
+ ROTATE,
+ EXIT
+}
+
+interface UserInput {
+ fun readCommands(): List
+}
+
+class GameField(val width: Int, val height: Int, val visualizer: GameFieldVisualizer) {
+ private val MARGIN = 4
+
+ private val field: Field = Array(height + MARGIN * 2) { ByteArray(width + MARGIN * 2) }
+ private val origin: Point
+ private val nextPieceField: Field
+
+ init {
+ for (i in field.indices) {
+ val row = field[i]
+ for (j in row.indices) {
+ if (i >= (MARGIN + height) // Bottom (field is flipped over).
+ || (j < MARGIN) // Left
+ || (j >= MARGIN + width)) // Right
+ row[j] = BRICK
+ }
+ }
+ // Coordinates are relative to the central axis and top of the field.
+ origin = Point(MARGIN, MARGIN + (width + 1) / 2)
+ nextPieceField = Array(4) { ByteArray(4) }
+ }
+
+ lateinit var currentPiece: Piece
+ lateinit var nextPiece: Piece
+ lateinit var currentPosition: PiecePosition
+
+ fun reset() {
+ for (i in 0..height - 1)
+ for (j in 0..width - 1)
+ field[i + MARGIN][j + MARGIN] = 0
+ nextPiece = getNextPiece(false)
+ switchCurrentPiece()
+ }
+
+ private fun getNextPiece(denyPrevious: Boolean): Piece {
+ val pieces = Piece.values()
+ if (!denyPrevious)
+ return pieces[Random.nextInt(pieces.size)]
+ while (true) {
+ val nextPiece = pieces[Random.nextInt(pieces.size)]
+ if (nextPiece != currentPiece) return nextPiece
+ }
+ }
+
+ private fun switchCurrentPiece() {
+ currentPiece = nextPiece
+ nextPiece = getNextPiece(denyPrevious = true) // Forbid repeating the same piece for better distribution.
+ currentPosition = PiecePosition(currentPiece, origin)
+ }
+
+ fun makeMove(move: Move): Boolean {
+ currentPosition.makeMove(move)
+ if (currentPiece.canBePlaced(field, currentPosition))
+ return true
+ currentPosition.unMakeMove(move)
+ return false
+ }
+
+ /**
+ * Places current piece at its current location.
+ */
+ fun place(): PlacementResult {
+ currentPiece.place(field, currentPosition)
+ val linesCleared = clearLines()
+ if (isOutOfBorders()) return PlacementResult.GAMEOVER
+ switchCurrentPiece()
+ if (!currentPiece.canBePlaced(field, currentPosition))
+ return PlacementResult.GAMEOVER
+ when (linesCleared) {
+ 1 -> return PlacementResult.SINGLE
+ 2 -> return PlacementResult.DOUBLE
+ 3 -> return PlacementResult.TRIPLE
+ 4 -> return PlacementResult.TETRIS
+ else -> return PlacementResult.NOTHING
+ }
+ }
+
+ private fun clearLines(): Int {
+ val clearedLines = mutableListOf()
+ for (i in 0..height - 1) {
+ val row = field[i + MARGIN]
+ if ((0..width - 1).all { j -> row[j + MARGIN] != EMPTY }) {
+ clearedLines.add(i + MARGIN)
+ (0..width - 1).forEach { j -> row[j + MARGIN] = EMPTY }
+ }
+ }
+ if (clearedLines.size == 0) return 0
+ draw(false)
+ visualizer.refresh()
+ SDL_Delay(500)
+ for (i in clearedLines) {
+ for (k in i - 1 downTo 1)
+ for (j in 0..width - 1)
+ field[k + 1][j + MARGIN] = field[k][j + MARGIN]
+ }
+ draw(false)
+ visualizer.refresh()
+ return clearedLines.size
+ }
+
+ private fun isOutOfBorders(): Boolean {
+ for (i in 0 until MARGIN)
+ for (j in 0 until width)
+ if (field[i][j + MARGIN] != EMPTY)
+ return true
+ return false
+ }
+
+ fun draw() {
+ draw(true)
+ drawNextPiece()
+ }
+
+ private fun drawNextPiece() {
+ for (i in 0..3)
+ for (j in 0..3)
+ nextPieceField[i][j] = 0
+ nextPiece.place(nextPieceField, PiecePosition(nextPiece, Point(1, 2)))
+ for (i in 0..3)
+ for (j in 0..3)
+ visualizer.drawNextPieceCell(i, j, nextPieceField[i][j])
+ }
+
+ private fun draw(drawCurrentPiece: Boolean) {
+ if (drawCurrentPiece)
+ currentPiece.place(field, currentPosition)
+ for (i in 0..height - 1)
+ for (j in 0..width - 1)
+ visualizer.drawCell(i, j, field[i + MARGIN][j + MARGIN])
+ if (drawCurrentPiece)
+ currentPiece.unPlace(field, currentPosition)
+ }
+}
+
+class Game(width: Int, height: Int, val visualizer: GameFieldVisualizer, val userInput: UserInput) {
+ private val field = GameField(width, height, visualizer)
+
+ private var gameOver = true
+ private var startLevel = 0
+ private var leveledUp = false
+ private var level = 0
+ private var linesClearedAtCurrentLevel = 0
+ private var linesCleared = 0
+ private var tetrises = 0
+ private var score = 0
+
+ /*
+ * For speed constants and level up thresholds see https://tetris.wiki/Tetris_(NES,_Nintendo)
+ */
+ private val speeds = intArrayOf(48, 43, 38, 33, 28, 23, 18, 13, 8, 6, 5, 5, 5, 4, 4, 4, 3, 3, 3,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2)
+ private val levelUpThreshold
+ get() =
+ if (leveledUp) 10
+ else minOf(startLevel * 10 + 10, maxOf(100, startLevel * 10 - 50))
+ private val speed get() = if (level < 29) speeds[level] else 1
+
+ private var ticks = 0
+
+ fun startNewGame() {
+ gameOver = false
+ startLevel = level
+ leveledUp = false
+ this.level = level
+ linesClearedAtCurrentLevel = 0
+ linesCleared = 0
+ tetrises = 0
+ score = 0
+ ticks = 0
+ field.reset()
+
+ visualizer.setInfo(linesCleared, level, score, tetrises)
+ field.draw()
+ visualizer.refresh()
+
+ mainLoop()
+ }
+
+ private fun placePiece() {
+ val placementResult = field.place()
+ ticks = 0
+ when (placementResult) {
+ PlacementResult.NOTHING -> return
+ PlacementResult.GAMEOVER -> {
+ gameOver = true
+ return
+ }
+ else -> {
+ linesCleared += placementResult.linesCleared
+ linesClearedAtCurrentLevel += placementResult.linesCleared
+ score += placementResult.bonus * (level + 1)
+ if (placementResult == PlacementResult.TETRIS)
+ ++tetrises
+ val levelUpThreshold = levelUpThreshold
+ if (linesClearedAtCurrentLevel >= levelUpThreshold) {
+ ++level
+ linesClearedAtCurrentLevel -= levelUpThreshold
+ leveledUp = true
+ }
+
+ visualizer.setInfo(linesCleared, level, score, tetrises)
+ }
+ }
+ }
+
+ /*
+ * Number of additional gravity shifts before locking a piece landed on the ground.
+ * This is needed in order to let user to move a piece to the left/right before locking.
+ */
+ private val LOCK_DELAY = 1
+
+ private fun mainLoop() {
+ var attemptsToLock = 0
+ while (!gameOver) {
+ SDL_Delay((1000 / 60)) // Refresh rate - 60 frames per second.
+ val commands = userInput.readCommands()
+ for (cmd in commands) {
+ val success: Boolean
+ when (cmd) {
+ UserCommand.EXIT -> return
+ UserCommand.LEFT -> success = field.makeMove(Move.LEFT)
+ UserCommand.RIGHT -> success = field.makeMove(Move.RIGHT)
+ UserCommand.ROTATE -> success = field.makeMove(Move.ROTATE)
+ UserCommand.DOWN -> {
+ success = field.makeMove(Move.DOWN)
+ if (!success) placePiece()
+ }
+ UserCommand.DROP -> {
+ while (field.makeMove(Move.DOWN)) {
+ }
+ success = true
+ placePiece()
+ }
+ }
+ if (success) {
+ field.draw()
+ visualizer.refresh()
+ }
+ }
+ ++ticks
+ if (ticks < speed) continue
+ if (!field.makeMove(Move.DOWN)) {
+ if (++attemptsToLock >= LOCK_DELAY) {
+ placePiece()
+ attemptsToLock = 0
+ }
+ }
+ field.draw()
+ visualizer.refresh()
+ ticks -= speed
+ }
+ }
+
+}
+
diff --git a/bindings/sdl/examples/snake/src/main/kotlin/io/ygdrasil/tetris/main.kt b/bindings/sdl/examples/snake/src/main/kotlin/io/ygdrasil/tetris/main.kt
new file mode 100644
index 00000000..ca988910
--- /dev/null
+++ b/bindings/sdl/examples/snake/src/main/kotlin/io/ygdrasil/tetris/main.kt
@@ -0,0 +1,11 @@
+package io.ygdrasil.tetris
+
+
+fun main() {
+
+ val visualizer = SDLView(10, 20)
+ val game = Game(10, 20, visualizer, visualizer)
+ game.startNewGame()
+
+ return
+}
\ No newline at end of file
diff --git a/bindings/sdl/libsdl/src/main/resources/Crowander-Stop-on-a-Bench.wav b/bindings/sdl/examples/snake/src/main/resources/Crowander-Stop-on-a-Bench.wav
similarity index 100%
rename from bindings/sdl/libsdl/src/main/resources/Crowander-Stop-on-a-Bench.wav
rename to bindings/sdl/examples/snake/src/main/resources/Crowander-Stop-on-a-Bench.wav
diff --git a/bindings/sdl/libsdl/src/main/resources/Font16_42_Normal4_sheet.bmp b/bindings/sdl/examples/snake/src/main/resources/Font16_42_Normal4_sheet.bmp
similarity index 100%
rename from bindings/sdl/libsdl/src/main/resources/Font16_42_Normal4_sheet.bmp
rename to bindings/sdl/examples/snake/src/main/resources/Font16_42_Normal4_sheet.bmp
diff --git a/bindings/sdl/libsdl/src/main/resources/License.txt b/bindings/sdl/examples/snake/src/main/resources/License.txt
similarity index 100%
rename from bindings/sdl/libsdl/src/main/resources/License.txt
rename to bindings/sdl/examples/snake/src/main/resources/License.txt
diff --git a/bindings/sdl/libsdl/src/main/resources/grass.bmp b/bindings/sdl/examples/snake/src/main/resources/grass.bmp
similarity index 100%
rename from bindings/sdl/libsdl/src/main/resources/grass.bmp
rename to bindings/sdl/examples/snake/src/main/resources/grass.bmp
diff --git a/bindings/sdl/libsdl/src/main/resources/snake-graphics.bmp b/bindings/sdl/examples/snake/src/main/resources/snake-graphics.bmp
similarity index 100%
rename from bindings/sdl/libsdl/src/main/resources/snake-graphics.bmp
rename to bindings/sdl/examples/snake/src/main/resources/snake-graphics.bmp
diff --git a/bindings/sdl/examples/tetris/build.gradle.kts b/bindings/sdl/examples/tetris/build.gradle.kts
new file mode 100644
index 00000000..00ea6754
--- /dev/null
+++ b/bindings/sdl/examples/tetris/build.gradle.kts
@@ -0,0 +1,19 @@
+
+plugins {
+ kotlin("jvm") version libs.versions.kotlin
+ application
+}
+
+dependencies {
+ api(project(":sdl2-4k"))
+ api(project(":sdl2-binaries"))
+ testImplementation("org.junit.jupiter:junit-jupiter")
+ testImplementation(libs.kotest)
+}
+
+
+application {
+ mainClass.set("tetris.MainKt")
+ applicationDefaultJvmArgs += "-XstartOnFirstThread"
+ tasks.run.get().workingDir = project.projectDir.resolve("src").resolve("main").resolve("resources")
+}
\ No newline at end of file
diff --git a/bindings/sdl/examples/tetris/src/main/kotlin/SDLView.kt b/bindings/sdl/examples/tetris/src/main/kotlin/SDLView.kt
new file mode 100644
index 00000000..17b8863a
--- /dev/null
+++ b/bindings/sdl/examples/tetris/src/main/kotlin/SDLView.kt
@@ -0,0 +1,465 @@
+package tetris
+
+import com.sun.jna.ptr.IntByReference
+import io.ygdrasil.libsdl.*
+
+class SDLView(private val width: Int, private val height: Int) : GameFieldVisualizer, UserInput {
+
+ fun error(message: Any): Nothing {
+ if (this::renderer.isInitialized) SDL_DestroyRenderer(renderer)
+ if (this::window.isInitialized) SDL_DestroyWindow(window)
+ println("$message: ${SDL_GetError()}")
+ SDL_Quit()
+ throw IllegalStateException()
+ }
+
+ private val CELL_SIZE = 20
+ private val COLORS = 10
+ private val CELLS_WIDTH = COLORS * CELL_SIZE
+ private val CELLS_HEIGHT = 3 * CELL_SIZE
+ private val SYMBOL_SIZE = 21
+ private val INFO_MARGIN = 10
+ private val MARGIN = 2
+ private val BORDER_WIDTH = 18
+ private val INFO_SPACE_WIDTH = SYMBOL_SIZE * (2 + 8)
+ private val LINES_LABEL_WIDTH = 104
+ private val SCORE_LABEL_WIDTH = 107
+ private val LEVEL_LABEL_WIDTH = 103
+ private val NEXT_LABEL_WIDTH = 85
+ private val TETRISES_LABEL_WIDTH = 162
+
+ private var ratio: Float
+
+ private fun stretch(value: Int) = (value.toFloat() * ratio + 0.5).toInt()
+
+ inner class GamePadButtons(width: Int, height: Int, gamePadHeight: Int) {
+ val MOVE_BUTTON_SIZE = 50
+ val ROTATE_BUTTON_SIZE = 80
+ val BUTTONS_MARGIN = 25
+
+ val leftRect: SDL_Rect
+ val rightRect: SDL_Rect
+ val downRect: SDL_Rect
+ val dropRect: SDL_Rect
+ val rotateRect: SDL_Rect
+
+ init {
+ val moveButtonsWidth = 3 * MOVE_BUTTON_SIZE + 2 * BUTTONS_MARGIN + BUTTONS_MARGIN
+ val x = (width - moveButtonsWidth - ROTATE_BUTTON_SIZE) / 2 - MOVE_BUTTON_SIZE
+ val y2 = (gamePadHeight - 2 * MOVE_BUTTON_SIZE - BUTTONS_MARGIN) / 2
+ leftRect = SDL_Rect()
+ leftRect.w = MOVE_BUTTON_SIZE
+ leftRect.h = MOVE_BUTTON_SIZE
+ leftRect.x = x
+ leftRect.y = height - gamePadHeight + y2 + MOVE_BUTTON_SIZE + BUTTONS_MARGIN
+
+ downRect = SDL_Rect()
+ downRect.w = MOVE_BUTTON_SIZE
+ downRect.h = MOVE_BUTTON_SIZE
+ downRect.x = x + MOVE_BUTTON_SIZE + BUTTONS_MARGIN
+ downRect.y = leftRect.y
+
+ dropRect = SDL_Rect().apply {
+ this.x = MOVE_BUTTON_SIZE
+ y = MOVE_BUTTON_SIZE
+ h = downRect.x
+ w =height - gamePadHeight + y2
+ }
+
+ rightRect = SDL_Rect()
+ rightRect.w = MOVE_BUTTON_SIZE
+ rightRect.h = MOVE_BUTTON_SIZE
+ rightRect.x = x + 2 * MOVE_BUTTON_SIZE + 2 * BUTTONS_MARGIN
+ rightRect.y = height - gamePadHeight + y2 + MOVE_BUTTON_SIZE + BUTTONS_MARGIN
+
+ rotateRect = SDL_Rect()
+ rotateRect.w = ROTATE_BUTTON_SIZE
+ rotateRect.h = ROTATE_BUTTON_SIZE
+ rotateRect.x = x + moveButtonsWidth
+ rotateRect.y = height - gamePadHeight + y2 - BUTTONS_MARGIN
+ }
+
+ fun getCommandAt(x: Int, y: Int): UserCommand? {
+ return when {
+ inside(leftRect, x, y) -> UserCommand.LEFT
+ inside(rightRect, x, y) -> UserCommand.RIGHT
+ inside(downRect, x, y) -> UserCommand.DOWN
+ inside(dropRect, x, y) -> UserCommand.DROP
+ inside(rotateRect, x, y) -> UserCommand.ROTATE
+ else -> null
+ }
+ }
+
+ private fun inside(rect: SDL_Rect, x: Int, y: Int): Boolean {
+ return x >= stretch(rect.x) && x <= stretch(rect.x + rect.w)
+ && y >= stretch(rect.y) && y <= stretch(rect.y + rect.h)
+ }
+
+ }
+
+ private val field: Field = Array(height) { ByteArray(width) }
+ private val nextPieceField: Field = Array(4) { ByteArray(4) }
+ private var linesCleared: Int = 0
+ private var level: Int = 0
+ private var score: Int = 0
+ private var tetrises: Int = 0
+
+ private var displayWidth: Int = 0
+ private var displayHeight: Int = 0
+ private val fieldWidth: Int
+ private val fieldHeight: Int
+ private var windowX: Int
+ private var windowY: Int
+ private lateinit var window: SDL_Window
+ private lateinit var renderer: SDL_Renderer
+ private val texture: SDL_Texture
+ private val gamePadButtons: GamePadButtons?
+
+ init {
+ if (SDL_Init(SDL_INIT_EVERYTHING.toInt()) != 0) {
+ throw Error("SDL_Init Error: ${SDL_GetError()}")
+ }
+
+ val platform: String = SDL_GetPlatform() ?: error("fail to get platform")
+
+ val displayMode = SDL_DisplayMode()
+ if (SDL_GetCurrentDisplayMode(0, displayMode) != 0) {
+ println("SDL_GetCurrentDisplayMode Error: ${SDL_GetError()}")
+ SDL_Quit()
+ throw Error()
+ }
+ displayWidth = displayMode.w
+ displayHeight = displayMode.h
+ fieldWidth = width * (CELL_SIZE + MARGIN) + MARGIN + BORDER_WIDTH * 2
+ fieldHeight = height * (CELL_SIZE + MARGIN) + MARGIN + BORDER_WIDTH * 2
+ var windowWidth = fieldWidth + INFO_SPACE_WIDTH
+ var windowHeight: Int
+ if (platform == "iOS") {
+ val gamePadHeight = (displayHeight * windowWidth - fieldHeight * displayWidth) / displayWidth
+ windowHeight = fieldHeight + gamePadHeight
+ gamePadButtons = GamePadButtons(windowWidth, windowHeight, gamePadHeight)
+ windowX = 0
+ windowY = 0
+ ratio = displayHeight.toFloat() / windowHeight
+ windowWidth = displayWidth
+ windowHeight = displayHeight
+ } else {
+ windowHeight = fieldHeight
+ gamePadButtons = null
+ windowX = (displayWidth - windowWidth) / 2
+ windowY = (displayHeight - windowHeight) / 2
+ ratio = 1.0f
+ }
+
+ window = SDL_CreateWindow(
+ "Tetris", windowX, windowY, windowWidth, windowHeight,
+ SDL_WindowFlags.SDL_WINDOW_SHOWN or SDL_WindowFlags.SDL_WINDOW_ALLOW_HIGHDPI
+ ) ?: error("")
+
+ renderer = SDL_CreateRenderer(window, -1, SDL_RendererFlags.SDL_RENDERER_ACCELERATED or SDL_RendererFlags.SDL_RENDERER_PRESENTVSYNC)
+ ?: error("")
+
+ val realWidth = IntByReference()
+ val realHeight = IntByReference()
+ SDL_GetRendererOutputSize(renderer, realWidth.pointer, realHeight.pointer)
+ if (platform != "iOS" && windowHeight != realHeight.value) {
+ println("DPI differs ${realWidth} x ${realHeight} vs $windowWidth x $windowHeight")
+ ratio = realHeight.value.toFloat() / windowHeight
+ }
+
+ texture = loadImage(renderer, "tetris_all.bmp")
+ }
+
+ private fun loadImage(ren: SDL_Renderer, imagePath: String): SDL_Texture {
+ val bmp = SDL_LoadBMP_RW(SDL_RWFromFile(imagePath, "rb"), 1)
+
+ val tex = SDL_CreateTextureFromSurface(ren, bmp) ?: error("")
+ SDL_FreeSurface(bmp)
+ return tex
+ }
+
+ override fun drawCell(x: Int, y: Int, cell: Byte) {
+ field[x][y] = cell
+ }
+
+ override fun drawNextPieceCell(x: Int, y: Int, cell: Byte) {
+ nextPieceField[x][y] = cell
+ }
+
+ override fun setInfo(linesCleared: Int, level: Int, score: Int, tetrises: Int) {
+ this.linesCleared = linesCleared
+ this.level = level
+ this.score = score
+ this.tetrises = tetrises
+ }
+
+ override fun refresh() {
+ SDL_RenderClear(renderer)
+ drawField()
+ drawInfo()
+ drawNextPiece()
+ drawGamePad()
+ SDL_RenderPresent(renderer)
+ }
+
+ private fun drawBorder(topLeftX: Int, topLeftY: Int, width: Int, height: Int) {
+ // Upper-left corner.
+ var srcX = CELLS_WIDTH
+ var srcY = 0
+ var destX = topLeftX
+ var destY = topLeftY
+ copyRect(srcX, srcY, destX, destY, BORDER_WIDTH + MARGIN, BORDER_WIDTH)
+
+ // Upper margin.
+ srcX += BORDER_WIDTH + MARGIN
+ destX += BORDER_WIDTH + MARGIN
+ for (i in 0..width - 1) {
+ copyRect(srcX, srcY, destX, destY, CELL_SIZE + MARGIN, BORDER_WIDTH)
+ destX += CELL_SIZE + MARGIN
+ }
+
+ // Upper-right corner.
+ srcX += CELL_SIZE + MARGIN
+ copyRect(srcX, srcY, destX, destY, BORDER_WIDTH, BORDER_WIDTH + MARGIN)
+
+ // Right margin.
+ srcY += BORDER_WIDTH + MARGIN
+ destY += BORDER_WIDTH + MARGIN
+ for (j in 0..height - 1) {
+ copyRect(srcX, srcY, destX, destY, BORDER_WIDTH, CELL_SIZE + MARGIN)
+ destY += CELL_SIZE + MARGIN
+ }
+
+ // Left margin.
+ srcX = CELLS_WIDTH
+ srcY = BORDER_WIDTH
+ destX = topLeftX
+ destY = topLeftY + BORDER_WIDTH
+ for (j in 0..height - 1) {
+ copyRect(srcX, srcY, destX, destY, BORDER_WIDTH, CELL_SIZE + MARGIN)
+ destY += CELL_SIZE + MARGIN
+ }
+
+ // Left-down corner.
+ srcY += CELL_SIZE + MARGIN
+ copyRect(srcX, srcY, destX, destY, BORDER_WIDTH, BORDER_WIDTH + MARGIN)
+
+ // Down marign.
+ srcX += BORDER_WIDTH
+ srcY += MARGIN
+ destX += BORDER_WIDTH
+ destY += MARGIN
+ for (i in 0..width - 1) {
+ copyRect(srcX, srcY, destX, destY, CELL_SIZE + MARGIN, BORDER_WIDTH)
+ destX += CELL_SIZE + MARGIN
+
+ }
+ // Right-down corner.
+ srcX += CELL_SIZE + MARGIN
+ copyRect(srcX, srcY, destX, destY, BORDER_WIDTH + MARGIN, BORDER_WIDTH)
+ }
+
+ private fun drawField() {
+ drawField(
+ field = field,
+ topLeftX = 0,
+ topLeftY = 0,
+ width = width,
+ height = height
+ )
+ }
+
+ private fun drawNextPiece() {
+ drawInt(
+ labelSrcX = LEVEL_LABEL_WIDTH,
+ labelSrcY = CELLS_HEIGHT + SYMBOL_SIZE,
+ labelDestX = fieldWidth + SYMBOL_SIZE,
+ labelDestY = getInfoY(5),
+ labelWidth = NEXT_LABEL_WIDTH,
+ totalDigits = 0,
+ value = 0
+ )
+ drawField(
+ field = nextPieceField,
+ topLeftX = fieldWidth + SYMBOL_SIZE,
+ topLeftY = getInfoY(6),
+ width = 4,
+ height = 4
+ )
+ }
+
+ private fun drawField(field: Field, topLeftX: Int, topLeftY: Int, width: Int, height: Int) {
+ drawBorder(
+ topLeftX = topLeftX,
+ topLeftY = topLeftY,
+ width = width,
+ height = height
+ )
+ for (i in 0..height - 1)
+ for (j in 0..width - 1) {
+ val cell = field[i][j].toInt()
+ if (cell == 0) continue
+ copyRect(
+ srcX = (level % COLORS) * CELL_SIZE,
+ srcY = (3 - cell) * CELL_SIZE,
+ destX = topLeftX + BORDER_WIDTH + MARGIN + j * (CELL_SIZE + MARGIN),
+ destY = topLeftY + BORDER_WIDTH + MARGIN + i * (CELL_SIZE + MARGIN),
+ width = CELL_SIZE,
+ height = CELL_SIZE
+ )
+ }
+ }
+
+ private fun drawInfo() {
+ drawInt(
+ labelSrcX = LINES_LABEL_WIDTH,
+ labelSrcY = CELLS_HEIGHT,
+ labelDestX = fieldWidth + SYMBOL_SIZE,
+ labelDestY = getInfoY(0),
+ labelWidth = SCORE_LABEL_WIDTH,
+ totalDigits = 6,
+ value = score
+ )
+ drawInt(
+ labelSrcX = 0,
+ labelSrcY = CELLS_HEIGHT,
+ labelDestX = fieldWidth + SYMBOL_SIZE,
+ labelDestY = getInfoY(1),
+ labelWidth = LINES_LABEL_WIDTH,
+ totalDigits = 3,
+ value = linesCleared
+ )
+ drawInt(
+ labelSrcX = 0,
+ labelSrcY = CELLS_HEIGHT + SYMBOL_SIZE,
+ labelDestX = fieldWidth + SYMBOL_SIZE,
+ labelDestY = getInfoY(2),
+ labelWidth = LEVEL_LABEL_WIDTH,
+ totalDigits = 2,
+ value = level
+ )
+ drawInt(
+ labelSrcX = 0,
+ labelSrcY = CELLS_HEIGHT + SYMBOL_SIZE * 2,
+ labelDestX = fieldWidth + SYMBOL_SIZE,
+ labelDestY = getInfoY(3),
+ labelWidth = TETRISES_LABEL_WIDTH,
+ totalDigits = 2,
+ value = tetrises
+ )
+ }
+
+ private fun getInfoY(line: Int): Int {
+ return SYMBOL_SIZE * (2 * line + 1) + INFO_MARGIN * line
+ }
+
+ private fun drawInt(
+ labelSrcX: Int, labelSrcY: Int, labelDestX: Int, labelDestY: Int,
+ labelWidth: Int, totalDigits: Int, value: Int
+ ) {
+ copyRect(
+ srcX = labelSrcX,
+ srcY = labelSrcY,
+ destX = labelDestX,
+ destY = labelDestY,
+ width = labelWidth,
+ height = SYMBOL_SIZE
+ )
+ val digits = IntArray(totalDigits)
+ var x = value
+ for (i in 0..totalDigits - 1) {
+ digits[totalDigits - 1 - i] = x % 10
+ x = x / 10
+ }
+ for (i in 0..totalDigits - 1) {
+ copyRect(
+ srcX = digits[i] * SYMBOL_SIZE,
+ srcY = CELLS_HEIGHT + 3 * SYMBOL_SIZE,
+ destX = labelDestX + SYMBOL_SIZE + i * SYMBOL_SIZE,
+ destY = labelDestY + SYMBOL_SIZE,
+ width = SYMBOL_SIZE,
+ height = SYMBOL_SIZE
+ )
+ }
+ }
+
+ private fun drawGamePad() {
+ if (gamePadButtons == null) return
+ SDL_SetRenderDrawColor(renderer, 127, 127, 127, SDL_ALPHA_OPAQUE.toByte())
+ fillRect(gamePadButtons.leftRect)
+ fillRect(gamePadButtons.downRect)
+ fillRect(gamePadButtons.dropRect)
+ fillRect(gamePadButtons.rightRect)
+ fillRect(gamePadButtons.rotateRect)
+ SDL_SetRenderDrawColor(renderer, 0, 0, 0, SDL_ALPHA_OPAQUE.toByte())
+ }
+
+ private fun fillRect(rect: SDL_Rect) {
+ val stretchedRect = SDL_Rect().apply {
+ w = stretch(rect.w)
+ h = stretch(rect.h)
+ x = stretch(rect.x)
+ y = stretch(rect.y)
+ }
+ SDL_RenderFillRect(renderer, stretchedRect)
+ }
+
+
+ private fun copyRect(srcX: Int, srcY: Int, destX: Int, destY: Int, width: Int, height: Int) {
+ val srcRect = SDL_Rect().apply {
+ w = width
+ h = height
+ x = srcX
+ y = srcY
+ }
+ val destRect = SDL_Rect().apply {
+ w = stretch(width)
+ h = stretch(height)
+ x = stretch(destX)
+ y = stretch(destY)
+ }
+ SDL_RenderCopy(renderer, texture, srcRect, destRect)
+ }
+
+ override fun readCommands(): List {
+ val commands = mutableListOf()
+ val event = SDL_Event()
+ SDL_PollEvent(event)
+ while (event != null) {
+ when (SDL_EventType.of(event.type)) {
+ SDL_EventType.SDL_QUIT -> commands.add(UserCommand.EXIT)
+ SDL_EventType.SDL_KEYDOWN -> {
+ val keyboardEvent = event.key
+ when (keyboardEvent.keysym.scancode.toInt()) {
+ SDL_Scancode.SDL_SCANCODE_LEFT.value -> commands.add(UserCommand.LEFT)
+ SDL_Scancode.SDL_SCANCODE_RIGHT.value -> commands.add(UserCommand.RIGHT)
+ SDL_Scancode.SDL_SCANCODE_DOWN.value -> commands.add(UserCommand.DOWN)
+ SDL_Scancode.SDL_SCANCODE_Z.value, SDL_Scancode.SDL_SCANCODE_SPACE.value -> commands.add(UserCommand.ROTATE)
+ SDL_Scancode.SDL_SCANCODE_UP.value -> commands.add(UserCommand.DROP)
+ SDL_Scancode.SDL_SCANCODE_ESCAPE.value -> commands.add(UserCommand.EXIT)
+ }
+ }
+ SDL_EventType.SDL_MOUSEBUTTONDOWN -> if (gamePadButtons != null) {
+ val mouseEvent = event as SDL_MouseButtonEvent
+ val x = mouseEvent.x
+ val y = mouseEvent.y
+ val command = gamePadButtons.getCommandAt(x, y)
+ if (command != null)
+ commands.add(command)
+ }
+
+ else -> { }
+ }
+
+ SDL_PollEvent(event)
+ }
+ return commands
+ }
+
+ fun destroy() {
+ SDL_DestroyTexture(texture)
+ SDL_DestroyRenderer(renderer)
+ SDL_DestroyWindow(window)
+ SDL_Quit()
+ }
+}
diff --git a/bindings/sdl/examples/tetris/src/main/kotlin/Tetris.kt b/bindings/sdl/examples/tetris/src/main/kotlin/Tetris.kt
new file mode 100644
index 00000000..6ce7e6f4
--- /dev/null
+++ b/bindings/sdl/examples/tetris/src/main/kotlin/Tetris.kt
@@ -0,0 +1,489 @@
+package tetris
+
+import io.ygdrasil.libsdl.SDL_Delay
+import kotlin.random.Random
+
+typealias Field = Array
+
+enum class Move {
+ LEFT,
+ RIGHT,
+ DOWN,
+ ROTATE
+}
+
+enum class PlacementResult(val linesCleared: Int = 0, val bonus: Int = 0) {
+ NOTHING,
+ GAMEOVER,
+ // For values of bonuses see https://tetris.wiki/Scoring
+ SINGLE(1, 40),
+ DOUBLE(2, 100),
+ TRIPLE(3, 300),
+ TETRIS(4, 1200)
+}
+
+const val EMPTY: Byte = 0
+const val CELL1: Byte = 1
+const val CELL2: Byte = 2
+const val CELL3: Byte = 3
+const val BRICK: Byte = -1
+
+class Point(var x: Int, var y: Int)
+
+operator fun Point.plus(other: Point): Point {
+ return Point(x + other.x, y + other.y)
+}
+
+class PiecePosition(piece: Piece, private val origin: Point) {
+ private var p = piece.origin
+ val x get() = p.x + origin.x
+ val y get() = p.y + origin.y
+
+ var state: Int private set
+ val numberOfStates = piece.numberOfStates
+
+ init {
+ state = 0
+ }
+
+ fun makeMove(move: Move) {
+ when (move) {
+ Move.LEFT -> --p.y
+ Move.RIGHT -> ++p.y
+ Move.DOWN -> ++p.x
+ Move.ROTATE -> state = (state + 1) % numberOfStates
+ }
+ }
+
+ fun unMakeMove(move: Move) {
+ when (move) {
+ Move.LEFT -> ++p.y
+ Move.RIGHT -> --p.y
+ Move.DOWN -> --p.x
+ Move.ROTATE -> state = (state + numberOfStates - 1) % numberOfStates
+ }
+ }
+}
+
+/*
+ * We use Nintendo Rotation System, right-handed version.
+ * See https://tetris.wiki/Nintendo_Rotation_System
+ */
+enum class Piece(private val origin_: Point, private vararg val states: Field) {
+ T(
+ Point(-1, -2),
+ arrayOf(
+ byteArrayOf(EMPTY, EMPTY, EMPTY),
+ byteArrayOf(CELL1, CELL1, CELL1),
+ byteArrayOf(EMPTY, CELL1, EMPTY)),
+ arrayOf(
+ byteArrayOf(EMPTY, CELL1, EMPTY),
+ byteArrayOf(CELL1, CELL1, EMPTY),
+ byteArrayOf(EMPTY, CELL1, EMPTY)),
+ arrayOf(
+ byteArrayOf(EMPTY, CELL1, EMPTY),
+ byteArrayOf(CELL1, CELL1, CELL1),
+ byteArrayOf(EMPTY, EMPTY, EMPTY)),
+ arrayOf(
+ byteArrayOf(EMPTY, CELL1, EMPTY),
+ byteArrayOf(EMPTY, CELL1, CELL1),
+ byteArrayOf(EMPTY, CELL1, EMPTY))
+ ),
+ J(
+ Point(-1, -2),
+ arrayOf(
+ byteArrayOf(EMPTY, EMPTY, EMPTY),
+ byteArrayOf(CELL2, CELL2, CELL2),
+ byteArrayOf(EMPTY, EMPTY, CELL2)),
+ arrayOf(
+ byteArrayOf(EMPTY, CELL2, EMPTY),
+ byteArrayOf(EMPTY, CELL2, EMPTY),
+ byteArrayOf(CELL2, CELL2, EMPTY)),
+ arrayOf(
+ byteArrayOf(CELL2, EMPTY, EMPTY),
+ byteArrayOf(CELL2, CELL2, CELL2),
+ byteArrayOf(EMPTY, EMPTY, EMPTY)),
+ arrayOf(
+ byteArrayOf(EMPTY, CELL2, CELL2),
+ byteArrayOf(EMPTY, CELL2, EMPTY),
+ byteArrayOf(EMPTY, CELL2, EMPTY))
+ ),
+ Z(
+ Point(-1, -2),
+ arrayOf(
+ byteArrayOf(EMPTY, EMPTY, EMPTY),
+ byteArrayOf(CELL3, CELL3, EMPTY),
+ byteArrayOf(EMPTY, CELL3, CELL3)),
+ arrayOf(
+ byteArrayOf(EMPTY, EMPTY, CELL3),
+ byteArrayOf(EMPTY, CELL3, CELL3),
+ byteArrayOf(EMPTY, CELL3, EMPTY))
+ ),
+ O(
+ Point(0, -1),
+ arrayOf(
+ byteArrayOf(CELL1, CELL1),
+ byteArrayOf(CELL1, CELL1))
+ ),
+ S(
+ Point(-1, -2),
+ arrayOf(
+ byteArrayOf(EMPTY, EMPTY, EMPTY),
+ byteArrayOf(EMPTY, CELL2, CELL2),
+ byteArrayOf(CELL2, CELL2, EMPTY)),
+ arrayOf(
+ byteArrayOf(EMPTY, CELL2, EMPTY),
+ byteArrayOf(EMPTY, CELL2, CELL2),
+ byteArrayOf(EMPTY, EMPTY, CELL2))
+ ),
+ L(
+ Point(-1, -2),
+ arrayOf(
+ byteArrayOf(EMPTY, EMPTY, EMPTY),
+ byteArrayOf(CELL3, CELL3, CELL3),
+ byteArrayOf(CELL3, EMPTY, EMPTY)),
+ arrayOf(
+ byteArrayOf(CELL3, CELL3, EMPTY),
+ byteArrayOf(EMPTY, CELL3, EMPTY),
+ byteArrayOf(EMPTY, CELL3, EMPTY)),
+ arrayOf(
+ byteArrayOf(EMPTY, EMPTY, CELL3),
+ byteArrayOf(CELL3, CELL3, CELL3),
+ byteArrayOf(EMPTY, EMPTY, EMPTY)),
+ arrayOf(
+ byteArrayOf(EMPTY, CELL3, EMPTY),
+ byteArrayOf(EMPTY, CELL3, EMPTY),
+ byteArrayOf(EMPTY, CELL3, CELL3))
+ ),
+ I(
+ Point(-2, -2),
+ arrayOf(
+ byteArrayOf(EMPTY, EMPTY, EMPTY, EMPTY),
+ byteArrayOf(EMPTY, EMPTY, EMPTY, EMPTY),
+ byteArrayOf(CELL1, CELL1, CELL1, CELL1),
+ byteArrayOf(EMPTY, EMPTY, EMPTY, EMPTY)),
+ arrayOf(
+ byteArrayOf(EMPTY, EMPTY, CELL1, EMPTY),
+ byteArrayOf(EMPTY, EMPTY, CELL1, EMPTY),
+ byteArrayOf(EMPTY, EMPTY, CELL1, EMPTY),
+ byteArrayOf(EMPTY, EMPTY, CELL1, EMPTY))
+ );
+
+ val origin get() = Point(origin_.x, origin_.y)
+ val numberOfStates: Int = states.size
+
+ fun canBePlaced(field: Field, position: PiecePosition): Boolean {
+ val piece = states[position.state]
+ val x = position.x
+ val y = position.y
+ for (i in piece.indices) {
+ val pieceRow = piece[i]
+ val boardRow = field[x + i]
+ for (j in pieceRow.indices) {
+ if (pieceRow[j] != EMPTY && boardRow[y + j] != EMPTY)
+ return false
+ }
+ }
+ return true
+ }
+
+ fun place(field: Field, position: PiecePosition) {
+ val piece = states[position.state]
+ val x = position.x
+ val y = position.y
+ for (i in piece.indices) {
+ val pieceRow = piece[i]
+ for (j in pieceRow.indices) {
+ if (pieceRow[j] != EMPTY) field[x + i][y + j] = pieceRow[j]
+ }
+ }
+ }
+
+ fun unPlace(field: Field, position: PiecePosition) {
+ val piece = states[position.state]
+ val x = position.x
+ val y = position.y
+ for (i in piece.indices) {
+ val pieceRow = piece[i]
+ for (j in pieceRow.indices) {
+ if (pieceRow[j] != EMPTY) field[x + i][y + j] = EMPTY
+ }
+ }
+ }
+}
+
+interface GameFieldVisualizer {
+ fun drawCell(x: Int, y: Int, cell: Byte)
+ fun drawNextPieceCell(x: Int, y: Int, cell: Byte)
+ fun setInfo(linesCleared: Int, level: Int, score: Int, tetrises: Int)
+ fun refresh()
+}
+
+enum class UserCommand {
+ LEFT,
+ RIGHT,
+ DOWN,
+ DROP,
+ ROTATE,
+ EXIT
+}
+
+interface UserInput {
+ fun readCommands(): List
+}
+
+class GameField(val width: Int, val height: Int, val visualizer: GameFieldVisualizer) {
+ private val MARGIN = 4
+
+ private val field: Field = Array(height + MARGIN * 2) { ByteArray(width + MARGIN * 2) }
+ private val origin: Point
+ private val nextPieceField: Field
+
+ init {
+ for (i in field.indices) {
+ val row = field[i]
+ for (j in row.indices) {
+ if (i >= (MARGIN + height) // Bottom (field is flipped over).
+ || (j < MARGIN) // Left
+ || (j >= MARGIN + width)) // Right
+ row[j] = BRICK
+ }
+ }
+ // Coordinates are relative to the central axis and top of the field.
+ origin = Point(MARGIN, MARGIN + (width + 1) / 2)
+ nextPieceField = Array(4) { ByteArray(4) }
+ }
+
+ lateinit var currentPiece: Piece
+ lateinit var nextPiece: Piece
+ lateinit var currentPosition: PiecePosition
+
+ fun reset() {
+ for (i in 0..height - 1)
+ for (j in 0..width - 1)
+ field[i + MARGIN][j + MARGIN] = 0
+ nextPiece = getNextPiece(false)
+ switchCurrentPiece()
+ }
+
+ private fun getNextPiece(denyPrevious: Boolean): Piece {
+ val pieces = Piece.values()
+ if (!denyPrevious)
+ return pieces[Random.nextInt(pieces.size)]
+ while (true) {
+ val nextPiece = pieces[Random.nextInt(pieces.size)]
+ if (nextPiece != currentPiece) return nextPiece
+ }
+ }
+
+ private fun switchCurrentPiece() {
+ currentPiece = nextPiece
+ nextPiece = getNextPiece(denyPrevious = true) // Forbid repeating the same piece for better distribution.
+ currentPosition = PiecePosition(currentPiece, origin)
+ }
+
+ fun makeMove(move: Move): Boolean {
+ currentPosition.makeMove(move)
+ if (currentPiece.canBePlaced(field, currentPosition))
+ return true
+ currentPosition.unMakeMove(move)
+ return false
+ }
+
+ /**
+ * Places current piece at its current location.
+ */
+ fun place(): PlacementResult {
+ currentPiece.place(field, currentPosition)
+ val linesCleared = clearLines()
+ if (isOutOfBorders()) return PlacementResult.GAMEOVER
+ switchCurrentPiece()
+ if (!currentPiece.canBePlaced(field, currentPosition))
+ return PlacementResult.GAMEOVER
+ when (linesCleared) {
+ 1 -> return PlacementResult.SINGLE
+ 2 -> return PlacementResult.DOUBLE
+ 3 -> return PlacementResult.TRIPLE
+ 4 -> return PlacementResult.TETRIS
+ else -> return PlacementResult.NOTHING
+ }
+ }
+
+ private fun clearLines(): Int {
+ val clearedLines = mutableListOf()
+ for (i in 0..height - 1) {
+ val row = field[i + MARGIN]
+ if ((0..width - 1).all { j -> row[j + MARGIN] != EMPTY }) {
+ clearedLines.add(i + MARGIN)
+ (0..width - 1).forEach { j -> row[j + MARGIN] = EMPTY }
+ }
+ }
+ if (clearedLines.size == 0) return 0
+ draw(false)
+ visualizer.refresh()
+ SDL_Delay(500)
+ for (i in clearedLines) {
+ for (k in i - 1 downTo 1)
+ for (j in 0..width - 1)
+ field[k + 1][j + MARGIN] = field[k][j + MARGIN]
+ }
+ draw(false)
+ visualizer.refresh()
+ return clearedLines.size
+ }
+
+ private fun isOutOfBorders(): Boolean {
+ for (i in 0 until MARGIN)
+ for (j in 0 until width)
+ if (field[i][j + MARGIN] != EMPTY)
+ return true
+ return false
+ }
+
+ fun draw() {
+ draw(true)
+ drawNextPiece()
+ }
+
+ private fun drawNextPiece() {
+ for (i in 0..3)
+ for (j in 0..3)
+ nextPieceField[i][j] = 0
+ nextPiece.place(nextPieceField, PiecePosition(nextPiece, Point(1, 2)))
+ for (i in 0..3)
+ for (j in 0..3)
+ visualizer.drawNextPieceCell(i, j, nextPieceField[i][j])
+ }
+
+ private fun draw(drawCurrentPiece: Boolean) {
+ if (drawCurrentPiece)
+ currentPiece.place(field, currentPosition)
+ for (i in 0..height - 1)
+ for (j in 0..width - 1)
+ visualizer.drawCell(i, j, field[i + MARGIN][j + MARGIN])
+ if (drawCurrentPiece)
+ currentPiece.unPlace(field, currentPosition)
+ }
+}
+
+class Game(width: Int, height: Int, val visualizer: GameFieldVisualizer, val userInput: UserInput) {
+ private val field = GameField(width, height, visualizer)
+
+ private var gameOver = true
+ private var startLevel = 0
+ private var leveledUp = false
+ private var level = 0
+ private var linesClearedAtCurrentLevel = 0
+ private var linesCleared = 0
+ private var tetrises = 0
+ private var score = 0
+
+ /*
+ * For speed constants and level up thresholds see https://tetris.wiki/Tetris_(NES,_Nintendo)
+ */
+ private val speeds = intArrayOf(48, 43, 38, 33, 28, 23, 18, 13, 8, 6, 5, 5, 5, 4, 4, 4, 3, 3, 3,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2)
+ private val levelUpThreshold
+ get() =
+ if (leveledUp) 10
+ else minOf(startLevel * 10 + 10, maxOf(100, startLevel * 10 - 50))
+ private val speed get() = if (level < 29) speeds[level] else 1
+
+ private var ticks = 0
+
+ fun startNewGame() {
+ gameOver = false
+ startLevel = level
+ leveledUp = false
+ this.level = level
+ linesClearedAtCurrentLevel = 0
+ linesCleared = 0
+ tetrises = 0
+ score = 0
+ ticks = 0
+ field.reset()
+
+ visualizer.setInfo(linesCleared, level, score, tetrises)
+ field.draw()
+ visualizer.refresh()
+
+ mainLoop()
+ }
+
+ private fun placePiece() {
+ val placementResult = field.place()
+ ticks = 0
+ when (placementResult) {
+ PlacementResult.NOTHING -> return
+ PlacementResult.GAMEOVER -> {
+ gameOver = true
+ return
+ }
+ else -> {
+ linesCleared += placementResult.linesCleared
+ linesClearedAtCurrentLevel += placementResult.linesCleared
+ score += placementResult.bonus * (level + 1)
+ if (placementResult == PlacementResult.TETRIS)
+ ++tetrises
+ val levelUpThreshold = levelUpThreshold
+ if (linesClearedAtCurrentLevel >= levelUpThreshold) {
+ ++level
+ linesClearedAtCurrentLevel -= levelUpThreshold
+ leveledUp = true
+ }
+
+ visualizer.setInfo(linesCleared, level, score, tetrises)
+ }
+ }
+ }
+
+ /*
+ * Number of additional gravity shifts before locking a piece landed on the ground.
+ * This is needed in order to let user to move a piece to the left/right before locking.
+ */
+ private val LOCK_DELAY = 1
+
+ private fun mainLoop() {
+ var attemptsToLock = 0
+ while (!gameOver) {
+ SDL_Delay((1000 / 60)) // Refresh rate - 60 frames per second.
+ val commands = userInput.readCommands()
+ for (cmd in commands) {
+ val success: Boolean
+ when (cmd) {
+ UserCommand.EXIT -> return
+ UserCommand.LEFT -> success = field.makeMove(Move.LEFT)
+ UserCommand.RIGHT -> success = field.makeMove(Move.RIGHT)
+ UserCommand.ROTATE -> success = field.makeMove(Move.ROTATE)
+ UserCommand.DOWN -> {
+ success = field.makeMove(Move.DOWN)
+ if (!success) placePiece()
+ }
+ UserCommand.DROP -> {
+ while (field.makeMove(Move.DOWN)) {
+ }
+ success = true
+ placePiece()
+ }
+ }
+ if (success) {
+ field.draw()
+ visualizer.refresh()
+ }
+ }
+ ++ticks
+ if (ticks < speed) continue
+ if (!field.makeMove(Move.DOWN)) {
+ if (++attemptsToLock >= LOCK_DELAY) {
+ placePiece()
+ attemptsToLock = 0
+ }
+ }
+ field.draw()
+ visualizer.refresh()
+ ticks -= speed
+ }
+ }
+
+}
+
diff --git a/bindings/sdl/examples/tetris/src/main/kotlin/main.kt b/bindings/sdl/examples/tetris/src/main/kotlin/main.kt
new file mode 100644
index 00000000..b78e5c5a
--- /dev/null
+++ b/bindings/sdl/examples/tetris/src/main/kotlin/main.kt
@@ -0,0 +1,11 @@
+package tetris
+
+
+fun main() {
+
+ val visualizer = SDLView(10, 20)
+ val game = Game(10, 20, visualizer, visualizer)
+ game.startNewGame()
+
+ return
+}
\ No newline at end of file
diff --git a/bindings/sdl/examples/tetris/src/main/resources/tetris_all.bmp b/bindings/sdl/examples/tetris/src/main/resources/tetris_all.bmp
new file mode 100644
index 00000000..e5c57a6c
Binary files /dev/null and b/bindings/sdl/examples/tetris/src/main/resources/tetris_all.bmp differ
diff --git a/bindings/sdl/gradle.properties b/bindings/sdl/gradle.properties
new file mode 100644
index 00000000..1a9f3845
--- /dev/null
+++ b/bindings/sdl/gradle.properties
@@ -0,0 +1,3 @@
+# Enable to use panama class on klang gradle plugin
+org.gradle.jvmargs=--enable-preview
+org.gradle.daemon=false
\ No newline at end of file
diff --git a/bindings/sdl/gradle/libs.versions.toml b/bindings/sdl/gradle/libs.versions.toml
index 12809027..849f8965 100644
--- a/bindings/sdl/gradle/libs.versions.toml
+++ b/bindings/sdl/gradle/libs.versions.toml
@@ -2,6 +2,7 @@
kotest = "5.6.1"
klang = "0.0.0"
jna = "5.13.0"
+kotlin = "1.9.22"
[libraries]
kotest = { module = "io.kotest:kotest-runner-junit5-jvm", version.ref = "kotest" }
diff --git a/bindings/sdl/gradle/wrapper/gradle-wrapper.properties b/bindings/sdl/gradle/wrapper/gradle-wrapper.properties
index c30b486a..3499ded5 100644
--- a/bindings/sdl/gradle/wrapper/gradle-wrapper.properties
+++ b/bindings/sdl/gradle/wrapper/gradle-wrapper.properties
@@ -1,6 +1,6 @@
distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
-distributionUrl=https\://services.gradle.org/distributions/gradle-8.3-bin.zip
+distributionUrl=https\://services.gradle.org/distributions/gradle-8.5-bin.zip
networkTimeout=10000
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists
diff --git a/bindings/sdl/libsdl/build.gradle.kts b/bindings/sdl/libsdl/build.gradle.kts
index 33786408..f76e2ce8 100644
--- a/bindings/sdl/libsdl/build.gradle.kts
+++ b/bindings/sdl/libsdl/build.gradle.kts
@@ -1,8 +1,10 @@
+import io.ygdrasil.ParsingMethod
+import klang.domain.TypeRefField
import klang.domain.typeOf
import klang.domain.unchecked
import org.gradle.api.tasks.testing.logging.TestExceptionFormat
import org.gradle.api.tasks.testing.logging.TestLogEvent
-import java.net.URL
+import java.net.URI
buildscript {
dependencies {
@@ -16,7 +18,7 @@ buildscript {
}
plugins {
- kotlin("jvm") version "1.9.10"
+ kotlin("jvm") version libs.versions.kotlin
alias(libs.plugins.klang)
}
@@ -50,12 +52,16 @@ sourceSets.main {
java.srcDirs(buildDir)
}
-val headerUrl = URL("https://github.com/klang-toolkit/SDL-binary/releases/download/2.28.2-Alpha3/headers.zip")
+val headerUrl = URI("https://github.com/klang-toolkit/SDL-binary/releases/download/2.30.0/headers.zip")
+ .toURL() ?: error("cannot create header url")
klang {
+
+ parsingMethod = ParsingMethod.Libclang
+
download(headerUrl)
.let(::unpack)
- .let {
+ .let { it ->
parse(fileToParse = "SDL2/SDL.h", at = it) {
findTypeAliasByName("Uint8")?.apply {
// Type is dumped as Int instead of char
@@ -64,15 +70,25 @@ klang {
// Replace SDL_PixelFormat by void * to avoid circular dependency when calculating size of structure
findStructureByName("SDL_PixelFormat")?.apply {
- fields = fields.map { (name, fields) ->
- when (name) {
- "next" -> name to typeOf("void *").unchecked()
- else -> name to fields
- }
- }
+ fields = fields
+ .filterIsInstance()
+ .map { (name, fields) ->
+ when (name) {
+ "next" -> name to typeOf("void *").unchecked()
+ else -> name to fields
+ }
+ }.map { TypeRefField(it.first, it.second) }
}
}
+ parse(fileToParse = "SDL2/SDL_syswm.h", at = it)
}
- generateBinding("libsdl", "SDL2")
+ generateBinding("io.ygdrasil.libsdl", "SDL2")
}
+
+tasks.named("compileJava", JavaCompile::class.java) {
+ options.compilerArgumentProviders.add(CommandLineArgumentProvider {
+ // Provide compiled Kotlin classes to javac – needed for Java/Kotlin mixed sources to work
+ listOf("--patch-module", "io.ygdrasil.libsdl=${sourceSets["main"].output.asPath}")
+ })
+}
\ No newline at end of file
diff --git a/bindings/sdl/libsdl/src/main/java/module-info.java b/bindings/sdl/libsdl/src/main/java/module-info.java
new file mode 100644
index 00000000..4bffb2f3
--- /dev/null
+++ b/bindings/sdl/libsdl/src/main/java/module-info.java
@@ -0,0 +1,5 @@
+module io.ygdrasil.libsdl {
+ requires kotlin.stdlib;
+ requires com.sun.jna;
+ exports io.ygdrasil.libsdl;
+}
\ No newline at end of file
diff --git a/bindings/sdl/libsdl/src/main/kotlin/libsdl/Constants.kt b/bindings/sdl/libsdl/src/main/kotlin/libsdl/Constants.kt
deleted file mode 100644
index 89f05881..00000000
--- a/bindings/sdl/libsdl/src/main/kotlin/libsdl/Constants.kt
+++ /dev/null
@@ -1,16 +0,0 @@
-package libsdl
-
-const val SDL_INIT_TIMER: Int = 0x00000001
-const val SDL_INIT_AUDIO: Int = 0x00000010
-const val SDL_INIT_VIDEO: Int = 0x00000020 // SDL_INIT_VIDEO implies SDL_INIT_EVENTS
-const val SDL_INIT_JOYSTICK: Int = 0x00000200 // SDL_INIT_JOYSTICK implies SDL_INIT_EVENTS
-const val SDL_INIT_HAPTIC: Int = 0x00001000
-const val SDL_INIT_GAMECONTROLLER: Int = 0x00002000 // SDL_INIT_GAMECONTROLLER implies SDL_INIT_JOYSTICK
-const val SDL_INIT_EVENTS: Int = 0x00004000
-const val SDL_INIT_SENSOR: Int = 0x00008000
-const val SDL_INIT_NOPARACHUTE: Int = 0x00100000 // compatibility; this flag is ignored.
-
-val SDL_INIT_EVERYTHING: Int = SDL_INIT_TIMER or SDL_INIT_AUDIO or SDL_INIT_VIDEO or SDL_INIT_EVENTS or SDL_INIT_JOYSTICK or SDL_INIT_HAPTIC or SDL_INIT_GAMECONTROLLER or SDL_INIT_SENSOR
-
-
-const val SDL_ALPHA_OPAQUE: Byte = 255.toByte()
\ No newline at end of file
diff --git a/bindings/sdl/libsdl/src/main/kotlin/libsdl/FixTypeAlias.kt b/bindings/sdl/libsdl/src/main/kotlin/libsdl/FixTypeAlias.kt
index a47079eb..08daf7e4 100644
--- a/bindings/sdl/libsdl/src/main/kotlin/libsdl/FixTypeAlias.kt
+++ b/bindings/sdl/libsdl/src/main/kotlin/libsdl/FixTypeAlias.kt
@@ -1,92 +1,5 @@
-package libsdl
+package io.ygdrasil.libsdl
import com.sun.jna.Pointer
-import com.sun.jna.PointerType
-import com.sun.jna.ptr.PointerByReference
-typealias SDL_iconv_t = Pointer
-typealias SDL_JoystickGUID = Pointer
-
-public class SDL_Haptic : PointerType {
- public constructor() : super()
-
- public constructor(pointer: Pointer?) : super(pointer)
-
- public class ByReference : PointerByReference {
- public constructor() : super()
-
- public constructor(pointer: Pointer?) : super(pointer)
- }
-}
-
-public class SDL_AudioStream : PointerType {
- public constructor() : super()
-
- public constructor(pointer: Pointer?) : super(pointer)
-
- public class ByReference : PointerByReference {
- public constructor() : super()
-
- public constructor(pointer: Pointer?) : super(pointer)
- }
-}
-
-public class SDL_hid_device : PointerType {
- public constructor() : super()
-
- public constructor(pointer: Pointer?) : super(pointer)
-
- public class ByReference : PointerByReference {
- public constructor() : super()
-
- public constructor(pointer: Pointer?) : super(pointer)
- }
-}
-
-public class SDL_GameController : PointerType {
- public constructor() : super()
-
- public constructor(pointer: Pointer?) : super(pointer)
-
- public class ByReference : PointerByReference {
- public constructor() : super()
-
- public constructor(pointer: Pointer?) : super(pointer)
- }
-}
-
-public class SDL_Sensor : PointerType {
- public constructor() : super()
-
- public constructor(pointer: Pointer?) : super(pointer)
-
- public class ByReference : PointerByReference {
- public constructor() : super()
-
- public constructor(pointer: Pointer?) : super(pointer)
- }
-}
-
-public class SDL_sem : PointerType {
- public constructor() : super()
-
- public constructor(pointer: Pointer?) : super(pointer)
-
- public class ByReference : PointerByReference {
- public constructor() : super()
-
- public constructor(pointer: Pointer?) : super(pointer)
- }
-}
-
-public class SDL_Joystick : PointerType {
- public constructor() : super()
-
- public constructor(pointer: Pointer?) : super(pointer)
-
- public class ByReference : PointerByReference {
- public constructor() : super()
-
- public constructor(pointer: Pointer?) : super(pointer)
- }
-}
\ No newline at end of file
+typealias va_list = Pointer
diff --git a/bindings/sdl/libsdl/src/main/kotlin/libsdl/UnionDelegate.kt b/bindings/sdl/libsdl/src/main/kotlin/libsdl/UnionDelegate.kt
index a6d61fe1..4d355b0a 100644
--- a/bindings/sdl/libsdl/src/main/kotlin/libsdl/UnionDelegate.kt
+++ b/bindings/sdl/libsdl/src/main/kotlin/libsdl/UnionDelegate.kt
@@ -1,6 +1,6 @@
-package libsdl
+package io.ygdrasil.libsdl
-import libsdl.SDL_EventType.*
+import io.ygdrasil.libsdl.SDL_EventType.*
object SDL_HapticEffectDelegate {
fun read(union: SDL_HapticEffect) {
diff --git a/bindings/sdl/libsdl/src/main/kotlin/main.kt b/bindings/sdl/libsdl/src/main/kotlin/main.kt
deleted file mode 100644
index 2e435ec9..00000000
--- a/bindings/sdl/libsdl/src/main/kotlin/main.kt
+++ /dev/null
@@ -1,49 +0,0 @@
-import com.sun.jna.Pointer
-import libsdl.SDL_WindowFlags
-import libsdl.libSDL2Library
-
-typealias unnamed = Pointer
-
-const val SDL_INIT_TIMER: Int = 0x00000001
-const val SDL_INIT_AUDIO: Int = 0x00000010
-const val SDL_INIT_VIDEO: Int = 0x00000020 // SDL_INIT_VIDEO implies SDL_INIT_EVENTS
-const val SDL_INIT_JOYSTICK: Int = 0x00000200 // SDL_INIT_JOYSTICK implies SDL_INIT_EVENTS
-const val SDL_INIT_HAPTIC: Int = 0x00001000
-const val SDL_INIT_GAMECONTROLLER: Int = 0x00002000 // SDL_INIT_GAMECONTROLLER implies SDL_INIT_JOYSTICK
-const val SDL_INIT_EVENTS: Int = 0x00004000
-const val SDL_INIT_SENSOR: Int = 0x00008000
-const val SDL_INIT_NOPARACHUTE: Int = 0x00100000 // compatibility; this flag is ignored.
-
-val SDL_INIT_EVERYTHING: Int = SDL_INIT_TIMER or SDL_INIT_AUDIO or SDL_INIT_VIDEO or SDL_INIT_EVENTS or SDL_INIT_JOYSTICK or SDL_INIT_HAPTIC or SDL_INIT_GAMECONTROLLER or SDL_INIT_SENSOR
-
-const val SDL_WINDOWPOS_CENTERED_MASK: Int = 0x2FFF0000
-
-fun SDL_WINDOWPOS_CENTERED_DISPLAY(X: Int): Int {
- return SDL_WINDOWPOS_CENTERED_MASK or X
-}
-
-val SDL_WINDOWPOS_CENTERED: Int = SDL_WINDOWPOS_CENTERED_DISPLAY(0)
-
-fun main() {
- libSDL2Library.SDL_Init(0)
-
- if (libSDL2Library.SDL_Init(SDL_INIT_EVERYTHING) != 0) {
- println("error initializing SDL: ${libSDL2Library.SDL_GetError()}" );
- return
- }
- libSDL2Library.SDL_CreateWindow(
- "Game",
- SDL_WINDOWPOS_CENTERED,
- SDL_WINDOWPOS_CENTERED,
- 800, 600,
- SDL_WindowFlags.SDL_WINDOW_SHOWN or SDL_WindowFlags.SDL_WINDOW_RESIZABLE
- )
- do {
-
-
- // Set to ~60 fps.
- // 1000 ms/ 60 fps = 1/16 s^2/frame
- libSDL2Library.SDL_Delay(16);
- } while (true)
-
-}
\ No newline at end of file
diff --git a/bindings/sdl/libsdl/src/main/kotlin/snake/main.kt b/bindings/sdl/libsdl/src/main/kotlin/snake/main.kt
deleted file mode 100644
index aa26f7a8..00000000
--- a/bindings/sdl/libsdl/src/main/kotlin/snake/main.kt
+++ /dev/null
@@ -1,472 +0,0 @@
-package snake
-
-
-import SDL_WINDOWPOS_CENTERED
-import com.sun.jna.Native
-import com.sun.jna.Pointer
-import com.sun.jna.ptr.IntByReference
-import com.sun.jna.ptr.PointerByReference
-import libsdl.*
-import java.io.File
-import java.nio.ByteBuffer
-import kotlin.math.max
-import kotlin.random.Random
-
-
-fun main() {
- val initialGame = Game(
- width = 20,
- height = 10,
- snake = Snake(
- cells = listOf(Cell(4, 4), Cell(3, 4), Cell(2, 4), Cell(1, 4), Cell(0, 4)),
- direction = Direction.right
- )
- )
- var game = initialGame
-
- SdlUI(game.width, game.height).use { sdlUI ->
-
- var ticks = 0
- val speed = 10
- while (true) {
-
- sdlUI.draw(game)
-
- sdlUI.delay(1000 / 60)
- ticks++
- if (ticks >= speed) {
- game = game.update()
- ticks -= speed
- }
-
- sdlUI.readCommands().forEach { command ->
- var direction: Direction? = null
- when (command) {
- SdlUI.UserCommand.up -> direction = Direction.up
- SdlUI.UserCommand.down -> direction = Direction.down
- SdlUI.UserCommand.left -> direction = Direction.left
- SdlUI.UserCommand.right -> direction = Direction.right
- SdlUI.UserCommand.restart -> game = initialGame
- SdlUI.UserCommand.quit -> return
- }
- game = game.update(direction)
- sdlUI.draw(game)
- }
- }
- }
-}
-
-class SdlUI(width: Int, height: Int): AutoCloseable {
- private val window: SDL_Window
- private val renderer: SDL_Renderer
- private val controller: SDL_GameController?
- private val font: Font
- private val sprites: Sprites
-
- private val pixelWidth = width * Sprites.w
- private val pixelHeight = height * Sprites.h
-
- init {
- if (libSDL2Library.SDL_Init(SDL_INIT_EVERYTHING) != 0) {
- println("SDL_Init Error: ${libSDL2Library.SDL_GetError()}")
- throw Error()
- }
-
- window = libSDL2Library.SDL_CreateWindow("Snake", SDL_WINDOWPOS_CENTERED,
- SDL_WINDOWPOS_CENTERED, pixelWidth, pixelHeight,
- SDL_WindowFlags.SDL_WINDOW_SHOWN.value
- )
-
- renderer = libSDL2Library.SDL_CreateRenderer(
- window, -1, SDL_RendererFlags.SDL_RENDERER_ACCELERATED or SDL_RendererFlags.SDL_RENDERER_PRESENTVSYNC
- )
-
- controller = when (libSDL2Library.SDL_NumJoysticks() != 0) {
- true -> libSDL2Library.SDL_GameControllerOpen(0)
- false -> null
- }
-
- font = Font(renderer)
- sprites = Sprites(renderer)
-
- playMusic()
- }
-
- fun draw(game: Game) {
- libSDL2Library.SDL_RenderClear(renderer)
- libSDL2Library.SDL_SetRenderDrawColor(renderer, (200 / 2).toByte(), (230 / 2).toByte(), (151 / 2).toByte(), SDL_ALPHA_OPAQUE)
-
- val grassW = 256
- val grassScaledW = 400 // scale grass up to reduce its resolution so that it's similar to snake sprites
- 0.until(pixelWidth / grassW + 1).forEach { x ->
- 0.until(pixelHeight / grassW + 1).forEach { y ->
- sprites.render(sprites.grassRect, allocRect(x * grassW, y * grassW, grassScaledW, grassScaledW))
- }
- }
-
- game.apples.cells.forEach {
- sprites.render(sprites.appleRect, cellRect(it))
- }
-
- game.snake.tail.dropLast(1).forEachIndexed { i, it ->
- val index = i + 1
- val direction = direction(from = game.snake.cells[index - 1], to = it)
- val nextDirection = direction(from = it, to = game.snake.cells[index + 1])
-
- val srcRect = if (direction == nextDirection) {
- when (direction) {
- Direction.right, Direction.left -> sprites.bodyHorRect
- Direction.up, Direction.down -> sprites.bodyVertRect
- }
- } else if ((direction == Direction.left && nextDirection == Direction.down) || (direction == Direction.up && nextDirection == Direction.right)) {
- sprites.bodyLeftDownRect
- } else if ((direction == Direction.left && nextDirection == Direction.up) || (direction == Direction.down && nextDirection == Direction.right)) {
- sprites.bodyLeftUpRect
- } else if ((direction == Direction.right && nextDirection == Direction.down) || (direction == Direction.up && nextDirection == Direction.left)) {
- sprites.bodyRightDownRect
- } else if ((direction == Direction.right && nextDirection == Direction.up) || (direction == Direction.down && nextDirection == Direction.left)) {
- sprites.bodyRightUpRect
- } else {
- sprites.emptyRect
- }
- sprites.render(srcRect, cellRect(it))
- }
-
- val tipRect = when (game.snake.cells.let { direction(from = it.last(), to = it[it.size - 2]) }) {
- Direction.up -> sprites.tipUpRect
- Direction.down -> sprites.tipDownRect
- Direction.left -> sprites.tipLeftRect
- Direction.right -> sprites.tipRightRect
- }
- sprites.render(tipRect, cellRect(game.snake.tail.last()))
-
- val headRect = when (game.snake.direction) {
- Direction.up -> sprites.headUpRect
- Direction.down -> sprites.headDownRect
- Direction.left -> sprites.headLeftRect
- Direction.right -> sprites.headRightRect
- }
- sprites.render(headRect, cellRect(game.snake.head))
-
- if (game.isOver) {
- renderStringCentered(3, game.width, "game over")
- renderStringCentered(5, game.width, "your score is ${game.score}")
- }
-
- libSDL2Library.SDL_RenderPresent(renderer)
-
- }
-
- fun delay(timeMs: Int) {
- libSDL2Library.SDL_Delay(timeMs)
- }
-
- fun readCommands(): List {
- val result = ArrayList()
- val event = SDL_Event()
- while (libSDL2Library.SDL_PollEvent(event) != 0) {
- event.read()
- println("event(${event.type}): ${SDL_EventType.of(event.type)}")
- when (SDL_EventType.of(event.type)) {
- SDL_EventType.SDL_WINDOWEVENT -> {
- val windowEvent = SDL_WindowEventID.of(event.window.event.toInt())
- println("controllerButtonEvent(${windowEvent})")
-
- if (windowEvent == SDL_WindowEventID.SDL_WINDOWEVENT_SHOWN) {
- //playMusic()
- }
- }
- SDL_EventType.SDL_QUIT -> result.add(UserCommand.quit)
- SDL_EventType.SDL_CONTROLLERBUTTONDOWN -> {
- val controllerButtonEvent = event.cbutton
- val button = controllerButtonEvent.button.toInt()
- println("controllerButtonEvent($button): ${SDL_GameControllerButton.of(button)}")
- val command = when (SDL_GameControllerButton.of(button)) {
- SDL_GameControllerButton.SDL_CONTROLLER_BUTTON_DPAD_UP -> UserCommand.up
- SDL_GameControllerButton.SDL_CONTROLLER_BUTTON_DPAD_DOWN -> UserCommand.down
- SDL_GameControllerButton.SDL_CONTROLLER_BUTTON_DPAD_LEFT -> UserCommand.left
- SDL_GameControllerButton.SDL_CONTROLLER_BUTTON_DPAD_RIGHT -> UserCommand.right
- SDL_GameControllerButton.SDL_CONTROLLER_BUTTON_START -> UserCommand.restart
- SDL_GameControllerButton.SDL_CONTROLLER_BUTTON_BACK -> UserCommand.quit
- else -> null
- }
- if (command != null) result.add(command)
- }
- SDL_EventType.SDL_KEYDOWN -> {
- val keyboardEvent = event.key
- val keysym = keyboardEvent.keysym
- println("keyboardEvent(${keysym.scancode}): ${SDL_Scancode.of(keysym.scancode)}")
- val command = when (SDL_Scancode.of(keysym.scancode)) {
- SDL_Scancode.SDL_SCANCODE_I -> UserCommand.up
- SDL_Scancode.SDL_SCANCODE_J -> UserCommand.left
- SDL_Scancode.SDL_SCANCODE_K -> UserCommand.down
- SDL_Scancode.SDL_SCANCODE_L -> UserCommand.right
- SDL_Scancode.SDL_SCANCODE_R -> UserCommand.restart
- SDL_Scancode.SDL_SCANCODE_Q -> UserCommand.quit
- else -> null
- }
- if (command != null) result.add(command)
- }
- else -> Unit
- }
- }
- return result
- }
-
- private fun playMusic() {
- val fileName = "Crowander-Stop-on-a-Bench.wav"
- val paths = listOf(fileName, "resources/$fileName", "../resources/$fileName")
- val filePath = paths.find { File(it).canRead() } ?: error("Can't find sound file.")
- val audioFile = libSDL2Library.SDL_RWFromFile(filePath, "rb")
- val audio_spec = SDL_AudioSpec()
- val audio_buf = PointerByReference()
- val audio_len = IntByReference()
- libSDL2Library.SDL_LoadWAV_RW(
- src = audioFile,
- freesrc = 1,
- spec = audio_spec,
- audio_buf.pointer,
- audio_len.pointer
- )
-
- val deviceName = libSDL2Library.SDL_GetAudioDeviceName(0, 0)
- val device_id = libSDL2Library.SDL_OpenAudioDevice(deviceName, 0, audio_spec, SDL_AudioSpec(), 0)
- libSDL2Library.SDL_QueueAudio(device_id, audio_buf.value, audio_len.value)
- libSDL2Library.SDL_PauseAudioDevice(device_id, 0)
- }
-
- private fun direction(from: Cell, to: Cell): Direction = when {
- from.x == to.x && from.y > to.y -> Direction.up
- from.x == to.x && from.y < to.y -> Direction.down
- from.x > to.x && from.y == to.y -> Direction.left
- from.x < to.x && from.y == to.y -> Direction.right
- else -> error("")
- }
-
- private fun cellRect(cell: Cell): SDL_Rect {
- val x = cell.x * Sprites.w
- val y = cell.y * Sprites.h
- return allocRect(x, y, Sprites.w, Sprites.h)
- }
-
- private fun renderStringCentered(y: Int, width: Int, s: String) {
- var x = (width / 2) - (s.length / 2)
- if (x.rem(2) != 0) x--
- renderString(Cell(x, y), s)
- }
-
- private fun renderString(atCell: Cell, s: String) {
- s.toCharArray().forEachIndexed { i, c ->
- font.render(c, cellRect(atCell.copy(x = atCell.x + i)))
- }
- }
-
- enum class UserCommand {
- up, down, left, right, restart, quit
- }
-
-
- class Font(private val renderer: SDL_Renderer) {
- companion object {
- const val w = 48
- const val h = 46
- }
-
- internal val texture = renderer.loadTexture("Font16_42_Normal4_sheet.bmp")
- private val letters: Map
-
- init {
- letters = mapOf(
- 'A' to textureRect(0, 0, -7),
- 'B' to textureRect(1, 0),
- 'C' to textureRect(2, 0, -9),
- 'D' to textureRect(3, 0),
- 'E' to textureRect(4, 0, -5),
- 'F' to textureRect(5, 0, -5),
- 'G' to textureRect(6, 0),
- 'H' to textureRect(7, 0, -7),
- 'I' to textureRect(8, 0, -15),
- 'J' to textureRect(9, 0, -5),
- 'K' to textureRect(0, 1, -10),
- 'L' to textureRect(1, 1, -5),
- 'M' to textureRect(2, 1),
- 'N' to textureRect(3, 1),
- 'O' to textureRect(4, 1, -7),
- 'P' to textureRect(5, 1, -7),
- 'Q' to textureRect(6, 1),
- 'R' to textureRect(7, 1),
- 'S' to textureRect(8, 1),
- 'T' to textureRect(9, 1),
- 'U' to textureRect(0, 2, -13),
- 'V' to textureRect(1, 2, -10),
- 'W' to textureRect(2, 2),
- 'X' to textureRect(3, 2),
- 'Y' to textureRect(4, 2, -5),
- 'Z' to textureRect(5, 2),
- '0' to textureRect(2, 5),
- '1' to textureRect(3, 5, -15),
- '2' to textureRect(4, 5),
- '3' to textureRect(5, 5),
- '4' to textureRect(6, 5),
- '5' to textureRect(7, 5),
- '6' to textureRect(8, 5),
- '7' to textureRect(9, 5),
- '8' to textureRect(0, 6),
- '9' to textureRect(1, 6),
- ' ' to allocRect(0, 0, 0, 0)
- )
- }
-
- fun render(char: Char, cellRect: SDL_Rect) {
- val charRect = letters[char.uppercaseChar()] ?: (letters[' '] ?: error(""))
- libSDL2Library.SDL_RenderCopy(renderer, texture, charRect, cellRect)
- }
-
- private fun textureRect(x: Int, y: Int, wAdjust: Int = 0): SDL_Rect {
- val xShift = x * w
- val yShift = y * h
- return allocRect(xShift, yShift, w + wAdjust, h)
- }
- }
-
- class Sprites(private val renderer: SDL_Renderer) {
- companion object {
- const val w = 64
- const val h = 64
- }
-
- internal val texture = renderer.loadTexture("snake-graphics.bmp")
- internal val grassTexture = renderer.loadTexture("grass.bmp")
-
- val headUpRect = textureRect(3, 0)
- val headRightRect = textureRect(4, 0)
- val headLeftRect = textureRect(3, 1)
- val headDownRect = textureRect(4, 1)
-
- val tipUpRect = textureRect(3, 2)
- val tipRightRect = textureRect(4, 2)
- val tipLeftRect = textureRect(3, 3)
- val tipDownRect = textureRect(4, 3)
-
- val bodyHorRect = textureRect(1, 0)
- val bodyVertRect = textureRect(2, 1)
- val bodyLeftDownRect = textureRect(0, 0)
- val bodyLeftUpRect = textureRect(0, 1)
- val bodyRightDownRect = textureRect(2, 0)
- val bodyRightUpRect = textureRect(2, 2)
-
- val appleRect = textureRect(0, 3)
- val emptyRect = textureRect(0, 2)
-
- val grassRect = allocRect(0, 0, 256, 256)
-
- private fun textureRect(x: Int, y: Int) = allocRect(x * w, y * h, w, h)
-
- fun render(srcRect: SDL_Rect, dstRect: SDL_Rect) {
- if (srcRect == grassRect) libSDL2Library.SDL_RenderCopy(renderer, grassTexture, srcRect, dstRect)
- else libSDL2Library.SDL_RenderCopy(renderer, texture, srcRect, dstRect)
- }
- }
-
- companion object {
- fun SDL_Renderer.loadTexture(fileName: String): SDL_Texture {
- val paths = listOf(fileName, "resources/$fileName", "../resources/$fileName")
- val filePath = paths.find { File(it).canRead() } ?: error("Can't find image file.")
-
- val bmp = libSDL2Library.SDL_LoadBMP_RW(libSDL2Library.SDL_RWFromFile(filePath, "rb"), 1)
-
- return libSDL2Library.SDL_CreateTextureFromSurface(this@loadTexture, bmp)
- }
-
- fun allocRect(x: Int, y: Int, w: Int, h: Int) = SDL_Rect().also {
- it.x = x
- it.y = y
- it.w = w
- it.h = h
- }
- }
-
- override fun close() {
- controller.takeIf { it != null }
- ?.let { libSDL2Library.SDL_GameControllerClose(it) }
- libSDL2Library.SDL_DestroyTexture(sprites.texture)
- libSDL2Library.SDL_DestroyTexture(sprites.grassTexture)
- libSDL2Library.SDL_DestroyTexture(font.texture)
- libSDL2Library.SDL_DestroyRenderer(renderer)
- libSDL2Library.SDL_DestroyWindow(window)
- libSDL2Library.SDL_Quit()
- }
-}
-
-data class Game(
- val width: Int,
- val height: Int,
- val snake: Snake,
- val apples: Apples = Apples(width, height)
-) {
- val isOver =
- snake.tail.contains(snake.head) ||
- snake.cells.any { it.x < 0 || it.x >= width || it.y < 0 || it.y >= height }
-
- val score = snake.cells.size
-
- fun update(direction: Direction? = null): Game {
- if (isOver) return this
- val (newSnake, newApples) = snake.turn(direction).move().eat(apples.grow())
- return copy(snake = newSnake, apples = newApples)
- }
-}
-
-data class Snake(
- val cells: List,
- val direction: Direction,
- val eatenApples: Int = 0
-) {
- val head = cells.first()
- val tail = cells.subList(1, cells.size)
-
- fun move(): Snake {
- val newHead = head.move(direction)
- val newTail = if (eatenApples == 0) cells.dropLast(1) else cells
- return copy(
- cells = listOf(newHead) + newTail,
- eatenApples = max(eatenApples - 1, 0)
- )
- }
-
- fun turn(newDirection: Direction?): Snake {
- if (newDirection == null || newDirection.isOpposite(direction)) return this
- return copy(direction = newDirection)
- }
-
- fun eat(apples: Apples): Pair {
- if (!apples.cells.contains(head)) return Pair(this, apples)
- return Pair(
- copy(eatenApples = eatenApples + 1),
- apples.copy(cells = apples.cells - head)
- )
- }
-}
-
-data class Apples(
- val fieldWidth: Int,
- val fieldHeight: Int,
- val cells: Set = emptySet(),
- val growthSpeed: Int = 3,
- val random: Random = Random
-) {
- fun grow(): Apples {
- if (random.nextInt(growthSpeed) != 0) return this
- return copy(cells = cells + Cell(random.nextInt(fieldWidth), random.nextInt(fieldHeight)))
- }
-}
-
-data class Cell(val x: Int, val y: Int) {
- fun move(direction: Direction) = Cell(x + direction.dx, y + direction.dy)
-}
-
-enum class Direction(val dx: Int, val dy: Int) {
- up(0, -1), down(0, 1), left(-1, 0), right(1, 0);
-
- fun isOpposite(that: Direction) = dx + that.dx == 0 && dy + that.dy == 0
-}
\ No newline at end of file
diff --git a/bindings/sdl/settings.gradle.kts b/bindings/sdl/settings.gradle.kts
index 4325a12b..12e90d21 100644
--- a/bindings/sdl/settings.gradle.kts
+++ b/bindings/sdl/settings.gradle.kts
@@ -8,6 +8,8 @@ pluginManagement {
}
}
-include(":libsdl")
-findProject(":libsdl")?.name = "sdl4k"
+include(":libsdl", ":binaries", ":examples:snake", ":examples:tetris")
+findProject(":libsdl")?.name = "sdl2-4k"
+findProject(":binaries")?.name = "sdl2-binaries"
+
diff --git a/bindings/sdl2wgpu/build.gradle.kts b/bindings/sdl2wgpu/build.gradle.kts
new file mode 100644
index 00000000..b0696f62
--- /dev/null
+++ b/bindings/sdl2wgpu/build.gradle.kts
@@ -0,0 +1,31 @@
+import org.apache.tools.ant.taskdefs.condition.Os
+
+plugins {
+ `cpp-library`
+ `maven-publish`
+}
+
+group = "io.ygdrasil"
+version = "1.0.0-SNAPSHOT"
+
+library {
+
+ linkage = listOf(Linkage.SHARED)
+
+ targetMachines.add(machines.windows.x86_64)
+ targetMachines.add(machines.linux.architecture("aarch64"))
+ targetMachines.add(machines.linux.x86_64)
+ targetMachines.add(machines.macOS.x86_64)
+ targetMachines.add(machines.macOS.architecture("aarch64"))
+}
+
+tasks.withType().configureEach {
+
+ if (Os.isFamily(Os.FAMILY_MAC)) {
+ compilerArgs.addAll("-x", "objective-c++")
+ }
+}
+
+tasks.withType().configureEach {
+ linkerArgs.add("-Wl,-undefined,dynamic_lookup")
+}
diff --git a/bindings/sdl2wgpu/gradle/libs.versions.toml b/bindings/sdl2wgpu/gradle/libs.versions.toml
new file mode 100644
index 00000000..7a38d765
--- /dev/null
+++ b/bindings/sdl2wgpu/gradle/libs.versions.toml
@@ -0,0 +1,14 @@
+[versions]
+kotest = "5.6.1"
+klang = "0.0.0"
+jna = "5.13.0"
+kotlin = "1.9.22"
+wgpu = "v0.19.1.1"
+
+
+[libraries]
+kotest = { module = "io.kotest:kotest-runner-junit5-jvm", version.ref = "kotest" }
+jna = { module = "net.java.dev.jna:jna", version.ref = "jna" }
+
+[plugins]
+klang = { id = "io.ygdrasil.klang-plugin", version.ref = "klang" }
\ No newline at end of file
diff --git a/bindings/sdl2wgpu/gradle/wrapper/gradle-wrapper.properties b/bindings/sdl2wgpu/gradle/wrapper/gradle-wrapper.properties
new file mode 100644
index 00000000..a80b22ce
--- /dev/null
+++ b/bindings/sdl2wgpu/gradle/wrapper/gradle-wrapper.properties
@@ -0,0 +1,7 @@
+distributionBase=GRADLE_USER_HOME
+distributionPath=wrapper/dists
+distributionUrl=https\://services.gradle.org/distributions/gradle-8.6-bin.zip
+networkTimeout=10000
+validateDistributionUrl=true
+zipStoreBase=GRADLE_USER_HOME
+zipStorePath=wrapper/dists
diff --git a/bindings/sdl2wgpu/gradlew b/bindings/sdl2wgpu/gradlew
new file mode 100755
index 00000000..1aa94a42
--- /dev/null
+++ b/bindings/sdl2wgpu/gradlew
@@ -0,0 +1,249 @@
+#!/bin/sh
+
+#
+# Copyright © 2015-2021 the original authors.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# https://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+
+##############################################################################
+#
+# Gradle start up script for POSIX generated by Gradle.
+#
+# Important for running:
+#
+# (1) You need a POSIX-compliant shell to run this script. If your /bin/sh is
+# noncompliant, but you have some other compliant shell such as ksh or
+# bash, then to run this script, type that shell name before the whole
+# command line, like:
+#
+# ksh Gradle
+#
+# Busybox and similar reduced shells will NOT work, because this script
+# requires all of these POSIX shell features:
+# * functions;
+# * expansions «$var», «${var}», «${var:-default}», «${var+SET}»,
+# «${var#prefix}», «${var%suffix}», and «$( cmd )»;
+# * compound commands having a testable exit status, especially «case»;
+# * various built-in commands including «command», «set», and «ulimit».
+#
+# Important for patching:
+#
+# (2) This script targets any POSIX shell, so it avoids extensions provided
+# by Bash, Ksh, etc; in particular arrays are avoided.
+#
+# The "traditional" practice of packing multiple parameters into a
+# space-separated string is a well documented source of bugs and security
+# problems, so this is (mostly) avoided, by progressively accumulating
+# options in "$@", and eventually passing that to Java.
+#
+# Where the inherited environment variables (DEFAULT_JVM_OPTS, JAVA_OPTS,
+# and GRADLE_OPTS) rely on word-splitting, this is performed explicitly;
+# see the in-line comments for details.
+#
+# There are tweaks for specific operating systems such as AIX, CygWin,
+# Darwin, MinGW, and NonStop.
+#
+# (3) This script is generated from the Groovy template
+# https://github.com/gradle/gradle/blob/HEAD/subprojects/plugins/src/main/resources/org/gradle/api/internal/plugins/unixStartScript.txt
+# within the Gradle project.
+#
+# You can find Gradle at https://github.com/gradle/gradle/.
+#
+##############################################################################
+
+# Attempt to set APP_HOME
+
+# Resolve links: $0 may be a link
+app_path=$0
+
+# Need this for daisy-chained symlinks.
+while
+ APP_HOME=${app_path%"${app_path##*/}"} # leaves a trailing /; empty if no leading path
+ [ -h "$app_path" ]
+do
+ ls=$( ls -ld "$app_path" )
+ link=${ls#*' -> '}
+ case $link in #(
+ /*) app_path=$link ;; #(
+ *) app_path=$APP_HOME$link ;;
+ esac
+done
+
+# This is normally unused
+# shellcheck disable=SC2034
+APP_BASE_NAME=${0##*/}
+# Discard cd standard output in case $CDPATH is set (https://github.com/gradle/gradle/issues/25036)
+APP_HOME=$( cd "${APP_HOME:-./}" > /dev/null && pwd -P ) || exit
+
+# Use the maximum available, or set MAX_FD != -1 to use that value.
+MAX_FD=maximum
+
+warn () {
+ echo "$*"
+} >&2
+
+die () {
+ echo
+ echo "$*"
+ echo
+ exit 1
+} >&2
+
+# OS specific support (must be 'true' or 'false').
+cygwin=false
+msys=false
+darwin=false
+nonstop=false
+case "$( uname )" in #(
+ CYGWIN* ) cygwin=true ;; #(
+ Darwin* ) darwin=true ;; #(
+ MSYS* | MINGW* ) msys=true ;; #(
+ NONSTOP* ) nonstop=true ;;
+esac
+
+CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar
+
+
+# Determine the Java command to use to start the JVM.
+if [ -n "$JAVA_HOME" ] ; then
+ if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
+ # IBM's JDK on AIX uses strange locations for the executables
+ JAVACMD=$JAVA_HOME/jre/sh/java
+ else
+ JAVACMD=$JAVA_HOME/bin/java
+ fi
+ if [ ! -x "$JAVACMD" ] ; then
+ die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME
+
+Please set the JAVA_HOME variable in your environment to match the
+location of your Java installation."
+ fi
+else
+ JAVACMD=java
+ if ! command -v java >/dev/null 2>&1
+ then
+ die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
+
+Please set the JAVA_HOME variable in your environment to match the
+location of your Java installation."
+ fi
+fi
+
+# Increase the maximum file descriptors if we can.
+if ! "$cygwin" && ! "$darwin" && ! "$nonstop" ; then
+ case $MAX_FD in #(
+ max*)
+ # In POSIX sh, ulimit -H is undefined. That's why the result is checked to see if it worked.
+ # shellcheck disable=SC2039,SC3045
+ MAX_FD=$( ulimit -H -n ) ||
+ warn "Could not query maximum file descriptor limit"
+ esac
+ case $MAX_FD in #(
+ '' | soft) :;; #(
+ *)
+ # In POSIX sh, ulimit -n is undefined. That's why the result is checked to see if it worked.
+ # shellcheck disable=SC2039,SC3045
+ ulimit -n "$MAX_FD" ||
+ warn "Could not set maximum file descriptor limit to $MAX_FD"
+ esac
+fi
+
+# Collect all arguments for the java command, stacking in reverse order:
+# * args from the command line
+# * the main class name
+# * -classpath
+# * -D...appname settings
+# * --module-path (only if needed)
+# * DEFAULT_JVM_OPTS, JAVA_OPTS, and GRADLE_OPTS environment variables.
+
+# For Cygwin or MSYS, switch paths to Windows format before running java
+if "$cygwin" || "$msys" ; then
+ APP_HOME=$( cygpath --path --mixed "$APP_HOME" )
+ CLASSPATH=$( cygpath --path --mixed "$CLASSPATH" )
+
+ JAVACMD=$( cygpath --unix "$JAVACMD" )
+
+ # Now convert the arguments - kludge to limit ourselves to /bin/sh
+ for arg do
+ if
+ case $arg in #(
+ -*) false ;; # don't mess with options #(
+ /?*) t=${arg#/} t=/${t%%/*} # looks like a POSIX filepath
+ [ -e "$t" ] ;; #(
+ *) false ;;
+ esac
+ then
+ arg=$( cygpath --path --ignore --mixed "$arg" )
+ fi
+ # Roll the args list around exactly as many times as the number of
+ # args, so each arg winds up back in the position where it started, but
+ # possibly modified.
+ #
+ # NB: a `for` loop captures its iteration list before it begins, so
+ # changing the positional parameters here affects neither the number of
+ # iterations, nor the values presented in `arg`.
+ shift # remove old arg
+ set -- "$@" "$arg" # push replacement arg
+ done
+fi
+
+
+# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
+DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"'
+
+# Collect all arguments for the java command:
+# * DEFAULT_JVM_OPTS, JAVA_OPTS, JAVA_OPTS, and optsEnvironmentVar are not allowed to contain shell fragments,
+# and any embedded shellness will be escaped.
+# * For example: A user cannot expect ${Hostname} to be expanded, as it is an environment variable and will be
+# treated as '${Hostname}' itself on the command line.
+
+set -- \
+ "-Dorg.gradle.appname=$APP_BASE_NAME" \
+ -classpath "$CLASSPATH" \
+ org.gradle.wrapper.GradleWrapperMain \
+ "$@"
+
+# Stop when "xargs" is not available.
+if ! command -v xargs >/dev/null 2>&1
+then
+ die "xargs is not available"
+fi
+
+# Use "xargs" to parse quoted args.
+#
+# With -n1 it outputs one arg per line, with the quotes and backslashes removed.
+#
+# In Bash we could simply go:
+#
+# readarray ARGS < <( xargs -n1 <<<"$var" ) &&
+# set -- "${ARGS[@]}" "$@"
+#
+# but POSIX shell has neither arrays nor command substitution, so instead we
+# post-process each arg (as a line of input to sed) to backslash-escape any
+# character that might be a shell metacharacter, then use eval to reverse
+# that process (while maintaining the separation between arguments), and wrap
+# the whole thing up as a single "set" statement.
+#
+# This will of course break if any of these variables contains a newline or
+# an unmatched quote.
+#
+
+eval "set -- $(
+ printf '%s\n' "$DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS" |
+ xargs -n1 |
+ sed ' s~[^-[:alnum:]+,./:=@_]~\\&~g; ' |
+ tr '\n' ' '
+ )" '"$@"'
+
+exec "$JAVACMD" "$@"
diff --git a/bindings/sdl2wgpu/gradlew.bat b/bindings/sdl2wgpu/gradlew.bat
new file mode 100644
index 00000000..93e3f59f
--- /dev/null
+++ b/bindings/sdl2wgpu/gradlew.bat
@@ -0,0 +1,92 @@
+@rem
+@rem Copyright 2015 the original author or authors.
+@rem
+@rem Licensed under the Apache License, Version 2.0 (the "License");
+@rem you may not use this file except in compliance with the License.
+@rem You may obtain a copy of the License at
+@rem
+@rem https://www.apache.org/licenses/LICENSE-2.0
+@rem
+@rem Unless required by applicable law or agreed to in writing, software
+@rem distributed under the License is distributed on an "AS IS" BASIS,
+@rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+@rem See the License for the specific language governing permissions and
+@rem limitations under the License.
+@rem
+
+@if "%DEBUG%"=="" @echo off
+@rem ##########################################################################
+@rem
+@rem Gradle startup script for Windows
+@rem
+@rem ##########################################################################
+
+@rem Set local scope for the variables with windows NT shell
+if "%OS%"=="Windows_NT" setlocal
+
+set DIRNAME=%~dp0
+if "%DIRNAME%"=="" set DIRNAME=.
+@rem This is normally unused
+set APP_BASE_NAME=%~n0
+set APP_HOME=%DIRNAME%
+
+@rem Resolve any "." and ".." in APP_HOME to make it shorter.
+for %%i in ("%APP_HOME%") do set APP_HOME=%%~fi
+
+@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
+set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m"
+
+@rem Find java.exe
+if defined JAVA_HOME goto findJavaFromJavaHome
+
+set JAVA_EXE=java.exe
+%JAVA_EXE% -version >NUL 2>&1
+if %ERRORLEVEL% equ 0 goto execute
+
+echo.
+echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
+echo.
+echo Please set the JAVA_HOME variable in your environment to match the
+echo location of your Java installation.
+
+goto fail
+
+:findJavaFromJavaHome
+set JAVA_HOME=%JAVA_HOME:"=%
+set JAVA_EXE=%JAVA_HOME%/bin/java.exe
+
+if exist "%JAVA_EXE%" goto execute
+
+echo.
+echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%
+echo.
+echo Please set the JAVA_HOME variable in your environment to match the
+echo location of your Java installation.
+
+goto fail
+
+:execute
+@rem Setup the command line
+
+set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar
+
+
+@rem Execute Gradle
+"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %*
+
+:end
+@rem End local scope for the variables with windows NT shell
+if %ERRORLEVEL% equ 0 goto mainEnd
+
+:fail
+rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of
+rem the _cmd.exe /c_ return code!
+set EXIT_CODE=%ERRORLEVEL%
+if %EXIT_CODE% equ 0 set EXIT_CODE=1
+if not ""=="%GRADLE_EXIT_CONSOLE%" exit %EXIT_CODE%
+exit /b %EXIT_CODE%
+
+:mainEnd
+if "%OS%"=="Windows_NT" endlocal
+
+:omega
diff --git a/bindings/sdl2wgpu/settings.gradle.kts b/bindings/sdl2wgpu/settings.gradle.kts
new file mode 100644
index 00000000..1010e0a9
--- /dev/null
+++ b/bindings/sdl2wgpu/settings.gradle.kts
@@ -0,0 +1,10 @@
+rootProject.name = "sdl2wgpu"
+
+pluginManagement {
+ repositories {
+ gradlePluginPortal()
+ mavenCentral()
+ mavenLocal()
+ }
+}
+
diff --git a/bindings/sdl2wgpu/src/main/cpp/sdl2webgpu.cpp b/bindings/sdl2wgpu/src/main/cpp/sdl2webgpu.cpp
new file mode 100644
index 00000000..1dc8502c
--- /dev/null
+++ b/bindings/sdl2wgpu/src/main/cpp/sdl2webgpu.cpp
@@ -0,0 +1,139 @@
+/**
+ * This is an extension of SDL2 for WebGPU, abstracting away the details of
+ * OS-specific operations.
+ *
+ * This file is part of the "Learn WebGPU for C++" book.
+ * https://eliemichel.github.io/LearnWebGPU
+ *
+ * Most of this code comes from the wgpu-native triangle example:
+ * https://github.com/gfx-rs/wgpu-native/blob/master/examples/triangle/main.c
+ *
+ * MIT License
+ * Copyright (c) 2022-2023 Elie Michel and the wgpu-native authors
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in all
+ * copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ * SOFTWARE.
+ */
+
+#include "sdl2webgpu.h"
+
+#include
+
+#if defined(SDL_VIDEO_DRIVER_COCOA)
+#include
+#include
+#include
+#endif
+
+#include
+#include
+
+WGPUSurface SDL_GetWGPUSurface(WGPUInstance instance, SDL_Window* window) {
+ SDL_SysWMinfo windowWMInfo;
+ SDL_VERSION(&windowWMInfo.version);
+ SDL_GetWindowWMInfo(window, &windowWMInfo);
+
+#if defined(SDL_VIDEO_DRIVER_COCOA)
+ {
+ id metal_layer = NULL;
+ NSWindow* ns_window = windowWMInfo.info.cocoa.window;
+ [ns_window.contentView setWantsLayer : YES] ;
+ metal_layer = [CAMetalLayer layer];
+ [ns_window.contentView setLayer : metal_layer];
+
+ WGPUSurfaceDescriptor surfaceDescriptor;
+ surfaceDescriptor.label = NULL;
+
+ WGPUSurfaceDescriptorFromMetalLayer metalLayerDescriptor;
+ metalLayerDescriptor.chain.next = NULL;
+ metalLayerDescriptor.chain.sType = WGPUSType_SurfaceDescriptorFromMetalLayer;
+ metalLayerDescriptor.layer = metal_layer;
+
+ surfaceDescriptor.nextInChain = reinterpret_cast(&metalLayerDescriptor);
+
+ return wgpuInstanceCreateSurface(instance, &surfaceDescriptor);
+ }
+#elif defined(SDL_VIDEO_DRIVER_X11)
+ {
+ Display* x11_display = windowWMInfo.info.x11.display;
+ Window x11_window = windowWMInfo.info.x11.window;
+ return wgpuInstanceCreateSurface(
+ instance,
+ &(WGPUSurfaceDescriptor){
+ .label = NULL,
+ .nextInChain =
+ (const WGPUChainedStruct*)&(
+ WGPUSurfaceDescriptorFromXlibWindow) {
+ .chain =
+ (WGPUChainedStruct){
+ .next = NULL,
+ .sType = WGPUSType_SurfaceDescriptorFromXlibWindow,
+ },
+ .display = x11_display,
+ .window = x11_window,
+ },
+ });
+ }
+#elif defined(SDL_VIDEO_DRIVER_WAYLAND)
+ {
+ struct wl_display* wayland_display = windowWMInfo.info.wl.display;
+ struct wl_surface* wayland_surface = windowWMInfo.info.wl.display;
+ return wgpuInstanceCreateSurface(
+ instance,
+ &(WGPUSurfaceDescriptor){
+ .label = NULL,
+ .nextInChain =
+ (const WGPUChainedStruct*)&(
+ WGPUSurfaceDescriptorFromWaylandSurface) {
+ .chain =
+ (WGPUChainedStruct){
+ .next = NULL,
+ .sType =
+ WGPUSType_SurfaceDescriptorFromWaylandSurface,
+ },
+ .display = wayland_display,
+ .surface = wayland_surface,
+ },
+ });
+ }
+#elif defined(SDL_VIDEO_DRIVER_WINDOWS)
+ {
+ HWND hwnd = windowWMInfo.info.win.window;
+ HINSTANCE hinstance = GetModuleHandle(NULL);
+ return wgpuInstanceCreateSurface(
+ instance,
+ &(WGPUSurfaceDescriptor){
+ .label = NULL,
+ .nextInChain =
+ (const WGPUChainedStruct*)&(
+ WGPUSurfaceDescriptorFromWindowsHWND) {
+ .chain =
+ (WGPUChainedStruct){
+ .next = NULL,
+ .sType = WGPUSType_SurfaceDescriptorFromWindowsHWND,
+ },
+ .hinstance = hinstance,
+ .hwnd = hwnd,
+ },
+ });
+ }
+#else
+ // TODO: See SDL_syswm.h for other possible enum values!
+#error "Unsupported WGPU_TARGET"
+#endif
+}
diff --git a/bindings/sdl2wgpu/src/main/headers/SDL2/SDL.h b/bindings/sdl2wgpu/src/main/headers/SDL2/SDL.h
new file mode 100644
index 00000000..0b81a215
--- /dev/null
+++ b/bindings/sdl2wgpu/src/main/headers/SDL2/SDL.h
@@ -0,0 +1,233 @@
+/*
+ Simple DirectMedia Layer
+ Copyright (C) 1997-2023 Sam Lantinga
+
+ This software is provided 'as-is', without any express or implied
+ warranty. In no event will the authors be held liable for any damages
+ arising from the use of this software.
+
+ Permission is granted to anyone to use this software for any purpose,
+ including commercial applications, and to alter it and redistribute it
+ freely, subject to the following restrictions:
+
+ 1. The origin of this software must not be misrepresented; you must not
+ claim that you wrote the original software. If you use this software
+ in a product, an acknowledgment in the product documentation would be
+ appreciated but is not required.
+ 2. Altered source versions must be plainly marked as such, and must not be
+ misrepresented as being the original software.
+ 3. This notice may not be removed or altered from any source distribution.
+*/
+
+/**
+ * \file SDL.h
+ *
+ * Main include header for the SDL library
+ */
+
+
+#ifndef SDL_h_
+#define SDL_h_
+
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+
+#include
+/* Set up for C function definitions, even when using C++ */
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* As of version 0.5, SDL is loaded dynamically into the application */
+
+/**
+ * \name SDL_INIT_*
+ *
+ * These are the flags which may be passed to SDL_Init(). You should
+ * specify the subsystems which you will be using in your application.
+ */
+/* @{ */
+#define SDL_INIT_TIMER 0x00000001u
+#define SDL_INIT_AUDIO 0x00000010u
+#define SDL_INIT_VIDEO 0x00000020u /**< SDL_INIT_VIDEO implies SDL_INIT_EVENTS */
+#define SDL_INIT_JOYSTICK 0x00000200u /**< SDL_INIT_JOYSTICK implies SDL_INIT_EVENTS */
+#define SDL_INIT_HAPTIC 0x00001000u
+#define SDL_INIT_GAMECONTROLLER 0x00002000u /**< SDL_INIT_GAMECONTROLLER implies SDL_INIT_JOYSTICK */
+#define SDL_INIT_EVENTS 0x00004000u
+#define SDL_INIT_SENSOR 0x00008000u
+#define SDL_INIT_NOPARACHUTE 0x00100000u /**< compatibility; this flag is ignored. */
+#define SDL_INIT_EVERYTHING ( \
+ SDL_INIT_TIMER | SDL_INIT_AUDIO | SDL_INIT_VIDEO | SDL_INIT_EVENTS | \
+ SDL_INIT_JOYSTICK | SDL_INIT_HAPTIC | SDL_INIT_GAMECONTROLLER | SDL_INIT_SENSOR \
+ )
+/* @} */
+
+/**
+ * Initialize the SDL library.
+ *
+ * SDL_Init() simply forwards to calling SDL_InitSubSystem(). Therefore, the
+ * two may be used interchangeably. Though for readability of your code
+ * SDL_InitSubSystem() might be preferred.
+ *
+ * The file I/O (for example: SDL_RWFromFile) and threading (SDL_CreateThread)
+ * subsystems are initialized by default. Message boxes
+ * (SDL_ShowSimpleMessageBox) also attempt to work without initializing the
+ * video subsystem, in hopes of being useful in showing an error dialog when
+ * SDL_Init fails. You must specifically initialize other subsystems if you
+ * use them in your application.
+ *
+ * Logging (such as SDL_Log) works without initialization, too.
+ *
+ * `flags` may be any of the following OR'd together:
+ *
+ * - `SDL_INIT_TIMER`: timer subsystem
+ * - `SDL_INIT_AUDIO`: audio subsystem
+ * - `SDL_INIT_VIDEO`: video subsystem; automatically initializes the events
+ * subsystem
+ * - `SDL_INIT_JOYSTICK`: joystick subsystem; automatically initializes the
+ * events subsystem
+ * - `SDL_INIT_HAPTIC`: haptic (force feedback) subsystem
+ * - `SDL_INIT_GAMECONTROLLER`: controller subsystem; automatically
+ * initializes the joystick subsystem
+ * - `SDL_INIT_EVENTS`: events subsystem
+ * - `SDL_INIT_EVERYTHING`: all of the above subsystems
+ * - `SDL_INIT_NOPARACHUTE`: compatibility; this flag is ignored
+ *
+ * Subsystem initialization is ref-counted, you must call SDL_QuitSubSystem()
+ * for each SDL_InitSubSystem() to correctly shutdown a subsystem manually (or
+ * call SDL_Quit() to force shutdown). If a subsystem is already loaded then
+ * this call will increase the ref-count and return.
+ *
+ * \param flags subsystem initialization flags
+ * \returns 0 on success or a negative error code on failure; call
+ * SDL_GetError() for more information.
+ *
+ * \since This function is available since SDL 2.0.0.
+ *
+ * \sa SDL_InitSubSystem
+ * \sa SDL_Quit
+ * \sa SDL_SetMainReady
+ * \sa SDL_WasInit
+ */
+extern DECLSPEC int SDLCALL SDL_Init(Uint32 flags);
+
+/**
+ * Compatibility function to initialize the SDL library.
+ *
+ * In SDL2, this function and SDL_Init() are interchangeable.
+ *
+ * \param flags any of the flags used by SDL_Init(); see SDL_Init for details.
+ * \returns 0 on success or a negative error code on failure; call
+ * SDL_GetError() for more information.
+ *
+ * \since This function is available since SDL 2.0.0.
+ *
+ * \sa SDL_Init
+ * \sa SDL_Quit
+ * \sa SDL_QuitSubSystem
+ */
+extern DECLSPEC int SDLCALL SDL_InitSubSystem(Uint32 flags);
+
+/**
+ * Shut down specific SDL subsystems.
+ *
+ * If you start a subsystem using a call to that subsystem's init function
+ * (for example SDL_VideoInit()) instead of SDL_Init() or SDL_InitSubSystem(),
+ * SDL_QuitSubSystem() and SDL_WasInit() will not work. You will need to use
+ * that subsystem's quit function (SDL_VideoQuit()) directly instead. But
+ * generally, you should not be using those functions directly anyhow; use
+ * SDL_Init() instead.
+ *
+ * You still need to call SDL_Quit() even if you close all open subsystems
+ * with SDL_QuitSubSystem().
+ *
+ * \param flags any of the flags used by SDL_Init(); see SDL_Init for details.
+ *
+ * \since This function is available since SDL 2.0.0.
+ *
+ * \sa SDL_InitSubSystem
+ * \sa SDL_Quit
+ */
+extern DECLSPEC void SDLCALL SDL_QuitSubSystem(Uint32 flags);
+
+/**
+ * Get a mask of the specified subsystems which are currently initialized.
+ *
+ * \param flags any of the flags used by SDL_Init(); see SDL_Init for details.
+ * \returns a mask of all initialized subsystems if `flags` is 0, otherwise it
+ * returns the initialization status of the specified subsystems.
+ *
+ * The return value does not include SDL_INIT_NOPARACHUTE.
+ *
+ * \since This function is available since SDL 2.0.0.
+ *
+ * \sa SDL_Init
+ * \sa SDL_InitSubSystem
+ */
+extern DECLSPEC Uint32 SDLCALL SDL_WasInit(Uint32 flags);
+
+/**
+ * Clean up all initialized subsystems.
+ *
+ * You should call this function even if you have already shutdown each
+ * initialized subsystem with SDL_QuitSubSystem(). It is safe to call this
+ * function even in the case of errors in initialization.
+ *
+ * If you start a subsystem using a call to that subsystem's init function
+ * (for example SDL_VideoInit()) instead of SDL_Init() or SDL_InitSubSystem(),
+ * then you must use that subsystem's quit function (SDL_VideoQuit()) to shut
+ * it down before calling SDL_Quit(). But generally, you should not be using
+ * those functions directly anyhow; use SDL_Init() instead.
+ *
+ * You can use this function with atexit() to ensure that it is run when your
+ * application is shutdown, but it is not wise to do this from a library or
+ * other dynamically loaded code.
+ *
+ * \since This function is available since SDL 2.0.0.
+ *
+ * \sa SDL_Init
+ * \sa SDL_QuitSubSystem
+ */
+extern DECLSPEC void SDLCALL SDL_Quit(void);
+
+/* Ends C function definitions when using C++ */
+#ifdef __cplusplus
+}
+#endif
+#include
+
+#endif /* SDL_h_ */
+
+/* vi: set ts=4 sw=4 expandtab: */
diff --git a/bindings/sdl2wgpu/src/main/headers/SDL2/SDL_assert.h b/bindings/sdl2wgpu/src/main/headers/SDL2/SDL_assert.h
new file mode 100644
index 00000000..597acdc0
--- /dev/null
+++ b/bindings/sdl2wgpu/src/main/headers/SDL2/SDL_assert.h
@@ -0,0 +1,320 @@
+/*
+ Simple DirectMedia Layer
+ Copyright (C) 1997-2023 Sam Lantinga
+
+ This software is provided 'as-is', without any express or implied
+ warranty. In no event will the authors be held liable for any damages
+ arising from the use of this software.
+
+ Permission is granted to anyone to use this software for any purpose,
+ including commercial applications, and to alter it and redistribute it
+ freely, subject to the following restrictions:
+
+ 1. The origin of this software must not be misrepresented; you must not
+ claim that you wrote the original software. If you use this software
+ in a product, an acknowledgment in the product documentation would be
+ appreciated but is not required.
+ 2. Altered source versions must be plainly marked as such, and must not be
+ misrepresented as being the original software.
+ 3. This notice may not be removed or altered from any source distribution.
+*/
+
+#ifndef SDL_assert_h_
+#define SDL_assert_h_
+
+#include
+
+#include
+/* Set up for C function definitions, even when using C++ */
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#ifndef SDL_ASSERT_LEVEL
+#ifdef SDL_DEFAULT_ASSERT_LEVEL
+#define SDL_ASSERT_LEVEL SDL_DEFAULT_ASSERT_LEVEL
+#elif defined(_DEBUG) || defined(DEBUG) || \
+ (defined(__GNUC__) && !defined(__OPTIMIZE__))
+#define SDL_ASSERT_LEVEL 2
+#else
+#define SDL_ASSERT_LEVEL 1
+#endif
+#endif /* SDL_ASSERT_LEVEL */
+
+/*
+These are macros and not first class functions so that the debugger breaks
+on the assertion line and not in some random guts of SDL, and so each
+assert can have unique static variables associated with it.
+*/
+
+#if defined(_MSC_VER)
+/* Don't include intrin.h here because it contains C++ code */
+ extern void __cdecl __debugbreak(void);
+ #define SDL_TriggerBreakpoint() __debugbreak()
+#elif _SDL_HAS_BUILTIN(__builtin_debugtrap)
+ #define SDL_TriggerBreakpoint() __builtin_debugtrap()
+#elif ( (!defined(__NACL__)) && ((defined(__GNUC__) || defined(__clang__)) && (defined(__i386__) || defined(__x86_64__))) )
+ #define SDL_TriggerBreakpoint() __asm__ __volatile__ ( "int $3\n\t" )
+#elif ( defined(__APPLE__) && (defined(__arm64__) || defined(__aarch64__)) ) /* this might work on other ARM targets, but this is a known quantity... */
+ #define SDL_TriggerBreakpoint() __asm__ __volatile__ ( "brk #22\n\t" )
+#elif defined(__APPLE__) && defined(__arm__)
+ #define SDL_TriggerBreakpoint() __asm__ __volatile__ ( "bkpt #22\n\t" )
+#elif defined(__386__) && defined(__WATCOMC__)
+ #define SDL_TriggerBreakpoint() { _asm { int 0x03 } }
+#elif defined(HAVE_SIGNAL_H) && !defined(__WATCOMC__)
+ #include
+ #define SDL_TriggerBreakpoint() raise(SIGTRAP)
+#else
+ /* How do we trigger breakpoints on this platform? */
+ #define SDL_TriggerBreakpoint()
+#endif
+
+#if defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L) /* C99 supports __func__ as a standard. */
+# define SDL_FUNCTION __func__
+#elif ((defined(__GNUC__) && (__GNUC__ >= 2)) || defined(_MSC_VER) || defined (__WATCOMC__))
+# define SDL_FUNCTION __FUNCTION__
+#else
+# define SDL_FUNCTION "???"
+#endif
+#define SDL_FILE __FILE__
+#define SDL_LINE __LINE__
+
+/*
+sizeof (x) makes the compiler still parse the expression even without
+assertions enabled, so the code is always checked at compile time, but
+doesn't actually generate code for it, so there are no side effects or
+expensive checks at run time, just the constant size of what x WOULD be,
+which presumably gets optimized out as unused.
+This also solves the problem of...
+
+ int somevalue = blah();
+ SDL_assert(somevalue == 1);
+
+...which would cause compiles to complain that somevalue is unused if we
+disable assertions.
+*/
+
+/* "while (0,0)" fools Microsoft's compiler's /W4 warning level into thinking
+ this condition isn't constant. And looks like an owl's face! */
+#ifdef _MSC_VER /* stupid /W4 warnings. */
+#define SDL_NULL_WHILE_LOOP_CONDITION (0,0)
+#else
+#define SDL_NULL_WHILE_LOOP_CONDITION (0)
+#endif
+
+#define SDL_disabled_assert(condition) \
+ do { (void) sizeof ((condition)); } while (SDL_NULL_WHILE_LOOP_CONDITION)
+
+typedef enum
+{
+ SDL_ASSERTION_RETRY, /**< Retry the assert immediately. */
+ SDL_ASSERTION_BREAK, /**< Make the debugger trigger a breakpoint. */
+ SDL_ASSERTION_ABORT, /**< Terminate the program. */
+ SDL_ASSERTION_IGNORE, /**< Ignore the assert. */
+ SDL_ASSERTION_ALWAYS_IGNORE /**< Ignore the assert from now on. */
+} SDL_AssertState;
+
+typedef struct SDL_AssertData
+{
+ int always_ignore;
+ unsigned int trigger_count;
+ const char *condition;
+ const char *filename;
+ int linenum;
+ const char *function;
+ const struct SDL_AssertData *next;
+} SDL_AssertData;
+
+/* Never call this directly. Use the SDL_assert* macros. */
+extern DECLSPEC SDL_AssertState SDLCALL SDL_ReportAssertion(SDL_AssertData *,
+ const char *,
+ const char *, int)
+#if defined(__clang__)
+#if __has_feature(attribute_analyzer_noreturn)
+/* this tells Clang's static analysis that we're a custom assert function,
+ and that the analyzer should assume the condition was always true past this
+ SDL_assert test. */
+ __attribute__((analyzer_noreturn))
+#endif
+#endif
+;
+
+/* the do {} while(0) avoids dangling else problems:
+ if (x) SDL_assert(y); else blah();
+ ... without the do/while, the "else" could attach to this macro's "if".
+ We try to handle just the minimum we need here in a macro...the loop,
+ the static vars, and break points. The heavy lifting is handled in
+ SDL_ReportAssertion(), in SDL_assert.c.
+*/
+#define SDL_enabled_assert(condition) \
+ do { \
+ while ( !(condition) ) { \
+ static struct SDL_AssertData sdl_assert_data = { 0, 0, #condition, 0, 0, 0, 0 }; \
+ const SDL_AssertState sdl_assert_state = SDL_ReportAssertion(&sdl_assert_data, SDL_FUNCTION, SDL_FILE, SDL_LINE); \
+ if (sdl_assert_state == SDL_ASSERTION_RETRY) { \
+ continue; /* go again. */ \
+ } else if (sdl_assert_state == SDL_ASSERTION_BREAK) { \
+ SDL_TriggerBreakpoint(); \
+ } \
+ break; /* not retrying. */ \
+ } \
+ } while (SDL_NULL_WHILE_LOOP_CONDITION)
+
+/* Enable various levels of assertions. */
+#if SDL_ASSERT_LEVEL == 0 /* assertions disabled */
+# define SDL_assert(condition) SDL_disabled_assert(condition)
+# define SDL_assert_release(condition) SDL_disabled_assert(condition)
+# define SDL_assert_paranoid(condition) SDL_disabled_assert(condition)
+#elif SDL_ASSERT_LEVEL == 1 /* release settings. */
+# define SDL_assert(condition) SDL_disabled_assert(condition)
+# define SDL_assert_release(condition) SDL_enabled_assert(condition)
+# define SDL_assert_paranoid(condition) SDL_disabled_assert(condition)
+#elif SDL_ASSERT_LEVEL == 2 /* normal settings. */
+# define SDL_assert(condition) SDL_enabled_assert(condition)
+# define SDL_assert_release(condition) SDL_enabled_assert(condition)
+# define SDL_assert_paranoid(condition) SDL_disabled_assert(condition)
+#elif SDL_ASSERT_LEVEL == 3 /* paranoid settings. */
+# define SDL_assert(condition) SDL_enabled_assert(condition)
+# define SDL_assert_release(condition) SDL_enabled_assert(condition)
+# define SDL_assert_paranoid(condition) SDL_enabled_assert(condition)
+#else
+# error Unknown assertion level.
+#endif
+
+/* this assertion is never disabled at any level. */
+#define SDL_assert_always(condition) SDL_enabled_assert(condition)
+
+
+/**
+ * A callback that fires when an SDL assertion fails.
+ *
+ * \param data a pointer to the SDL_AssertData structure corresponding to the
+ * current assertion
+ * \param userdata what was passed as `userdata` to SDL_SetAssertionHandler()
+ * \returns an SDL_AssertState value indicating how to handle the failure.
+ */
+typedef SDL_AssertState (SDLCALL *SDL_AssertionHandler)(
+ const SDL_AssertData* data, void* userdata);
+
+/**
+ * Set an application-defined assertion handler.
+ *
+ * This function allows an application to show its own assertion UI and/or
+ * force the response to an assertion failure. If the application doesn't
+ * provide this, SDL will try to do the right thing, popping up a
+ * system-specific GUI dialog, and probably minimizing any fullscreen windows.
+ *
+ * This callback may fire from any thread, but it runs wrapped in a mutex, so
+ * it will only fire from one thread at a time.
+ *
+ * This callback is NOT reset to SDL's internal handler upon SDL_Quit()!
+ *
+ * \param handler the SDL_AssertionHandler function to call when an assertion
+ * fails or NULL for the default handler
+ * \param userdata a pointer that is passed to `handler`
+ *
+ * \since This function is available since SDL 2.0.0.
+ *
+ * \sa SDL_GetAssertionHandler
+ */
+extern DECLSPEC void SDLCALL SDL_SetAssertionHandler(
+ SDL_AssertionHandler handler,
+ void *userdata);
+
+/**
+ * Get the default assertion handler.
+ *
+ * This returns the function pointer that is called by default when an
+ * assertion is triggered. This is an internal function provided by SDL, that
+ * is used for assertions when SDL_SetAssertionHandler() hasn't been used to
+ * provide a different function.
+ *
+ * \returns the default SDL_AssertionHandler that is called when an assert
+ * triggers.
+ *
+ * \since This function is available since SDL 2.0.2.
+ *
+ * \sa SDL_GetAssertionHandler
+ */
+extern DECLSPEC SDL_AssertionHandler SDLCALL SDL_GetDefaultAssertionHandler(void);
+
+/**
+ * Get the current assertion handler.
+ *
+ * This returns the function pointer that is called when an assertion is
+ * triggered. This is either the value last passed to
+ * SDL_SetAssertionHandler(), or if no application-specified function is set,
+ * is equivalent to calling SDL_GetDefaultAssertionHandler().
+ *
+ * The parameter `puserdata` is a pointer to a void*, which will store the
+ * "userdata" pointer that was passed to SDL_SetAssertionHandler(). This value
+ * will always be NULL for the default handler. If you don't care about this
+ * data, it is safe to pass a NULL pointer to this function to ignore it.
+ *
+ * \param puserdata pointer which is filled with the "userdata" pointer that
+ * was passed to SDL_SetAssertionHandler()
+ * \returns the SDL_AssertionHandler that is called when an assert triggers.
+ *
+ * \since This function is available since SDL 2.0.2.
+ *
+ * \sa SDL_SetAssertionHandler
+ */
+extern DECLSPEC SDL_AssertionHandler SDLCALL SDL_GetAssertionHandler(void **puserdata);
+
+/**
+ * Get a list of all assertion failures.
+ *
+ * This function gets all assertions triggered since the last call to
+ * SDL_ResetAssertionReport(), or the start of the program.
+ *
+ * The proper way to examine this data looks something like this:
+ *
+ * ```c
+ * const SDL_AssertData *item = SDL_GetAssertionReport();
+ * while (item) {
+ * printf("'%s', %s (%s:%d), triggered %u times, always ignore: %s.\\n",
+ * item->condition, item->function, item->filename,
+ * item->linenum, item->trigger_count,
+ * item->always_ignore ? "yes" : "no");
+ * item = item->next;
+ * }
+ * ```
+ *
+ * \returns a list of all failed assertions or NULL if the list is empty. This
+ * memory should not be modified or freed by the application.
+ *
+ * \since This function is available since SDL 2.0.0.
+ *
+ * \sa SDL_ResetAssertionReport
+ */
+extern DECLSPEC const SDL_AssertData * SDLCALL SDL_GetAssertionReport(void);
+
+/**
+ * Clear the list of all assertion failures.
+ *
+ * This function will clear the list of all assertions triggered up to that
+ * point. Immediately following this call, SDL_GetAssertionReport will return
+ * no items. In addition, any previously-triggered assertions will be reset to
+ * a trigger_count of zero, and their always_ignore state will be false.
+ *
+ * \since This function is available since SDL 2.0.0.
+ *
+ * \sa SDL_GetAssertionReport
+ */
+extern DECLSPEC void SDLCALL SDL_ResetAssertionReport(void);
+
+
+/* these had wrong naming conventions until 2.0.4. Please update your app! */
+#define SDL_assert_state SDL_AssertState
+#define SDL_assert_data SDL_AssertData
+
+
+/* Ends C function definitions when using C++ */
+#ifdef __cplusplus
+}
+#endif
+#include
+
+#endif /* SDL_assert_h_ */
+
+/* vi: set ts=4 sw=4 expandtab: */
diff --git a/bindings/sdl2wgpu/src/main/headers/SDL2/SDL_atomic.h b/bindings/sdl2wgpu/src/main/headers/SDL2/SDL_atomic.h
new file mode 100644
index 00000000..7c12b48e
--- /dev/null
+++ b/bindings/sdl2wgpu/src/main/headers/SDL2/SDL_atomic.h
@@ -0,0 +1,414 @@
+/*
+ Simple DirectMedia Layer
+ Copyright (C) 1997-2023 Sam Lantinga
+
+ This software is provided 'as-is', without any express or implied
+ warranty. In no event will the authors be held liable for any damages
+ arising from the use of this software.
+
+ Permission is granted to anyone to use this software for any purpose,
+ including commercial applications, and to alter it and redistribute it
+ freely, subject to the following restrictions:
+
+ 1. The origin of this software must not be misrepresented; you must not
+ claim that you wrote the original software. If you use this software
+ in a product, an acknowledgment in the product documentation would be
+ appreciated but is not required.
+ 2. Altered source versions must be plainly marked as such, and must not be
+ misrepresented as being the original software.
+ 3. This notice may not be removed or altered from any source distribution.
+*/
+
+/**
+ * \file SDL_atomic.h
+ *
+ * Atomic operations.
+ *
+ * IMPORTANT:
+ * If you are not an expert in concurrent lockless programming, you should
+ * only be using the atomic lock and reference counting functions in this
+ * file. In all other cases you should be protecting your data structures
+ * with full mutexes.
+ *
+ * The list of "safe" functions to use are:
+ * SDL_AtomicLock()
+ * SDL_AtomicUnlock()
+ * SDL_AtomicIncRef()
+ * SDL_AtomicDecRef()
+ *
+ * Seriously, here be dragons!
+ * ^^^^^^^^^^^^^^^^^^^^^^^^^^^
+ *
+ * You can find out a little more about lockless programming and the
+ * subtle issues that can arise here:
+ * http://msdn.microsoft.com/en-us/library/ee418650%28v=vs.85%29.aspx
+ *
+ * There's also lots of good information here:
+ * http://www.1024cores.net/home/lock-free-algorithms
+ * http://preshing.com/
+ *
+ * These operations may or may not actually be implemented using
+ * processor specific atomic operations. When possible they are
+ * implemented as true processor specific atomic operations. When that
+ * is not possible the are implemented using locks that *do* use the
+ * available atomic operations.
+ *
+ * All of the atomic operations that modify memory are full memory barriers.
+ */
+
+#ifndef SDL_atomic_h_
+#define SDL_atomic_h_
+
+#include
+#include
+
+#include
+
+/* Set up for C function definitions, even when using C++ */
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * \name SDL AtomicLock
+ *
+ * The atomic locks are efficient spinlocks using CPU instructions,
+ * but are vulnerable to starvation and can spin forever if a thread
+ * holding a lock has been terminated. For this reason you should
+ * minimize the code executed inside an atomic lock and never do
+ * expensive things like API or system calls while holding them.
+ *
+ * The atomic locks are not safe to lock recursively.
+ *
+ * Porting Note:
+ * The spin lock functions and type are required and can not be
+ * emulated because they are used in the atomic emulation code.
+ */
+/* @{ */
+
+typedef int SDL_SpinLock;
+
+/**
+ * Try to lock a spin lock by setting it to a non-zero value.
+ *
+ * ***Please note that spinlocks are dangerous if you don't know what you're
+ * doing. Please be careful using any sort of spinlock!***
+ *
+ * \param lock a pointer to a lock variable
+ * \returns SDL_TRUE if the lock succeeded, SDL_FALSE if the lock is already
+ * held.
+ *
+ * \since This function is available since SDL 2.0.0.
+ *
+ * \sa SDL_AtomicLock
+ * \sa SDL_AtomicUnlock
+ */
+extern DECLSPEC SDL_bool SDLCALL SDL_AtomicTryLock(SDL_SpinLock *lock);
+
+/**
+ * Lock a spin lock by setting it to a non-zero value.
+ *
+ * ***Please note that spinlocks are dangerous if you don't know what you're
+ * doing. Please be careful using any sort of spinlock!***
+ *
+ * \param lock a pointer to a lock variable
+ *
+ * \since This function is available since SDL 2.0.0.
+ *
+ * \sa SDL_AtomicTryLock
+ * \sa SDL_AtomicUnlock
+ */
+extern DECLSPEC void SDLCALL SDL_AtomicLock(SDL_SpinLock *lock);
+
+/**
+ * Unlock a spin lock by setting it to 0.
+ *
+ * Always returns immediately.
+ *
+ * ***Please note that spinlocks are dangerous if you don't know what you're
+ * doing. Please be careful using any sort of spinlock!***
+ *
+ * \param lock a pointer to a lock variable
+ *
+ * \since This function is available since SDL 2.0.0.
+ *
+ * \sa SDL_AtomicLock
+ * \sa SDL_AtomicTryLock
+ */
+extern DECLSPEC void SDLCALL SDL_AtomicUnlock(SDL_SpinLock *lock);
+
+/* @} *//* SDL AtomicLock */
+
+
+/**
+ * The compiler barrier prevents the compiler from reordering
+ * reads and writes to globally visible variables across the call.
+ */
+#if defined(_MSC_VER) && (_MSC_VER > 1200) && !defined(__clang__)
+void _ReadWriteBarrier(void);
+#pragma intrinsic(_ReadWriteBarrier)
+#define SDL_CompilerBarrier() _ReadWriteBarrier()
+#elif (defined(__GNUC__) && !defined(__EMSCRIPTEN__)) || (defined(__SUNPRO_C) && (__SUNPRO_C >= 0x5120))
+/* This is correct for all CPUs when using GCC or Solaris Studio 12.1+. */
+#define SDL_CompilerBarrier() __asm__ __volatile__ ("" : : : "memory")
+#elif defined(__WATCOMC__)
+extern __inline void SDL_CompilerBarrier(void);
+#pragma aux SDL_CompilerBarrier = "" parm [] modify exact [];
+#else
+#define SDL_CompilerBarrier() \
+{ SDL_SpinLock _tmp = 0; SDL_AtomicLock(&_tmp); SDL_AtomicUnlock(&_tmp); }
+#endif
+
+/**
+ * Memory barriers are designed to prevent reads and writes from being
+ * reordered by the compiler and being seen out of order on multi-core CPUs.
+ *
+ * A typical pattern would be for thread A to write some data and a flag, and
+ * for thread B to read the flag and get the data. In this case you would
+ * insert a release barrier between writing the data and the flag,
+ * guaranteeing that the data write completes no later than the flag is
+ * written, and you would insert an acquire barrier between reading the flag
+ * and reading the data, to ensure that all the reads associated with the flag
+ * have completed.
+ *
+ * In this pattern you should always see a release barrier paired with an
+ * acquire barrier and you should gate the data reads/writes with a single
+ * flag variable.
+ *
+ * For more information on these semantics, take a look at the blog post:
+ * http://preshing.com/20120913/acquire-and-release-semantics
+ *
+ * \since This function is available since SDL 2.0.6.
+ */
+extern DECLSPEC void SDLCALL SDL_MemoryBarrierReleaseFunction(void);
+extern DECLSPEC void SDLCALL SDL_MemoryBarrierAcquireFunction(void);
+
+#if defined(__GNUC__) && (defined(__powerpc__) || defined(__ppc__))
+#define SDL_MemoryBarrierRelease() __asm__ __volatile__ ("lwsync" : : : "memory")
+#define SDL_MemoryBarrierAcquire() __asm__ __volatile__ ("lwsync" : : : "memory")
+#elif defined(__GNUC__) && defined(__aarch64__)
+#define SDL_MemoryBarrierRelease() __asm__ __volatile__ ("dmb ish" : : : "memory")
+#define SDL_MemoryBarrierAcquire() __asm__ __volatile__ ("dmb ish" : : : "memory")
+#elif defined(__GNUC__) && defined(__arm__)
+#if 0 /* defined(__LINUX__) || defined(__ANDROID__) */
+/* Information from:
+ https://chromium.googlesource.com/chromium/chromium/+/trunk/base/atomicops_internals_arm_gcc.h#19
+
+ The Linux kernel provides a helper function which provides the right code for a memory barrier,
+ hard-coded at address 0xffff0fa0
+*/
+typedef void (*SDL_KernelMemoryBarrierFunc)();
+#define SDL_MemoryBarrierRelease() ((SDL_KernelMemoryBarrierFunc)0xffff0fa0)()
+#define SDL_MemoryBarrierAcquire() ((SDL_KernelMemoryBarrierFunc)0xffff0fa0)()
+#elif 0 /* defined(__QNXNTO__) */
+#include
+
+#define SDL_MemoryBarrierRelease() __cpu_membarrier()
+#define SDL_MemoryBarrierAcquire() __cpu_membarrier()
+#else
+#if defined(__ARM_ARCH_7__) || defined(__ARM_ARCH_7A__) || defined(__ARM_ARCH_7EM__) || defined(__ARM_ARCH_7R__) || defined(__ARM_ARCH_7M__) || defined(__ARM_ARCH_7S__) || defined(__ARM_ARCH_8A__)
+#define SDL_MemoryBarrierRelease() __asm__ __volatile__ ("dmb ish" : : : "memory")
+#define SDL_MemoryBarrierAcquire() __asm__ __volatile__ ("dmb ish" : : : "memory")
+#elif defined(__ARM_ARCH_6__) || defined(__ARM_ARCH_6J__) || defined(__ARM_ARCH_6K__) || defined(__ARM_ARCH_6T2__) || defined(__ARM_ARCH_6Z__) || defined(__ARM_ARCH_6ZK__) || defined(__ARM_ARCH_5TE__)
+#ifdef __thumb__
+/* The mcr instruction isn't available in thumb mode, use real functions */
+#define SDL_MEMORY_BARRIER_USES_FUNCTION
+#define SDL_MemoryBarrierRelease() SDL_MemoryBarrierReleaseFunction()
+#define SDL_MemoryBarrierAcquire() SDL_MemoryBarrierAcquireFunction()
+#else
+#define SDL_MemoryBarrierRelease() __asm__ __volatile__ ("mcr p15, 0, %0, c7, c10, 5" : : "r"(0) : "memory")
+#define SDL_MemoryBarrierAcquire() __asm__ __volatile__ ("mcr p15, 0, %0, c7, c10, 5" : : "r"(0) : "memory")
+#endif /* __thumb__ */
+#else
+#define SDL_MemoryBarrierRelease() __asm__ __volatile__ ("" : : : "memory")
+#define SDL_MemoryBarrierAcquire() __asm__ __volatile__ ("" : : : "memory")
+#endif /* __LINUX__ || __ANDROID__ */
+#endif /* __GNUC__ && __arm__ */
+#else
+#if (defined(__SUNPRO_C) && (__SUNPRO_C >= 0x5120))
+/* This is correct for all CPUs on Solaris when using Solaris Studio 12.1+. */
+#include
+#define SDL_MemoryBarrierRelease() __machine_rel_barrier()
+#define SDL_MemoryBarrierAcquire() __machine_acq_barrier()
+#else
+/* This is correct for the x86 and x64 CPUs, and we'll expand this over time. */
+#define SDL_MemoryBarrierRelease() SDL_CompilerBarrier()
+#define SDL_MemoryBarrierAcquire() SDL_CompilerBarrier()
+#endif
+#endif
+
+/* "REP NOP" is PAUSE, coded for tools that don't know it by that name. */
+#if (defined(__GNUC__) || defined(__clang__)) && (defined(__i386__) || defined(__x86_64__))
+ #define SDL_CPUPauseInstruction() __asm__ __volatile__("pause\n") /* Some assemblers can't do REP NOP, so go with PAUSE. */
+#elif (defined(__arm__) && defined(__ARM_ARCH) && __ARM_ARCH >= 7) || defined(__aarch64__)
+ #define SDL_CPUPauseInstruction() __asm__ __volatile__("yield" ::: "memory")
+#elif (defined(__powerpc__) || defined(__powerpc64__))
+ #define SDL_CPUPauseInstruction() __asm__ __volatile__("or 27,27,27");
+#elif defined(_MSC_VER) && (defined(_M_IX86) || defined(_M_X64))
+ #define SDL_CPUPauseInstruction() _mm_pause() /* this is actually "rep nop" and not a SIMD instruction. No inline asm in MSVC x86-64! */
+#elif defined(_MSC_VER) && (defined(_M_ARM) || defined(_M_ARM64))
+ #define SDL_CPUPauseInstruction() __yield()
+#elif defined(__WATCOMC__) && defined(__386__)
+ extern __inline void SDL_CPUPauseInstruction(void);
+ #pragma aux SDL_CPUPauseInstruction = ".686p" ".xmm2" "pause"
+#else
+ #define SDL_CPUPauseInstruction()
+#endif
+
+
+/**
+ * \brief A type representing an atomic integer value. It is a struct
+ * so people don't accidentally use numeric operations on it.
+ */
+typedef struct { int value; } SDL_atomic_t;
+
+/**
+ * Set an atomic variable to a new value if it is currently an old value.
+ *
+ * ***Note: If you don't know what this function is for, you shouldn't use
+ * it!***
+ *
+ * \param a a pointer to an SDL_atomic_t variable to be modified
+ * \param oldval the old value
+ * \param newval the new value
+ * \returns SDL_TRUE if the atomic variable was set, SDL_FALSE otherwise.
+ *
+ * \since This function is available since SDL 2.0.0.
+ *
+ * \sa SDL_AtomicCASPtr
+ * \sa SDL_AtomicGet
+ * \sa SDL_AtomicSet
+ */
+extern DECLSPEC SDL_bool SDLCALL SDL_AtomicCAS(SDL_atomic_t *a, int oldval, int newval);
+
+/**
+ * Set an atomic variable to a value.
+ *
+ * This function also acts as a full memory barrier.
+ *
+ * ***Note: If you don't know what this function is for, you shouldn't use
+ * it!***
+ *
+ * \param a a pointer to an SDL_atomic_t variable to be modified
+ * \param v the desired value
+ * \returns the previous value of the atomic variable.
+ *
+ * \since This function is available since SDL 2.0.2.
+ *
+ * \sa SDL_AtomicGet
+ */
+extern DECLSPEC int SDLCALL SDL_AtomicSet(SDL_atomic_t *a, int v);
+
+/**
+ * Get the value of an atomic variable.
+ *
+ * ***Note: If you don't know what this function is for, you shouldn't use
+ * it!***
+ *
+ * \param a a pointer to an SDL_atomic_t variable
+ * \returns the current value of an atomic variable.
+ *
+ * \since This function is available since SDL 2.0.2.
+ *
+ * \sa SDL_AtomicSet
+ */
+extern DECLSPEC int SDLCALL SDL_AtomicGet(SDL_atomic_t *a);
+
+/**
+ * Add to an atomic variable.
+ *
+ * This function also acts as a full memory barrier.
+ *
+ * ***Note: If you don't know what this function is for, you shouldn't use
+ * it!***
+ *
+ * \param a a pointer to an SDL_atomic_t variable to be modified
+ * \param v the desired value to add
+ * \returns the previous value of the atomic variable.
+ *
+ * \since This function is available since SDL 2.0.2.
+ *
+ * \sa SDL_AtomicDecRef
+ * \sa SDL_AtomicIncRef
+ */
+extern DECLSPEC int SDLCALL SDL_AtomicAdd(SDL_atomic_t *a, int v);
+
+/**
+ * \brief Increment an atomic variable used as a reference count.
+ */
+#ifndef SDL_AtomicIncRef
+#define SDL_AtomicIncRef(a) SDL_AtomicAdd(a, 1)
+#endif
+
+/**
+ * \brief Decrement an atomic variable used as a reference count.
+ *
+ * \return SDL_TRUE if the variable reached zero after decrementing,
+ * SDL_FALSE otherwise
+ */
+#ifndef SDL_AtomicDecRef
+#define SDL_AtomicDecRef(a) (SDL_AtomicAdd(a, -1) == 1)
+#endif
+
+/**
+ * Set a pointer to a new value if it is currently an old value.
+ *
+ * ***Note: If you don't know what this function is for, you shouldn't use
+ * it!***
+ *
+ * \param a a pointer to a pointer
+ * \param oldval the old pointer value
+ * \param newval the new pointer value
+ * \returns SDL_TRUE if the pointer was set, SDL_FALSE otherwise.
+ *
+ * \since This function is available since SDL 2.0.0.
+ *
+ * \sa SDL_AtomicCAS
+ * \sa SDL_AtomicGetPtr
+ * \sa SDL_AtomicSetPtr
+ */
+extern DECLSPEC SDL_bool SDLCALL SDL_AtomicCASPtr(void **a, void *oldval, void *newval);
+
+/**
+ * Set a pointer to a value atomically.
+ *
+ * ***Note: If you don't know what this function is for, you shouldn't use
+ * it!***
+ *
+ * \param a a pointer to a pointer
+ * \param v the desired pointer value
+ * \returns the previous value of the pointer.
+ *
+ * \since This function is available since SDL 2.0.2.
+ *
+ * \sa SDL_AtomicCASPtr
+ * \sa SDL_AtomicGetPtr
+ */
+extern DECLSPEC void* SDLCALL SDL_AtomicSetPtr(void **a, void* v);
+
+/**
+ * Get the value of a pointer atomically.
+ *
+ * ***Note: If you don't know what this function is for, you shouldn't use
+ * it!***
+ *
+ * \param a a pointer to a pointer
+ * \returns the current value of a pointer.
+ *
+ * \since This function is available since SDL 2.0.2.
+ *
+ * \sa SDL_AtomicCASPtr
+ * \sa SDL_AtomicSetPtr
+ */
+extern DECLSPEC void* SDLCALL SDL_AtomicGetPtr(void **a);
+
+/* Ends C function definitions when using C++ */
+#ifdef __cplusplus
+}
+#endif
+
+#include
+
+#endif /* SDL_atomic_h_ */
+
+/* vi: set ts=4 sw=4 expandtab: */
diff --git a/bindings/sdl2wgpu/src/main/headers/SDL2/SDL_audio.h b/bindings/sdl2wgpu/src/main/headers/SDL2/SDL_audio.h
new file mode 100644
index 00000000..2eeb542b
--- /dev/null
+++ b/bindings/sdl2wgpu/src/main/headers/SDL2/SDL_audio.h
@@ -0,0 +1,1500 @@
+/*
+ Simple DirectMedia Layer
+ Copyright (C) 1997-2023 Sam Lantinga
+
+ This software is provided 'as-is', without any express or implied
+ warranty. In no event will the authors be held liable for any damages
+ arising from the use of this software.
+
+ Permission is granted to anyone to use this software for any purpose,
+ including commercial applications, and to alter it and redistribute it
+ freely, subject to the following restrictions:
+
+ 1. The origin of this software must not be misrepresented; you must not
+ claim that you wrote the original software. If you use this software
+ in a product, an acknowledgment in the product documentation would be
+ appreciated but is not required.
+ 2. Altered source versions must be plainly marked as such, and must not be
+ misrepresented as being the original software.
+ 3. This notice may not be removed or altered from any source distribution.
+*/
+
+/* !!! FIXME: several functions in here need Doxygen comments. */
+
+/**
+ * \file SDL_audio.h
+ *
+ * Access to the raw audio mixing buffer for the SDL library.
+ */
+
+#ifndef SDL_audio_h_
+#define SDL_audio_h_
+
+#include
+#include
+#include
+#include
+#include
+#include
+
+#include
+/* Set up for C function definitions, even when using C++ */
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * \brief Audio format flags.
+ *
+ * These are what the 16 bits in SDL_AudioFormat currently mean...
+ * (Unspecified bits are always zero).
+ *
+ * \verbatim
+ ++-----------------------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
+ \endverbatim
+ *
+ * There are macros in SDL 2.0 and later to query these bits.
+ */
+typedef Uint16 SDL_AudioFormat;
+
+/**
+ * \name Audio flags
+ */
+/* @{ */
+
+#define SDL_AUDIO_MASK_BITSIZE (0xFF)
+#define SDL_AUDIO_MASK_DATATYPE (1<<8)
+#define SDL_AUDIO_MASK_ENDIAN (1<<12)
+#define SDL_AUDIO_MASK_SIGNED (1<<15)
+#define SDL_AUDIO_BITSIZE(x) (x & SDL_AUDIO_MASK_BITSIZE)
+#define SDL_AUDIO_ISFLOAT(x) (x & SDL_AUDIO_MASK_DATATYPE)
+#define SDL_AUDIO_ISBIGENDIAN(x) (x & SDL_AUDIO_MASK_ENDIAN)
+#define SDL_AUDIO_ISSIGNED(x) (x & SDL_AUDIO_MASK_SIGNED)
+#define SDL_AUDIO_ISINT(x) (!SDL_AUDIO_ISFLOAT(x))
+#define SDL_AUDIO_ISLITTLEENDIAN(x) (!SDL_AUDIO_ISBIGENDIAN(x))
+#define SDL_AUDIO_ISUNSIGNED(x) (!SDL_AUDIO_ISSIGNED(x))
+
+/**
+ * \name Audio format flags
+ *
+ * Defaults to LSB byte order.
+ */
+/* @{ */
+#define AUDIO_U8 0x0008 /**< Unsigned 8-bit samples */
+#define AUDIO_S8 0x8008 /**< Signed 8-bit samples */
+#define AUDIO_U16LSB 0x0010 /**< Unsigned 16-bit samples */
+#define AUDIO_S16LSB 0x8010 /**< Signed 16-bit samples */
+#define AUDIO_U16MSB 0x1010 /**< As above, but big-endian byte order */
+#define AUDIO_S16MSB 0x9010 /**< As above, but big-endian byte order */
+#define AUDIO_U16 AUDIO_U16LSB
+#define AUDIO_S16 AUDIO_S16LSB
+/* @} */
+
+/**
+ * \name int32 support
+ */
+/* @{ */
+#define AUDIO_S32LSB 0x8020 /**< 32-bit integer samples */
+#define AUDIO_S32MSB 0x9020 /**< As above, but big-endian byte order */
+#define AUDIO_S32 AUDIO_S32LSB
+/* @} */
+
+/**
+ * \name float32 support
+ */
+/* @{ */
+#define AUDIO_F32LSB 0x8120 /**< 32-bit floating point samples */
+#define AUDIO_F32MSB 0x9120 /**< As above, but big-endian byte order */
+#define AUDIO_F32 AUDIO_F32LSB
+/* @} */
+
+/**
+ * \name Native audio byte ordering
+ */
+/* @{ */
+#if SDL_BYTEORDER == SDL_LIL_ENDIAN
+#define AUDIO_U16SYS AUDIO_U16LSB
+#define AUDIO_S16SYS AUDIO_S16LSB
+#define AUDIO_S32SYS AUDIO_S32LSB
+#define AUDIO_F32SYS AUDIO_F32LSB
+#else
+#define AUDIO_U16SYS AUDIO_U16MSB
+#define AUDIO_S16SYS AUDIO_S16MSB
+#define AUDIO_S32SYS AUDIO_S32MSB
+#define AUDIO_F32SYS AUDIO_F32MSB
+#endif
+/* @} */
+
+/**
+ * \name Allow change flags
+ *
+ * Which audio format changes are allowed when opening a device.
+ */
+/* @{ */
+#define SDL_AUDIO_ALLOW_FREQUENCY_CHANGE 0x00000001
+#define SDL_AUDIO_ALLOW_FORMAT_CHANGE 0x00000002
+#define SDL_AUDIO_ALLOW_CHANNELS_CHANGE 0x00000004
+#define SDL_AUDIO_ALLOW_SAMPLES_CHANGE 0x00000008
+#define SDL_AUDIO_ALLOW_ANY_CHANGE (SDL_AUDIO_ALLOW_FREQUENCY_CHANGE|SDL_AUDIO_ALLOW_FORMAT_CHANGE|SDL_AUDIO_ALLOW_CHANNELS_CHANGE|SDL_AUDIO_ALLOW_SAMPLES_CHANGE)
+/* @} */
+
+/* @} *//* Audio flags */
+
+/**
+ * This function is called when the audio device needs more data.
+ *
+ * \param userdata An application-specific parameter saved in
+ * the SDL_AudioSpec structure
+ * \param stream A pointer to the audio data buffer.
+ * \param len The length of that buffer in bytes.
+ *
+ * Once the callback returns, the buffer will no longer be valid.
+ * Stereo samples are stored in a LRLRLR ordering.
+ *
+ * You can choose to avoid callbacks and use SDL_QueueAudio() instead, if
+ * you like. Just open your audio device with a NULL callback.
+ */
+typedef void (SDLCALL * SDL_AudioCallback) (void *userdata, Uint8 * stream,
+ int len);
+
+/**
+ * The calculated values in this structure are calculated by SDL_OpenAudio().
+ *
+ * For multi-channel audio, the default SDL channel mapping is:
+ * 2: FL FR (stereo)
+ * 3: FL FR LFE (2.1 surround)
+ * 4: FL FR BL BR (quad)
+ * 5: FL FR LFE BL BR (4.1 surround)
+ * 6: FL FR FC LFE SL SR (5.1 surround - last two can also be BL BR)
+ * 7: FL FR FC LFE BC SL SR (6.1 surround)
+ * 8: FL FR FC LFE BL BR SL SR (7.1 surround)
+ */
+typedef struct SDL_AudioSpec
+{
+ int freq; /**< DSP frequency -- samples per second */
+ SDL_AudioFormat format; /**< Audio data format */
+ Uint8 channels; /**< Number of channels: 1 mono, 2 stereo */
+ Uint8 silence; /**< Audio buffer silence value (calculated) */
+ Uint16 samples; /**< Audio buffer size in sample FRAMES (total samples divided by channel count) */
+ Uint16 padding; /**< Necessary for some compile environments */
+ Uint32 size; /**< Audio buffer size in bytes (calculated) */
+ SDL_AudioCallback callback; /**< Callback that feeds the audio device (NULL to use SDL_QueueAudio()). */
+ void *userdata; /**< Userdata passed to callback (ignored for NULL callbacks). */
+} SDL_AudioSpec;
+
+
+struct SDL_AudioCVT;
+typedef void (SDLCALL * SDL_AudioFilter) (struct SDL_AudioCVT * cvt,
+ SDL_AudioFormat format);
+
+/**
+ * \brief Upper limit of filters in SDL_AudioCVT
+ *
+ * The maximum number of SDL_AudioFilter functions in SDL_AudioCVT is
+ * currently limited to 9. The SDL_AudioCVT.filters array has 10 pointers,
+ * one of which is the terminating NULL pointer.
+ */
+#define SDL_AUDIOCVT_MAX_FILTERS 9
+
+/**
+ * \struct SDL_AudioCVT
+ * \brief A structure to hold a set of audio conversion filters and buffers.
+ *
+ * Note that various parts of the conversion pipeline can take advantage
+ * of SIMD operations (like SSE2, for example). SDL_AudioCVT doesn't require
+ * you to pass it aligned data, but can possibly run much faster if you
+ * set both its (buf) field to a pointer that is aligned to 16 bytes, and its
+ * (len) field to something that's a multiple of 16, if possible.
+ */
+#if defined(__GNUC__) && !defined(__CHERI_PURE_CAPABILITY__)
+/* This structure is 84 bytes on 32-bit architectures, make sure GCC doesn't
+ pad it out to 88 bytes to guarantee ABI compatibility between compilers.
+ This is not a concern on CHERI architectures, where pointers must be stored
+ at aligned locations otherwise they will become invalid, and thus structs
+ containing pointers cannot be packed without giving a warning or error.
+ vvv
+ The next time we rev the ABI, make sure to size the ints and add padding.
+*/
+#define SDL_AUDIOCVT_PACKED __attribute__((packed))
+#else
+#define SDL_AUDIOCVT_PACKED
+#endif
+/* */
+typedef struct SDL_AudioCVT
+{
+ int needed; /**< Set to 1 if conversion possible */
+ SDL_AudioFormat src_format; /**< Source audio format */
+ SDL_AudioFormat dst_format; /**< Target audio format */
+ double rate_incr; /**< Rate conversion increment */
+ Uint8 *buf; /**< Buffer to hold entire audio data */
+ int len; /**< Length of original audio buffer */
+ int len_cvt; /**< Length of converted audio buffer */
+ int len_mult; /**< buffer must be len*len_mult big */
+ double len_ratio; /**< Given len, final size is len*len_ratio */
+ SDL_AudioFilter filters[SDL_AUDIOCVT_MAX_FILTERS + 1]; /**< NULL-terminated list of filter functions */
+ int filter_index; /**< Current audio conversion function */
+} SDL_AUDIOCVT_PACKED SDL_AudioCVT;
+
+
+/* Function prototypes */
+
+/**
+ * \name Driver discovery functions
+ *
+ * These functions return the list of built in audio drivers, in the
+ * order that they are normally initialized by default.
+ */
+/* @{ */
+
+/**
+ * Use this function to get the number of built-in audio drivers.
+ *
+ * This function returns a hardcoded number. This never returns a negative
+ * value; if there are no drivers compiled into this build of SDL, this
+ * function returns zero. The presence of a driver in this list does not mean
+ * it will function, it just means SDL is capable of interacting with that
+ * interface. For example, a build of SDL might have esound support, but if
+ * there's no esound server available, SDL's esound driver would fail if used.
+ *
+ * By default, SDL tries all drivers, in its preferred order, until one is
+ * found to be usable.
+ *
+ * \returns the number of built-in audio drivers.
+ *
+ * \since This function is available since SDL 2.0.0.
+ *
+ * \sa SDL_GetAudioDriver
+ */
+extern DECLSPEC int SDLCALL SDL_GetNumAudioDrivers(void);
+
+/**
+ * Use this function to get the name of a built in audio driver.
+ *
+ * The list of audio drivers is given in the order that they are normally
+ * initialized by default; the drivers that seem more reasonable to choose
+ * first (as far as the SDL developers believe) are earlier in the list.
+ *
+ * The names of drivers are all simple, low-ASCII identifiers, like "alsa",
+ * "coreaudio" or "xaudio2". These never have Unicode characters, and are not
+ * meant to be proper names.
+ *
+ * \param index the index of the audio driver; the value ranges from 0 to
+ * SDL_GetNumAudioDrivers() - 1
+ * \returns the name of the audio driver at the requested index, or NULL if an
+ * invalid index was specified.
+ *
+ * \since This function is available since SDL 2.0.0.
+ *
+ * \sa SDL_GetNumAudioDrivers
+ */
+extern DECLSPEC const char *SDLCALL SDL_GetAudioDriver(int index);
+/* @} */
+
+/**
+ * \name Initialization and cleanup
+ *
+ * \internal These functions are used internally, and should not be used unless
+ * you have a specific need to specify the audio driver you want to
+ * use. You should normally use SDL_Init() or SDL_InitSubSystem().
+ */
+/* @{ */
+
+/**
+ * Use this function to initialize a particular audio driver.
+ *
+ * This function is used internally, and should not be used unless you have a
+ * specific need to designate the audio driver you want to use. You should
+ * normally use SDL_Init() or SDL_InitSubSystem().
+ *
+ * \param driver_name the name of the desired audio driver
+ * \returns 0 on success or a negative error code on failure; call
+ * SDL_GetError() for more information.
+ *
+ * \since This function is available since SDL 2.0.0.
+ *
+ * \sa SDL_AudioQuit
+ */
+extern DECLSPEC int SDLCALL SDL_AudioInit(const char *driver_name);
+
+/**
+ * Use this function to shut down audio if you initialized it with
+ * SDL_AudioInit().
+ *
+ * This function is used internally, and should not be used unless you have a
+ * specific need to specify the audio driver you want to use. You should
+ * normally use SDL_Quit() or SDL_QuitSubSystem().
+ *
+ * \since This function is available since SDL 2.0.0.
+ *
+ * \sa SDL_AudioInit
+ */
+extern DECLSPEC void SDLCALL SDL_AudioQuit(void);
+/* @} */
+
+/**
+ * Get the name of the current audio driver.
+ *
+ * The returned string points to internal static memory and thus never becomes
+ * invalid, even if you quit the audio subsystem and initialize a new driver
+ * (although such a case would return a different static string from another
+ * call to this function, of course). As such, you should not modify or free
+ * the returned string.
+ *
+ * \returns the name of the current audio driver or NULL if no driver has been
+ * initialized.
+ *
+ * \since This function is available since SDL 2.0.0.
+ *
+ * \sa SDL_AudioInit
+ */
+extern DECLSPEC const char *SDLCALL SDL_GetCurrentAudioDriver(void);
+
+/**
+ * This function is a legacy means of opening the audio device.
+ *
+ * This function remains for compatibility with SDL 1.2, but also because it's
+ * slightly easier to use than the new functions in SDL 2.0. The new, more
+ * powerful, and preferred way to do this is SDL_OpenAudioDevice().
+ *
+ * This function is roughly equivalent to:
+ *
+ * ```c
+ * SDL_OpenAudioDevice(NULL, 0, desired, obtained, SDL_AUDIO_ALLOW_ANY_CHANGE);
+ * ```
+ *
+ * With two notable exceptions:
+ *
+ * - If `obtained` is NULL, we use `desired` (and allow no changes), which
+ * means desired will be modified to have the correct values for silence,
+ * etc, and SDL will convert any differences between your app's specific
+ * request and the hardware behind the scenes.
+ * - The return value is always success or failure, and not a device ID, which
+ * means you can only have one device open at a time with this function.
+ *
+ * \param desired an SDL_AudioSpec structure representing the desired output
+ * format. Please refer to the SDL_OpenAudioDevice
+ * documentation for details on how to prepare this structure.
+ * \param obtained an SDL_AudioSpec structure filled in with the actual
+ * parameters, or NULL.
+ * \returns 0 if successful, placing the actual hardware parameters in the
+ * structure pointed to by `obtained`.
+ *
+ * If `obtained` is NULL, the audio data passed to the callback
+ * function will be guaranteed to be in the requested format, and
+ * will be automatically converted to the actual hardware audio
+ * format if necessary. If `obtained` is NULL, `desired` will have
+ * fields modified.
+ *
+ * This function returns a negative error code on failure to open the
+ * audio device or failure to set up the audio thread; call
+ * SDL_GetError() for more information.
+ *
+ * \since This function is available since SDL 2.0.0.
+ *
+ * \sa SDL_CloseAudio
+ * \sa SDL_LockAudio
+ * \sa SDL_PauseAudio
+ * \sa SDL_UnlockAudio
+ */
+extern DECLSPEC int SDLCALL SDL_OpenAudio(SDL_AudioSpec * desired,
+ SDL_AudioSpec * obtained);
+
+/**
+ * SDL Audio Device IDs.
+ *
+ * A successful call to SDL_OpenAudio() is always device id 1, and legacy
+ * SDL audio APIs assume you want this device ID. SDL_OpenAudioDevice() calls
+ * always returns devices >= 2 on success. The legacy calls are good both
+ * for backwards compatibility and when you don't care about multiple,
+ * specific, or capture devices.
+ */
+typedef Uint32 SDL_AudioDeviceID;
+
+/**
+ * Get the number of built-in audio devices.
+ *
+ * This function is only valid after successfully initializing the audio
+ * subsystem.
+ *
+ * Note that audio capture support is not implemented as of SDL 2.0.4, so the
+ * `iscapture` parameter is for future expansion and should always be zero for
+ * now.
+ *
+ * This function will return -1 if an explicit list of devices can't be
+ * determined. Returning -1 is not an error. For example, if SDL is set up to
+ * talk to a remote audio server, it can't list every one available on the
+ * Internet, but it will still allow a specific host to be specified in
+ * SDL_OpenAudioDevice().
+ *
+ * In many common cases, when this function returns a value <= 0, it can still
+ * successfully open the default device (NULL for first argument of
+ * SDL_OpenAudioDevice()).
+ *
+ * This function may trigger a complete redetect of available hardware. It
+ * should not be called for each iteration of a loop, but rather once at the
+ * start of a loop:
+ *
+ * ```c
+ * // Don't do this:
+ * for (int i = 0; i < SDL_GetNumAudioDevices(0); i++)
+ *
+ * // do this instead:
+ * const int count = SDL_GetNumAudioDevices(0);
+ * for (int i = 0; i < count; ++i) { do_something_here(); }
+ * ```
+ *
+ * \param iscapture zero to request playback devices, non-zero to request
+ * recording devices
+ * \returns the number of available devices exposed by the current driver or
+ * -1 if an explicit list of devices can't be determined. A return
+ * value of -1 does not necessarily mean an error condition.
+ *
+ * \since This function is available since SDL 2.0.0.
+ *
+ * \sa SDL_GetAudioDeviceName
+ * \sa SDL_OpenAudioDevice
+ */
+extern DECLSPEC int SDLCALL SDL_GetNumAudioDevices(int iscapture);
+
+/**
+ * Get the human-readable name of a specific audio device.
+ *
+ * This function is only valid after successfully initializing the audio
+ * subsystem. The values returned by this function reflect the latest call to
+ * SDL_GetNumAudioDevices(); re-call that function to redetect available
+ * hardware.
+ *
+ * The string returned by this function is UTF-8 encoded, read-only, and
+ * managed internally. You are not to free it. If you need to keep the string
+ * for any length of time, you should make your own copy of it, as it will be
+ * invalid next time any of several other SDL functions are called.
+ *
+ * \param index the index of the audio device; valid values range from 0 to
+ * SDL_GetNumAudioDevices() - 1
+ * \param iscapture non-zero to query the list of recording devices, zero to
+ * query the list of output devices.
+ * \returns the name of the audio device at the requested index, or NULL on
+ * error.
+ *
+ * \since This function is available since SDL 2.0.0.
+ *
+ * \sa SDL_GetNumAudioDevices
+ * \sa SDL_GetDefaultAudioInfo
+ */
+extern DECLSPEC const char *SDLCALL SDL_GetAudioDeviceName(int index,
+ int iscapture);
+
+/**
+ * Get the preferred audio format of a specific audio device.
+ *
+ * This function is only valid after a successfully initializing the audio
+ * subsystem. The values returned by this function reflect the latest call to
+ * SDL_GetNumAudioDevices(); re-call that function to redetect available
+ * hardware.
+ *
+ * `spec` will be filled with the sample rate, sample format, and channel
+ * count.
+ *
+ * \param index the index of the audio device; valid values range from 0 to
+ * SDL_GetNumAudioDevices() - 1
+ * \param iscapture non-zero to query the list of recording devices, zero to
+ * query the list of output devices.
+ * \param spec The SDL_AudioSpec to be initialized by this function.
+ * \returns 0 on success, nonzero on error
+ *
+ * \since This function is available since SDL 2.0.16.
+ *
+ * \sa SDL_GetNumAudioDevices
+ * \sa SDL_GetDefaultAudioInfo
+ */
+extern DECLSPEC int SDLCALL SDL_GetAudioDeviceSpec(int index,
+ int iscapture,
+ SDL_AudioSpec *spec);
+
+
+/**
+ * Get the name and preferred format of the default audio device.
+ *
+ * Some (but not all!) platforms have an isolated mechanism to get information
+ * about the "default" device. This can actually be a completely different
+ * device that's not in the list you get from SDL_GetAudioDeviceSpec(). It can
+ * even be a network address! (This is discussed in SDL_OpenAudioDevice().)
+ *
+ * As a result, this call is not guaranteed to be performant, as it can query
+ * the sound server directly every time, unlike the other query functions. You
+ * should call this function sparingly!
+ *
+ * `spec` will be filled with the sample rate, sample format, and channel
+ * count, if a default device exists on the system. If `name` is provided,
+ * will be filled with either a dynamically-allocated UTF-8 string or NULL.
+ *
+ * \param name A pointer to be filled with the name of the default device (can
+ * be NULL). Please call SDL_free() when you are done with this
+ * pointer!
+ * \param spec The SDL_AudioSpec to be initialized by this function.
+ * \param iscapture non-zero to query the default recording device, zero to
+ * query the default output device.
+ * \returns 0 on success, nonzero on error
+ *
+ * \since This function is available since SDL 2.24.0.
+ *
+ * \sa SDL_GetAudioDeviceName
+ * \sa SDL_GetAudioDeviceSpec
+ * \sa SDL_OpenAudioDevice
+ */
+extern DECLSPEC int SDLCALL SDL_GetDefaultAudioInfo(char **name,
+ SDL_AudioSpec *spec,
+ int iscapture);
+
+
+/**
+ * Open a specific audio device.
+ *
+ * SDL_OpenAudio(), unlike this function, always acts on device ID 1. As such,
+ * this function will never return a 1 so as not to conflict with the legacy
+ * function.
+ *
+ * Please note that SDL 2.0 before 2.0.5 did not support recording; as such,
+ * this function would fail if `iscapture` was not zero. Starting with SDL
+ * 2.0.5, recording is implemented and this value can be non-zero.
+ *
+ * Passing in a `device` name of NULL requests the most reasonable default
+ * (and is equivalent to what SDL_OpenAudio() does to choose a device). The
+ * `device` name is a UTF-8 string reported by SDL_GetAudioDeviceName(), but
+ * some drivers allow arbitrary and driver-specific strings, such as a
+ * hostname/IP address for a remote audio server, or a filename in the
+ * diskaudio driver.
+ *
+ * An opened audio device starts out paused, and should be enabled for playing
+ * by calling SDL_PauseAudioDevice(devid, 0) when you are ready for your audio
+ * callback function to be called. Since the audio driver may modify the
+ * requested size of the audio buffer, you should allocate any local mixing
+ * buffers after you open the audio device.
+ *
+ * The audio callback runs in a separate thread in most cases; you can prevent
+ * race conditions between your callback and other threads without fully
+ * pausing playback with SDL_LockAudioDevice(). For more information about the
+ * callback, see SDL_AudioSpec.
+ *
+ * Managing the audio spec via 'desired' and 'obtained':
+ *
+ * When filling in the desired audio spec structure:
+ *
+ * - `desired->freq` should be the frequency in sample-frames-per-second (Hz).
+ * - `desired->format` should be the audio format (`AUDIO_S16SYS`, etc).
+ * - `desired->samples` is the desired size of the audio buffer, in _sample
+ * frames_ (with stereo output, two samples--left and right--would make a
+ * single sample frame). This number should be a power of two, and may be
+ * adjusted by the audio driver to a value more suitable for the hardware.
+ * Good values seem to range between 512 and 8096 inclusive, depending on
+ * the application and CPU speed. Smaller values reduce latency, but can
+ * lead to underflow if the application is doing heavy processing and cannot
+ * fill the audio buffer in time. Note that the number of sample frames is
+ * directly related to time by the following formula: `ms =
+ * (sampleframes*1000)/freq`
+ * - `desired->size` is the size in _bytes_ of the audio buffer, and is
+ * calculated by SDL_OpenAudioDevice(). You don't initialize this.
+ * - `desired->silence` is the value used to set the buffer to silence, and is
+ * calculated by SDL_OpenAudioDevice(). You don't initialize this.
+ * - `desired->callback` should be set to a function that will be called when
+ * the audio device is ready for more data. It is passed a pointer to the
+ * audio buffer, and the length in bytes of the audio buffer. This function
+ * usually runs in a separate thread, and so you should protect data
+ * structures that it accesses by calling SDL_LockAudioDevice() and
+ * SDL_UnlockAudioDevice() in your code. Alternately, you may pass a NULL
+ * pointer here, and call SDL_QueueAudio() with some frequency, to queue
+ * more audio samples to be played (or for capture devices, call
+ * SDL_DequeueAudio() with some frequency, to obtain audio samples).
+ * - `desired->userdata` is passed as the first parameter to your callback
+ * function. If you passed a NULL callback, this value is ignored.
+ *
+ * `allowed_changes` can have the following flags OR'd together:
+ *
+ * - `SDL_AUDIO_ALLOW_FREQUENCY_CHANGE`
+ * - `SDL_AUDIO_ALLOW_FORMAT_CHANGE`
+ * - `SDL_AUDIO_ALLOW_CHANNELS_CHANGE`
+ * - `SDL_AUDIO_ALLOW_SAMPLES_CHANGE`
+ * - `SDL_AUDIO_ALLOW_ANY_CHANGE`
+ *
+ * These flags specify how SDL should behave when a device cannot offer a
+ * specific feature. If the application requests a feature that the hardware
+ * doesn't offer, SDL will always try to get the closest equivalent.
+ *
+ * For example, if you ask for float32 audio format, but the sound card only
+ * supports int16, SDL will set the hardware to int16. If you had set
+ * SDL_AUDIO_ALLOW_FORMAT_CHANGE, SDL will change the format in the `obtained`
+ * structure. If that flag was *not* set, SDL will prepare to convert your
+ * callback's float32 audio to int16 before feeding it to the hardware and
+ * will keep the originally requested format in the `obtained` structure.
+ *
+ * The resulting audio specs, varying depending on hardware and on what
+ * changes were allowed, will then be written back to `obtained`.
+ *
+ * If your application can only handle one specific data format, pass a zero
+ * for `allowed_changes` and let SDL transparently handle any differences.
+ *
+ * \param device a UTF-8 string reported by SDL_GetAudioDeviceName() or a
+ * driver-specific name as appropriate. NULL requests the most
+ * reasonable default device.
+ * \param iscapture non-zero to specify a device should be opened for
+ * recording, not playback
+ * \param desired an SDL_AudioSpec structure representing the desired output
+ * format; see SDL_OpenAudio() for more information
+ * \param obtained an SDL_AudioSpec structure filled in with the actual output
+ * format; see SDL_OpenAudio() for more information
+ * \param allowed_changes 0, or one or more flags OR'd together
+ * \returns a valid device ID that is > 0 on success or 0 on failure; call
+ * SDL_GetError() for more information.
+ *
+ * For compatibility with SDL 1.2, this will never return 1, since
+ * SDL reserves that ID for the legacy SDL_OpenAudio() function.
+ *
+ * \since This function is available since SDL 2.0.0.
+ *
+ * \sa SDL_CloseAudioDevice
+ * \sa SDL_GetAudioDeviceName
+ * \sa SDL_LockAudioDevice
+ * \sa SDL_OpenAudio
+ * \sa SDL_PauseAudioDevice
+ * \sa SDL_UnlockAudioDevice
+ */
+extern DECLSPEC SDL_AudioDeviceID SDLCALL SDL_OpenAudioDevice(
+ const char *device,
+ int iscapture,
+ const SDL_AudioSpec *desired,
+ SDL_AudioSpec *obtained,
+ int allowed_changes);
+
+
+
+/**
+ * \name Audio state
+ *
+ * Get the current audio state.
+ */
+/* @{ */
+typedef enum
+{
+ SDL_AUDIO_STOPPED = 0,
+ SDL_AUDIO_PLAYING,
+ SDL_AUDIO_PAUSED
+} SDL_AudioStatus;
+
+/**
+ * This function is a legacy means of querying the audio device.
+ *
+ * New programs might want to use SDL_GetAudioDeviceStatus() instead. This
+ * function is equivalent to calling...
+ *
+ * ```c
+ * SDL_GetAudioDeviceStatus(1);
+ * ```
+ *
+ * ...and is only useful if you used the legacy SDL_OpenAudio() function.
+ *
+ * \returns the SDL_AudioStatus of the audio device opened by SDL_OpenAudio().
+ *
+ * \since This function is available since SDL 2.0.0.
+ *
+ * \sa SDL_GetAudioDeviceStatus
+ */
+extern DECLSPEC SDL_AudioStatus SDLCALL SDL_GetAudioStatus(void);
+
+/**
+ * Use this function to get the current audio state of an audio device.
+ *
+ * \param dev the ID of an audio device previously opened with
+ * SDL_OpenAudioDevice()
+ * \returns the SDL_AudioStatus of the specified audio device.
+ *
+ * \since This function is available since SDL 2.0.0.
+ *
+ * \sa SDL_PauseAudioDevice
+ */
+extern DECLSPEC SDL_AudioStatus SDLCALL SDL_GetAudioDeviceStatus(SDL_AudioDeviceID dev);
+/* @} *//* Audio State */
+
+/**
+ * \name Pause audio functions
+ *
+ * These functions pause and unpause the audio callback processing.
+ * They should be called with a parameter of 0 after opening the audio
+ * device to start playing sound. This is so you can safely initialize
+ * data for your callback function after opening the audio device.
+ * Silence will be written to the audio device during the pause.
+ */
+/* @{ */
+
+/**
+ * This function is a legacy means of pausing the audio device.
+ *
+ * New programs might want to use SDL_PauseAudioDevice() instead. This
+ * function is equivalent to calling...
+ *
+ * ```c
+ * SDL_PauseAudioDevice(1, pause_on);
+ * ```
+ *
+ * ...and is only useful if you used the legacy SDL_OpenAudio() function.
+ *
+ * \param pause_on non-zero to pause, 0 to unpause
+ *
+ * \since This function is available since SDL 2.0.0.
+ *
+ * \sa SDL_GetAudioStatus
+ * \sa SDL_PauseAudioDevice
+ */
+extern DECLSPEC void SDLCALL SDL_PauseAudio(int pause_on);
+
+/**
+ * Use this function to pause and unpause audio playback on a specified
+ * device.
+ *
+ * This function pauses and unpauses the audio callback processing for a given
+ * device. Newly-opened audio devices start in the paused state, so you must
+ * call this function with **pause_on**=0 after opening the specified audio
+ * device to start playing sound. This allows you to safely initialize data
+ * for your callback function after opening the audio device. Silence will be
+ * written to the audio device while paused, and the audio callback is
+ * guaranteed to not be called. Pausing one device does not prevent other
+ * unpaused devices from running their callbacks.
+ *
+ * Pausing state does not stack; even if you pause a device several times, a
+ * single unpause will start the device playing again, and vice versa. This is
+ * different from how SDL_LockAudioDevice() works.
+ *
+ * If you just need to protect a few variables from race conditions vs your
+ * callback, you shouldn't pause the audio device, as it will lead to dropouts
+ * in the audio playback. Instead, you should use SDL_LockAudioDevice().
+ *
+ * \param dev a device opened by SDL_OpenAudioDevice()
+ * \param pause_on non-zero to pause, 0 to unpause
+ *
+ * \since This function is available since SDL 2.0.0.
+ *
+ * \sa SDL_LockAudioDevice
+ */
+extern DECLSPEC void SDLCALL SDL_PauseAudioDevice(SDL_AudioDeviceID dev,
+ int pause_on);
+/* @} *//* Pause audio functions */
+
+/**
+ * Load the audio data of a WAVE file into memory.
+ *
+ * Loading a WAVE file requires `src`, `spec`, `audio_buf` and `audio_len` to
+ * be valid pointers. The entire data portion of the file is then loaded into
+ * memory and decoded if necessary.
+ *
+ * If `freesrc` is non-zero, the data source gets automatically closed and
+ * freed before the function returns.
+ *
+ * Supported formats are RIFF WAVE files with the formats PCM (8, 16, 24, and
+ * 32 bits), IEEE Float (32 bits), Microsoft ADPCM and IMA ADPCM (4 bits), and
+ * A-law and mu-law (8 bits). Other formats are currently unsupported and
+ * cause an error.
+ *
+ * If this function succeeds, the pointer returned by it is equal to `spec`
+ * and the pointer to the audio data allocated by the function is written to
+ * `audio_buf` and its length in bytes to `audio_len`. The SDL_AudioSpec
+ * members `freq`, `channels`, and `format` are set to the values of the audio
+ * data in the buffer. The `samples` member is set to a sane default and all
+ * others are set to zero.
+ *
+ * It's necessary to use SDL_FreeWAV() to free the audio data returned in
+ * `audio_buf` when it is no longer used.
+ *
+ * Because of the underspecification of the .WAV format, there are many
+ * problematic files in the wild that cause issues with strict decoders. To
+ * provide compatibility with these files, this decoder is lenient in regards
+ * to the truncation of the file, the fact chunk, and the size of the RIFF
+ * chunk. The hints `SDL_HINT_WAVE_RIFF_CHUNK_SIZE`,
+ * `SDL_HINT_WAVE_TRUNCATION`, and `SDL_HINT_WAVE_FACT_CHUNK` can be used to
+ * tune the behavior of the loading process.
+ *
+ * Any file that is invalid (due to truncation, corruption, or wrong values in
+ * the headers), too big, or unsupported causes an error. Additionally, any
+ * critical I/O error from the data source will terminate the loading process
+ * with an error. The function returns NULL on error and in all cases (with
+ * the exception of `src` being NULL), an appropriate error message will be
+ * set.
+ *
+ * It is required that the data source supports seeking.
+ *
+ * Example:
+ *
+ * ```c
+ * SDL_LoadWAV_RW(SDL_RWFromFile("sample.wav", "rb"), 1, &spec, &buf, &len);
+ * ```
+ *
+ * Note that the SDL_LoadWAV macro does this same thing for you, but in a less
+ * messy way:
+ *
+ * ```c
+ * SDL_LoadWAV("sample.wav", &spec, &buf, &len);
+ * ```
+ *
+ * \param src The data source for the WAVE data
+ * \param freesrc If non-zero, SDL will _always_ free the data source
+ * \param spec An SDL_AudioSpec that will be filled in with the wave file's
+ * format details
+ * \param audio_buf A pointer filled with the audio data, allocated by the
+ * function.
+ * \param audio_len A pointer filled with the length of the audio data buffer
+ * in bytes
+ * \returns This function, if successfully called, returns `spec`, which will
+ * be filled with the audio data format of the wave source data.
+ * `audio_buf` will be filled with a pointer to an allocated buffer
+ * containing the audio data, and `audio_len` is filled with the
+ * length of that audio buffer in bytes.
+ *
+ * This function returns NULL if the .WAV file cannot be opened, uses
+ * an unknown data format, or is corrupt; call SDL_GetError() for
+ * more information.
+ *
+ * When the application is done with the data returned in
+ * `audio_buf`, it should call SDL_FreeWAV() to dispose of it.
+ *
+ * \since This function is available since SDL 2.0.0.
+ *
+ * \sa SDL_FreeWAV
+ * \sa SDL_LoadWAV
+ */
+extern DECLSPEC SDL_AudioSpec *SDLCALL SDL_LoadWAV_RW(SDL_RWops * src,
+ int freesrc,
+ SDL_AudioSpec * spec,
+ Uint8 ** audio_buf,
+ Uint32 * audio_len);
+
+/**
+ * Loads a WAV from a file.
+ * Compatibility convenience function.
+ */
+#define SDL_LoadWAV(file, spec, audio_buf, audio_len) \
+ SDL_LoadWAV_RW(SDL_RWFromFile(file, "rb"),1, spec,audio_buf,audio_len)
+
+/**
+ * Free data previously allocated with SDL_LoadWAV() or SDL_LoadWAV_RW().
+ *
+ * After a WAVE file has been opened with SDL_LoadWAV() or SDL_LoadWAV_RW()
+ * its data can eventually be freed with SDL_FreeWAV(). It is safe to call
+ * this function with a NULL pointer.
+ *
+ * \param audio_buf a pointer to the buffer created by SDL_LoadWAV() or
+ * SDL_LoadWAV_RW()
+ *
+ * \since This function is available since SDL 2.0.0.
+ *
+ * \sa SDL_LoadWAV
+ * \sa SDL_LoadWAV_RW
+ */
+extern DECLSPEC void SDLCALL SDL_FreeWAV(Uint8 * audio_buf);
+
+/**
+ * Initialize an SDL_AudioCVT structure for conversion.
+ *
+ * Before an SDL_AudioCVT structure can be used to convert audio data it must
+ * be initialized with source and destination information.
+ *
+ * This function will zero out every field of the SDL_AudioCVT, so it must be
+ * called before the application fills in the final buffer information.
+ *
+ * Once this function has returned successfully, and reported that a
+ * conversion is necessary, the application fills in the rest of the fields in
+ * SDL_AudioCVT, now that it knows how large a buffer it needs to allocate,
+ * and then can call SDL_ConvertAudio() to complete the conversion.
+ *
+ * \param cvt an SDL_AudioCVT structure filled in with audio conversion
+ * information
+ * \param src_format the source format of the audio data; for more info see
+ * SDL_AudioFormat
+ * \param src_channels the number of channels in the source
+ * \param src_rate the frequency (sample-frames-per-second) of the source
+ * \param dst_format the destination format of the audio data; for more info
+ * see SDL_AudioFormat
+ * \param dst_channels the number of channels in the destination
+ * \param dst_rate the frequency (sample-frames-per-second) of the destination
+ * \returns 1 if the audio filter is prepared, 0 if no conversion is needed,
+ * or a negative error code on failure; call SDL_GetError() for more
+ * information.
+ *
+ * \since This function is available since SDL 2.0.0.
+ *
+ * \sa SDL_ConvertAudio
+ */
+extern DECLSPEC int SDLCALL SDL_BuildAudioCVT(SDL_AudioCVT * cvt,
+ SDL_AudioFormat src_format,
+ Uint8 src_channels,
+ int src_rate,
+ SDL_AudioFormat dst_format,
+ Uint8 dst_channels,
+ int dst_rate);
+
+/**
+ * Convert audio data to a desired audio format.
+ *
+ * This function does the actual audio data conversion, after the application
+ * has called SDL_BuildAudioCVT() to prepare the conversion information and
+ * then filled in the buffer details.
+ *
+ * Once the application has initialized the `cvt` structure using
+ * SDL_BuildAudioCVT(), allocated an audio buffer and filled it with audio
+ * data in the source format, this function will convert the buffer, in-place,
+ * to the desired format.
+ *
+ * The data conversion may go through several passes; any given pass may
+ * possibly temporarily increase the size of the data. For example, SDL might
+ * expand 16-bit data to 32 bits before resampling to a lower frequency,
+ * shrinking the data size after having grown it briefly. Since the supplied
+ * buffer will be both the source and destination, converting as necessary
+ * in-place, the application must allocate a buffer that will fully contain
+ * the data during its largest conversion pass. After SDL_BuildAudioCVT()
+ * returns, the application should set the `cvt->len` field to the size, in
+ * bytes, of the source data, and allocate a buffer that is `cvt->len *
+ * cvt->len_mult` bytes long for the `buf` field.
+ *
+ * The source data should be copied into this buffer before the call to
+ * SDL_ConvertAudio(). Upon successful return, this buffer will contain the
+ * converted audio, and `cvt->len_cvt` will be the size of the converted data,
+ * in bytes. Any bytes in the buffer past `cvt->len_cvt` are undefined once
+ * this function returns.
+ *
+ * \param cvt an SDL_AudioCVT structure that was previously set up by
+ * SDL_BuildAudioCVT().
+ * \returns 0 if the conversion was completed successfully or a negative error
+ * code on failure; call SDL_GetError() for more information.
+ *
+ * \since This function is available since SDL 2.0.0.
+ *
+ * \sa SDL_BuildAudioCVT
+ */
+extern DECLSPEC int SDLCALL SDL_ConvertAudio(SDL_AudioCVT * cvt);
+
+/* SDL_AudioStream is a new audio conversion interface.
+ The benefits vs SDL_AudioCVT:
+ - it can handle resampling data in chunks without generating
+ artifacts, when it doesn't have the complete buffer available.
+ - it can handle incoming data in any variable size.
+ - You push data as you have it, and pull it when you need it
+ */
+/* this is opaque to the outside world. */
+struct _SDL_AudioStream;
+typedef struct _SDL_AudioStream SDL_AudioStream;
+
+/**
+ * Create a new audio stream.
+ *
+ * \param src_format The format of the source audio
+ * \param src_channels The number of channels of the source audio
+ * \param src_rate The sampling rate of the source audio
+ * \param dst_format The format of the desired audio output
+ * \param dst_channels The number of channels of the desired audio output
+ * \param dst_rate The sampling rate of the desired audio output
+ * \returns 0 on success, or -1 on error.
+ *
+ * \since This function is available since SDL 2.0.7.
+ *
+ * \sa SDL_AudioStreamPut
+ * \sa SDL_AudioStreamGet
+ * \sa SDL_AudioStreamAvailable
+ * \sa SDL_AudioStreamFlush
+ * \sa SDL_AudioStreamClear
+ * \sa SDL_FreeAudioStream
+ */
+extern DECLSPEC SDL_AudioStream * SDLCALL SDL_NewAudioStream(const SDL_AudioFormat src_format,
+ const Uint8 src_channels,
+ const int src_rate,
+ const SDL_AudioFormat dst_format,
+ const Uint8 dst_channels,
+ const int dst_rate);
+
+/**
+ * Add data to be converted/resampled to the stream.
+ *
+ * \param stream The stream the audio data is being added to
+ * \param buf A pointer to the audio data to add
+ * \param len The number of bytes to write to the stream
+ * \returns 0 on success, or -1 on error.
+ *
+ * \since This function is available since SDL 2.0.7.
+ *
+ * \sa SDL_NewAudioStream
+ * \sa SDL_AudioStreamGet
+ * \sa SDL_AudioStreamAvailable
+ * \sa SDL_AudioStreamFlush
+ * \sa SDL_AudioStreamClear
+ * \sa SDL_FreeAudioStream
+ */
+extern DECLSPEC int SDLCALL SDL_AudioStreamPut(SDL_AudioStream *stream, const void *buf, int len);
+
+/**
+ * Get converted/resampled data from the stream
+ *
+ * \param stream The stream the audio is being requested from
+ * \param buf A buffer to fill with audio data
+ * \param len The maximum number of bytes to fill
+ * \returns the number of bytes read from the stream, or -1 on error
+ *
+ * \since This function is available since SDL 2.0.7.
+ *
+ * \sa SDL_NewAudioStream
+ * \sa SDL_AudioStreamPut
+ * \sa SDL_AudioStreamAvailable
+ * \sa SDL_AudioStreamFlush
+ * \sa SDL_AudioStreamClear
+ * \sa SDL_FreeAudioStream
+ */
+extern DECLSPEC int SDLCALL SDL_AudioStreamGet(SDL_AudioStream *stream, void *buf, int len);
+
+/**
+ * Get the number of converted/resampled bytes available.
+ *
+ * The stream may be buffering data behind the scenes until it has enough to
+ * resample correctly, so this number might be lower than what you expect, or
+ * even be zero. Add more data or flush the stream if you need the data now.
+ *
+ * \since This function is available since SDL 2.0.7.
+ *
+ * \sa SDL_NewAudioStream
+ * \sa SDL_AudioStreamPut
+ * \sa SDL_AudioStreamGet
+ * \sa SDL_AudioStreamFlush
+ * \sa SDL_AudioStreamClear
+ * \sa SDL_FreeAudioStream
+ */
+extern DECLSPEC int SDLCALL SDL_AudioStreamAvailable(SDL_AudioStream *stream);
+
+/**
+ * Tell the stream that you're done sending data, and anything being buffered
+ * should be converted/resampled and made available immediately.
+ *
+ * It is legal to add more data to a stream after flushing, but there will be
+ * audio gaps in the output. Generally this is intended to signal the end of
+ * input, so the complete output becomes available.
+ *
+ * \since This function is available since SDL 2.0.7.
+ *
+ * \sa SDL_NewAudioStream
+ * \sa SDL_AudioStreamPut
+ * \sa SDL_AudioStreamGet
+ * \sa SDL_AudioStreamAvailable
+ * \sa SDL_AudioStreamClear
+ * \sa SDL_FreeAudioStream
+ */
+extern DECLSPEC int SDLCALL SDL_AudioStreamFlush(SDL_AudioStream *stream);
+
+/**
+ * Clear any pending data in the stream without converting it
+ *
+ * \since This function is available since SDL 2.0.7.
+ *
+ * \sa SDL_NewAudioStream
+ * \sa SDL_AudioStreamPut
+ * \sa SDL_AudioStreamGet
+ * \sa SDL_AudioStreamAvailable
+ * \sa SDL_AudioStreamFlush
+ * \sa SDL_FreeAudioStream
+ */
+extern DECLSPEC void SDLCALL SDL_AudioStreamClear(SDL_AudioStream *stream);
+
+/**
+ * Free an audio stream
+ *
+ * \since This function is available since SDL 2.0.7.
+ *
+ * \sa SDL_NewAudioStream
+ * \sa SDL_AudioStreamPut
+ * \sa SDL_AudioStreamGet
+ * \sa SDL_AudioStreamAvailable
+ * \sa SDL_AudioStreamFlush
+ * \sa SDL_AudioStreamClear
+ */
+extern DECLSPEC void SDLCALL SDL_FreeAudioStream(SDL_AudioStream *stream);
+
+#define SDL_MIX_MAXVOLUME 128
+
+/**
+ * This function is a legacy means of mixing audio.
+ *
+ * This function is equivalent to calling...
+ *
+ * ```c
+ * SDL_MixAudioFormat(dst, src, format, len, volume);
+ * ```
+ *
+ * ...where `format` is the obtained format of the audio device from the
+ * legacy SDL_OpenAudio() function.
+ *
+ * \param dst the destination for the mixed audio
+ * \param src the source audio buffer to be mixed
+ * \param len the length of the audio buffer in bytes
+ * \param volume ranges from 0 - 128, and should be set to SDL_MIX_MAXVOLUME
+ * for full audio volume
+ *
+ * \since This function is available since SDL 2.0.0.
+ *
+ * \sa SDL_MixAudioFormat
+ */
+extern DECLSPEC void SDLCALL SDL_MixAudio(Uint8 * dst, const Uint8 * src,
+ Uint32 len, int volume);
+
+/**
+ * Mix audio data in a specified format.
+ *
+ * This takes an audio buffer `src` of `len` bytes of `format` data and mixes
+ * it into `dst`, performing addition, volume adjustment, and overflow
+ * clipping. The buffer pointed to by `dst` must also be `len` bytes of
+ * `format` data.
+ *
+ * This is provided for convenience -- you can mix your own audio data.
+ *
+ * Do not use this function for mixing together more than two streams of
+ * sample data. The output from repeated application of this function may be
+ * distorted by clipping, because there is no accumulator with greater range
+ * than the input (not to mention this being an inefficient way of doing it).
+ *
+ * It is a common misconception that this function is required to write audio
+ * data to an output stream in an audio callback. While you can do that,
+ * SDL_MixAudioFormat() is really only needed when you're mixing a single
+ * audio stream with a volume adjustment.
+ *
+ * \param dst the destination for the mixed audio
+ * \param src the source audio buffer to be mixed
+ * \param format the SDL_AudioFormat structure representing the desired audio
+ * format
+ * \param len the length of the audio buffer in bytes
+ * \param volume ranges from 0 - 128, and should be set to SDL_MIX_MAXVOLUME
+ * for full audio volume
+ *
+ * \since This function is available since SDL 2.0.0.
+ */
+extern DECLSPEC void SDLCALL SDL_MixAudioFormat(Uint8 * dst,
+ const Uint8 * src,
+ SDL_AudioFormat format,
+ Uint32 len, int volume);
+
+/**
+ * Queue more audio on non-callback devices.
+ *
+ * If you are looking to retrieve queued audio from a non-callback capture
+ * device, you want SDL_DequeueAudio() instead. SDL_QueueAudio() will return
+ * -1 to signify an error if you use it with capture devices.
+ *
+ * SDL offers two ways to feed audio to the device: you can either supply a
+ * callback that SDL triggers with some frequency to obtain more audio (pull
+ * method), or you can supply no callback, and then SDL will expect you to
+ * supply data at regular intervals (push method) with this function.
+ *
+ * There are no limits on the amount of data you can queue, short of
+ * exhaustion of address space. Queued data will drain to the device as
+ * necessary without further intervention from you. If the device needs audio
+ * but there is not enough queued, it will play silence to make up the
+ * difference. This means you will have skips in your audio playback if you
+ * aren't routinely queueing sufficient data.
+ *
+ * This function copies the supplied data, so you are safe to free it when the
+ * function returns. This function is thread-safe, but queueing to the same
+ * device from two threads at once does not promise which buffer will be
+ * queued first.
+ *
+ * You may not queue audio on a device that is using an application-supplied
+ * callback; doing so returns an error. You have to use the audio callback or
+ * queue audio with this function, but not both.
+ *
+ * You should not call SDL_LockAudio() on the device before queueing; SDL
+ * handles locking internally for this function.
+ *
+ * Note that SDL2 does not support planar audio. You will need to resample
+ * from planar audio formats into a non-planar one (see SDL_AudioFormat)
+ * before queuing audio.
+ *
+ * \param dev the device ID to which we will queue audio
+ * \param data the data to queue to the device for later playback
+ * \param len the number of bytes (not samples!) to which `data` points
+ * \returns 0 on success or a negative error code on failure; call
+ * SDL_GetError() for more information.
+ *
+ * \since This function is available since SDL 2.0.4.
+ *
+ * \sa SDL_ClearQueuedAudio
+ * \sa SDL_GetQueuedAudioSize
+ */
+extern DECLSPEC int SDLCALL SDL_QueueAudio(SDL_AudioDeviceID dev, const void *data, Uint32 len);
+
+/**
+ * Dequeue more audio on non-callback devices.
+ *
+ * If you are looking to queue audio for output on a non-callback playback
+ * device, you want SDL_QueueAudio() instead. SDL_DequeueAudio() will always
+ * return 0 if you use it with playback devices.
+ *
+ * SDL offers two ways to retrieve audio from a capture device: you can either
+ * supply a callback that SDL triggers with some frequency as the device
+ * records more audio data, (push method), or you can supply no callback, and
+ * then SDL will expect you to retrieve data at regular intervals (pull
+ * method) with this function.
+ *
+ * There are no limits on the amount of data you can queue, short of
+ * exhaustion of address space. Data from the device will keep queuing as
+ * necessary without further intervention from you. This means you will
+ * eventually run out of memory if you aren't routinely dequeueing data.
+ *
+ * Capture devices will not queue data when paused; if you are expecting to
+ * not need captured audio for some length of time, use SDL_PauseAudioDevice()
+ * to stop the capture device from queueing more data. This can be useful
+ * during, say, level loading times. When unpaused, capture devices will start
+ * queueing data from that point, having flushed any capturable data available
+ * while paused.
+ *
+ * This function is thread-safe, but dequeueing from the same device from two
+ * threads at once does not promise which thread will dequeue data first.
+ *
+ * You may not dequeue audio from a device that is using an
+ * application-supplied callback; doing so returns an error. You have to use
+ * the audio callback, or dequeue audio with this function, but not both.
+ *
+ * You should not call SDL_LockAudio() on the device before dequeueing; SDL
+ * handles locking internally for this function.
+ *
+ * \param dev the device ID from which we will dequeue audio
+ * \param data a pointer into where audio data should be copied
+ * \param len the number of bytes (not samples!) to which (data) points
+ * \returns the number of bytes dequeued, which could be less than requested;
+ * call SDL_GetError() for more information.
+ *
+ * \since This function is available since SDL 2.0.5.
+ *
+ * \sa SDL_ClearQueuedAudio
+ * \sa SDL_GetQueuedAudioSize
+ */
+extern DECLSPEC Uint32 SDLCALL SDL_DequeueAudio(SDL_AudioDeviceID dev, void *data, Uint32 len);
+
+/**
+ * Get the number of bytes of still-queued audio.
+ *
+ * For playback devices: this is the number of bytes that have been queued for
+ * playback with SDL_QueueAudio(), but have not yet been sent to the hardware.
+ *
+ * Once we've sent it to the hardware, this function can not decide the exact
+ * byte boundary of what has been played. It's possible that we just gave the
+ * hardware several kilobytes right before you called this function, but it
+ * hasn't played any of it yet, or maybe half of it, etc.
+ *
+ * For capture devices, this is the number of bytes that have been captured by
+ * the device and are waiting for you to dequeue. This number may grow at any
+ * time, so this only informs of the lower-bound of available data.
+ *
+ * You may not queue or dequeue audio on a device that is using an
+ * application-supplied callback; calling this function on such a device
+ * always returns 0. You have to use the audio callback or queue audio, but
+ * not both.
+ *
+ * You should not call SDL_LockAudio() on the device before querying; SDL
+ * handles locking internally for this function.
+ *
+ * \param dev the device ID of which we will query queued audio size
+ * \returns the number of bytes (not samples!) of queued audio.
+ *
+ * \since This function is available since SDL 2.0.4.
+ *
+ * \sa SDL_ClearQueuedAudio
+ * \sa SDL_QueueAudio
+ * \sa SDL_DequeueAudio
+ */
+extern DECLSPEC Uint32 SDLCALL SDL_GetQueuedAudioSize(SDL_AudioDeviceID dev);
+
+/**
+ * Drop any queued audio data waiting to be sent to the hardware.
+ *
+ * Immediately after this call, SDL_GetQueuedAudioSize() will return 0. For
+ * output devices, the hardware will start playing silence if more audio isn't
+ * queued. For capture devices, the hardware will start filling the empty
+ * queue with new data if the capture device isn't paused.
+ *
+ * This will not prevent playback of queued audio that's already been sent to
+ * the hardware, as we can not undo that, so expect there to be some fraction
+ * of a second of audio that might still be heard. This can be useful if you
+ * want to, say, drop any pending music or any unprocessed microphone input
+ * during a level change in your game.
+ *
+ * You may not queue or dequeue audio on a device that is using an
+ * application-supplied callback; calling this function on such a device
+ * always returns 0. You have to use the audio callback or queue audio, but
+ * not both.
+ *
+ * You should not call SDL_LockAudio() on the device before clearing the
+ * queue; SDL handles locking internally for this function.
+ *
+ * This function always succeeds and thus returns void.
+ *
+ * \param dev the device ID of which to clear the audio queue
+ *
+ * \since This function is available since SDL 2.0.4.
+ *
+ * \sa SDL_GetQueuedAudioSize
+ * \sa SDL_QueueAudio
+ * \sa SDL_DequeueAudio
+ */
+extern DECLSPEC void SDLCALL SDL_ClearQueuedAudio(SDL_AudioDeviceID dev);
+
+
+/**
+ * \name Audio lock functions
+ *
+ * The lock manipulated by these functions protects the callback function.
+ * During a SDL_LockAudio()/SDL_UnlockAudio() pair, you can be guaranteed that
+ * the callback function is not running. Do not call these from the callback
+ * function or you will cause deadlock.
+ */
+/* @{ */
+
+/**
+ * This function is a legacy means of locking the audio device.
+ *
+ * New programs might want to use SDL_LockAudioDevice() instead. This function
+ * is equivalent to calling...
+ *
+ * ```c
+ * SDL_LockAudioDevice(1);
+ * ```
+ *
+ * ...and is only useful if you used the legacy SDL_OpenAudio() function.
+ *
+ * \since This function is available since SDL 2.0.0.
+ *
+ * \sa SDL_LockAudioDevice
+ * \sa SDL_UnlockAudio
+ * \sa SDL_UnlockAudioDevice
+ */
+extern DECLSPEC void SDLCALL SDL_LockAudio(void);
+
+/**
+ * Use this function to lock out the audio callback function for a specified
+ * device.
+ *
+ * The lock manipulated by these functions protects the audio callback
+ * function specified in SDL_OpenAudioDevice(). During a
+ * SDL_LockAudioDevice()/SDL_UnlockAudioDevice() pair, you can be guaranteed
+ * that the callback function for that device is not running, even if the
+ * device is not paused. While a device is locked, any other unpaused,
+ * unlocked devices may still run their callbacks.
+ *
+ * Calling this function from inside your audio callback is unnecessary. SDL
+ * obtains this lock before calling your function, and releases it when the
+ * function returns.
+ *
+ * You should not hold the lock longer than absolutely necessary. If you hold
+ * it too long, you'll experience dropouts in your audio playback. Ideally,
+ * your application locks the device, sets a few variables and unlocks again.
+ * Do not do heavy work while holding the lock for a device.
+ *
+ * It is safe to lock the audio device multiple times, as long as you unlock
+ * it an equivalent number of times. The callback will not run until the
+ * device has been unlocked completely in this way. If your application fails
+ * to unlock the device appropriately, your callback will never run, you might
+ * hear repeating bursts of audio, and SDL_CloseAudioDevice() will probably
+ * deadlock.
+ *
+ * Internally, the audio device lock is a mutex; if you lock from two threads
+ * at once, not only will you block the audio callback, you'll block the other
+ * thread.
+ *
+ * \param dev the ID of the device to be locked
+ *
+ * \since This function is available since SDL 2.0.0.
+ *
+ * \sa SDL_UnlockAudioDevice
+ */
+extern DECLSPEC void SDLCALL SDL_LockAudioDevice(SDL_AudioDeviceID dev);
+
+/**
+ * This function is a legacy means of unlocking the audio device.
+ *
+ * New programs might want to use SDL_UnlockAudioDevice() instead. This
+ * function is equivalent to calling...
+ *
+ * ```c
+ * SDL_UnlockAudioDevice(1);
+ * ```
+ *
+ * ...and is only useful if you used the legacy SDL_OpenAudio() function.
+ *
+ * \since This function is available since SDL 2.0.0.
+ *
+ * \sa SDL_LockAudio
+ * \sa SDL_UnlockAudioDevice
+ */
+extern DECLSPEC void SDLCALL SDL_UnlockAudio(void);
+
+/**
+ * Use this function to unlock the audio callback function for a specified
+ * device.
+ *
+ * This function should be paired with a previous SDL_LockAudioDevice() call.
+ *
+ * \param dev the ID of the device to be unlocked
+ *
+ * \since This function is available since SDL 2.0.0.
+ *
+ * \sa SDL_LockAudioDevice
+ */
+extern DECLSPEC void SDLCALL SDL_UnlockAudioDevice(SDL_AudioDeviceID dev);
+/* @} *//* Audio lock functions */
+
+/**
+ * This function is a legacy means of closing the audio device.
+ *
+ * This function is equivalent to calling...
+ *
+ * ```c
+ * SDL_CloseAudioDevice(1);
+ * ```
+ *
+ * ...and is only useful if you used the legacy SDL_OpenAudio() function.
+ *
+ * \since This function is available since SDL 2.0.0.
+ *
+ * \sa SDL_OpenAudio
+ */
+extern DECLSPEC void SDLCALL SDL_CloseAudio(void);
+
+/**
+ * Use this function to shut down audio processing and close the audio device.
+ *
+ * The application should close open audio devices once they are no longer
+ * needed. Calling this function will wait until the device's audio callback
+ * is not running, release the audio hardware and then clean up internal
+ * state. No further audio will play from this device once this function
+ * returns.
+ *
+ * This function may block briefly while pending audio data is played by the
+ * hardware, so that applications don't drop the last buffer of data they
+ * supplied.
+ *
+ * The device ID is invalid as soon as the device is closed, and is eligible
+ * for reuse in a new SDL_OpenAudioDevice() call immediately.
+ *
+ * \param dev an audio device previously opened with SDL_OpenAudioDevice()
+ *
+ * \since This function is available since SDL 2.0.0.
+ *
+ * \sa SDL_OpenAudioDevice
+ */
+extern DECLSPEC void SDLCALL SDL_CloseAudioDevice(SDL_AudioDeviceID dev);
+
+/* Ends C function definitions when using C++ */
+#ifdef __cplusplus
+}
+#endif
+#include
+
+#endif /* SDL_audio_h_ */
+
+/* vi: set ts=4 sw=4 expandtab: */
diff --git a/bindings/sdl2wgpu/src/main/headers/SDL2/SDL_bits.h b/bindings/sdl2wgpu/src/main/headers/SDL2/SDL_bits.h
new file mode 100644
index 00000000..ce32dc13
--- /dev/null
+++ b/bindings/sdl2wgpu/src/main/headers/SDL2/SDL_bits.h
@@ -0,0 +1,126 @@
+/*
+ Simple DirectMedia Layer
+ Copyright (C) 1997-2023 Sam Lantinga
+
+ This software is provided 'as-is', without any express or implied
+ warranty. In no event will the authors be held liable for any damages
+ arising from the use of this software.
+
+ Permission is granted to anyone to use this software for any purpose,
+ including commercial applications, and to alter it and redistribute it
+ freely, subject to the following restrictions:
+
+ 1. The origin of this software must not be misrepresented; you must not
+ claim that you wrote the original software. If you use this software
+ in a product, an acknowledgment in the product documentation would be
+ appreciated but is not required.
+ 2. Altered source versions must be plainly marked as such, and must not be
+ misrepresented as being the original software.
+ 3. This notice may not be removed or altered from any source distribution.
+*/
+
+/**
+ * \file SDL_bits.h
+ *
+ * Functions for fiddling with bits and bitmasks.
+ */
+
+#ifndef SDL_bits_h_
+#define SDL_bits_h_
+
+#include
+
+#include
+/* Set up for C function definitions, even when using C++ */
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * \file SDL_bits.h
+ */
+
+/**
+ * Get the index of the most significant bit. Result is undefined when called
+ * with 0. This operation can also be stated as "count leading zeroes" and
+ * "log base 2".
+ *
+ * \return the index of the most significant bit, or -1 if the value is 0.
+ */
+#if defined(__WATCOMC__) && defined(__386__)
+extern __inline int _SDL_bsr_watcom(Uint32);
+#pragma aux _SDL_bsr_watcom = \
+ "bsr eax, eax" \
+ parm [eax] nomemory \
+ value [eax] \
+ modify exact [eax] nomemory;
+#endif
+
+SDL_FORCE_INLINE int
+SDL_MostSignificantBitIndex32(Uint32 x)
+{
+#if defined(__GNUC__) && (__GNUC__ >= 4 || (__GNUC__ == 3 && __GNUC_MINOR__ >= 4))
+ /* Count Leading Zeroes builtin in GCC.
+ * http://gcc.gnu.org/onlinedocs/gcc-4.3.4/gcc/Other-Builtins.html
+ */
+ if (x == 0) {
+ return -1;
+ }
+ return 31 - __builtin_clz(x);
+#elif defined(__WATCOMC__) && defined(__386__)
+ if (x == 0) {
+ return -1;
+ }
+ return _SDL_bsr_watcom(x);
+#elif defined(_MSC_VER)
+ unsigned long index;
+ if (_BitScanReverse(&index, x)) {
+ return index;
+ }
+ return -1;
+#else
+ /* Based off of Bit Twiddling Hacks by Sean Eron Anderson
+ * , released in the public domain.
+ * http://graphics.stanford.edu/~seander/bithacks.html#IntegerLog
+ */
+ const Uint32 b[] = {0x2, 0xC, 0xF0, 0xFF00, 0xFFFF0000};
+ const int S[] = {1, 2, 4, 8, 16};
+
+ int msbIndex = 0;
+ int i;
+
+ if (x == 0) {
+ return -1;
+ }
+
+ for (i = 4; i >= 0; i--)
+ {
+ if (x & b[i])
+ {
+ x >>= S[i];
+ msbIndex |= S[i];
+ }
+ }
+
+ return msbIndex;
+#endif
+}
+
+SDL_FORCE_INLINE SDL_bool
+SDL_HasExactlyOneBitSet32(Uint32 x)
+{
+ if (x && !(x & (x - 1))) {
+ return SDL_TRUE;
+ }
+ return SDL_FALSE;
+}
+
+/* Ends C function definitions when using C++ */
+#ifdef __cplusplus
+}
+#endif
+#include
+
+#endif /* SDL_bits_h_ */
+
+/* vi: set ts=4 sw=4 expandtab: */
diff --git a/bindings/sdl2wgpu/src/main/headers/SDL2/SDL_blendmode.h b/bindings/sdl2wgpu/src/main/headers/SDL2/SDL_blendmode.h
new file mode 100644
index 00000000..cdd84e77
--- /dev/null
+++ b/bindings/sdl2wgpu/src/main/headers/SDL2/SDL_blendmode.h
@@ -0,0 +1,198 @@
+/*
+ Simple DirectMedia Layer
+ Copyright (C) 1997-2023 Sam Lantinga
+
+ This software is provided 'as-is', without any express or implied
+ warranty. In no event will the authors be held liable for any damages
+ arising from the use of this software.
+
+ Permission is granted to anyone to use this software for any purpose,
+ including commercial applications, and to alter it and redistribute it
+ freely, subject to the following restrictions:
+
+ 1. The origin of this software must not be misrepresented; you must not
+ claim that you wrote the original software. If you use this software
+ in a product, an acknowledgment in the product documentation would be
+ appreciated but is not required.
+ 2. Altered source versions must be plainly marked as such, and must not be
+ misrepresented as being the original software.
+ 3. This notice may not be removed or altered from any source distribution.
+*/
+
+/**
+ * \file SDL_blendmode.h
+ *
+ * Header file declaring the SDL_BlendMode enumeration
+ */
+
+#ifndef SDL_blendmode_h_
+#define SDL_blendmode_h_
+
+#include
+/* Set up for C function definitions, even when using C++ */
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * \brief The blend mode used in SDL_RenderCopy() and drawing operations.
+ */
+typedef enum
+{
+ SDL_BLENDMODE_NONE = 0x00000000, /**< no blending
+ dstRGBA = srcRGBA */
+ SDL_BLENDMODE_BLEND = 0x00000001, /**< alpha blending
+ dstRGB = (srcRGB * srcA) + (dstRGB * (1-srcA))
+ dstA = srcA + (dstA * (1-srcA)) */
+ SDL_BLENDMODE_ADD = 0x00000002, /**< additive blending
+ dstRGB = (srcRGB * srcA) + dstRGB
+ dstA = dstA */
+ SDL_BLENDMODE_MOD = 0x00000004, /**< color modulate
+ dstRGB = srcRGB * dstRGB
+ dstA = dstA */
+ SDL_BLENDMODE_MUL = 0x00000008, /**< color multiply
+ dstRGB = (srcRGB * dstRGB) + (dstRGB * (1-srcA))
+ dstA = dstA */
+ SDL_BLENDMODE_INVALID = 0x7FFFFFFF
+
+ /* Additional custom blend modes can be returned by SDL_ComposeCustomBlendMode() */
+
+} SDL_BlendMode;
+
+/**
+ * \brief The blend operation used when combining source and destination pixel components
+ */
+typedef enum
+{
+ SDL_BLENDOPERATION_ADD = 0x1, /**< dst + src: supported by all renderers */
+ SDL_BLENDOPERATION_SUBTRACT = 0x2, /**< dst - src : supported by D3D9, D3D11, OpenGL, OpenGLES */
+ SDL_BLENDOPERATION_REV_SUBTRACT = 0x3, /**< src - dst : supported by D3D9, D3D11, OpenGL, OpenGLES */
+ SDL_BLENDOPERATION_MINIMUM = 0x4, /**< min(dst, src) : supported by D3D9, D3D11 */
+ SDL_BLENDOPERATION_MAXIMUM = 0x5 /**< max(dst, src) : supported by D3D9, D3D11 */
+} SDL_BlendOperation;
+
+/**
+ * \brief The normalized factor used to multiply pixel components
+ */
+typedef enum
+{
+ SDL_BLENDFACTOR_ZERO = 0x1, /**< 0, 0, 0, 0 */
+ SDL_BLENDFACTOR_ONE = 0x2, /**< 1, 1, 1, 1 */
+ SDL_BLENDFACTOR_SRC_COLOR = 0x3, /**< srcR, srcG, srcB, srcA */
+ SDL_BLENDFACTOR_ONE_MINUS_SRC_COLOR = 0x4, /**< 1-srcR, 1-srcG, 1-srcB, 1-srcA */
+ SDL_BLENDFACTOR_SRC_ALPHA = 0x5, /**< srcA, srcA, srcA, srcA */
+ SDL_BLENDFACTOR_ONE_MINUS_SRC_ALPHA = 0x6, /**< 1-srcA, 1-srcA, 1-srcA, 1-srcA */
+ SDL_BLENDFACTOR_DST_COLOR = 0x7, /**< dstR, dstG, dstB, dstA */
+ SDL_BLENDFACTOR_ONE_MINUS_DST_COLOR = 0x8, /**< 1-dstR, 1-dstG, 1-dstB, 1-dstA */
+ SDL_BLENDFACTOR_DST_ALPHA = 0x9, /**< dstA, dstA, dstA, dstA */
+ SDL_BLENDFACTOR_ONE_MINUS_DST_ALPHA = 0xA /**< 1-dstA, 1-dstA, 1-dstA, 1-dstA */
+} SDL_BlendFactor;
+
+/**
+ * Compose a custom blend mode for renderers.
+ *
+ * The functions SDL_SetRenderDrawBlendMode and SDL_SetTextureBlendMode accept
+ * the SDL_BlendMode returned by this function if the renderer supports it.
+ *
+ * A blend mode controls how the pixels from a drawing operation (source) get
+ * combined with the pixels from the render target (destination). First, the
+ * components of the source and destination pixels get multiplied with their
+ * blend factors. Then, the blend operation takes the two products and
+ * calculates the result that will get stored in the render target.
+ *
+ * Expressed in pseudocode, it would look like this:
+ *
+ * ```c
+ * dstRGB = colorOperation(srcRGB * srcColorFactor, dstRGB * dstColorFactor);
+ * dstA = alphaOperation(srcA * srcAlphaFactor, dstA * dstAlphaFactor);
+ * ```
+ *
+ * Where the functions `colorOperation(src, dst)` and `alphaOperation(src,
+ * dst)` can return one of the following:
+ *
+ * - `src + dst`
+ * - `src - dst`
+ * - `dst - src`
+ * - `min(src, dst)`
+ * - `max(src, dst)`
+ *
+ * The red, green, and blue components are always multiplied with the first,
+ * second, and third components of the SDL_BlendFactor, respectively. The
+ * fourth component is not used.
+ *
+ * The alpha component is always multiplied with the fourth component of the
+ * SDL_BlendFactor. The other components are not used in the alpha
+ * calculation.
+ *
+ * Support for these blend modes varies for each renderer. To check if a
+ * specific SDL_BlendMode is supported, create a renderer and pass it to
+ * either SDL_SetRenderDrawBlendMode or SDL_SetTextureBlendMode. They will
+ * return with an error if the blend mode is not supported.
+ *
+ * This list describes the support of custom blend modes for each renderer in
+ * SDL 2.0.6. All renderers support the four blend modes listed in the
+ * SDL_BlendMode enumeration.
+ *
+ * - **direct3d**: Supports all operations with all factors. However, some
+ * factors produce unexpected results with `SDL_BLENDOPERATION_MINIMUM` and
+ * `SDL_BLENDOPERATION_MAXIMUM`.
+ * - **direct3d11**: Same as Direct3D 9.
+ * - **opengl**: Supports the `SDL_BLENDOPERATION_ADD` operation with all
+ * factors. OpenGL versions 1.1, 1.2, and 1.3 do not work correctly with SDL
+ * 2.0.6.
+ * - **opengles**: Supports the `SDL_BLENDOPERATION_ADD` operation with all
+ * factors. Color and alpha factors need to be the same. OpenGL ES 1
+ * implementation specific: May also support `SDL_BLENDOPERATION_SUBTRACT`
+ * and `SDL_BLENDOPERATION_REV_SUBTRACT`. May support color and alpha
+ * operations being different from each other. May support color and alpha
+ * factors being different from each other.
+ * - **opengles2**: Supports the `SDL_BLENDOPERATION_ADD`,
+ * `SDL_BLENDOPERATION_SUBTRACT`, `SDL_BLENDOPERATION_REV_SUBTRACT`
+ * operations with all factors.
+ * - **psp**: No custom blend mode support.
+ * - **software**: No custom blend mode support.
+ *
+ * Some renderers do not provide an alpha component for the default render
+ * target. The `SDL_BLENDFACTOR_DST_ALPHA` and
+ * `SDL_BLENDFACTOR_ONE_MINUS_DST_ALPHA` factors do not have an effect in this
+ * case.
+ *
+ * \param srcColorFactor the SDL_BlendFactor applied to the red, green, and
+ * blue components of the source pixels
+ * \param dstColorFactor the SDL_BlendFactor applied to the red, green, and
+ * blue components of the destination pixels
+ * \param colorOperation the SDL_BlendOperation used to combine the red,
+ * green, and blue components of the source and
+ * destination pixels
+ * \param srcAlphaFactor the SDL_BlendFactor applied to the alpha component of
+ * the source pixels
+ * \param dstAlphaFactor the SDL_BlendFactor applied to the alpha component of
+ * the destination pixels
+ * \param alphaOperation the SDL_BlendOperation used to combine the alpha
+ * component of the source and destination pixels
+ * \returns an SDL_BlendMode that represents the chosen factors and
+ * operations.
+ *
+ * \since This function is available since SDL 2.0.6.
+ *
+ * \sa SDL_SetRenderDrawBlendMode
+ * \sa SDL_GetRenderDrawBlendMode
+ * \sa SDL_SetTextureBlendMode
+ * \sa SDL_GetTextureBlendMode
+ */
+extern DECLSPEC SDL_BlendMode SDLCALL SDL_ComposeCustomBlendMode(SDL_BlendFactor srcColorFactor,
+ SDL_BlendFactor dstColorFactor,
+ SDL_BlendOperation colorOperation,
+ SDL_BlendFactor srcAlphaFactor,
+ SDL_BlendFactor dstAlphaFactor,
+ SDL_BlendOperation alphaOperation);
+
+/* Ends C function definitions when using C++ */
+#ifdef __cplusplus
+}
+#endif
+#include
+
+#endif /* SDL_blendmode_h_ */
+
+/* vi: set ts=4 sw=4 expandtab: */
diff --git a/bindings/sdl2wgpu/src/main/headers/SDL2/SDL_clipboard.h b/bindings/sdl2wgpu/src/main/headers/SDL2/SDL_clipboard.h
new file mode 100644
index 00000000..6a287b5d
--- /dev/null
+++ b/bindings/sdl2wgpu/src/main/headers/SDL2/SDL_clipboard.h
@@ -0,0 +1,141 @@
+/*
+ Simple DirectMedia Layer
+ Copyright (C) 1997-2023 Sam Lantinga
+
+ This software is provided 'as-is', without any express or implied
+ warranty. In no event will the authors be held liable for any damages
+ arising from the use of this software.
+
+ Permission is granted to anyone to use this software for any purpose,
+ including commercial applications, and to alter it and redistribute it
+ freely, subject to the following restrictions:
+
+ 1. The origin of this software must not be misrepresented; you must not
+ claim that you wrote the original software. If you use this software
+ in a product, an acknowledgment in the product documentation would be
+ appreciated but is not required.
+ 2. Altered source versions must be plainly marked as such, and must not be
+ misrepresented as being the original software.
+ 3. This notice may not be removed or altered from any source distribution.
+*/
+
+/**
+ * \file SDL_clipboard.h
+ *
+ * Include file for SDL clipboard handling
+ */
+
+#ifndef SDL_clipboard_h_
+#define SDL_clipboard_h_
+
+#include
+
+#include
+/* Set up for C function definitions, even when using C++ */
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* Function prototypes */
+
+/**
+ * Put UTF-8 text into the clipboard.
+ *
+ * \param text the text to store in the clipboard
+ * \returns 0 on success or a negative error code on failure; call
+ * SDL_GetError() for more information.
+ *
+ * \since This function is available since SDL 2.0.0.
+ *
+ * \sa SDL_GetClipboardText
+ * \sa SDL_HasClipboardText
+ */
+extern DECLSPEC int SDLCALL SDL_SetClipboardText(const char *text);
+
+/**
+ * Get UTF-8 text from the clipboard, which must be freed with SDL_free().
+ *
+ * This functions returns empty string if there was not enough memory left for
+ * a copy of the clipboard's content.
+ *
+ * \returns the clipboard text on success or an empty string on failure; call
+ * SDL_GetError() for more information. Caller must call SDL_free()
+ * on the returned pointer when done with it (even if there was an
+ * error).
+ *
+ * \since This function is available since SDL 2.0.0.
+ *
+ * \sa SDL_HasClipboardText
+ * \sa SDL_SetClipboardText
+ */
+extern DECLSPEC char * SDLCALL SDL_GetClipboardText(void);
+
+/**
+ * Query whether the clipboard exists and contains a non-empty text string.
+ *
+ * \returns SDL_TRUE if the clipboard has text, or SDL_FALSE if it does not.
+ *
+ * \since This function is available since SDL 2.0.0.
+ *
+ * \sa SDL_GetClipboardText
+ * \sa SDL_SetClipboardText
+ */
+extern DECLSPEC SDL_bool SDLCALL SDL_HasClipboardText(void);
+
+/**
+ * Put UTF-8 text into the primary selection.
+ *
+ * \param text the text to store in the primary selection
+ * \returns 0 on success or a negative error code on failure; call
+ * SDL_GetError() for more information.
+ *
+ * \since This function is available since SDL 2.26.0.
+ *
+ * \sa SDL_GetPrimarySelectionText
+ * \sa SDL_HasPrimarySelectionText
+ */
+extern DECLSPEC int SDLCALL SDL_SetPrimarySelectionText(const char *text);
+
+/**
+ * Get UTF-8 text from the primary selection, which must be freed with
+ * SDL_free().
+ *
+ * This functions returns empty string if there was not enough memory left for
+ * a copy of the primary selection's content.
+ *
+ * \returns the primary selection text on success or an empty string on
+ * failure; call SDL_GetError() for more information. Caller must
+ * call SDL_free() on the returned pointer when done with it (even if
+ * there was an error).
+ *
+ * \since This function is available since SDL 2.26.0.
+ *
+ * \sa SDL_HasPrimarySelectionText
+ * \sa SDL_SetPrimarySelectionText
+ */
+extern DECLSPEC char * SDLCALL SDL_GetPrimarySelectionText(void);
+
+/**
+ * Query whether the primary selection exists and contains a non-empty text
+ * string.
+ *
+ * \returns SDL_TRUE if the primary selection has text, or SDL_FALSE if it
+ * does not.
+ *
+ * \since This function is available since SDL 2.26.0.
+ *
+ * \sa SDL_GetPrimarySelectionText
+ * \sa SDL_SetPrimarySelectionText
+ */
+extern DECLSPEC SDL_bool SDLCALL SDL_HasPrimarySelectionText(void);
+
+
+/* Ends C function definitions when using C++ */
+#ifdef __cplusplus
+}
+#endif
+#include
+
+#endif /* SDL_clipboard_h_ */
+
+/* vi: set ts=4 sw=4 expandtab: */
diff --git a/bindings/sdl2wgpu/src/main/headers/SDL2/SDL_config.h b/bindings/sdl2wgpu/src/main/headers/SDL2/SDL_config.h
new file mode 100644
index 00000000..a168a00c
--- /dev/null
+++ b/bindings/sdl2wgpu/src/main/headers/SDL2/SDL_config.h
@@ -0,0 +1,61 @@
+/*
+ Simple DirectMedia Layer
+ Copyright (C) 1997-2023 Sam Lantinga
+
+ This software is provided 'as-is', without any express or implied
+ warranty. In no event will the authors be held liable for any damages
+ arising from the use of this software.
+
+ Permission is granted to anyone to use this software for any purpose,
+ including commercial applications, and to alter it and redistribute it
+ freely, subject to the following restrictions:
+
+ 1. The origin of this software must not be misrepresented; you must not
+ claim that you wrote the original software. If you use this software
+ in a product, an acknowledgment in the product documentation would be
+ appreciated but is not required.
+ 2. Altered source versions must be plainly marked as such, and must not be
+ misrepresented as being the original software.
+ 3. This notice may not be removed or altered from any source distribution.
+*/
+
+#ifndef SDL_config_h_
+#define SDL_config_h_
+
+#include
+
+/**
+ * \file SDL_config.h
+ */
+
+/* Add any platform that doesn't build using the configure system. */
+#if defined(__WIN32__)
+#include
+#elif defined(__WINRT__)
+#include
+#elif defined(__WINGDK__)
+#include
+#elif defined(__XBOXONE__) || defined(__XBOXSERIES__)
+#include
+#elif defined(__MACOSX__)
+#include
+#elif defined(__IPHONEOS__)
+#include
+#elif defined(__ANDROID__)
+#include
+#elif defined(__OS2__)
+#include
+#elif defined(__EMSCRIPTEN__)
+#include
+#elif defined(__NGAGE__)
+#include
+#else
+/* This is a minimal configuration just to get SDL running on new platforms. */
+#include
+#endif /* platform config */
+
+#ifdef USING_GENERATED_CONFIG_H
+#error Wrong SDL_config.h, check your include path?
+#endif
+
+#endif /* SDL_config_h_ */
diff --git a/bindings/sdl2wgpu/src/main/headers/SDL2/SDL_config_macosx.h b/bindings/sdl2wgpu/src/main/headers/SDL2/SDL_config_macosx.h
new file mode 100644
index 00000000..2f36d7af
--- /dev/null
+++ b/bindings/sdl2wgpu/src/main/headers/SDL2/SDL_config_macosx.h
@@ -0,0 +1,277 @@
+/*
+ Simple DirectMedia Layer
+ Copyright (C) 1997-2023 Sam Lantinga
+
+ This software is provided 'as-is', without any express or implied
+ warranty. In no event will the authors be held liable for any damages
+ arising from the use of this software.
+
+ Permission is granted to anyone to use this software for any purpose,
+ including commercial applications, and to alter it and redistribute it
+ freely, subject to the following restrictions:
+
+ 1. The origin of this software must not be misrepresented; you must not
+ claim that you wrote the original software. If you use this software
+ in a product, an acknowledgment in the product documentation would be
+ appreciated but is not required.
+ 2. Altered source versions must be plainly marked as such, and must not be
+ misrepresented as being the original software.
+ 3. This notice may not be removed or altered from any source distribution.
+*/
+
+#ifndef SDL_config_macosx_h_
+#define SDL_config_macosx_h_
+#define SDL_config_h_
+
+#include
+
+/* This gets us MAC_OS_X_VERSION_MIN_REQUIRED... */
+#include
+
+/* This is a set of defines to configure the SDL features */
+
+#ifdef __LP64__
+ #define SIZEOF_VOIDP 8
+#else
+ #define SIZEOF_VOIDP 4
+#endif
+
+/* Useful headers */
+#define STDC_HEADERS 1
+#define HAVE_ALLOCA_H 1
+#define HAVE_CTYPE_H 1
+#define HAVE_FLOAT_H 1
+#define HAVE_INTTYPES_H 1
+#define HAVE_LIMITS_H 1
+#define HAVE_MATH_H 1
+#define HAVE_SIGNAL_H 1
+#define HAVE_STDINT_H 1
+#define HAVE_STDIO_H 1
+#define HAVE_STRING_H 1
+#define HAVE_SYS_TYPES_H 1
+#define HAVE_LIBUNWIND_H 1
+
+/* C library functions */
+#define HAVE_DLOPEN 1
+#define HAVE_MALLOC 1
+#define HAVE_CALLOC 1
+#define HAVE_REALLOC 1
+#define HAVE_FREE 1
+#define HAVE_ALLOCA 1
+#define HAVE_GETENV 1
+#define HAVE_SETENV 1
+#define HAVE_PUTENV 1
+#define HAVE_UNSETENV 1
+#define HAVE_QSORT 1
+#define HAVE_BSEARCH 1
+#define HAVE_ABS 1
+#define HAVE_BCOPY 1
+#define HAVE_MEMSET 1
+#define HAVE_MEMCPY 1
+#define HAVE_MEMMOVE 1
+#define HAVE_MEMCMP 1
+#define HAVE_STRLEN 1
+#define HAVE_STRLCPY 1
+#define HAVE_STRLCAT 1
+#define HAVE_STRCHR 1
+#define HAVE_STRRCHR 1
+#define HAVE_STRSTR 1
+#define HAVE_STRTOK_R 1
+#define HAVE_STRTOL 1
+#define HAVE_STRTOUL 1
+#define HAVE_STRTOLL 1
+#define HAVE_STRTOULL 1
+#define HAVE_STRTOD 1
+#define HAVE_ATOI 1
+#define HAVE_ATOF 1
+#define HAVE_STRCMP 1
+#define HAVE_STRNCMP 1
+#define HAVE_STRCASECMP 1
+#define HAVE_STRNCASECMP 1
+#define HAVE_STRCASESTR 1
+#define HAVE_VSSCANF 1
+#define HAVE_VSNPRINTF 1
+#define HAVE_M_PI 1
+#define HAVE_ACOS 1
+#define HAVE_ACOSF 1
+#define HAVE_ASIN 1
+#define HAVE_ASINF 1
+#define HAVE_ATAN 1
+#define HAVE_ATANF 1
+#define HAVE_ATAN2 1
+#define HAVE_ATAN2F 1
+#define HAVE_CEIL 1
+#define HAVE_CEILF 1
+#define HAVE_COPYSIGN 1
+#define HAVE_COPYSIGNF 1
+#define HAVE_COS 1
+#define HAVE_COSF 1
+#define HAVE_EXP 1
+#define HAVE_EXPF 1
+#define HAVE_FABS 1
+#define HAVE_FABSF 1
+#define HAVE_FLOOR 1
+#define HAVE_FLOORF 1
+#define HAVE_FMOD 1
+#define HAVE_FMODF 1
+#define HAVE_LOG 1
+#define HAVE_LOGF 1
+#define HAVE_LOG10 1
+#define HAVE_LOG10F 1
+#define HAVE_LROUND 1
+#define HAVE_LROUNDF 1
+#define HAVE_POW 1
+#define HAVE_POWF 1
+#define HAVE_ROUND 1
+#define HAVE_ROUNDF 1
+#define HAVE_SCALBN 1
+#define HAVE_SCALBNF 1
+#define HAVE_SIN 1
+#define HAVE_SINF 1
+#define HAVE_SQRT 1
+#define HAVE_SQRTF 1
+#define HAVE_TAN 1
+#define HAVE_TANF 1
+#define HAVE_TRUNC 1
+#define HAVE_TRUNCF 1
+#define HAVE_SIGACTION 1
+#define HAVE_SETJMP 1
+#define HAVE_NANOSLEEP 1
+#define HAVE_SYSCONF 1
+#define HAVE_SYSCTLBYNAME 1
+
+#if defined(__has_include) && (defined(__i386__) || defined(__x86_64))
+# if __has_include()
+# define HAVE_IMMINTRIN_H 1
+# endif
+#endif
+
+#if (MAC_OS_X_VERSION_MAX_ALLOWED >= 1070)
+#define HAVE_O_CLOEXEC 1
+#endif
+
+#define HAVE_GCC_ATOMICS 1
+
+/* Enable various audio drivers */
+#define SDL_AUDIO_DRIVER_COREAUDIO 1
+#define SDL_AUDIO_DRIVER_DISK 1
+#define SDL_AUDIO_DRIVER_DUMMY 1
+
+/* Enable various input drivers */
+#define SDL_JOYSTICK_HIDAPI 1
+#define SDL_JOYSTICK_IOKIT 1
+#define SDL_JOYSTICK_VIRTUAL 1
+#define SDL_HAPTIC_IOKIT 1
+
+/* The MFI controller support requires ARC Objective C runtime */
+#if MAC_OS_X_VERSION_MIN_REQUIRED >= 1080 && !defined(__i386__)
+#define SDL_JOYSTICK_MFI 1
+#endif
+
+/* Enable the dummy sensor driver */
+#define SDL_SENSOR_DUMMY 1
+
+/* Enable various shared object loading systems */
+#define SDL_LOADSO_DLOPEN 1
+
+/* Enable various threading systems */
+#define SDL_THREAD_PTHREAD 1
+#define SDL_THREAD_PTHREAD_RECURSIVE_MUTEX 1
+
+/* Enable various timer systems */
+#define SDL_TIMER_UNIX 1
+
+/* Enable various video drivers */
+#define SDL_VIDEO_DRIVER_COCOA 1
+#define SDL_VIDEO_DRIVER_DUMMY 1
+#undef SDL_VIDEO_DRIVER_X11
+#define SDL_VIDEO_DRIVER_X11_DYNAMIC "/opt/X11/lib/libX11.6.dylib"
+#define SDL_VIDEO_DRIVER_X11_DYNAMIC_XEXT "/opt/X11/lib/libXext.6.dylib"
+#define SDL_VIDEO_DRIVER_X11_DYNAMIC_XINPUT2 "/opt/X11/lib/libXi.6.dylib"
+#define SDL_VIDEO_DRIVER_X11_DYNAMIC_XRANDR "/opt/X11/lib/libXrandr.2.dylib"
+#define SDL_VIDEO_DRIVER_X11_DYNAMIC_XSS "/opt/X11/lib/libXss.1.dylib"
+#define SDL_VIDEO_DRIVER_X11_XDBE 1
+#define SDL_VIDEO_DRIVER_X11_XRANDR 1
+#define SDL_VIDEO_DRIVER_X11_XSCRNSAVER 1
+#define SDL_VIDEO_DRIVER_X11_XSHAPE 1
+#define SDL_VIDEO_DRIVER_X11_HAS_XKBKEYCODETOKEYSYM 1
+
+#ifdef MAC_OS_X_VERSION_10_8
+/*
+ * No matter the versions targeted, this is the 10.8 or later SDK, so you have
+ * to use the external Xquartz, which is a more modern Xlib. Previous SDKs
+ * used an older Xlib.
+ */
+#define SDL_VIDEO_DRIVER_X11_XINPUT2 1
+#define SDL_VIDEO_DRIVER_X11_SUPPORTS_GENERIC_EVENTS 1
+#endif
+
+#ifndef SDL_VIDEO_RENDER_OGL
+#define SDL_VIDEO_RENDER_OGL 1
+#endif
+
+#ifndef SDL_VIDEO_RENDER_OGL_ES2
+#define SDL_VIDEO_RENDER_OGL_ES2 1
+#endif
+
+/* Metal only supported on 64-bit architectures with 10.11+ */
+#if TARGET_RT_64_BIT && (MAC_OS_X_VERSION_MAX_ALLOWED >= 101100)
+#define SDL_PLATFORM_SUPPORTS_METAL 1
+#else
+#define SDL_PLATFORM_SUPPORTS_METAL 0
+#endif
+
+#ifndef SDL_VIDEO_RENDER_METAL
+#if SDL_PLATFORM_SUPPORTS_METAL
+#define SDL_VIDEO_RENDER_METAL 1
+#else
+#define SDL_VIDEO_RENDER_METAL 0
+#endif
+#endif
+
+/* Enable OpenGL support */
+#ifndef SDL_VIDEO_OPENGL
+#define SDL_VIDEO_OPENGL 1
+#endif
+#ifndef SDL_VIDEO_OPENGL_ES2
+#define SDL_VIDEO_OPENGL_ES2 1
+#endif
+#ifndef SDL_VIDEO_OPENGL_EGL
+#define SDL_VIDEO_OPENGL_EGL 1
+#endif
+#ifndef SDL_VIDEO_OPENGL_CGL
+#define SDL_VIDEO_OPENGL_CGL 1
+#endif
+#ifndef SDL_VIDEO_OPENGL_GLX
+#define SDL_VIDEO_OPENGL_GLX 1
+#endif
+
+/* Enable Vulkan and Metal support */
+#ifndef SDL_VIDEO_VULKAN
+#if SDL_PLATFORM_SUPPORTS_METAL
+#define SDL_VIDEO_VULKAN 1
+#else
+#define SDL_VIDEO_VULKAN 0
+#endif
+#endif
+
+#ifndef SDL_VIDEO_METAL
+#if SDL_PLATFORM_SUPPORTS_METAL
+#define SDL_VIDEO_METAL 1
+#else
+#define SDL_VIDEO_METAL 0
+#endif
+#endif
+
+/* Enable system power support */
+#define SDL_POWER_MACOSX 1
+
+/* enable filesystem support */
+#define SDL_FILESYSTEM_COCOA 1
+
+/* Enable assembly routines */
+#ifdef __ppc__
+#define SDL_ALTIVEC_BLITTERS 1
+#endif
+
+#endif /* SDL_config_macosx_h_ */
diff --git a/bindings/sdl2wgpu/src/main/headers/SDL2/SDL_copying.h b/bindings/sdl2wgpu/src/main/headers/SDL2/SDL_copying.h
new file mode 100644
index 00000000..b6028bab
--- /dev/null
+++ b/bindings/sdl2wgpu/src/main/headers/SDL2/SDL_copying.h
@@ -0,0 +1,20 @@
+/*
+ Simple DirectMedia Layer
+ Copyright (C) 1997-2023 Sam Lantinga
+
+ This software is provided 'as-is', without any express or implied
+ warranty. In no event will the authors be held liable for any damages
+ arising from the use of this software.
+
+ Permission is granted to anyone to use this software for any purpose,
+ including commercial applications, and to alter it and redistribute it
+ freely, subject to the following restrictions:
+
+ 1. The origin of this software must not be misrepresented; you must not
+ claim that you wrote the original software. If you use this software
+ in a product, an acknowledgment in the product documentation would be
+ appreciated but is not required.
+ 2. Altered source versions must be plainly marked as such, and must not be
+ misrepresented as being the original software.
+ 3. This notice may not be removed or altered from any source distribution.
+*/
diff --git a/bindings/sdl2wgpu/src/main/headers/SDL2/SDL_cpuinfo.h b/bindings/sdl2wgpu/src/main/headers/SDL2/SDL_cpuinfo.h
new file mode 100644
index 00000000..900224db
--- /dev/null
+++ b/bindings/sdl2wgpu/src/main/headers/SDL2/SDL_cpuinfo.h
@@ -0,0 +1,594 @@
+/*
+ Simple DirectMedia Layer
+ Copyright (C) 1997-2023 Sam Lantinga
+
+ This software is provided 'as-is', without any express or implied
+ warranty. In no event will the authors be held liable for any damages
+ arising from the use of this software.
+
+ Permission is granted to anyone to use this software for any purpose,
+ including commercial applications, and to alter it and redistribute it
+ freely, subject to the following restrictions:
+
+ 1. The origin of this software must not be misrepresented; you must not
+ claim that you wrote the original software. If you use this software
+ in a product, an acknowledgment in the product documentation would be
+ appreciated but is not required.
+ 2. Altered source versions must be plainly marked as such, and must not be
+ misrepresented as being the original software.
+ 3. This notice may not be removed or altered from any source distribution.
+*/
+
+/**
+ * \file SDL_cpuinfo.h
+ *
+ * CPU feature detection for SDL.
+ */
+
+#ifndef SDL_cpuinfo_h_
+#define SDL_cpuinfo_h_
+
+#include
+
+/* Need to do this here because intrin.h has C++ code in it */
+/* Visual Studio 2005 has a bug where intrin.h conflicts with winnt.h */
+#if defined(_MSC_VER) && (_MSC_VER >= 1500) && (defined(_M_IX86) || defined(_M_X64))
+#ifdef __clang__
+/* As of Clang 11, '_m_prefetchw' is conflicting with the winnt.h's version,
+ so we define the needed '_m_prefetch' here as a pseudo-header, until the issue is fixed. */
+
+#ifndef __PRFCHWINTRIN_H
+#define __PRFCHWINTRIN_H
+
+static __inline__ void __attribute__((__always_inline__, __nodebug__))
+_m_prefetch(void *__P)
+{
+ __builtin_prefetch (__P, 0, 3 /* _MM_HINT_T0 */);
+}
+
+#endif /* __PRFCHWINTRIN_H */
+#endif /* __clang__ */
+#include
+#ifndef _WIN64
+#ifndef __MMX__
+#define __MMX__
+#endif
+#ifndef __3dNOW__
+#define __3dNOW__
+#endif
+#endif
+#ifndef __SSE__
+#define __SSE__
+#endif
+#ifndef __SSE2__
+#define __SSE2__
+#endif
+#ifndef __SSE3__
+#define __SSE3__
+#endif
+#elif defined(__MINGW64_VERSION_MAJOR)
+#include
+#if !defined(SDL_DISABLE_ARM_NEON_H) && defined(__ARM_NEON)
+# include
+#endif
+#else
+/* altivec.h redefining bool causes a number of problems, see bugs 3993 and 4392, so you need to explicitly define SDL_ENABLE_ALTIVEC_H to have it included. */
+#if defined(HAVE_ALTIVEC_H) && defined(__ALTIVEC__) && !defined(__APPLE_ALTIVEC__) && defined(SDL_ENABLE_ALTIVEC_H)
+#include
+#endif
+#if !defined(SDL_DISABLE_ARM_NEON_H)
+# if defined(__ARM_NEON)
+# include
+# elif defined(__WINDOWS__) || defined(__WINRT__) || defined(__GDK__)
+/* Visual Studio doesn't define __ARM_ARCH, but _M_ARM (if set, always 7), and _M_ARM64 (if set, always 1). */
+# if defined(_M_ARM)
+# include
+# include
+# define __ARM_NEON 1 /* Set __ARM_NEON so that it can be used elsewhere, at compile time */
+# endif
+# if defined (_M_ARM64)
+# include
+# include
+# define __ARM_NEON 1 /* Set __ARM_NEON so that it can be used elsewhere, at compile time */
+# define __ARM_ARCH 8
+# endif
+# endif
+#endif
+#endif /* compiler version */
+
+#if defined(__3dNOW__) && !defined(SDL_DISABLE_MM3DNOW_H)
+#include
+#endif
+#if defined(__loongarch_sx) && !defined(SDL_DISABLE_LSX_H)
+#include
+#define __LSX__
+#endif
+#if defined(__loongarch_asx) && !defined(SDL_DISABLE_LASX_H)
+#include
+#define __LASX__
+#endif
+#if defined(HAVE_IMMINTRIN_H) && !defined(SDL_DISABLE_IMMINTRIN_H)
+#include
+#else
+#if defined(__MMX__) && !defined(SDL_DISABLE_MMINTRIN_H)
+#include
+#endif
+#if defined(__SSE__) && !defined(SDL_DISABLE_XMMINTRIN_H)
+#include
+#endif
+#if defined(__SSE2__) && !defined(SDL_DISABLE_EMMINTRIN_H)
+#include
+#endif
+#if defined(__SSE3__) && !defined(SDL_DISABLE_PMMINTRIN_H)
+#include
+#endif
+#endif /* HAVE_IMMINTRIN_H */
+
+#include
+/* Set up for C function definitions, even when using C++ */
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* This is a guess for the cacheline size used for padding.
+ * Most x86 processors have a 64 byte cache line.
+ * The 64-bit PowerPC processors have a 128 byte cache line.
+ * We'll use the larger value to be generally safe.
+ */
+#define SDL_CACHELINE_SIZE 128
+
+/**
+ * Get the number of CPU cores available.
+ *
+ * \returns the total number of logical CPU cores. On CPUs that include
+ * technologies such as hyperthreading, the number of logical cores
+ * may be more than the number of physical cores.
+ *
+ * \since This function is available since SDL 2.0.0.
+ */
+extern DECLSPEC int SDLCALL SDL_GetCPUCount(void);
+
+/**
+ * Determine the L1 cache line size of the CPU.
+ *
+ * This is useful for determining multi-threaded structure padding or SIMD
+ * prefetch sizes.
+ *
+ * \returns the L1 cache line size of the CPU, in bytes.
+ *
+ * \since This function is available since SDL 2.0.0.
+ */
+extern DECLSPEC int SDLCALL SDL_GetCPUCacheLineSize(void);
+
+/**
+ * Determine whether the CPU has the RDTSC instruction.
+ *
+ * This always returns false on CPUs that aren't using Intel instruction sets.
+ *
+ * \returns SDL_TRUE if the CPU has the RDTSC instruction or SDL_FALSE if not.
+ *
+ * \since This function is available since SDL 2.0.0.
+ *
+ * \sa SDL_Has3DNow
+ * \sa SDL_HasAltiVec
+ * \sa SDL_HasAVX
+ * \sa SDL_HasAVX2
+ * \sa SDL_HasMMX
+ * \sa SDL_HasSSE
+ * \sa SDL_HasSSE2
+ * \sa SDL_HasSSE3
+ * \sa SDL_HasSSE41
+ * \sa SDL_HasSSE42
+ */
+extern DECLSPEC SDL_bool SDLCALL SDL_HasRDTSC(void);
+
+/**
+ * Determine whether the CPU has AltiVec features.
+ *
+ * This always returns false on CPUs that aren't using PowerPC instruction
+ * sets.
+ *
+ * \returns SDL_TRUE if the CPU has AltiVec features or SDL_FALSE if not.
+ *
+ * \since This function is available since SDL 2.0.0.
+ *
+ * \sa SDL_Has3DNow
+ * \sa SDL_HasAVX
+ * \sa SDL_HasAVX2
+ * \sa SDL_HasMMX
+ * \sa SDL_HasRDTSC
+ * \sa SDL_HasSSE
+ * \sa SDL_HasSSE2
+ * \sa SDL_HasSSE3
+ * \sa SDL_HasSSE41
+ * \sa SDL_HasSSE42
+ */
+extern DECLSPEC SDL_bool SDLCALL SDL_HasAltiVec(void);
+
+/**
+ * Determine whether the CPU has MMX features.
+ *
+ * This always returns false on CPUs that aren't using Intel instruction sets.
+ *
+ * \returns SDL_TRUE if the CPU has MMX features or SDL_FALSE if not.
+ *
+ * \since This function is available since SDL 2.0.0.
+ *
+ * \sa SDL_Has3DNow
+ * \sa SDL_HasAltiVec
+ * \sa SDL_HasAVX
+ * \sa SDL_HasAVX2
+ * \sa SDL_HasRDTSC
+ * \sa SDL_HasSSE
+ * \sa SDL_HasSSE2
+ * \sa SDL_HasSSE3
+ * \sa SDL_HasSSE41
+ * \sa SDL_HasSSE42
+ */
+extern DECLSPEC SDL_bool SDLCALL SDL_HasMMX(void);
+
+/**
+ * Determine whether the CPU has 3DNow! features.
+ *
+ * This always returns false on CPUs that aren't using AMD instruction sets.
+ *
+ * \returns SDL_TRUE if the CPU has 3DNow! features or SDL_FALSE if not.
+ *
+ * \since This function is available since SDL 2.0.0.
+ *
+ * \sa SDL_HasAltiVec
+ * \sa SDL_HasAVX
+ * \sa SDL_HasAVX2
+ * \sa SDL_HasMMX
+ * \sa SDL_HasRDTSC
+ * \sa SDL_HasSSE
+ * \sa SDL_HasSSE2
+ * \sa SDL_HasSSE3
+ * \sa SDL_HasSSE41
+ * \sa SDL_HasSSE42
+ */
+extern DECLSPEC SDL_bool SDLCALL SDL_Has3DNow(void);
+
+/**
+ * Determine whether the CPU has SSE features.
+ *
+ * This always returns false on CPUs that aren't using Intel instruction sets.
+ *
+ * \returns SDL_TRUE if the CPU has SSE features or SDL_FALSE if not.
+ *
+ * \since This function is available since SDL 2.0.0.
+ *
+ * \sa SDL_Has3DNow
+ * \sa SDL_HasAltiVec
+ * \sa SDL_HasAVX
+ * \sa SDL_HasAVX2
+ * \sa SDL_HasMMX
+ * \sa SDL_HasRDTSC
+ * \sa SDL_HasSSE2
+ * \sa SDL_HasSSE3
+ * \sa SDL_HasSSE41
+ * \sa SDL_HasSSE42
+ */
+extern DECLSPEC SDL_bool SDLCALL SDL_HasSSE(void);
+
+/**
+ * Determine whether the CPU has SSE2 features.
+ *
+ * This always returns false on CPUs that aren't using Intel instruction sets.
+ *
+ * \returns SDL_TRUE if the CPU has SSE2 features or SDL_FALSE if not.
+ *
+ * \since This function is available since SDL 2.0.0.
+ *
+ * \sa SDL_Has3DNow
+ * \sa SDL_HasAltiVec
+ * \sa SDL_HasAVX
+ * \sa SDL_HasAVX2
+ * \sa SDL_HasMMX
+ * \sa SDL_HasRDTSC
+ * \sa SDL_HasSSE
+ * \sa SDL_HasSSE3
+ * \sa SDL_HasSSE41
+ * \sa SDL_HasSSE42
+ */
+extern DECLSPEC SDL_bool SDLCALL SDL_HasSSE2(void);
+
+/**
+ * Determine whether the CPU has SSE3 features.
+ *
+ * This always returns false on CPUs that aren't using Intel instruction sets.
+ *
+ * \returns SDL_TRUE if the CPU has SSE3 features or SDL_FALSE if not.
+ *
+ * \since This function is available since SDL 2.0.0.
+ *
+ * \sa SDL_Has3DNow
+ * \sa SDL_HasAltiVec
+ * \sa SDL_HasAVX
+ * \sa SDL_HasAVX2
+ * \sa SDL_HasMMX
+ * \sa SDL_HasRDTSC
+ * \sa SDL_HasSSE
+ * \sa SDL_HasSSE2
+ * \sa SDL_HasSSE41
+ * \sa SDL_HasSSE42
+ */
+extern DECLSPEC SDL_bool SDLCALL SDL_HasSSE3(void);
+
+/**
+ * Determine whether the CPU has SSE4.1 features.
+ *
+ * This always returns false on CPUs that aren't using Intel instruction sets.
+ *
+ * \returns SDL_TRUE if the CPU has SSE4.1 features or SDL_FALSE if not.
+ *
+ * \since This function is available since SDL 2.0.0.
+ *
+ * \sa SDL_Has3DNow
+ * \sa SDL_HasAltiVec
+ * \sa SDL_HasAVX
+ * \sa SDL_HasAVX2
+ * \sa SDL_HasMMX
+ * \sa SDL_HasRDTSC
+ * \sa SDL_HasSSE
+ * \sa SDL_HasSSE2
+ * \sa SDL_HasSSE3
+ * \sa SDL_HasSSE42
+ */
+extern DECLSPEC SDL_bool SDLCALL SDL_HasSSE41(void);
+
+/**
+ * Determine whether the CPU has SSE4.2 features.
+ *
+ * This always returns false on CPUs that aren't using Intel instruction sets.
+ *
+ * \returns SDL_TRUE if the CPU has SSE4.2 features or SDL_FALSE if not.
+ *
+ * \since This function is available since SDL 2.0.0.
+ *
+ * \sa SDL_Has3DNow
+ * \sa SDL_HasAltiVec
+ * \sa SDL_HasAVX
+ * \sa SDL_HasAVX2
+ * \sa SDL_HasMMX
+ * \sa SDL_HasRDTSC
+ * \sa SDL_HasSSE
+ * \sa SDL_HasSSE2
+ * \sa SDL_HasSSE3
+ * \sa SDL_HasSSE41
+ */
+extern DECLSPEC SDL_bool SDLCALL SDL_HasSSE42(void);
+
+/**
+ * Determine whether the CPU has AVX features.
+ *
+ * This always returns false on CPUs that aren't using Intel instruction sets.
+ *
+ * \returns SDL_TRUE if the CPU has AVX features or SDL_FALSE if not.
+ *
+ * \since This function is available since SDL 2.0.2.
+ *
+ * \sa SDL_Has3DNow
+ * \sa SDL_HasAltiVec
+ * \sa SDL_HasAVX2
+ * \sa SDL_HasMMX
+ * \sa SDL_HasRDTSC
+ * \sa SDL_HasSSE
+ * \sa SDL_HasSSE2
+ * \sa SDL_HasSSE3
+ * \sa SDL_HasSSE41
+ * \sa SDL_HasSSE42
+ */
+extern DECLSPEC SDL_bool SDLCALL SDL_HasAVX(void);
+
+/**
+ * Determine whether the CPU has AVX2 features.
+ *
+ * This always returns false on CPUs that aren't using Intel instruction sets.
+ *
+ * \returns SDL_TRUE if the CPU has AVX2 features or SDL_FALSE if not.
+ *
+ * \since This function is available since SDL 2.0.4.
+ *
+ * \sa SDL_Has3DNow
+ * \sa SDL_HasAltiVec
+ * \sa SDL_HasAVX
+ * \sa SDL_HasMMX
+ * \sa SDL_HasRDTSC
+ * \sa SDL_HasSSE
+ * \sa SDL_HasSSE2
+ * \sa SDL_HasSSE3
+ * \sa SDL_HasSSE41
+ * \sa SDL_HasSSE42
+ */
+extern DECLSPEC SDL_bool SDLCALL SDL_HasAVX2(void);
+
+/**
+ * Determine whether the CPU has AVX-512F (foundation) features.
+ *
+ * This always returns false on CPUs that aren't using Intel instruction sets.
+ *
+ * \returns SDL_TRUE if the CPU has AVX-512F features or SDL_FALSE if not.
+ *
+ * \since This function is available since SDL 2.0.9.
+ *
+ * \sa SDL_HasAVX
+ */
+extern DECLSPEC SDL_bool SDLCALL SDL_HasAVX512F(void);
+
+/**
+ * Determine whether the CPU has ARM SIMD (ARMv6) features.
+ *
+ * This is different from ARM NEON, which is a different instruction set.
+ *
+ * This always returns false on CPUs that aren't using ARM instruction sets.
+ *
+ * \returns SDL_TRUE if the CPU has ARM SIMD features or SDL_FALSE if not.
+ *
+ * \since This function is available since SDL 2.0.12.
+ *
+ * \sa SDL_HasNEON
+ */
+extern DECLSPEC SDL_bool SDLCALL SDL_HasARMSIMD(void);
+
+/**
+ * Determine whether the CPU has NEON (ARM SIMD) features.
+ *
+ * This always returns false on CPUs that aren't using ARM instruction sets.
+ *
+ * \returns SDL_TRUE if the CPU has ARM NEON features or SDL_FALSE if not.
+ *
+ * \since This function is available since SDL 2.0.6.
+ */
+extern DECLSPEC SDL_bool SDLCALL SDL_HasNEON(void);
+
+/**
+ * Determine whether the CPU has LSX (LOONGARCH SIMD) features.
+ *
+ * This always returns false on CPUs that aren't using LOONGARCH instruction
+ * sets.
+ *
+ * \returns SDL_TRUE if the CPU has LOONGARCH LSX features or SDL_FALSE if
+ * not.
+ *
+ * \since This function is available since SDL 2.24.0.
+ */
+extern DECLSPEC SDL_bool SDLCALL SDL_HasLSX(void);
+
+/**
+ * Determine whether the CPU has LASX (LOONGARCH SIMD) features.
+ *
+ * This always returns false on CPUs that aren't using LOONGARCH instruction
+ * sets.
+ *
+ * \returns SDL_TRUE if the CPU has LOONGARCH LASX features or SDL_FALSE if
+ * not.
+ *
+ * \since This function is available since SDL 2.24.0.
+ */
+extern DECLSPEC SDL_bool SDLCALL SDL_HasLASX(void);
+
+/**
+ * Get the amount of RAM configured in the system.
+ *
+ * \returns the amount of RAM configured in the system in MiB.
+ *
+ * \since This function is available since SDL 2.0.1.
+ */
+extern DECLSPEC int SDLCALL SDL_GetSystemRAM(void);
+
+/**
+ * Report the alignment this system needs for SIMD allocations.
+ *
+ * This will return the minimum number of bytes to which a pointer must be
+ * aligned to be compatible with SIMD instructions on the current machine. For
+ * example, if the machine supports SSE only, it will return 16, but if it
+ * supports AVX-512F, it'll return 64 (etc). This only reports values for
+ * instruction sets SDL knows about, so if your SDL build doesn't have
+ * SDL_HasAVX512F(), then it might return 16 for the SSE support it sees and
+ * not 64 for the AVX-512 instructions that exist but SDL doesn't know about.
+ * Plan accordingly.
+ *
+ * \returns the alignment in bytes needed for available, known SIMD
+ * instructions.
+ *
+ * \since This function is available since SDL 2.0.10.
+ */
+extern DECLSPEC size_t SDLCALL SDL_SIMDGetAlignment(void);
+
+/**
+ * Allocate memory in a SIMD-friendly way.
+ *
+ * This will allocate a block of memory that is suitable for use with SIMD
+ * instructions. Specifically, it will be properly aligned and padded for the
+ * system's supported vector instructions.
+ *
+ * The memory returned will be padded such that it is safe to read or write an
+ * incomplete vector at the end of the memory block. This can be useful so you
+ * don't have to drop back to a scalar fallback at the end of your SIMD
+ * processing loop to deal with the final elements without overflowing the
+ * allocated buffer.
+ *
+ * You must free this memory with SDL_FreeSIMD(), not free() or SDL_free() or
+ * delete[], etc.
+ *
+ * Note that SDL will only deal with SIMD instruction sets it is aware of; for
+ * example, SDL 2.0.8 knows that SSE wants 16-byte vectors (SDL_HasSSE()), and
+ * AVX2 wants 32 bytes (SDL_HasAVX2()), but doesn't know that AVX-512 wants
+ * 64. To be clear: if you can't decide to use an instruction set with an
+ * SDL_Has*() function, don't use that instruction set with memory allocated
+ * through here.
+ *
+ * SDL_AllocSIMD(0) will return a non-NULL pointer, assuming the system isn't
+ * out of memory, but you are not allowed to dereference it (because you only
+ * own zero bytes of that buffer).
+ *
+ * \param len The length, in bytes, of the block to allocate. The actual
+ * allocated block might be larger due to padding, etc.
+ * \returns a pointer to the newly-allocated block, NULL if out of memory.
+ *
+ * \since This function is available since SDL 2.0.10.
+ *
+ * \sa SDL_SIMDGetAlignment
+ * \sa SDL_SIMDRealloc
+ * \sa SDL_SIMDFree
+ */
+extern DECLSPEC void * SDLCALL SDL_SIMDAlloc(const size_t len);
+
+/**
+ * Reallocate memory obtained from SDL_SIMDAlloc
+ *
+ * It is not valid to use this function on a pointer from anything but
+ * SDL_SIMDAlloc(). It can't be used on pointers from malloc, realloc,
+ * SDL_malloc, memalign, new[], etc.
+ *
+ * \param mem The pointer obtained from SDL_SIMDAlloc. This function also
+ * accepts NULL, at which point this function is the same as
+ * calling SDL_SIMDAlloc with a NULL pointer.
+ * \param len The length, in bytes, of the block to allocated. The actual
+ * allocated block might be larger due to padding, etc. Passing 0
+ * will return a non-NULL pointer, assuming the system isn't out of
+ * memory.
+ * \returns a pointer to the newly-reallocated block, NULL if out of memory.
+ *
+ * \since This function is available since SDL 2.0.14.
+ *
+ * \sa SDL_SIMDGetAlignment
+ * \sa SDL_SIMDAlloc
+ * \sa SDL_SIMDFree
+ */
+extern DECLSPEC void * SDLCALL SDL_SIMDRealloc(void *mem, const size_t len);
+
+/**
+ * Deallocate memory obtained from SDL_SIMDAlloc
+ *
+ * It is not valid to use this function on a pointer from anything but
+ * SDL_SIMDAlloc() or SDL_SIMDRealloc(). It can't be used on pointers from
+ * malloc, realloc, SDL_malloc, memalign, new[], etc.
+ *
+ * However, SDL_SIMDFree(NULL) is a legal no-op.
+ *
+ * The memory pointed to by `ptr` is no longer valid for access upon return,
+ * and may be returned to the system or reused by a future allocation. The
+ * pointer passed to this function is no longer safe to dereference once this
+ * function returns, and should be discarded.
+ *
+ * \param ptr The pointer, returned from SDL_SIMDAlloc or SDL_SIMDRealloc, to
+ * deallocate. NULL is a legal no-op.
+ *
+ * \since This function is available since SDL 2.0.10.
+ *
+ * \sa SDL_SIMDAlloc
+ * \sa SDL_SIMDRealloc
+ */
+extern DECLSPEC void SDLCALL SDL_SIMDFree(void *ptr);
+
+/* Ends C function definitions when using C++ */
+#ifdef __cplusplus
+}
+#endif
+#include
+
+#endif /* SDL_cpuinfo_h_ */
+
+/* vi: set ts=4 sw=4 expandtab: */
diff --git a/bindings/sdl2wgpu/src/main/headers/SDL2/SDL_endian.h b/bindings/sdl2wgpu/src/main/headers/SDL2/SDL_endian.h
new file mode 100644
index 00000000..62f7ae49
--- /dev/null
+++ b/bindings/sdl2wgpu/src/main/headers/SDL2/SDL_endian.h
@@ -0,0 +1,348 @@
+/*
+ Simple DirectMedia Layer
+ Copyright (C) 1997-2023 Sam Lantinga
+
+ This software is provided 'as-is', without any express or implied
+ warranty. In no event will the authors be held liable for any damages
+ arising from the use of this software.
+
+ Permission is granted to anyone to use this software for any purpose,
+ including commercial applications, and to alter it and redistribute it
+ freely, subject to the following restrictions:
+
+ 1. The origin of this software must not be misrepresented; you must not
+ claim that you wrote the original software. If you use this software
+ in a product, an acknowledgment in the product documentation would be
+ appreciated but is not required.
+ 2. Altered source versions must be plainly marked as such, and must not be
+ misrepresented as being the original software.
+ 3. This notice may not be removed or altered from any source distribution.
+*/
+
+/**
+ * \file SDL_endian.h
+ *
+ * Functions for reading and writing endian-specific values
+ */
+
+#ifndef SDL_endian_h_
+#define SDL_endian_h_
+
+#include
+
+#if defined(_MSC_VER) && (_MSC_VER >= 1400)
+/* As of Clang 11, '_m_prefetchw' is conflicting with the winnt.h's version,
+ so we define the needed '_m_prefetch' here as a pseudo-header, until the issue is fixed. */
+#ifdef __clang__
+#ifndef __PRFCHWINTRIN_H
+#define __PRFCHWINTRIN_H
+static __inline__ void __attribute__((__always_inline__, __nodebug__))
+_m_prefetch(void *__P)
+{
+ __builtin_prefetch(__P, 0, 3 /* _MM_HINT_T0 */);
+}
+#endif /* __PRFCHWINTRIN_H */
+#endif /* __clang__ */
+
+#include
+#endif
+
+/**
+ * \name The two types of endianness
+ */
+/* @{ */
+#define SDL_LIL_ENDIAN 1234
+#define SDL_BIG_ENDIAN 4321
+/* @} */
+
+#ifndef SDL_BYTEORDER /* Not defined in SDL_config.h? */
+#ifdef __linux__
+#include
+#define SDL_BYTEORDER __BYTE_ORDER
+#elif defined(__OpenBSD__) || defined(__DragonFly__)
+#include
+#define SDL_BYTEORDER BYTE_ORDER
+#elif defined(__FreeBSD__) || defined(__NetBSD__)
+#include
+#define SDL_BYTEORDER BYTE_ORDER
+/* predefs from newer gcc and clang versions: */
+#elif defined(__ORDER_LITTLE_ENDIAN__) && defined(__ORDER_BIG_ENDIAN__) && defined(__BYTE_ORDER__)
+#if (__BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__)
+#define SDL_BYTEORDER SDL_LIL_ENDIAN
+#elif (__BYTE_ORDER__ == __ORDER_BIG_ENDIAN__)
+#define SDL_BYTEORDER SDL_BIG_ENDIAN
+#else
+#error Unsupported endianness
+#endif /**/
+#else
+#if defined(__hppa__) || \
+ defined(__m68k__) || defined(mc68000) || defined(_M_M68K) || \
+ (defined(__MIPS__) && defined(__MIPSEB__)) || \
+ defined(__ppc__) || defined(__POWERPC__) || defined(__powerpc__) || defined(__PPC__) || \
+ defined(__sparc__)
+#define SDL_BYTEORDER SDL_BIG_ENDIAN
+#else
+#define SDL_BYTEORDER SDL_LIL_ENDIAN
+#endif
+#endif /* __linux__ */
+#endif /* !SDL_BYTEORDER */
+
+#ifndef SDL_FLOATWORDORDER /* Not defined in SDL_config.h? */
+/* predefs from newer gcc versions: */
+#if defined(__ORDER_LITTLE_ENDIAN__) && defined(__ORDER_BIG_ENDIAN__) && defined(__FLOAT_WORD_ORDER__)
+#if (__FLOAT_WORD_ORDER__ == __ORDER_LITTLE_ENDIAN__)
+#define SDL_FLOATWORDORDER SDL_LIL_ENDIAN
+#elif (__FLOAT_WORD_ORDER__ == __ORDER_BIG_ENDIAN__)
+#define SDL_FLOATWORDORDER SDL_BIG_ENDIAN
+#else
+#error Unsupported endianness
+#endif /**/
+#elif defined(__MAVERICK__)
+/* For Maverick, float words are always little-endian. */
+#define SDL_FLOATWORDORDER SDL_LIL_ENDIAN
+#elif (defined(__arm__) || defined(__thumb__)) && !defined(__VFP_FP__) && !defined(__ARM_EABI__)
+/* For FPA, float words are always big-endian. */
+#define SDL_FLOATWORDORDER SDL_BIG_ENDIAN
+#else
+/* By default, assume that floats words follow the memory system mode. */
+#define SDL_FLOATWORDORDER SDL_BYTEORDER
+#endif /* __FLOAT_WORD_ORDER__ */
+#endif /* !SDL_FLOATWORDORDER */
+
+
+#include
+/* Set up for C function definitions, even when using C++ */
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * \file SDL_endian.h
+ */
+
+/* various modern compilers may have builtin swap */
+#if defined(__GNUC__) || defined(__clang__)
+# define HAS_BUILTIN_BSWAP16 (_SDL_HAS_BUILTIN(__builtin_bswap16)) || \
+ (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 8))
+# define HAS_BUILTIN_BSWAP32 (_SDL_HAS_BUILTIN(__builtin_bswap32)) || \
+ (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 3))
+# define HAS_BUILTIN_BSWAP64 (_SDL_HAS_BUILTIN(__builtin_bswap64)) || \
+ (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 3))
+
+ /* this one is broken */
+# define HAS_BROKEN_BSWAP (__GNUC__ == 2 && __GNUC_MINOR__ <= 95)
+#else
+# define HAS_BUILTIN_BSWAP16 0
+# define HAS_BUILTIN_BSWAP32 0
+# define HAS_BUILTIN_BSWAP64 0
+# define HAS_BROKEN_BSWAP 0
+#endif
+
+#if HAS_BUILTIN_BSWAP16
+#define SDL_Swap16(x) __builtin_bswap16(x)
+#elif (defined(_MSC_VER) && (_MSC_VER >= 1400)) && !defined(__ICL)
+#pragma intrinsic(_byteswap_ushort)
+#define SDL_Swap16(x) _byteswap_ushort(x)
+#elif defined(__i386__) && !HAS_BROKEN_BSWAP
+SDL_FORCE_INLINE Uint16
+SDL_Swap16(Uint16 x)
+{
+ __asm__("xchgb %b0,%h0": "=q"(x):"0"(x));
+ return x;
+}
+#elif defined(__x86_64__)
+SDL_FORCE_INLINE Uint16
+SDL_Swap16(Uint16 x)
+{
+ __asm__("xchgb %b0,%h0": "=Q"(x):"0"(x));
+ return x;
+}
+#elif (defined(__powerpc__) || defined(__ppc__))
+SDL_FORCE_INLINE Uint16
+SDL_Swap16(Uint16 x)
+{
+ int result;
+
+ __asm__("rlwimi %0,%2,8,16,23": "=&r"(result):"0"(x >> 8), "r"(x));
+ return (Uint16)result;
+}
+#elif (defined(__m68k__) && !defined(__mcoldfire__))
+SDL_FORCE_INLINE Uint16
+SDL_Swap16(Uint16 x)
+{
+ __asm__("rorw #8,%0": "=d"(x): "0"(x):"cc");
+ return x;
+}
+#elif defined(__WATCOMC__) && defined(__386__)
+extern __inline Uint16 SDL_Swap16(Uint16);
+#pragma aux SDL_Swap16 = \
+ "xchg al, ah" \
+ parm [ax] \
+ modify [ax];
+#else
+SDL_FORCE_INLINE Uint16
+SDL_Swap16(Uint16 x)
+{
+ return SDL_static_cast(Uint16, ((x << 8) | (x >> 8)));
+}
+#endif
+
+#if HAS_BUILTIN_BSWAP32
+#define SDL_Swap32(x) __builtin_bswap32(x)
+#elif (defined(_MSC_VER) && (_MSC_VER >= 1400)) && !defined(__ICL)
+#pragma intrinsic(_byteswap_ulong)
+#define SDL_Swap32(x) _byteswap_ulong(x)
+#elif defined(__i386__) && !HAS_BROKEN_BSWAP
+SDL_FORCE_INLINE Uint32
+SDL_Swap32(Uint32 x)
+{
+ __asm__("bswap %0": "=r"(x):"0"(x));
+ return x;
+}
+#elif defined(__x86_64__)
+SDL_FORCE_INLINE Uint32
+SDL_Swap32(Uint32 x)
+{
+ __asm__("bswapl %0": "=r"(x):"0"(x));
+ return x;
+}
+#elif (defined(__powerpc__) || defined(__ppc__))
+SDL_FORCE_INLINE Uint32
+SDL_Swap32(Uint32 x)
+{
+ Uint32 result;
+
+ __asm__("rlwimi %0,%2,24,16,23": "=&r"(result): "0" (x>>24), "r"(x));
+ __asm__("rlwimi %0,%2,8,8,15" : "=&r"(result): "0" (result), "r"(x));
+ __asm__("rlwimi %0,%2,24,0,7" : "=&r"(result): "0" (result), "r"(x));
+ return result;
+}
+#elif (defined(__m68k__) && !defined(__mcoldfire__))
+SDL_FORCE_INLINE Uint32
+SDL_Swap32(Uint32 x)
+{
+ __asm__("rorw #8,%0\n\tswap %0\n\trorw #8,%0": "=d"(x): "0"(x):"cc");
+ return x;
+}
+#elif defined(__WATCOMC__) && defined(__386__)
+extern __inline Uint32 SDL_Swap32(Uint32);
+#pragma aux SDL_Swap32 = \
+ "bswap eax" \
+ parm [eax] \
+ modify [eax];
+#else
+SDL_FORCE_INLINE Uint32
+SDL_Swap32(Uint32 x)
+{
+ return SDL_static_cast(Uint32, ((x << 24) | ((x << 8) & 0x00FF0000) |
+ ((x >> 8) & 0x0000FF00) | (x >> 24)));
+}
+#endif
+
+#if HAS_BUILTIN_BSWAP64
+#define SDL_Swap64(x) __builtin_bswap64(x)
+#elif (defined(_MSC_VER) && (_MSC_VER >= 1400)) && !defined(__ICL)
+#pragma intrinsic(_byteswap_uint64)
+#define SDL_Swap64(x) _byteswap_uint64(x)
+#elif defined(__i386__) && !HAS_BROKEN_BSWAP
+SDL_FORCE_INLINE Uint64
+SDL_Swap64(Uint64 x)
+{
+ union {
+ struct {
+ Uint32 a, b;
+ } s;
+ Uint64 u;
+ } v;
+ v.u = x;
+ __asm__("bswapl %0 ; bswapl %1 ; xchgl %0,%1"
+ : "=r"(v.s.a), "=r"(v.s.b)
+ : "0" (v.s.a), "1"(v.s.b));
+ return v.u;
+}
+#elif defined(__x86_64__)
+SDL_FORCE_INLINE Uint64
+SDL_Swap64(Uint64 x)
+{
+ __asm__("bswapq %0": "=r"(x):"0"(x));
+ return x;
+}
+#elif defined(__WATCOMC__) && defined(__386__)
+extern __inline Uint64 SDL_Swap64(Uint64);
+#pragma aux SDL_Swap64 = \
+ "bswap eax" \
+ "bswap edx" \
+ "xchg eax,edx" \
+ parm [eax edx] \
+ modify [eax edx];
+#else
+SDL_FORCE_INLINE Uint64
+SDL_Swap64(Uint64 x)
+{
+ Uint32 hi, lo;
+
+ /* Separate into high and low 32-bit values and swap them */
+ lo = SDL_static_cast(Uint32, x & 0xFFFFFFFF);
+ x >>= 32;
+ hi = SDL_static_cast(Uint32, x & 0xFFFFFFFF);
+ x = SDL_Swap32(lo);
+ x <<= 32;
+ x |= SDL_Swap32(hi);
+ return (x);
+}
+#endif
+
+
+SDL_FORCE_INLINE float
+SDL_SwapFloat(float x)
+{
+ union {
+ float f;
+ Uint32 ui32;
+ } swapper;
+ swapper.f = x;
+ swapper.ui32 = SDL_Swap32(swapper.ui32);
+ return swapper.f;
+}
+
+/* remove extra macros */
+#undef HAS_BROKEN_BSWAP
+#undef HAS_BUILTIN_BSWAP16
+#undef HAS_BUILTIN_BSWAP32
+#undef HAS_BUILTIN_BSWAP64
+
+/**
+ * \name Swap to native
+ * Byteswap item from the specified endianness to the native endianness.
+ */
+/* @{ */
+#if SDL_BYTEORDER == SDL_LIL_ENDIAN
+#define SDL_SwapLE16(X) (X)
+#define SDL_SwapLE32(X) (X)
+#define SDL_SwapLE64(X) (X)
+#define SDL_SwapFloatLE(X) (X)
+#define SDL_SwapBE16(X) SDL_Swap16(X)
+#define SDL_SwapBE32(X) SDL_Swap32(X)
+#define SDL_SwapBE64(X) SDL_Swap64(X)
+#define SDL_SwapFloatBE(X) SDL_SwapFloat(X)
+#else
+#define SDL_SwapLE16(X) SDL_Swap16(X)
+#define SDL_SwapLE32(X) SDL_Swap32(X)
+#define SDL_SwapLE64(X) SDL_Swap64(X)
+#define SDL_SwapFloatLE(X) SDL_SwapFloat(X)
+#define SDL_SwapBE16(X) (X)
+#define SDL_SwapBE32(X) (X)
+#define SDL_SwapBE64(X) (X)
+#define SDL_SwapFloatBE(X) (X)
+#endif
+/* @} *//* Swap to native */
+
+/* Ends C function definitions when using C++ */
+#ifdef __cplusplus
+}
+#endif
+#include
+
+#endif /* SDL_endian_h_ */
+
+/* vi: set ts=4 sw=4 expandtab: */
diff --git a/bindings/sdl2wgpu/src/main/headers/SDL2/SDL_error.h b/bindings/sdl2wgpu/src/main/headers/SDL2/SDL_error.h
new file mode 100644
index 00000000..0cf4f6d7
--- /dev/null
+++ b/bindings/sdl2wgpu/src/main/headers/SDL2/SDL_error.h
@@ -0,0 +1,163 @@
+/*
+ Simple DirectMedia Layer
+ Copyright (C) 1997-2023 Sam Lantinga
+
+ This software is provided 'as-is', without any express or implied
+ warranty. In no event will the authors be held liable for any damages
+ arising from the use of this software.
+
+ Permission is granted to anyone to use this software for any purpose,
+ including commercial applications, and to alter it and redistribute it
+ freely, subject to the following restrictions:
+
+ 1. The origin of this software must not be misrepresented; you must not
+ claim that you wrote the original software. If you use this software
+ in a product, an acknowledgment in the product documentation would be
+ appreciated but is not required.
+ 2. Altered source versions must be plainly marked as such, and must not be
+ misrepresented as being the original software.
+ 3. This notice may not be removed or altered from any source distribution.
+*/
+
+/**
+ * \file SDL_error.h
+ *
+ * Simple error message routines for SDL.
+ */
+
+#ifndef SDL_error_h_
+#define SDL_error_h_
+
+#include
+
+#include
+/* Set up for C function definitions, even when using C++ */
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* Public functions */
+
+
+/**
+ * Set the SDL error message for the current thread.
+ *
+ * Calling this function will replace any previous error message that was set.
+ *
+ * This function always returns -1, since SDL frequently uses -1 to signify an
+ * failing result, leading to this idiom:
+ *
+ * ```c
+ * if (error_code) {
+ * return SDL_SetError("This operation has failed: %d", error_code);
+ * }
+ * ```
+ *
+ * \param fmt a printf()-style message format string
+ * \param ... additional parameters matching % tokens in the `fmt` string, if
+ * any
+ * \returns always -1.
+ *
+ * \since This function is available since SDL 2.0.0.
+ *
+ * \sa SDL_ClearError
+ * \sa SDL_GetError
+ */
+extern DECLSPEC int SDLCALL SDL_SetError(SDL_PRINTF_FORMAT_STRING const char *fmt, ...) SDL_PRINTF_VARARG_FUNC(1);
+
+/**
+ * Retrieve a message about the last error that occurred on the current
+ * thread.
+ *
+ * It is possible for multiple errors to occur before calling SDL_GetError().
+ * Only the last error is returned.
+ *
+ * The message is only applicable when an SDL function has signaled an error.
+ * You must check the return values of SDL function calls to determine when to
+ * appropriately call SDL_GetError(). You should *not* use the results of
+ * SDL_GetError() to decide if an error has occurred! Sometimes SDL will set
+ * an error string even when reporting success.
+ *
+ * SDL will *not* clear the error string for successful API calls. You *must*
+ * check return values for failure cases before you can assume the error
+ * string applies.
+ *
+ * Error strings are set per-thread, so an error set in a different thread
+ * will not interfere with the current thread's operation.
+ *
+ * The returned string is internally allocated and must not be freed by the
+ * application.
+ *
+ * \returns a message with information about the specific error that occurred,
+ * or an empty string if there hasn't been an error message set since
+ * the last call to SDL_ClearError(). The message is only applicable
+ * when an SDL function has signaled an error. You must check the
+ * return values of SDL function calls to determine when to
+ * appropriately call SDL_GetError().
+ *
+ * \since This function is available since SDL 2.0.0.
+ *
+ * \sa SDL_ClearError
+ * \sa SDL_SetError
+ */
+extern DECLSPEC const char *SDLCALL SDL_GetError(void);
+
+/**
+ * Get the last error message that was set for the current thread.
+ *
+ * This allows the caller to copy the error string into a provided buffer, but
+ * otherwise operates exactly the same as SDL_GetError().
+ *
+ * \param errstr A buffer to fill with the last error message that was set for
+ * the current thread
+ * \param maxlen The size of the buffer pointed to by the errstr parameter
+ * \returns the pointer passed in as the `errstr` parameter.
+ *
+ * \since This function is available since SDL 2.0.14.
+ *
+ * \sa SDL_GetError
+ */
+extern DECLSPEC char * SDLCALL SDL_GetErrorMsg(char *errstr, int maxlen);
+
+/**
+ * Clear any previous error message for this thread.
+ *
+ * \since This function is available since SDL 2.0.0.
+ *
+ * \sa SDL_GetError
+ * \sa SDL_SetError
+ */
+extern DECLSPEC void SDLCALL SDL_ClearError(void);
+
+/**
+ * \name Internal error functions
+ *
+ * \internal
+ * Private error reporting function - used internally.
+ */
+/* @{ */
+#define SDL_OutOfMemory() SDL_Error(SDL_ENOMEM)
+#define SDL_Unsupported() SDL_Error(SDL_UNSUPPORTED)
+#define SDL_InvalidParamError(param) SDL_SetError("Parameter '%s' is invalid", (param))
+typedef enum
+{
+ SDL_ENOMEM,
+ SDL_EFREAD,
+ SDL_EFWRITE,
+ SDL_EFSEEK,
+ SDL_UNSUPPORTED,
+ SDL_LASTERROR
+} SDL_errorcode;
+/* SDL_Error() unconditionally returns -1. */
+extern DECLSPEC int SDLCALL SDL_Error(SDL_errorcode code);
+/* @} *//* Internal error functions */
+
+/* Ends C function definitions when using C++ */
+#ifdef __cplusplus
+}
+#endif
+#include
+
+#endif /* SDL_error_h_ */
+
+/* vi: set ts=4 sw=4 expandtab: */
diff --git a/bindings/sdl2wgpu/src/main/headers/SDL2/SDL_events.h b/bindings/sdl2wgpu/src/main/headers/SDL2/SDL_events.h
new file mode 100644
index 00000000..9b2ca2a3
--- /dev/null
+++ b/bindings/sdl2wgpu/src/main/headers/SDL2/SDL_events.h
@@ -0,0 +1,1166 @@
+/*
+ Simple DirectMedia Layer
+ Copyright (C) 1997-2023 Sam Lantinga
+
+ This software is provided 'as-is', without any express or implied
+ warranty. In no event will the authors be held liable for any damages
+ arising from the use of this software.
+
+ Permission is granted to anyone to use this software for any purpose,
+ including commercial applications, and to alter it and redistribute it
+ freely, subject to the following restrictions:
+
+ 1. The origin of this software must not be misrepresented; you must not
+ claim that you wrote the original software. If you use this software
+ in a product, an acknowledgment in the product documentation would be
+ appreciated but is not required.
+ 2. Altered source versions must be plainly marked as such, and must not be
+ misrepresented as being the original software.
+ 3. This notice may not be removed or altered from any source distribution.
+*/
+
+/**
+ * \file SDL_events.h
+ *
+ * Include file for SDL event handling.
+ */
+
+#ifndef SDL_events_h_
+#define SDL_events_h_
+
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+
+#include
+/* Set up for C function definitions, even when using C++ */
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* General keyboard/mouse state definitions */
+#define SDL_RELEASED 0
+#define SDL_PRESSED 1
+
+/**
+ * The types of events that can be delivered.
+ */
+typedef enum
+{
+ SDL_FIRSTEVENT = 0, /**< Unused (do not remove) */
+
+ /* Application events */
+ SDL_QUIT = 0x100, /**< User-requested quit */
+
+ /* These application events have special meaning on iOS, see README-ios.md for details */
+ SDL_APP_TERMINATING, /**< The application is being terminated by the OS
+ Called on iOS in applicationWillTerminate()
+ Called on Android in onDestroy()
+ */
+ SDL_APP_LOWMEMORY, /**< The application is low on memory, free memory if possible.
+ Called on iOS in applicationDidReceiveMemoryWarning()
+ Called on Android in onLowMemory()
+ */
+ SDL_APP_WILLENTERBACKGROUND, /**< The application is about to enter the background
+ Called on iOS in applicationWillResignActive()
+ Called on Android in onPause()
+ */
+ SDL_APP_DIDENTERBACKGROUND, /**< The application did enter the background and may not get CPU for some time
+ Called on iOS in applicationDidEnterBackground()
+ Called on Android in onPause()
+ */
+ SDL_APP_WILLENTERFOREGROUND, /**< The application is about to enter the foreground
+ Called on iOS in applicationWillEnterForeground()
+ Called on Android in onResume()
+ */
+ SDL_APP_DIDENTERFOREGROUND, /**< The application is now interactive
+ Called on iOS in applicationDidBecomeActive()
+ Called on Android in onResume()
+ */
+
+ SDL_LOCALECHANGED, /**< The user's locale preferences have changed. */
+
+ /* Display events */
+ SDL_DISPLAYEVENT = 0x150, /**< Display state change */
+
+ /* Window events */
+ SDL_WINDOWEVENT = 0x200, /**< Window state change */
+ SDL_SYSWMEVENT, /**< System specific event */
+
+ /* Keyboard events */
+ SDL_KEYDOWN = 0x300, /**< Key pressed */
+ SDL_KEYUP, /**< Key released */
+ SDL_TEXTEDITING, /**< Keyboard text editing (composition) */
+ SDL_TEXTINPUT, /**< Keyboard text input */
+ SDL_KEYMAPCHANGED, /**< Keymap changed due to a system event such as an
+ input language or keyboard layout change.
+ */
+ SDL_TEXTEDITING_EXT, /**< Extended keyboard text editing (composition) */
+
+ /* Mouse events */
+ SDL_MOUSEMOTION = 0x400, /**< Mouse moved */
+ SDL_MOUSEBUTTONDOWN, /**< Mouse button pressed */
+ SDL_MOUSEBUTTONUP, /**< Mouse button released */
+ SDL_MOUSEWHEEL, /**< Mouse wheel motion */
+
+ /* Joystick events */
+ SDL_JOYAXISMOTION = 0x600, /**< Joystick axis motion */
+ SDL_JOYBALLMOTION, /**< Joystick trackball motion */
+ SDL_JOYHATMOTION, /**< Joystick hat position change */
+ SDL_JOYBUTTONDOWN, /**< Joystick button pressed */
+ SDL_JOYBUTTONUP, /**< Joystick button released */
+ SDL_JOYDEVICEADDED, /**< A new joystick has been inserted into the system */
+ SDL_JOYDEVICEREMOVED, /**< An opened joystick has been removed */
+ SDL_JOYBATTERYUPDATED, /**< Joystick battery level change */
+
+ /* Game controller events */
+ SDL_CONTROLLERAXISMOTION = 0x650, /**< Game controller axis motion */
+ SDL_CONTROLLERBUTTONDOWN, /**< Game controller button pressed */
+ SDL_CONTROLLERBUTTONUP, /**< Game controller button released */
+ SDL_CONTROLLERDEVICEADDED, /**< A new Game controller has been inserted into the system */
+ SDL_CONTROLLERDEVICEREMOVED, /**< An opened Game controller has been removed */
+ SDL_CONTROLLERDEVICEREMAPPED, /**< The controller mapping was updated */
+ SDL_CONTROLLERTOUCHPADDOWN, /**< Game controller touchpad was touched */
+ SDL_CONTROLLERTOUCHPADMOTION, /**< Game controller touchpad finger was moved */
+ SDL_CONTROLLERTOUCHPADUP, /**< Game controller touchpad finger was lifted */
+ SDL_CONTROLLERSENSORUPDATE, /**< Game controller sensor was updated */
+
+ /* Touch events */
+ SDL_FINGERDOWN = 0x700,
+ SDL_FINGERUP,
+ SDL_FINGERMOTION,
+
+ /* Gesture events */
+ SDL_DOLLARGESTURE = 0x800,
+ SDL_DOLLARRECORD,
+ SDL_MULTIGESTURE,
+
+ /* Clipboard events */
+ SDL_CLIPBOARDUPDATE = 0x900, /**< The clipboard or primary selection changed */
+
+ /* Drag and drop events */
+ SDL_DROPFILE = 0x1000, /**< The system requests a file open */
+ SDL_DROPTEXT, /**< text/plain drag-and-drop event */
+ SDL_DROPBEGIN, /**< A new set of drops is beginning (NULL filename) */
+ SDL_DROPCOMPLETE, /**< Current set of drops is now complete (NULL filename) */
+
+ /* Audio hotplug events */
+ SDL_AUDIODEVICEADDED = 0x1100, /**< A new audio device is available */
+ SDL_AUDIODEVICEREMOVED, /**< An audio device has been removed. */
+
+ /* Sensor events */
+ SDL_SENSORUPDATE = 0x1200, /**< A sensor was updated */
+
+ /* Render events */
+ SDL_RENDER_TARGETS_RESET = 0x2000, /**< The render targets have been reset and their contents need to be updated */
+ SDL_RENDER_DEVICE_RESET, /**< The device has been reset and all textures need to be recreated */
+
+ /* Internal events */
+ SDL_POLLSENTINEL = 0x7F00, /**< Signals the end of an event poll cycle */
+
+ /** Events ::SDL_USEREVENT through ::SDL_LASTEVENT are for your use,
+ * and should be allocated with SDL_RegisterEvents()
+ */
+ SDL_USEREVENT = 0x8000,
+
+ /**
+ * This last event is only for bounding internal arrays
+ */
+ SDL_LASTEVENT = 0xFFFF
+} SDL_EventType;
+
+/**
+ * \brief Fields shared by every event
+ */
+typedef struct SDL_CommonEvent
+{
+ Uint32 type;
+ Uint32 timestamp; /**< In milliseconds, populated using SDL_GetTicks() */
+} SDL_CommonEvent;
+
+/**
+ * \brief Display state change event data (event.display.*)
+ */
+typedef struct SDL_DisplayEvent
+{
+ Uint32 type; /**< ::SDL_DISPLAYEVENT */
+ Uint32 timestamp; /**< In milliseconds, populated using SDL_GetTicks() */
+ Uint32 display; /**< The associated display index */
+ Uint8 event; /**< ::SDL_DisplayEventID */
+ Uint8 padding1;
+ Uint8 padding2;
+ Uint8 padding3;
+ Sint32 data1; /**< event dependent data */
+} SDL_DisplayEvent;
+
+/**
+ * \brief Window state change event data (event.window.*)
+ */
+typedef struct SDL_WindowEvent
+{
+ Uint32 type; /**< ::SDL_WINDOWEVENT */
+ Uint32 timestamp; /**< In milliseconds, populated using SDL_GetTicks() */
+ Uint32 windowID; /**< The associated window */
+ Uint8 event; /**< ::SDL_WindowEventID */
+ Uint8 padding1;
+ Uint8 padding2;
+ Uint8 padding3;
+ Sint32 data1; /**< event dependent data */
+ Sint32 data2; /**< event dependent data */
+} SDL_WindowEvent;
+
+/**
+ * \brief Keyboard button event structure (event.key.*)
+ */
+typedef struct SDL_KeyboardEvent
+{
+ Uint32 type; /**< ::SDL_KEYDOWN or ::SDL_KEYUP */
+ Uint32 timestamp; /**< In milliseconds, populated using SDL_GetTicks() */
+ Uint32 windowID; /**< The window with keyboard focus, if any */
+ Uint8 state; /**< ::SDL_PRESSED or ::SDL_RELEASED */
+ Uint8 repeat; /**< Non-zero if this is a key repeat */
+ Uint8 padding2;
+ Uint8 padding3;
+ SDL_Keysym keysym; /**< The key that was pressed or released */
+} SDL_KeyboardEvent;
+
+#define SDL_TEXTEDITINGEVENT_TEXT_SIZE (32)
+/**
+ * \brief Keyboard text editing event structure (event.edit.*)
+ */
+typedef struct SDL_TextEditingEvent
+{
+ Uint32 type; /**< ::SDL_TEXTEDITING */
+ Uint32 timestamp; /**< In milliseconds, populated using SDL_GetTicks() */
+ Uint32 windowID; /**< The window with keyboard focus, if any */
+ char text[SDL_TEXTEDITINGEVENT_TEXT_SIZE]; /**< The editing text */
+ Sint32 start; /**< The start cursor of selected editing text */
+ Sint32 length; /**< The length of selected editing text */
+} SDL_TextEditingEvent;
+
+/**
+ * \brief Extended keyboard text editing event structure (event.editExt.*) when text would be
+ * truncated if stored in the text buffer SDL_TextEditingEvent
+ */
+typedef struct SDL_TextEditingExtEvent
+{
+ Uint32 type; /**< ::SDL_TEXTEDITING_EXT */
+ Uint32 timestamp; /**< In milliseconds, populated using SDL_GetTicks() */
+ Uint32 windowID; /**< The window with keyboard focus, if any */
+ char* text; /**< The editing text, which should be freed with SDL_free(), and will not be NULL */
+ Sint32 start; /**< The start cursor of selected editing text */
+ Sint32 length; /**< The length of selected editing text */
+} SDL_TextEditingExtEvent;
+
+#define SDL_TEXTINPUTEVENT_TEXT_SIZE (32)
+/**
+ * \brief Keyboard text input event structure (event.text.*)
+ */
+typedef struct SDL_TextInputEvent
+{
+ Uint32 type; /**< ::SDL_TEXTINPUT */
+ Uint32 timestamp; /**< In milliseconds, populated using SDL_GetTicks() */
+ Uint32 windowID; /**< The window with keyboard focus, if any */
+ char text[SDL_TEXTINPUTEVENT_TEXT_SIZE]; /**< The input text */
+} SDL_TextInputEvent;
+
+/**
+ * \brief Mouse motion event structure (event.motion.*)
+ */
+typedef struct SDL_MouseMotionEvent
+{
+ Uint32 type; /**< ::SDL_MOUSEMOTION */
+ Uint32 timestamp; /**< In milliseconds, populated using SDL_GetTicks() */
+ Uint32 windowID; /**< The window with mouse focus, if any */
+ Uint32 which; /**< The mouse instance id, or SDL_TOUCH_MOUSEID */
+ Uint32 state; /**< The current button state */
+ Sint32 x; /**< X coordinate, relative to window */
+ Sint32 y; /**< Y coordinate, relative to window */
+ Sint32 xrel; /**< The relative motion in the X direction */
+ Sint32 yrel; /**< The relative motion in the Y direction */
+} SDL_MouseMotionEvent;
+
+/**
+ * \brief Mouse button event structure (event.button.*)
+ */
+typedef struct SDL_MouseButtonEvent
+{
+ Uint32 type; /**< ::SDL_MOUSEBUTTONDOWN or ::SDL_MOUSEBUTTONUP */
+ Uint32 timestamp; /**< In milliseconds, populated using SDL_GetTicks() */
+ Uint32 windowID; /**< The window with mouse focus, if any */
+ Uint32 which; /**< The mouse instance id, or SDL_TOUCH_MOUSEID */
+ Uint8 button; /**< The mouse button index */
+ Uint8 state; /**< ::SDL_PRESSED or ::SDL_RELEASED */
+ Uint8 clicks; /**< 1 for single-click, 2 for double-click, etc. */
+ Uint8 padding1;
+ Sint32 x; /**< X coordinate, relative to window */
+ Sint32 y; /**< Y coordinate, relative to window */
+} SDL_MouseButtonEvent;
+
+/**
+ * \brief Mouse wheel event structure (event.wheel.*)
+ */
+typedef struct SDL_MouseWheelEvent
+{
+ Uint32 type; /**< ::SDL_MOUSEWHEEL */
+ Uint32 timestamp; /**< In milliseconds, populated using SDL_GetTicks() */
+ Uint32 windowID; /**< The window with mouse focus, if any */
+ Uint32 which; /**< The mouse instance id, or SDL_TOUCH_MOUSEID */
+ Sint32 x; /**< The amount scrolled horizontally, positive to the right and negative to the left */
+ Sint32 y; /**< The amount scrolled vertically, positive away from the user and negative toward the user */
+ Uint32 direction; /**< Set to one of the SDL_MOUSEWHEEL_* defines. When FLIPPED the values in X and Y will be opposite. Multiply by -1 to change them back */
+ float preciseX; /**< The amount scrolled horizontally, positive to the right and negative to the left, with float precision (added in 2.0.18) */
+ float preciseY; /**< The amount scrolled vertically, positive away from the user and negative toward the user, with float precision (added in 2.0.18) */
+ Sint32 mouseX; /**< X coordinate, relative to window (added in 2.26.0) */
+ Sint32 mouseY; /**< Y coordinate, relative to window (added in 2.26.0) */
+} SDL_MouseWheelEvent;
+
+/**
+ * \brief Joystick axis motion event structure (event.jaxis.*)
+ */
+typedef struct SDL_JoyAxisEvent
+{
+ Uint32 type; /**< ::SDL_JOYAXISMOTION */
+ Uint32 timestamp; /**< In milliseconds, populated using SDL_GetTicks() */
+ SDL_JoystickID which; /**< The joystick instance id */
+ Uint8 axis; /**< The joystick axis index */
+ Uint8 padding1;
+ Uint8 padding2;
+ Uint8 padding3;
+ Sint16 value; /**< The axis value (range: -32768 to 32767) */
+ Uint16 padding4;
+} SDL_JoyAxisEvent;
+
+/**
+ * \brief Joystick trackball motion event structure (event.jball.*)
+ */
+typedef struct SDL_JoyBallEvent
+{
+ Uint32 type; /**< ::SDL_JOYBALLMOTION */
+ Uint32 timestamp; /**< In milliseconds, populated using SDL_GetTicks() */
+ SDL_JoystickID which; /**< The joystick instance id */
+ Uint8 ball; /**< The joystick trackball index */
+ Uint8 padding1;
+ Uint8 padding2;
+ Uint8 padding3;
+ Sint16 xrel; /**< The relative motion in the X direction */
+ Sint16 yrel; /**< The relative motion in the Y direction */
+} SDL_JoyBallEvent;
+
+/**
+ * \brief Joystick hat position change event structure (event.jhat.*)
+ */
+typedef struct SDL_JoyHatEvent
+{
+ Uint32 type; /**< ::SDL_JOYHATMOTION */
+ Uint32 timestamp; /**< In milliseconds, populated using SDL_GetTicks() */
+ SDL_JoystickID which; /**< The joystick instance id */
+ Uint8 hat; /**< The joystick hat index */
+ Uint8 value; /**< The hat position value.
+ * \sa ::SDL_HAT_LEFTUP ::SDL_HAT_UP ::SDL_HAT_RIGHTUP
+ * \sa ::SDL_HAT_LEFT ::SDL_HAT_CENTERED ::SDL_HAT_RIGHT
+ * \sa ::SDL_HAT_LEFTDOWN ::SDL_HAT_DOWN ::SDL_HAT_RIGHTDOWN
+ *
+ * Note that zero means the POV is centered.
+ */
+ Uint8 padding1;
+ Uint8 padding2;
+} SDL_JoyHatEvent;
+
+/**
+ * \brief Joystick button event structure (event.jbutton.*)
+ */
+typedef struct SDL_JoyButtonEvent
+{
+ Uint32 type; /**< ::SDL_JOYBUTTONDOWN or ::SDL_JOYBUTTONUP */
+ Uint32 timestamp; /**< In milliseconds, populated using SDL_GetTicks() */
+ SDL_JoystickID which; /**< The joystick instance id */
+ Uint8 button; /**< The joystick button index */
+ Uint8 state; /**< ::SDL_PRESSED or ::SDL_RELEASED */
+ Uint8 padding1;
+ Uint8 padding2;
+} SDL_JoyButtonEvent;
+
+/**
+ * \brief Joystick device event structure (event.jdevice.*)
+ */
+typedef struct SDL_JoyDeviceEvent
+{
+ Uint32 type; /**< ::SDL_JOYDEVICEADDED or ::SDL_JOYDEVICEREMOVED */
+ Uint32 timestamp; /**< In milliseconds, populated using SDL_GetTicks() */
+ Sint32 which; /**< The joystick device index for the ADDED event, instance id for the REMOVED event */
+} SDL_JoyDeviceEvent;
+
+/**
+ * \brief Joysick battery level change event structure (event.jbattery.*)
+ */
+typedef struct SDL_JoyBatteryEvent
+{
+ Uint32 type; /**< ::SDL_JOYBATTERYUPDATED */
+ Uint32 timestamp; /**< In milliseconds, populated using SDL_GetTicks() */
+ SDL_JoystickID which; /**< The joystick instance id */
+ SDL_JoystickPowerLevel level; /**< The joystick battery level */
+} SDL_JoyBatteryEvent;
+
+/**
+ * \brief Game controller axis motion event structure (event.caxis.*)
+ */
+typedef struct SDL_ControllerAxisEvent
+{
+ Uint32 type; /**< ::SDL_CONTROLLERAXISMOTION */
+ Uint32 timestamp; /**< In milliseconds, populated using SDL_GetTicks() */
+ SDL_JoystickID which; /**< The joystick instance id */
+ Uint8 axis; /**< The controller axis (SDL_GameControllerAxis) */
+ Uint8 padding1;
+ Uint8 padding2;
+ Uint8 padding3;
+ Sint16 value; /**< The axis value (range: -32768 to 32767) */
+ Uint16 padding4;
+} SDL_ControllerAxisEvent;
+
+
+/**
+ * \brief Game controller button event structure (event.cbutton.*)
+ */
+typedef struct SDL_ControllerButtonEvent
+{
+ Uint32 type; /**< ::SDL_CONTROLLERBUTTONDOWN or ::SDL_CONTROLLERBUTTONUP */
+ Uint32 timestamp; /**< In milliseconds, populated using SDL_GetTicks() */
+ SDL_JoystickID which; /**< The joystick instance id */
+ Uint8 button; /**< The controller button (SDL_GameControllerButton) */
+ Uint8 state; /**< ::SDL_PRESSED or ::SDL_RELEASED */
+ Uint8 padding1;
+ Uint8 padding2;
+} SDL_ControllerButtonEvent;
+
+
+/**
+ * \brief Controller device event structure (event.cdevice.*)
+ */
+typedef struct SDL_ControllerDeviceEvent
+{
+ Uint32 type; /**< ::SDL_CONTROLLERDEVICEADDED, ::SDL_CONTROLLERDEVICEREMOVED, or ::SDL_CONTROLLERDEVICEREMAPPED */
+ Uint32 timestamp; /**< In milliseconds, populated using SDL_GetTicks() */
+ Sint32 which; /**< The joystick device index for the ADDED event, instance id for the REMOVED or REMAPPED event */
+} SDL_ControllerDeviceEvent;
+
+/**
+ * \brief Game controller touchpad event structure (event.ctouchpad.*)
+ */
+typedef struct SDL_ControllerTouchpadEvent
+{
+ Uint32 type; /**< ::SDL_CONTROLLERTOUCHPADDOWN or ::SDL_CONTROLLERTOUCHPADMOTION or ::SDL_CONTROLLERTOUCHPADUP */
+ Uint32 timestamp; /**< In milliseconds, populated using SDL_GetTicks() */
+ SDL_JoystickID which; /**< The joystick instance id */
+ Sint32 touchpad; /**< The index of the touchpad */
+ Sint32 finger; /**< The index of the finger on the touchpad */
+ float x; /**< Normalized in the range 0...1 with 0 being on the left */
+ float y; /**< Normalized in the range 0...1 with 0 being at the top */
+ float pressure; /**< Normalized in the range 0...1 */
+} SDL_ControllerTouchpadEvent;
+
+/**
+ * \brief Game controller sensor event structure (event.csensor.*)
+ */
+typedef struct SDL_ControllerSensorEvent
+{
+ Uint32 type; /**< ::SDL_CONTROLLERSENSORUPDATE */
+ Uint32 timestamp; /**< In milliseconds, populated using SDL_GetTicks() */
+ SDL_JoystickID which; /**< The joystick instance id */
+ Sint32 sensor; /**< The type of the sensor, one of the values of ::SDL_SensorType */
+ float data[3]; /**< Up to 3 values from the sensor, as defined in SDL_sensor.h */
+ Uint64 timestamp_us; /**< The timestamp of the sensor reading in microseconds, if the hardware provides this information. */
+} SDL_ControllerSensorEvent;
+
+/**
+ * \brief Audio device event structure (event.adevice.*)
+ */
+typedef struct SDL_AudioDeviceEvent
+{
+ Uint32 type; /**< ::SDL_AUDIODEVICEADDED, or ::SDL_AUDIODEVICEREMOVED */
+ Uint32 timestamp; /**< In milliseconds, populated using SDL_GetTicks() */
+ Uint32 which; /**< The audio device index for the ADDED event (valid until next SDL_GetNumAudioDevices() call), SDL_AudioDeviceID for the REMOVED event */
+ Uint8 iscapture; /**< zero if an output device, non-zero if a capture device. */
+ Uint8 padding1;
+ Uint8 padding2;
+ Uint8 padding3;
+} SDL_AudioDeviceEvent;
+
+
+/**
+ * \brief Touch finger event structure (event.tfinger.*)
+ */
+typedef struct SDL_TouchFingerEvent
+{
+ Uint32 type; /**< ::SDL_FINGERMOTION or ::SDL_FINGERDOWN or ::SDL_FINGERUP */
+ Uint32 timestamp; /**< In milliseconds, populated using SDL_GetTicks() */
+ SDL_TouchID touchId; /**< The touch device id */
+ SDL_FingerID fingerId;
+ float x; /**< Normalized in the range 0...1 */
+ float y; /**< Normalized in the range 0...1 */
+ float dx; /**< Normalized in the range -1...1 */
+ float dy; /**< Normalized in the range -1...1 */
+ float pressure; /**< Normalized in the range 0...1 */
+ Uint32 windowID; /**< The window underneath the finger, if any */
+} SDL_TouchFingerEvent;
+
+
+/**
+ * \brief Multiple Finger Gesture Event (event.mgesture.*)
+ */
+typedef struct SDL_MultiGestureEvent
+{
+ Uint32 type; /**< ::SDL_MULTIGESTURE */
+ Uint32 timestamp; /**< In milliseconds, populated using SDL_GetTicks() */
+ SDL_TouchID touchId; /**< The touch device id */
+ float dTheta;
+ float dDist;
+ float x;
+ float y;
+ Uint16 numFingers;
+ Uint16 padding;
+} SDL_MultiGestureEvent;
+
+
+/**
+ * \brief Dollar Gesture Event (event.dgesture.*)
+ */
+typedef struct SDL_DollarGestureEvent
+{
+ Uint32 type; /**< ::SDL_DOLLARGESTURE or ::SDL_DOLLARRECORD */
+ Uint32 timestamp; /**< In milliseconds, populated using SDL_GetTicks() */
+ SDL_TouchID touchId; /**< The touch device id */
+ SDL_GestureID gestureId;
+ Uint32 numFingers;
+ float error;
+ float x; /**< Normalized center of gesture */
+ float y; /**< Normalized center of gesture */
+} SDL_DollarGestureEvent;
+
+
+/**
+ * \brief An event used to request a file open by the system (event.drop.*)
+ * This event is enabled by default, you can disable it with SDL_EventState().
+ * \note If this event is enabled, you must free the filename in the event.
+ */
+typedef struct SDL_DropEvent
+{
+ Uint32 type; /**< ::SDL_DROPBEGIN or ::SDL_DROPFILE or ::SDL_DROPTEXT or ::SDL_DROPCOMPLETE */
+ Uint32 timestamp; /**< In milliseconds, populated using SDL_GetTicks() */
+ char *file; /**< The file name, which should be freed with SDL_free(), is NULL on begin/complete */
+ Uint32 windowID; /**< The window that was dropped on, if any */
+} SDL_DropEvent;
+
+
+/**
+ * \brief Sensor event structure (event.sensor.*)
+ */
+typedef struct SDL_SensorEvent
+{
+ Uint32 type; /**< ::SDL_SENSORUPDATE */
+ Uint32 timestamp; /**< In milliseconds, populated using SDL_GetTicks() */
+ Sint32 which; /**< The instance ID of the sensor */
+ float data[6]; /**< Up to 6 values from the sensor - additional values can be queried using SDL_SensorGetData() */
+ Uint64 timestamp_us; /**< The timestamp of the sensor reading in microseconds, if the hardware provides this information. */
+} SDL_SensorEvent;
+
+/**
+ * \brief The "quit requested" event
+ */
+typedef struct SDL_QuitEvent
+{
+ Uint32 type; /**< ::SDL_QUIT */
+ Uint32 timestamp; /**< In milliseconds, populated using SDL_GetTicks() */
+} SDL_QuitEvent;
+
+/**
+ * \brief OS Specific event
+ */
+typedef struct SDL_OSEvent
+{
+ Uint32 type; /**< ::SDL_QUIT */
+ Uint32 timestamp; /**< In milliseconds, populated using SDL_GetTicks() */
+} SDL_OSEvent;
+
+/**
+ * \brief A user-defined event type (event.user.*)
+ */
+typedef struct SDL_UserEvent
+{
+ Uint32 type; /**< ::SDL_USEREVENT through ::SDL_LASTEVENT-1 */
+ Uint32 timestamp; /**< In milliseconds, populated using SDL_GetTicks() */
+ Uint32 windowID; /**< The associated window if any */
+ Sint32 code; /**< User defined event code */
+ void *data1; /**< User defined data pointer */
+ void *data2; /**< User defined data pointer */
+} SDL_UserEvent;
+
+
+struct SDL_SysWMmsg;
+typedef struct SDL_SysWMmsg SDL_SysWMmsg;
+
+/**
+ * \brief A video driver dependent system event (event.syswm.*)
+ * This event is disabled by default, you can enable it with SDL_EventState()
+ *
+ * \note If you want to use this event, you should include SDL_syswm.h.
+ */
+typedef struct SDL_SysWMEvent
+{
+ Uint32 type; /**< ::SDL_SYSWMEVENT */
+ Uint32 timestamp; /**< In milliseconds, populated using SDL_GetTicks() */
+ SDL_SysWMmsg *msg; /**< driver dependent data, defined in SDL_syswm.h */
+} SDL_SysWMEvent;
+
+/**
+ * \brief General event structure
+ */
+typedef union SDL_Event
+{
+ Uint32 type; /**< Event type, shared with all events */
+ SDL_CommonEvent common; /**< Common event data */
+ SDL_DisplayEvent display; /**< Display event data */
+ SDL_WindowEvent window; /**< Window event data */
+ SDL_KeyboardEvent key; /**< Keyboard event data */
+ SDL_TextEditingEvent edit; /**< Text editing event data */
+ SDL_TextEditingExtEvent editExt; /**< Extended text editing event data */
+ SDL_TextInputEvent text; /**< Text input event data */
+ SDL_MouseMotionEvent motion; /**< Mouse motion event data */
+ SDL_MouseButtonEvent button; /**< Mouse button event data */
+ SDL_MouseWheelEvent wheel; /**< Mouse wheel event data */
+ SDL_JoyAxisEvent jaxis; /**< Joystick axis event data */
+ SDL_JoyBallEvent jball; /**< Joystick ball event data */
+ SDL_JoyHatEvent jhat; /**< Joystick hat event data */
+ SDL_JoyButtonEvent jbutton; /**< Joystick button event data */
+ SDL_JoyDeviceEvent jdevice; /**< Joystick device change event data */
+ SDL_JoyBatteryEvent jbattery; /**< Joystick battery event data */
+ SDL_ControllerAxisEvent caxis; /**< Game Controller axis event data */
+ SDL_ControllerButtonEvent cbutton; /**< Game Controller button event data */
+ SDL_ControllerDeviceEvent cdevice; /**< Game Controller device event data */
+ SDL_ControllerTouchpadEvent ctouchpad; /**< Game Controller touchpad event data */
+ SDL_ControllerSensorEvent csensor; /**< Game Controller sensor event data */
+ SDL_AudioDeviceEvent adevice; /**< Audio device event data */
+ SDL_SensorEvent sensor; /**< Sensor event data */
+ SDL_QuitEvent quit; /**< Quit request event data */
+ SDL_UserEvent user; /**< Custom event data */
+ SDL_SysWMEvent syswm; /**< System dependent window event data */
+ SDL_TouchFingerEvent tfinger; /**< Touch finger event data */
+ SDL_MultiGestureEvent mgesture; /**< Gesture event data */
+ SDL_DollarGestureEvent dgesture; /**< Gesture event data */
+ SDL_DropEvent drop; /**< Drag and drop event data */
+
+ /* This is necessary for ABI compatibility between Visual C++ and GCC.
+ Visual C++ will respect the push pack pragma and use 52 bytes (size of
+ SDL_TextEditingEvent, the largest structure for 32-bit and 64-bit
+ architectures) for this union, and GCC will use the alignment of the
+ largest datatype within the union, which is 8 bytes on 64-bit
+ architectures.
+
+ So... we'll add padding to force the size to be 56 bytes for both.
+
+ On architectures where pointers are 16 bytes, this needs rounding up to
+ the next multiple of 16, 64, and on architectures where pointers are
+ even larger the size of SDL_UserEvent will dominate as being 3 pointers.
+ */
+ Uint8 padding[sizeof(void *) <= 8 ? 56 : sizeof(void *) == 16 ? 64 : 3 * sizeof(void *)];
+} SDL_Event;
+
+/* Make sure we haven't broken binary compatibility */
+SDL_COMPILE_TIME_ASSERT(SDL_Event, sizeof(SDL_Event) == sizeof(((SDL_Event *)NULL)->padding));
+
+
+/* Function prototypes */
+
+/**
+ * Pump the event loop, gathering events from the input devices.
+ *
+ * This function updates the event queue and internal input device state.
+ *
+ * **WARNING**: This should only be run in the thread that initialized the
+ * video subsystem, and for extra safety, you should consider only doing those
+ * things on the main thread in any case.
+ *
+ * SDL_PumpEvents() gathers all the pending input information from devices and
+ * places it in the event queue. Without calls to SDL_PumpEvents() no events
+ * would ever be placed on the queue. Often the need for calls to
+ * SDL_PumpEvents() is hidden from the user since SDL_PollEvent() and
+ * SDL_WaitEvent() implicitly call SDL_PumpEvents(). However, if you are not
+ * polling or waiting for events (e.g. you are filtering them), then you must
+ * call SDL_PumpEvents() to force an event queue update.
+ *
+ * \since This function is available since SDL 2.0.0.
+ *
+ * \sa SDL_PollEvent
+ * \sa SDL_WaitEvent
+ */
+extern DECLSPEC void SDLCALL SDL_PumpEvents(void);
+
+/* @{ */
+typedef enum
+{
+ SDL_ADDEVENT,
+ SDL_PEEKEVENT,
+ SDL_GETEVENT
+} SDL_eventaction;
+
+/**
+ * Check the event queue for messages and optionally return them.
+ *
+ * `action` may be any of the following:
+ *
+ * - `SDL_ADDEVENT`: up to `numevents` events will be added to the back of the
+ * event queue.
+ * - `SDL_PEEKEVENT`: `numevents` events at the front of the event queue,
+ * within the specified minimum and maximum type, will be returned to the
+ * caller and will _not_ be removed from the queue.
+ * - `SDL_GETEVENT`: up to `numevents` events at the front of the event queue,
+ * within the specified minimum and maximum type, will be returned to the
+ * caller and will be removed from the queue.
+ *
+ * You may have to call SDL_PumpEvents() before calling this function.
+ * Otherwise, the events may not be ready to be filtered when you call
+ * SDL_PeepEvents().
+ *
+ * This function is thread-safe.
+ *
+ * \param events destination buffer for the retrieved events
+ * \param numevents if action is SDL_ADDEVENT, the number of events to add
+ * back to the event queue; if action is SDL_PEEKEVENT or
+ * SDL_GETEVENT, the maximum number of events to retrieve
+ * \param action action to take; see [[#action|Remarks]] for details
+ * \param minType minimum value of the event type to be considered;
+ * SDL_FIRSTEVENT is a safe choice
+ * \param maxType maximum value of the event type to be considered;
+ * SDL_LASTEVENT is a safe choice
+ * \returns the number of events actually stored or a negative error code on
+ * failure; call SDL_GetError() for more information.
+ *
+ * \since This function is available since SDL 2.0.0.
+ *
+ * \sa SDL_PollEvent
+ * \sa SDL_PumpEvents
+ * \sa SDL_PushEvent
+ */
+extern DECLSPEC int SDLCALL SDL_PeepEvents(SDL_Event * events, int numevents,
+ SDL_eventaction action,
+ Uint32 minType, Uint32 maxType);
+/* @} */
+
+/**
+ * Check for the existence of a certain event type in the event queue.
+ *
+ * If you need to check for a range of event types, use SDL_HasEvents()
+ * instead.
+ *
+ * \param type the type of event to be queried; see SDL_EventType for details
+ * \returns SDL_TRUE if events matching `type` are present, or SDL_FALSE if
+ * events matching `type` are not present.
+ *
+ * \since This function is available since SDL 2.0.0.
+ *
+ * \sa SDL_HasEvents
+ */
+extern DECLSPEC SDL_bool SDLCALL SDL_HasEvent(Uint32 type);
+
+
+/**
+ * Check for the existence of certain event types in the event queue.
+ *
+ * If you need to check for a single event type, use SDL_HasEvent() instead.
+ *
+ * \param minType the low end of event type to be queried, inclusive; see
+ * SDL_EventType for details
+ * \param maxType the high end of event type to be queried, inclusive; see
+ * SDL_EventType for details
+ * \returns SDL_TRUE if events with type >= `minType` and <= `maxType` are
+ * present, or SDL_FALSE if not.
+ *
+ * \since This function is available since SDL 2.0.0.
+ *
+ * \sa SDL_HasEvents
+ */
+extern DECLSPEC SDL_bool SDLCALL SDL_HasEvents(Uint32 minType, Uint32 maxType);
+
+/**
+ * Clear events of a specific type from the event queue.
+ *
+ * This will unconditionally remove any events from the queue that match
+ * `type`. If you need to remove a range of event types, use SDL_FlushEvents()
+ * instead.
+ *
+ * It's also normal to just ignore events you don't care about in your event
+ * loop without calling this function.
+ *
+ * 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.
+ *
+ * \param type the type of event to be cleared; see SDL_EventType for details
+ *
+ * \since This function is available since SDL 2.0.0.
+ *
+ * \sa SDL_FlushEvents
+ */
+extern DECLSPEC void SDLCALL SDL_FlushEvent(Uint32 type);
+
+/**
+ * Clear events of a range of types from the event queue.
+ *
+ * This will unconditionally remove any events from the queue that are in the
+ * range of `minType` to `maxType`, inclusive. If you need to remove a single
+ * event type, use SDL_FlushEvent() instead.
+ *
+ * It's also normal to just ignore events you don't care about in your event
+ * loop without calling this function.
+ *
+ * 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.
+ *
+ * \param minType the low end of event type to be cleared, inclusive; see
+ * SDL_EventType for details
+ * \param maxType the high end of event type to be cleared, inclusive; see
+ * SDL_EventType for details
+ *
+ * \since This function is available since SDL 2.0.0.
+ *
+ * \sa SDL_FlushEvent
+ */
+extern DECLSPEC void SDLCALL SDL_FlushEvents(Uint32 minType, Uint32 maxType);
+
+/**
+ * Poll for currently pending events.
+ *
+ * If `event` is not NULL, the next event is removed from the queue and stored
+ * in the SDL_Event structure pointed to by `event`. The 1 returned refers to
+ * this event, immediately stored in the SDL Event structure -- not an event
+ * to follow.
+ *
+ * If `event` is NULL, it simply returns 1 if there is an event in the queue,
+ * but will not remove it from the queue.
+ *
+ * As this function may implicitly call SDL_PumpEvents(), you can only call
+ * this function in the thread that set the video mode.
+ *
+ * SDL_PollEvent() is the favored way of receiving system events since it can
+ * be done from the main loop and does not suspend the main loop while waiting
+ * on an event to be posted.
+ *
+ * The common practice is to fully process the event queue once every frame,
+ * usually as a first step before updating the game's state:
+ *
+ * ```c
+ * while (game_is_still_running) {
+ * SDL_Event event;
+ * while (SDL_PollEvent(&event)) { // poll until all events are handled!
+ * // decide what to do with this event.
+ * }
+ *
+ * // update game state, draw the current frame
+ * }
+ * ```
+ *
+ * \param event the SDL_Event structure to be filled with the next event from
+ * the queue, or NULL
+ * \returns 1 if there is a pending event or 0 if there are none available.
+ *
+ * \since This function is available since SDL 2.0.0.
+ *
+ * \sa SDL_GetEventFilter
+ * \sa SDL_PeepEvents
+ * \sa SDL_PushEvent
+ * \sa SDL_SetEventFilter
+ * \sa SDL_WaitEvent
+ * \sa SDL_WaitEventTimeout
+ */
+extern DECLSPEC int SDLCALL SDL_PollEvent(SDL_Event * event);
+
+/**
+ * Wait indefinitely for the next available event.
+ *
+ * If `event` is not NULL, the next event is removed from the queue and stored
+ * in the SDL_Event structure pointed to by `event`.
+ *
+ * As this function may implicitly call SDL_PumpEvents(), you can only call
+ * this function in the thread that initialized the video subsystem.
+ *
+ * \param event the SDL_Event structure to be filled in with the next event
+ * from the queue, or NULL
+ * \returns 1 on success or 0 if there was an error while waiting for events;
+ * call SDL_GetError() for more information.
+ *
+ * \since This function is available since SDL 2.0.0.
+ *
+ * \sa SDL_PollEvent
+ * \sa SDL_PumpEvents
+ * \sa SDL_WaitEventTimeout
+ */
+extern DECLSPEC int SDLCALL SDL_WaitEvent(SDL_Event * event);
+
+/**
+ * Wait 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 the SDL_Event structure pointed to by `event`.
+ *
+ * As this function may implicitly call SDL_PumpEvents(), you can only call
+ * this function in the thread that initialized the video subsystem.
+ *
+ * \param event the SDL_Event structure to be filled in with the next event
+ * from the queue, or NULL
+ * \param timeout the maximum number of milliseconds to wait for the next
+ * available event
+ * \returns 1 on success or 0 if there was an error while waiting for events;
+ * call SDL_GetError() for more information. This also returns 0 if
+ * the timeout elapsed without an event arriving.
+ *
+ * \since This function is available since SDL 2.0.0.
+ *
+ * \sa SDL_PollEvent
+ * \sa SDL_PumpEvents
+ * \sa SDL_WaitEvent
+ */
+extern DECLSPEC int SDLCALL SDL_WaitEventTimeout(SDL_Event * event,
+ int timeout);
+
+/**
+ * Add an event to the event queue.
+ *
+ * The event queue can actually be used as a two way communication channel.
+ * Not only can events be read from the queue, but the user can also push
+ * their own events onto it. `event` is a pointer to the event structure you
+ * wish to push onto the queue. The event is copied into the queue, and the
+ * caller may dispose of the memory pointed to after SDL_PushEvent() returns.
+ *
+ * Note: Pushing device input events onto the queue doesn't modify the state
+ * of the device within SDL.
+ *
+ * This function is thread-safe, and can be called from other threads safely.
+ *
+ * Note: Events pushed onto the queue with SDL_PushEvent() get passed through
+ * the event filter but events added with SDL_PeepEvents() do not.
+ *
+ * For pushing application-specific events, please use SDL_RegisterEvents() to
+ * get an event type that does not conflict with other code that also wants
+ * its own custom event types.
+ *
+ * \param event the SDL_Event to be added to the queue
+ * \returns 1 on success, 0 if the event was filtered, or a negative error
+ * code on failure; call SDL_GetError() for more information. A
+ * common reason for error is the event queue being full.
+ *
+ * \since This function is available since SDL 2.0.0.
+ *
+ * \sa SDL_PeepEvents
+ * \sa SDL_PollEvent
+ * \sa SDL_RegisterEvents
+ */
+extern DECLSPEC int SDLCALL SDL_PushEvent(SDL_Event * event);
+
+/**
+ * A function pointer used for callbacks that watch the event queue.
+ *
+ * \param userdata what was passed as `userdata` to SDL_SetEventFilter()
+ * or SDL_AddEventWatch, etc
+ * \param event the event that triggered the callback
+ * \returns 1 to permit event to be added to the queue, and 0 to disallow
+ * it. When used with SDL_AddEventWatch, the return value is ignored.
+ *
+ * \sa SDL_SetEventFilter
+ * \sa SDL_AddEventWatch
+ */
+typedef int (SDLCALL * SDL_EventFilter) (void *userdata, SDL_Event * event);
+
+/**
+ * Set up a filter to process all events before they change internal state and
+ * are posted to the internal event queue.
+ *
+ * If the filter function returns 1 when called, then the event will be added
+ * to the internal queue. If it returns 0, then the event will be dropped from
+ * the queue, but the internal state will still be updated. This allows
+ * selective filtering of dynamically arriving events.
+ *
+ * **WARNING**: Be very careful of what you do in the event filter function,
+ * as it may run in a different thread!
+ *
+ * On platforms that support it, if the quit event is generated by an
+ * interrupt signal (e.g. pressing Ctrl-C), it will be delivered to the
+ * application at the next event poll.
+ *
+ * There is one caveat when dealing with the ::SDL_QuitEvent event type. The
+ * event filter is only called when the window manager desires to close the
+ * application window. If the event filter returns 1, then the window will be
+ * closed, otherwise the window will remain open if possible.
+ *
+ * Note: Disabled events never make it to the event filter function; see
+ * SDL_EventState().
+ *
+ * Note: If you just want to inspect events without filtering, you should use
+ * SDL_AddEventWatch() instead.
+ *
+ * Note: Events pushed onto the queue with SDL_PushEvent() get passed through
+ * the event filter, but events pushed onto the queue with SDL_PeepEvents() do
+ * not.
+ *
+ * \param filter An SDL_EventFilter function to call when an event happens
+ * \param userdata a pointer that is passed to `filter`
+ *
+ * \since This function is available since SDL 2.0.0.
+ *
+ * \sa SDL_AddEventWatch
+ * \sa SDL_EventState
+ * \sa SDL_GetEventFilter
+ * \sa SDL_PeepEvents
+ * \sa SDL_PushEvent
+ */
+extern DECLSPEC void SDLCALL SDL_SetEventFilter(SDL_EventFilter filter,
+ void *userdata);
+
+/**
+ * Query the current event filter.
+ *
+ * This function can be used to "chain" filters, by saving the existing filter
+ * before replacing it with a function that will call that saved filter.
+ *
+ * \param filter the current callback function will be stored here
+ * \param userdata the pointer that is passed to the current event filter will
+ * be stored here
+ * \returns SDL_TRUE on success or SDL_FALSE if there is no event filter set.
+ *
+ * \since This function is available since SDL 2.0.0.
+ *
+ * \sa SDL_SetEventFilter
+ */
+extern DECLSPEC SDL_bool SDLCALL SDL_GetEventFilter(SDL_EventFilter * filter,
+ void **userdata);
+
+/**
+ * Add a callback to be triggered when an event is added to the event queue.
+ *
+ * `filter` will be called when an event happens, and its return value is
+ * ignored.
+ *
+ * **WARNING**: Be very careful of what you do in the event filter function,
+ * as it may run in a different thread!
+ *
+ * If the quit event is generated by a signal (e.g. SIGINT), it will bypass
+ * the internal queue and be delivered to the watch callback immediately, and
+ * arrive at the next event poll.
+ *
+ * Note: the callback is called for events posted by the user through
+ * SDL_PushEvent(), but not for disabled events, nor for events by a filter
+ * callback set with SDL_SetEventFilter(), nor for events posted by the user
+ * through SDL_PeepEvents().
+ *
+ * \param filter an SDL_EventFilter function to call when an event happens.
+ * \param userdata a pointer that is passed to `filter`
+ *
+ * \since This function is available since SDL 2.0.0.
+ *
+ * \sa SDL_DelEventWatch
+ * \sa SDL_SetEventFilter
+ */
+extern DECLSPEC void SDLCALL SDL_AddEventWatch(SDL_EventFilter filter,
+ void *userdata);
+
+/**
+ * Remove an event watch callback added with SDL_AddEventWatch().
+ *
+ * This function takes the same input as SDL_AddEventWatch() to identify and
+ * delete the corresponding callback.
+ *
+ * \param filter the function originally passed to SDL_AddEventWatch()
+ * \param userdata the pointer originally passed to SDL_AddEventWatch()
+ *
+ * \since This function is available since SDL 2.0.0.
+ *
+ * \sa SDL_AddEventWatch
+ */
+extern DECLSPEC void SDLCALL SDL_DelEventWatch(SDL_EventFilter filter,
+ void *userdata);
+
+/**
+ * Run a specific filter function on the current event queue, removing any
+ * events for which the filter returns 0.
+ *
+ * See SDL_SetEventFilter() for more information. Unlike SDL_SetEventFilter(),
+ * this function does not change the filter permanently, it only uses the
+ * supplied filter until this function returns.
+ *
+ * \param filter the SDL_EventFilter function to call when an event happens
+ * \param userdata a pointer that is passed to `filter`
+ *
+ * \since This function is available since SDL 2.0.0.
+ *
+ * \sa SDL_GetEventFilter
+ * \sa SDL_SetEventFilter
+ */
+extern DECLSPEC void SDLCALL SDL_FilterEvents(SDL_EventFilter filter,
+ void *userdata);
+
+/* @{ */
+#define SDL_QUERY -1
+#define SDL_IGNORE 0
+#define SDL_DISABLE 0
+#define SDL_ENABLE 1
+
+/**
+ * Set the state of processing events by type.
+ *
+ * `state` may be any of the following:
+ *
+ * - `SDL_QUERY`: returns the current processing state of the specified event
+ * - `SDL_IGNORE` (aka `SDL_DISABLE`): the event will automatically be dropped
+ * from the event queue and will not be filtered
+ * - `SDL_ENABLE`: the event will be processed normally
+ *
+ * \param type the type of event; see SDL_EventType for details
+ * \param state how to process the event
+ * \returns `SDL_DISABLE` or `SDL_ENABLE`, representing the processing state
+ * of the event before this function makes any changes to it.
+ *
+ * \since This function is available since SDL 2.0.0.
+ *
+ * \sa SDL_GetEventState
+ */
+extern DECLSPEC Uint8 SDLCALL SDL_EventState(Uint32 type, int state);
+/* @} */
+#define SDL_GetEventState(type) SDL_EventState(type, SDL_QUERY)
+
+/**
+ * Allocate a set of user-defined events, and return the beginning event
+ * number for that set of events.
+ *
+ * Calling this function with `numevents` <= 0 is an error and will return
+ * (Uint32)-1.
+ *
+ * Note, (Uint32)-1 means the maximum unsigned 32-bit integer value (or
+ * 0xFFFFFFFF), but is clearer to write.
+ *
+ * \param numevents the number of events to be allocated
+ * \returns the beginning event number, or (Uint32)-1 if there are not enough
+ * user-defined events left.
+ *
+ * \since This function is available since SDL 2.0.0.
+ *
+ * \sa SDL_PushEvent
+ */
+extern DECLSPEC Uint32 SDLCALL SDL_RegisterEvents(int numevents);
+
+/* Ends C function definitions when using C++ */
+#ifdef __cplusplus
+}
+#endif
+#include
+
+#endif /* SDL_events_h_ */
+
+/* vi: set ts=4 sw=4 expandtab: */
diff --git a/bindings/sdl2wgpu/src/main/headers/SDL2/SDL_filesystem.h b/bindings/sdl2wgpu/src/main/headers/SDL2/SDL_filesystem.h
new file mode 100644
index 00000000..3c3b5336
--- /dev/null
+++ b/bindings/sdl2wgpu/src/main/headers/SDL2/SDL_filesystem.h
@@ -0,0 +1,149 @@
+/*
+ Simple DirectMedia Layer
+ Copyright (C) 1997-2023 Sam Lantinga
+
+ This software is provided 'as-is', without any express or implied
+ warranty. In no event will the authors be held liable for any damages
+ arising from the use of this software.
+
+ Permission is granted to anyone to use this software for any purpose,
+ including commercial applications, and to alter it and redistribute it
+ freely, subject to the following restrictions:
+
+ 1. The origin of this software must not be misrepresented; you must not
+ claim that you wrote the original software. If you use this software
+ in a product, an acknowledgment in the product documentation would be
+ appreciated but is not required.
+ 2. Altered source versions must be plainly marked as such, and must not be
+ misrepresented as being the original software.
+ 3. This notice may not be removed or altered from any source distribution.
+*/
+
+/**
+ * \file SDL_filesystem.h
+ *
+ * \brief Include file for filesystem SDL API functions
+ */
+
+#ifndef SDL_filesystem_h_
+#define SDL_filesystem_h_
+
+#include
+
+#include
+
+/* Set up for C function definitions, even when using C++ */
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * Get the directory where the application was run from.
+ *
+ * This is not necessarily a fast call, so you should call this once near
+ * startup and save the string if you need it.
+ *
+ * **Mac OS X and iOS Specific Functionality**: If the application is in a
+ * ".app" bundle, this function returns the Resource directory (e.g.
+ * MyApp.app/Contents/Resources/). This behaviour can be overridden by adding
+ * a property to the Info.plist file. Adding a string key with the name
+ * SDL_FILESYSTEM_BASE_DIR_TYPE with a supported value will change the
+ * behaviour.
+ *
+ * Supported values for the SDL_FILESYSTEM_BASE_DIR_TYPE property (Given an
+ * application in /Applications/SDLApp/MyApp.app):
+ *
+ * - `resource`: bundle resource directory (the default). For example:
+ * `/Applications/SDLApp/MyApp.app/Contents/Resources`
+ * - `bundle`: the Bundle directory. For example:
+ * `/Applications/SDLApp/MyApp.app/`
+ * - `parent`: the containing directory of the bundle. For example:
+ * `/Applications/SDLApp/`
+ *
+ * **Nintendo 3DS Specific Functionality**: This function returns "romfs"
+ * directory of the application as it is uncommon to store resources outside
+ * the executable. As such it is not a writable directory.
+ *
+ * The returned path is guaranteed to end with a path separator ('\' on
+ * Windows, '/' on most other platforms).
+ *
+ * The pointer returned is owned by the caller. Please call SDL_free() on the
+ * pointer when done with it.
+ *
+ * \returns an absolute path in UTF-8 encoding to the application data
+ * directory. NULL will be returned on error or when the platform
+ * doesn't implement this functionality, call SDL_GetError() for more
+ * information.
+ *
+ * \since This function is available since SDL 2.0.1.
+ *
+ * \sa SDL_GetPrefPath
+ */
+extern DECLSPEC char *SDLCALL SDL_GetBasePath(void);
+
+/**
+ * Get the user-and-app-specific path where files can be written.
+ *
+ * Get the "pref dir". This is meant to be where users can write personal
+ * files (preferences and save games, etc) that are specific to your
+ * application. This directory is unique per user, per application.
+ *
+ * This function will decide the appropriate location in the native
+ * filesystem, create the directory if necessary, and return a string of the
+ * absolute path to the directory in UTF-8 encoding.
+ *
+ * On Windows, the string might look like:
+ *
+ * `C:\\Users\\bob\\AppData\\Roaming\\My Company\\My Program Name\\`
+ *
+ * On Linux, the string might look like:
+ *
+ * `/home/bob/.local/share/My Program Name/`
+ *
+ * On Mac OS X, the string might look like:
+ *
+ * `/Users/bob/Library/Application Support/My Program Name/`
+ *
+ * You should assume the path returned by this function is the only safe place
+ * to write files (and that SDL_GetBasePath(), while it might be writable, or
+ * even the parent of the returned path, isn't where you should be writing
+ * things).
+ *
+ * Both the org and app strings may become part of a directory name, so please
+ * follow these rules:
+ *
+ * - Try to use the same org string (_including case-sensitivity_) for all
+ * your applications that use this function.
+ * - Always use a unique app string for each one, and make sure it never
+ * changes for an app once you've decided on it.
+ * - Unicode characters are legal, as long as it's UTF-8 encoded, but...
+ * - ...only use letters, numbers, and spaces. Avoid punctuation like "Game
+ * Name 2: Bad Guy's Revenge!" ... "Game Name 2" is sufficient.
+ *
+ * The returned path is guaranteed to end with a path separator ('\' on
+ * Windows, '/' on most other platforms).
+ *
+ * The pointer returned is owned by the caller. Please call SDL_free() on the
+ * pointer when done with it.
+ *
+ * \param org the name of your organization
+ * \param app the name of your application
+ * \returns a UTF-8 string of the user directory in platform-dependent
+ * notation. NULL if there's a problem (creating directory failed,
+ * etc.).
+ *
+ * \since This function is available since SDL 2.0.1.
+ *
+ * \sa SDL_GetBasePath
+ */
+extern DECLSPEC char *SDLCALL SDL_GetPrefPath(const char *org, const char *app);
+
+/* Ends C function definitions when using C++ */
+#ifdef __cplusplus
+}
+#endif
+#include
+
+#endif /* SDL_filesystem_h_ */
+
+/* vi: set ts=4 sw=4 expandtab: */
diff --git a/bindings/sdl2wgpu/src/main/headers/SDL2/SDL_gamecontroller.h b/bindings/sdl2wgpu/src/main/headers/SDL2/SDL_gamecontroller.h
new file mode 100644
index 00000000..266e7067
--- /dev/null
+++ b/bindings/sdl2wgpu/src/main/headers/SDL2/SDL_gamecontroller.h
@@ -0,0 +1,1074 @@
+/*
+ Simple DirectMedia Layer
+ Copyright (C) 1997-2023 Sam Lantinga
+
+ This software is provided 'as-is', without any express or implied
+ warranty. In no event will the authors be held liable for any damages
+ arising from the use of this software.
+
+ Permission is granted to anyone to use this software for any purpose,
+ including commercial applications, and to alter it and redistribute it
+ freely, subject to the following restrictions:
+
+ 1. The origin of this software must not be misrepresented; you must not
+ claim that you wrote the original software. If you use this software
+ in a product, an acknowledgment in the product documentation would be
+ appreciated but is not required.
+ 2. Altered source versions must be plainly marked as such, and must not be
+ misrepresented as being the original software.
+ 3. This notice may not be removed or altered from any source distribution.
+*/
+
+/**
+ * \file SDL_gamecontroller.h
+ *
+ * Include file for SDL game controller event handling
+ */
+
+#ifndef SDL_gamecontroller_h_
+#define SDL_gamecontroller_h_
+
+#include
+#include
+#include
+#include
+#include
+
+#include
+/* Set up for C function definitions, even when using C++ */
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * \file SDL_gamecontroller.h
+ *
+ * In order to use these functions, SDL_Init() must have been called
+ * with the ::SDL_INIT_GAMECONTROLLER flag. This causes SDL to scan the system
+ * for game controllers, and load appropriate drivers.
+ *
+ * If you would like to receive controller updates while the application
+ * is in the background, you should set the following hint before calling
+ * SDL_Init(): SDL_HINT_JOYSTICK_ALLOW_BACKGROUND_EVENTS
+ */
+
+/**
+ * The gamecontroller structure used to identify an SDL game controller
+ */
+struct _SDL_GameController;
+typedef struct _SDL_GameController SDL_GameController;
+
+typedef enum
+{
+ SDL_CONTROLLER_TYPE_UNKNOWN = 0,
+ SDL_CONTROLLER_TYPE_XBOX360,
+ SDL_CONTROLLER_TYPE_XBOXONE,
+ SDL_CONTROLLER_TYPE_PS3,
+ SDL_CONTROLLER_TYPE_PS4,
+ SDL_CONTROLLER_TYPE_NINTENDO_SWITCH_PRO,
+ SDL_CONTROLLER_TYPE_VIRTUAL,
+ SDL_CONTROLLER_TYPE_PS5,
+ SDL_CONTROLLER_TYPE_AMAZON_LUNA,
+ SDL_CONTROLLER_TYPE_GOOGLE_STADIA,
+ SDL_CONTROLLER_TYPE_NVIDIA_SHIELD,
+ SDL_CONTROLLER_TYPE_NINTENDO_SWITCH_JOYCON_LEFT,
+ SDL_CONTROLLER_TYPE_NINTENDO_SWITCH_JOYCON_RIGHT,
+ SDL_CONTROLLER_TYPE_NINTENDO_SWITCH_JOYCON_PAIR
+} SDL_GameControllerType;
+
+typedef enum
+{
+ SDL_CONTROLLER_BINDTYPE_NONE = 0,
+ SDL_CONTROLLER_BINDTYPE_BUTTON,
+ SDL_CONTROLLER_BINDTYPE_AXIS,
+ SDL_CONTROLLER_BINDTYPE_HAT
+} SDL_GameControllerBindType;
+
+/**
+ * Get the SDL joystick layer binding for this controller button/axis mapping
+ */
+typedef struct SDL_GameControllerButtonBind
+{
+ SDL_GameControllerBindType bindType;
+ union
+ {
+ int button;
+ int axis;
+ struct {
+ int hat;
+ int hat_mask;
+ } hat;
+ } value;
+
+} SDL_GameControllerButtonBind;
+
+
+/**
+ * To count the number of game controllers in the system for the following:
+ *
+ * ```c
+ * int nJoysticks = SDL_NumJoysticks();
+ * int nGameControllers = 0;
+ * for (int i = 0; i < nJoysticks; i++) {
+ * if (SDL_IsGameController(i)) {
+ * nGameControllers++;
+ * }
+ * }
+ * ```
+ *
+ * Using the SDL_HINT_GAMECONTROLLERCONFIG hint or the SDL_GameControllerAddMapping() you can add support for controllers SDL is unaware of or cause an existing controller to have a different binding. The format is:
+ * guid,name,mappings
+ *
+ * Where GUID is the string value from SDL_JoystickGetGUIDString(), name is the human readable string for the device and mappings are controller mappings to joystick ones.
+ * Under Windows there is a reserved GUID of "xinput" that covers any XInput devices.
+ * The mapping format for joystick is:
+ * bX - a joystick button, index X
+ * hX.Y - hat X with value Y
+ * aX - axis X of the joystick
+ * Buttons can be used as a controller axis and vice versa.
+ *
+ * This string shows an example of a valid mapping for a controller
+ *
+ * ```c
+ * "03000000341a00003608000000000000,PS3 Controller,a:b1,b:b2,y:b3,x:b0,start:b9,guide:b12,back:b8,dpup:h0.1,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,leftshoulder:b4,rightshoulder:b5,leftstick:b10,rightstick:b11,leftx:a0,lefty:a1,rightx:a2,righty:a3,lefttrigger:b6,righttrigger:b7",
+ * ```
+ */
+
+/**
+ * Load a set of Game Controller mappings from a seekable SDL data stream.
+ *
+ * You can call this function several times, if needed, to load different
+ * database files.
+ *
+ * If a new mapping is loaded for an already known controller GUID, the later
+ * version will overwrite the one currently loaded.
+ *
+ * Mappings not belonging to the current platform or with no platform field
+ * specified will be ignored (i.e. mappings for Linux will be ignored in
+ * Windows, etc).
+ *
+ * This function will load the text database entirely in memory before
+ * processing it, so take this into consideration if you are in a memory
+ * constrained environment.
+ *
+ * \param rw the data stream for the mappings to be added
+ * \param freerw non-zero to close the stream after being read
+ * \returns the number of mappings added or -1 on error; call SDL_GetError()
+ * for more information.
+ *
+ * \since This function is available since SDL 2.0.2.
+ *
+ * \sa SDL_GameControllerAddMapping
+ * \sa SDL_GameControllerAddMappingsFromFile
+ * \sa SDL_GameControllerMappingForGUID
+ */
+extern DECLSPEC int SDLCALL SDL_GameControllerAddMappingsFromRW(SDL_RWops * rw, int freerw);
+
+/**
+ * Load a set of mappings from a file, filtered by the current SDL_GetPlatform()
+ *
+ * Convenience macro.
+ */
+#define SDL_GameControllerAddMappingsFromFile(file) SDL_GameControllerAddMappingsFromRW(SDL_RWFromFile(file, "rb"), 1)
+
+/**
+ * Add support for controllers that SDL is unaware of or to cause an existing
+ * controller to have a different binding.
+ *
+ * The mapping string has the format "GUID,name,mapping", where GUID is the
+ * string value from SDL_JoystickGetGUIDString(), name is the human readable
+ * string for the device and mappings are controller mappings to joystick
+ * ones. Under Windows there is a reserved GUID of "xinput" that covers all
+ * XInput devices. The mapping format for joystick is: {| |bX |a joystick
+ * button, index X |- |hX.Y |hat X with value Y |- |aX |axis X of the joystick
+ * |} Buttons can be used as a controller axes and vice versa.
+ *
+ * This string shows an example of a valid mapping for a controller:
+ *
+ * ```c
+ * "341a3608000000000000504944564944,Afterglow PS3 Controller,a:b1,b:b2,y:b3,x:b0,start:b9,guide:b12,back:b8,dpup:h0.1,dpleft:h0.8,dpdown:h0.4,dpright:h0.2,leftshoulder:b4,rightshoulder:b5,leftstick:b10,rightstick:b11,leftx:a0,lefty:a1,rightx:a2,righty:a3,lefttrigger:b6,righttrigger:b7"
+ * ```
+ *
+ * \param mappingString the mapping string
+ * \returns 1 if a new mapping is added, 0 if an existing mapping is updated,
+ * -1 on error; call SDL_GetError() for more information.
+ *
+ * \since This function is available since SDL 2.0.0.
+ *
+ * \sa SDL_GameControllerMapping
+ * \sa SDL_GameControllerMappingForGUID
+ */
+extern DECLSPEC int SDLCALL SDL_GameControllerAddMapping(const char* mappingString);
+
+/**
+ * Get the number of mappings installed.
+ *
+ * \returns the number of mappings.
+ *
+ * \since This function is available since SDL 2.0.6.
+ */
+extern DECLSPEC int SDLCALL SDL_GameControllerNumMappings(void);
+
+/**
+ * Get the mapping at a particular index.
+ *
+ * \returns the mapping string. Must be freed with SDL_free(). Returns NULL if
+ * the index is out of range.
+ *
+ * \since This function is available since SDL 2.0.6.
+ */
+extern DECLSPEC char * SDLCALL SDL_GameControllerMappingForIndex(int mapping_index);
+
+/**
+ * Get the game controller mapping string for a given GUID.
+ *
+ * The returned string must be freed with SDL_free().
+ *
+ * \param guid a structure containing the GUID for which a mapping is desired
+ * \returns a mapping string or NULL on error; call SDL_GetError() for more
+ * information.
+ *
+ * \since This function is available since SDL 2.0.0.
+ *
+ * \sa SDL_JoystickGetDeviceGUID
+ * \sa SDL_JoystickGetGUID
+ */
+extern DECLSPEC char * SDLCALL SDL_GameControllerMappingForGUID(SDL_JoystickGUID guid);
+
+/**
+ * Get the current mapping of a Game Controller.
+ *
+ * The returned string must be freed with SDL_free().
+ *
+ * Details about mappings are discussed with SDL_GameControllerAddMapping().
+ *
+ * \param gamecontroller the game controller you want to get the current
+ * mapping for
+ * \returns a string that has the controller's mapping or NULL if no mapping
+ * is available; call SDL_GetError() for more information.
+ *
+ * \since This function is available since SDL 2.0.0.
+ *
+ * \sa SDL_GameControllerAddMapping
+ * \sa SDL_GameControllerMappingForGUID
+ */
+extern DECLSPEC char * SDLCALL SDL_GameControllerMapping(SDL_GameController *gamecontroller);
+
+/**
+ * Check if the given joystick is supported by the game controller interface.
+ *
+ * `joystick_index` is the same as the `device_index` passed to
+ * SDL_JoystickOpen().
+ *
+ * \param joystick_index the device_index of a device, up to
+ * SDL_NumJoysticks()
+ * \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.
+ *
+ * \since This function is available since SDL 2.0.0.
+ *
+ * \sa SDL_GameControllerNameForIndex
+ * \sa SDL_GameControllerOpen
+ */
+extern DECLSPEC SDL_bool SDLCALL SDL_IsGameController(int joystick_index);
+
+/**
+ * Get the implementation dependent name for the game controller.
+ *
+ * This function can be called before any controllers are opened.
+ *
+ * `joystick_index` is the same as the `device_index` passed to
+ * SDL_JoystickOpen().
+ *
+ * \param joystick_index the device_index of a device, from zero to
+ * SDL_NumJoysticks()-1
+ * \returns the implementation-dependent name for the game controller, or NULL
+ * if there is no name or the index is invalid.
+ *
+ * \since This function is available since SDL 2.0.0.
+ *
+ * \sa SDL_GameControllerName
+ * \sa SDL_GameControllerOpen
+ * \sa SDL_IsGameController
+ */
+extern DECLSPEC const char *SDLCALL SDL_GameControllerNameForIndex(int joystick_index);
+
+/**
+ * Get the implementation dependent path for the game controller.
+ *
+ * This function can be called before any controllers are opened.
+ *
+ * `joystick_index` is the same as the `device_index` passed to
+ * SDL_JoystickOpen().
+ *
+ * \param joystick_index the device_index of a device, from zero to
+ * SDL_NumJoysticks()-1
+ * \returns the implementation-dependent path for the game controller, or NULL
+ * if there is no path or the index is invalid.
+ *
+ * \since This function is available since SDL 2.24.0.
+ *
+ * \sa SDL_GameControllerPath
+ */
+extern DECLSPEC const char *SDLCALL SDL_GameControllerPathForIndex(int joystick_index);
+
+/**
+ * Get the type of a game controller.
+ *
+ * This can be called before any controllers are opened.
+ *
+ * \param joystick_index the device_index of a device, from zero to
+ * SDL_NumJoysticks()-1
+ * \returns the controller type.
+ *
+ * \since This function is available since SDL 2.0.12.
+ */
+extern DECLSPEC SDL_GameControllerType SDLCALL SDL_GameControllerTypeForIndex(int joystick_index);
+
+/**
+ * Get the mapping of a game controller.
+ *
+ * This can be called before any controllers are opened.
+ *
+ * \param joystick_index the device_index of a device, from zero to
+ * SDL_NumJoysticks()-1
+ * \returns the mapping string. Must be freed with SDL_free(). Returns NULL if
+ * no mapping is available.
+ *
+ * \since This function is available since SDL 2.0.9.
+ */
+extern DECLSPEC char *SDLCALL SDL_GameControllerMappingForDeviceIndex(int joystick_index);
+
+/**
+ * Open a game controller for use.
+ *
+ * `joystick_index` is the same as the `device_index` passed to
+ * SDL_JoystickOpen().
+ *
+ * The index passed as an argument refers to the N'th game controller on the
+ * system. This index is not the value which will identify this controller in
+ * future controller events. The joystick's instance id (SDL_JoystickID) will
+ * be used there instead.
+ *
+ * \param joystick_index the device_index of a device, up to
+ * SDL_NumJoysticks()
+ * \returns a gamecontroller identifier or NULL if an error occurred; call
+ * SDL_GetError() for more information.
+ *
+ * \since This function is available since SDL 2.0.0.
+ *
+ * \sa SDL_GameControllerClose
+ * \sa SDL_GameControllerNameForIndex
+ * \sa SDL_IsGameController
+ */
+extern DECLSPEC SDL_GameController *SDLCALL SDL_GameControllerOpen(int joystick_index);
+
+/**
+ * Get the SDL_GameController associated with an instance id.
+ *
+ * \param joyid the instance id to get the SDL_GameController for
+ * \returns an SDL_GameController on success or NULL on failure; call
+ * SDL_GetError() for more information.
+ *
+ * \since This function is available since SDL 2.0.4.
+ */
+extern DECLSPEC SDL_GameController *SDLCALL SDL_GameControllerFromInstanceID(SDL_JoystickID joyid);
+
+/**
+ * Get the SDL_GameController associated with a player index.
+ *
+ * Please note that the player index is _not_ the device index, nor is it the
+ * instance id!
+ *
+ * \param player_index the player index, which is not the device index or the
+ * instance id!
+ * \returns the SDL_GameController associated with a player index.
+ *
+ * \since This function is available since SDL 2.0.12.
+ *
+ * \sa SDL_GameControllerGetPlayerIndex
+ * \sa SDL_GameControllerSetPlayerIndex
+ */
+extern DECLSPEC SDL_GameController *SDLCALL SDL_GameControllerFromPlayerIndex(int player_index);
+
+/**
+ * Get the implementation-dependent name for an opened game controller.
+ *
+ * This is the same name as returned by SDL_GameControllerNameForIndex(), but
+ * it takes a controller identifier instead of the (unstable) device index.
+ *
+ * \param gamecontroller a game controller identifier previously returned by
+ * SDL_GameControllerOpen()
+ * \returns the implementation dependent name for the game controller, or NULL
+ * if there is no name or the identifier passed is invalid.
+ *
+ * \since This function is available since SDL 2.0.0.
+ *
+ * \sa SDL_GameControllerNameForIndex
+ * \sa SDL_GameControllerOpen
+ */
+extern DECLSPEC const char *SDLCALL SDL_GameControllerName(SDL_GameController *gamecontroller);
+
+/**
+ * Get the implementation-dependent path for an opened game controller.
+ *
+ * This is the same path as returned by SDL_GameControllerNameForIndex(), but
+ * it takes a controller identifier instead of the (unstable) device index.
+ *
+ * \param gamecontroller a game controller identifier previously returned by
+ * SDL_GameControllerOpen()
+ * \returns the implementation dependent path for the game controller, or NULL
+ * if there is no path or the identifier passed is invalid.
+ *
+ * \since This function is available since SDL 2.24.0.
+ *
+ * \sa SDL_GameControllerPathForIndex
+ */
+extern DECLSPEC const char *SDLCALL SDL_GameControllerPath(SDL_GameController *gamecontroller);
+
+/**
+ * Get the type of this currently opened controller
+ *
+ * This is the same name as returned by SDL_GameControllerTypeForIndex(), but
+ * it takes a controller identifier instead of the (unstable) device index.
+ *
+ * \param gamecontroller the game controller object to query.
+ * \returns the controller type.
+ *
+ * \since This function is available since SDL 2.0.12.
+ */
+extern DECLSPEC SDL_GameControllerType SDLCALL SDL_GameControllerGetType(SDL_GameController *gamecontroller);
+
+/**
+ * Get the player index of an opened game controller.
+ *
+ * For XInput controllers this returns the XInput user index.
+ *
+ * \param gamecontroller the game controller object to query.
+ * \returns the player index for controller, or -1 if it's not available.
+ *
+ * \since This function is available since SDL 2.0.9.
+ */
+extern DECLSPEC int SDLCALL SDL_GameControllerGetPlayerIndex(SDL_GameController *gamecontroller);
+
+/**
+ * Set the player index of an opened game controller.
+ *
+ * \param gamecontroller the game controller object to adjust.
+ * \param player_index Player index to assign to this controller, or -1 to
+ * clear the player index and turn off player LEDs.
+ *
+ * \since This function is available since SDL 2.0.12.
+ */
+extern DECLSPEC void SDLCALL SDL_GameControllerSetPlayerIndex(SDL_GameController *gamecontroller, int player_index);
+
+/**
+ * Get the USB vendor ID of an opened controller, if available.
+ *
+ * If the vendor ID isn't available this function returns 0.
+ *
+ * \param gamecontroller the game controller object to query.
+ * \return the USB vendor ID, or zero if unavailable.
+ *
+ * \since This function is available since SDL 2.0.6.
+ */
+extern DECLSPEC Uint16 SDLCALL SDL_GameControllerGetVendor(SDL_GameController *gamecontroller);
+
+/**
+ * Get the USB product ID of an opened controller, if available.
+ *
+ * If the product ID isn't available this function returns 0.
+ *
+ * \param gamecontroller the game controller object to query.
+ * \return the USB product ID, or zero if unavailable.
+ *
+ * \since This function is available since SDL 2.0.6.
+ */
+extern DECLSPEC Uint16 SDLCALL SDL_GameControllerGetProduct(SDL_GameController *gamecontroller);
+
+/**
+ * Get the product version of an opened controller, if available.
+ *
+ * If the product version isn't available this function returns 0.
+ *
+ * \param gamecontroller the game controller object to query.
+ * \return the USB product version, or zero if unavailable.
+ *
+ * \since This function is available since SDL 2.0.6.
+ */
+extern DECLSPEC Uint16 SDLCALL SDL_GameControllerGetProductVersion(SDL_GameController *gamecontroller);
+
+/**
+ * Get the firmware version of an opened controller, if available.
+ *
+ * If the firmware version isn't available this function returns 0.
+ *
+ * \param gamecontroller the game controller object to query.
+ * \return the controller firmware version, or zero if unavailable.
+ *
+ * \since This function is available since SDL 2.24.0.
+ */
+extern DECLSPEC Uint16 SDLCALL SDL_GameControllerGetFirmwareVersion(SDL_GameController *gamecontroller);
+
+/**
+ * Get the serial number of an opened controller, if available.
+ *
+ * Returns the serial number of the controller, or NULL if it is not
+ * available.
+ *
+ * \param gamecontroller the game controller object to query.
+ * \return the serial number, or NULL if unavailable.
+ *
+ * \since This function is available since SDL 2.0.14.
+ */
+extern DECLSPEC const char * SDLCALL SDL_GameControllerGetSerial(SDL_GameController *gamecontroller);
+
+/**
+ * Check if a controller has been opened and is currently connected.
+ *
+ * \param gamecontroller a game controller identifier previously returned by
+ * SDL_GameControllerOpen()
+ * \returns SDL_TRUE if the controller has been opened and is currently
+ * connected, or SDL_FALSE if not.
+ *
+ * \since This function is available since SDL 2.0.0.
+ *
+ * \sa SDL_GameControllerClose
+ * \sa SDL_GameControllerOpen
+ */
+extern DECLSPEC SDL_bool SDLCALL SDL_GameControllerGetAttached(SDL_GameController *gamecontroller);
+
+/**
+ * Get the Joystick ID from a Game Controller.
+ *
+ * This function will give you a SDL_Joystick object, which allows you to use
+ * the SDL_Joystick functions with a SDL_GameController object. This would be
+ * useful for getting a joystick's position at any given time, even if it
+ * hasn't moved (moving it would produce an event, which would have the axis'
+ * value).
+ *
+ * The pointer returned is owned by the SDL_GameController. You should not
+ * call SDL_JoystickClose() on it, for example, since doing so will likely
+ * cause SDL to crash.
+ *
+ * \param gamecontroller the game controller object that you want to get a
+ * joystick from
+ * \returns a SDL_Joystick object; call SDL_GetError() for more information.
+ *
+ * \since This function is available since SDL 2.0.0.
+ */
+extern DECLSPEC SDL_Joystick *SDLCALL SDL_GameControllerGetJoystick(SDL_GameController *gamecontroller);
+
+/**
+ * Query or change current state of Game Controller events.
+ *
+ * If controller events are disabled, you must call SDL_GameControllerUpdate()
+ * yourself and check the state of the controller when you want controller
+ * information.
+ *
+ * Any number can be passed to SDL_GameControllerEventState(), but only -1, 0,
+ * and 1 will have any effect. Other numbers will just be returned.
+ *
+ * \param state can be one of `SDL_QUERY`, `SDL_IGNORE`, or `SDL_ENABLE`
+ * \returns the same value passed to the function, with exception to -1
+ * (SDL_QUERY), which will return the current state.
+ *
+ * \since This function is available since SDL 2.0.0.
+ *
+ * \sa SDL_JoystickEventState
+ */
+extern DECLSPEC int SDLCALL SDL_GameControllerEventState(int state);
+
+/**
+ * Manually pump game controller updates if not using the loop.
+ *
+ * This function is called automatically by the event loop if events are
+ * enabled. Under such circumstances, it will not be necessary to call this
+ * function.
+ *
+ * \since This function is available since SDL 2.0.0.
+ */
+extern DECLSPEC void SDLCALL SDL_GameControllerUpdate(void);
+
+
+/**
+ * The list of axes available from a controller
+ *
+ * Thumbstick axis values range from SDL_JOYSTICK_AXIS_MIN to SDL_JOYSTICK_AXIS_MAX,
+ * and are centered within ~8000 of zero, though advanced UI will allow users to set
+ * or autodetect the dead zone, which varies between controllers.
+ *
+ * Trigger axis values range from 0 to SDL_JOYSTICK_AXIS_MAX.
+ */
+typedef enum
+{
+ SDL_CONTROLLER_AXIS_INVALID = -1,
+ SDL_CONTROLLER_AXIS_LEFTX,
+ SDL_CONTROLLER_AXIS_LEFTY,
+ SDL_CONTROLLER_AXIS_RIGHTX,
+ SDL_CONTROLLER_AXIS_RIGHTY,
+ SDL_CONTROLLER_AXIS_TRIGGERLEFT,
+ SDL_CONTROLLER_AXIS_TRIGGERRIGHT,
+ SDL_CONTROLLER_AXIS_MAX
+} SDL_GameControllerAxis;
+
+/**
+ * Convert a string into SDL_GameControllerAxis enum.
+ *
+ * This function is called internally to translate SDL_GameController mapping
+ * strings for the underlying joystick device into the consistent
+ * SDL_GameController mapping. You do not normally need to call this function
+ * unless you are parsing SDL_GameController mappings in your own code.
+ *
+ * Note specially that "righttrigger" and "lefttrigger" map to
+ * `SDL_CONTROLLER_AXIS_TRIGGERRIGHT` and `SDL_CONTROLLER_AXIS_TRIGGERLEFT`,
+ * respectively.
+ *
+ * \param str string representing a SDL_GameController axis
+ * \returns the SDL_GameControllerAxis enum corresponding to the input string,
+ * or `SDL_CONTROLLER_AXIS_INVALID` if no match was found.
+ *
+ * \since This function is available since SDL 2.0.0.
+ *
+ * \sa SDL_GameControllerGetStringForAxis
+ */
+extern DECLSPEC SDL_GameControllerAxis SDLCALL SDL_GameControllerGetAxisFromString(const char *str);
+
+/**
+ * Convert from an SDL_GameControllerAxis enum to a string.
+ *
+ * The caller should not SDL_free() the returned string.
+ *
+ * \param axis an enum value for a given SDL_GameControllerAxis
+ * \returns a string for the given axis, or NULL if an invalid axis is
+ * specified. The string returned is of the format used by
+ * SDL_GameController mapping strings.
+ *
+ * \since This function is available since SDL 2.0.0.
+ *
+ * \sa SDL_GameControllerGetAxisFromString
+ */
+extern DECLSPEC const char* SDLCALL SDL_GameControllerGetStringForAxis(SDL_GameControllerAxis axis);
+
+/**
+ * Get the SDL joystick layer binding for a controller axis mapping.
+ *
+ * \param gamecontroller a game controller
+ * \param axis an axis enum value (one of the SDL_GameControllerAxis values)
+ * \returns a SDL_GameControllerButtonBind describing the bind. On failure
+ * (like the given Controller axis doesn't exist on the device), its
+ * `.bindType` will be `SDL_CONTROLLER_BINDTYPE_NONE`.
+ *
+ * \since This function is available since SDL 2.0.0.
+ *
+ * \sa SDL_GameControllerGetBindForButton
+ */
+extern DECLSPEC SDL_GameControllerButtonBind SDLCALL
+SDL_GameControllerGetBindForAxis(SDL_GameController *gamecontroller,
+ SDL_GameControllerAxis axis);
+
+/**
+ * Query whether a game controller has a given axis.
+ *
+ * This merely reports whether the controller's mapping defined this axis, as
+ * that is all the information SDL has about the physical device.
+ *
+ * \param gamecontroller a game controller
+ * \param axis an axis enum value (an SDL_GameControllerAxis value)
+ * \returns SDL_TRUE if the controller has this axis, SDL_FALSE otherwise.
+ *
+ * \since This function is available since SDL 2.0.14.
+ */
+extern DECLSPEC SDL_bool SDLCALL
+SDL_GameControllerHasAxis(SDL_GameController *gamecontroller, SDL_GameControllerAxis axis);
+
+/**
+ * Get the current state of an axis control on a game controller.
+ *
+ * The axis indices start at index 0.
+ *
+ * The state is a value ranging from -32768 to 32767. Triggers, however, range
+ * from 0 to 32767 (they never return a negative value).
+ *
+ * \param gamecontroller a game controller
+ * \param axis an axis index (one of the SDL_GameControllerAxis values)
+ * \returns axis state (including 0) on success or 0 (also) on failure; call
+ * SDL_GetError() for more information.
+ *
+ * \since This function is available since SDL 2.0.0.
+ *
+ * \sa SDL_GameControllerGetButton
+ */
+extern DECLSPEC Sint16 SDLCALL
+SDL_GameControllerGetAxis(SDL_GameController *gamecontroller, SDL_GameControllerAxis axis);
+
+/**
+ * The list of buttons available from a controller
+ */
+typedef enum
+{
+ SDL_CONTROLLER_BUTTON_INVALID = -1,
+ SDL_CONTROLLER_BUTTON_A,
+ SDL_CONTROLLER_BUTTON_B,
+ SDL_CONTROLLER_BUTTON_X,
+ SDL_CONTROLLER_BUTTON_Y,
+ SDL_CONTROLLER_BUTTON_BACK,
+ SDL_CONTROLLER_BUTTON_GUIDE,
+ SDL_CONTROLLER_BUTTON_START,
+ SDL_CONTROLLER_BUTTON_LEFTSTICK,
+ SDL_CONTROLLER_BUTTON_RIGHTSTICK,
+ SDL_CONTROLLER_BUTTON_LEFTSHOULDER,
+ SDL_CONTROLLER_BUTTON_RIGHTSHOULDER,
+ SDL_CONTROLLER_BUTTON_DPAD_UP,
+ SDL_CONTROLLER_BUTTON_DPAD_DOWN,
+ SDL_CONTROLLER_BUTTON_DPAD_LEFT,
+ SDL_CONTROLLER_BUTTON_DPAD_RIGHT,
+ SDL_CONTROLLER_BUTTON_MISC1, /* Xbox Series X share button, PS5 microphone button, Nintendo Switch Pro capture button, Amazon Luna microphone button */
+ SDL_CONTROLLER_BUTTON_PADDLE1, /* Xbox Elite paddle P1 (upper left, facing the back) */
+ SDL_CONTROLLER_BUTTON_PADDLE2, /* Xbox Elite paddle P3 (upper right, facing the back) */
+ SDL_CONTROLLER_BUTTON_PADDLE3, /* Xbox Elite paddle P2 (lower left, facing the back) */
+ SDL_CONTROLLER_BUTTON_PADDLE4, /* Xbox Elite paddle P4 (lower right, facing the back) */
+ SDL_CONTROLLER_BUTTON_TOUCHPAD, /* PS4/PS5 touchpad button */
+ SDL_CONTROLLER_BUTTON_MAX
+} SDL_GameControllerButton;
+
+/**
+ * Convert a string into an SDL_GameControllerButton enum.
+ *
+ * This function is called internally to translate SDL_GameController mapping
+ * strings for the underlying joystick device into the consistent
+ * SDL_GameController mapping. You do not normally need to call this function
+ * unless you are parsing SDL_GameController mappings in your own code.
+ *
+ * \param str string representing a SDL_GameController axis
+ * \returns the SDL_GameControllerButton enum corresponding to the input
+ * string, or `SDL_CONTROLLER_AXIS_INVALID` if no match was found.
+ *
+ * \since This function is available since SDL 2.0.0.
+ */
+extern DECLSPEC SDL_GameControllerButton SDLCALL SDL_GameControllerGetButtonFromString(const char *str);
+
+/**
+ * Convert from an SDL_GameControllerButton enum to a string.
+ *
+ * The caller should not SDL_free() the returned string.
+ *
+ * \param button an enum value for a given SDL_GameControllerButton
+ * \returns a string for the given button, or NULL if an invalid button is
+ * specified. The string returned is of the format used by
+ * SDL_GameController mapping strings.
+ *
+ * \since This function is available since SDL 2.0.0.
+ *
+ * \sa SDL_GameControllerGetButtonFromString
+ */
+extern DECLSPEC const char* SDLCALL SDL_GameControllerGetStringForButton(SDL_GameControllerButton button);
+
+/**
+ * Get the SDL joystick layer binding for a controller button mapping.
+ *
+ * \param gamecontroller a game controller
+ * \param button an button enum value (an SDL_GameControllerButton value)
+ * \returns a SDL_GameControllerButtonBind describing the bind. On failure
+ * (like the given Controller button doesn't exist on the device),
+ * its `.bindType` will be `SDL_CONTROLLER_BINDTYPE_NONE`.
+ *
+ * \since This function is available since SDL 2.0.0.
+ *
+ * \sa SDL_GameControllerGetBindForAxis
+ */
+extern DECLSPEC SDL_GameControllerButtonBind SDLCALL
+SDL_GameControllerGetBindForButton(SDL_GameController *gamecontroller,
+ SDL_GameControllerButton button);
+
+/**
+ * Query whether a game controller has a given button.
+ *
+ * This merely reports whether the controller's mapping defined this button,
+ * as that is all the information SDL has about the physical device.
+ *
+ * \param gamecontroller a game controller
+ * \param button a button enum value (an SDL_GameControllerButton value)
+ * \returns SDL_TRUE if the controller has this button, SDL_FALSE otherwise.
+ *
+ * \since This function is available since SDL 2.0.14.
+ */
+extern DECLSPEC SDL_bool SDLCALL SDL_GameControllerHasButton(SDL_GameController *gamecontroller,
+ SDL_GameControllerButton button);
+
+/**
+ * Get the current state of a button on a game controller.
+ *
+ * \param gamecontroller a game controller
+ * \param button a button index (one of the SDL_GameControllerButton values)
+ * \returns 1 for pressed state or 0 for not pressed state or error; call
+ * SDL_GetError() for more information.
+ *
+ * \since This function is available since SDL 2.0.0.
+ *
+ * \sa SDL_GameControllerGetAxis
+ */
+extern DECLSPEC Uint8 SDLCALL SDL_GameControllerGetButton(SDL_GameController *gamecontroller,
+ SDL_GameControllerButton button);
+
+/**
+ * Get the number of touchpads on a game controller.
+ *
+ * \since This function is available since SDL 2.0.14.
+ */
+extern DECLSPEC int SDLCALL SDL_GameControllerGetNumTouchpads(SDL_GameController *gamecontroller);
+
+/**
+ * Get the number of supported simultaneous fingers on a touchpad on a game
+ * controller.
+ *
+ * \since This function is available since SDL 2.0.14.
+ */
+extern DECLSPEC int SDLCALL SDL_GameControllerGetNumTouchpadFingers(SDL_GameController *gamecontroller, int touchpad);
+
+/**
+ * Get the current state of a finger on a touchpad on a game controller.
+ *
+ * \since This function is available since SDL 2.0.14.
+ */
+extern DECLSPEC int SDLCALL SDL_GameControllerGetTouchpadFinger(SDL_GameController *gamecontroller, int touchpad, int finger, Uint8 *state, float *x, float *y, float *pressure);
+
+/**
+ * Return whether a game controller has a particular sensor.
+ *
+ * \param gamecontroller The controller to query
+ * \param type The type of sensor to query
+ * \returns SDL_TRUE if the sensor exists, SDL_FALSE otherwise.
+ *
+ * \since This function is available since SDL 2.0.14.
+ */
+extern DECLSPEC SDL_bool SDLCALL SDL_GameControllerHasSensor(SDL_GameController *gamecontroller, SDL_SensorType type);
+
+/**
+ * Set whether data reporting for a game controller sensor is enabled.
+ *
+ * \param gamecontroller The controller to update
+ * \param type The type of sensor to enable/disable
+ * \param enabled Whether data reporting should be enabled
+ * \returns 0 or -1 if an error occurred.
+ *
+ * \since This function is available since SDL 2.0.14.
+ */
+extern DECLSPEC int SDLCALL SDL_GameControllerSetSensorEnabled(SDL_GameController *gamecontroller, SDL_SensorType type, SDL_bool enabled);
+
+/**
+ * Query whether sensor data reporting is enabled for a game controller.
+ *
+ * \param gamecontroller The controller to query
+ * \param type The type of sensor to query
+ * \returns SDL_TRUE if the sensor is enabled, SDL_FALSE otherwise.
+ *
+ * \since This function is available since SDL 2.0.14.
+ */
+extern DECLSPEC SDL_bool SDLCALL SDL_GameControllerIsSensorEnabled(SDL_GameController *gamecontroller, SDL_SensorType type);
+
+/**
+ * Get the data rate (number of events per second) of a game controller
+ * sensor.
+ *
+ * \param gamecontroller The controller to query
+ * \param type The type of sensor to query
+ * \return the data rate, or 0.0f if the data rate is not available.
+ *
+ * \since This function is available since SDL 2.0.16.
+ */
+extern DECLSPEC float SDLCALL SDL_GameControllerGetSensorDataRate(SDL_GameController *gamecontroller, SDL_SensorType type);
+
+/**
+ * Get the current state of a game controller sensor.
+ *
+ * The number of values and interpretation of the data is sensor dependent.
+ * See SDL_sensor.h for the details for each type of sensor.
+ *
+ * \param gamecontroller The controller to query
+ * \param type The type of sensor to query
+ * \param data A pointer filled with the current sensor state
+ * \param num_values The number of values to write to data
+ * \return 0 or -1 if an error occurred.
+ *
+ * \since This function is available since SDL 2.0.14.
+ */
+extern DECLSPEC int SDLCALL SDL_GameControllerGetSensorData(SDL_GameController *gamecontroller, SDL_SensorType type, float *data, int num_values);
+
+/**
+ * Get the current state of a game controller sensor with the timestamp of the
+ * last update.
+ *
+ * The number of values and interpretation of the data is sensor dependent.
+ * See SDL_sensor.h for the details for each type of sensor.
+ *
+ * \param gamecontroller The controller to query
+ * \param type The type of sensor to query
+ * \param timestamp A pointer filled with the timestamp in microseconds of the
+ * current sensor reading if available, or 0 if not
+ * \param data A pointer filled with the current sensor state
+ * \param num_values The number of values to write to data
+ * \return 0 or -1 if an error occurred.
+ *
+ * \since This function is available since SDL 2.26.0.
+ */
+extern DECLSPEC int SDLCALL SDL_GameControllerGetSensorDataWithTimestamp(SDL_GameController *gamecontroller, SDL_SensorType type, Uint64 *timestamp, float *data, int num_values);
+
+/**
+ * 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.
+ *
+ * \param gamecontroller The controller to vibrate
+ * \param low_frequency_rumble The intensity of the low frequency (left)
+ * rumble motor, from 0 to 0xFFFF
+ * \param high_frequency_rumble The intensity of the high frequency (right)
+ * rumble motor, from 0 to 0xFFFF
+ * \param duration_ms The duration of the rumble effect, in milliseconds
+ * \returns 0, or -1 if rumble isn't supported on this controller
+ *
+ * \since This function is available since SDL 2.0.9.
+ *
+ * \sa SDL_GameControllerHasRumble
+ */
+extern DECLSPEC int SDLCALL SDL_GameControllerRumble(SDL_GameController *gamecontroller, Uint16 low_frequency_rumble, Uint16 high_frequency_rumble, Uint32 duration_ms);
+
+/**
+ * Start a rumble effect in the game controller's triggers.
+ *
+ * Each call to this function cancels any previous trigger rumble effect, and
+ * calling it with 0 intensity stops any rumbling.
+ *
+ * Note that this is rumbling of the _triggers_ and not the game controller as
+ * a whole. This is currently only supported on Xbox One controllers. If you
+ * want the (more common) whole-controller rumble, use
+ * SDL_GameControllerRumble() instead.
+ *
+ * \param gamecontroller The controller to vibrate
+ * \param left_rumble The intensity of the left trigger rumble motor, from 0
+ * to 0xFFFF
+ * \param right_rumble The intensity of the right trigger rumble motor, from 0
+ * to 0xFFFF
+ * \param duration_ms The duration of the rumble effect, in milliseconds
+ * \returns 0, or -1 if trigger rumble isn't supported on this controller
+ *
+ * \since This function is available since SDL 2.0.14.
+ *
+ * \sa SDL_GameControllerHasRumbleTriggers
+ */
+extern DECLSPEC int SDLCALL SDL_GameControllerRumbleTriggers(SDL_GameController *gamecontroller, Uint16 left_rumble, Uint16 right_rumble, Uint32 duration_ms);
+
+/**
+ * Query whether a game controller has an LED.
+ *
+ * \param gamecontroller The controller to query
+ * \returns SDL_TRUE, or SDL_FALSE if this controller does not have a
+ * modifiable LED
+ *
+ * \since This function is available since SDL 2.0.14.
+ */
+extern DECLSPEC SDL_bool SDLCALL SDL_GameControllerHasLED(SDL_GameController *gamecontroller);
+
+/**
+ * Query whether a game controller has rumble support.
+ *
+ * \param gamecontroller The controller to query
+ * \returns SDL_TRUE, or SDL_FALSE if this controller does not have rumble
+ * support
+ *
+ * \since This function is available since SDL 2.0.18.
+ *
+ * \sa SDL_GameControllerRumble
+ */
+extern DECLSPEC SDL_bool SDLCALL SDL_GameControllerHasRumble(SDL_GameController *gamecontroller);
+
+/**
+ * Query whether a game controller has rumble support on triggers.
+ *
+ * \param gamecontroller The controller to query
+ * \returns SDL_TRUE, or SDL_FALSE if this controller does not have trigger
+ * rumble support
+ *
+ * \since This function is available since SDL 2.0.18.
+ *
+ * \sa SDL_GameControllerRumbleTriggers
+ */
+extern DECLSPEC SDL_bool SDLCALL SDL_GameControllerHasRumbleTriggers(SDL_GameController *gamecontroller);
+
+/**
+ * Update a game controller's LED color.
+ *
+ * \param gamecontroller The controller to update
+ * \param red The intensity of the red LED
+ * \param green The intensity of the green LED
+ * \param blue The intensity of the blue LED
+ * \returns 0, or -1 if this controller does not have a modifiable LED
+ *
+ * \since This function is available since SDL 2.0.14.
+ */
+extern DECLSPEC int SDLCALL SDL_GameControllerSetLED(SDL_GameController *gamecontroller, Uint8 red, Uint8 green, Uint8 blue);
+
+/**
+ * Send a controller specific effect packet
+ *
+ * \param gamecontroller The controller to affect
+ * \param data The data to send to the controller
+ * \param size The size of the data to send to the controller
+ * \returns 0, or -1 if this controller or driver doesn't support effect
+ * packets
+ *
+ * \since This function is available since SDL 2.0.16.
+ */
+extern DECLSPEC int SDLCALL SDL_GameControllerSendEffect(SDL_GameController *gamecontroller, const void *data, int size);
+
+/**
+ * Close a game controller previously opened with SDL_GameControllerOpen().
+ *
+ * \param gamecontroller a game controller identifier previously returned by
+ * SDL_GameControllerOpen()
+ *
+ * \since This function is available since SDL 2.0.0.
+ *
+ * \sa SDL_GameControllerOpen
+ */
+extern DECLSPEC void SDLCALL SDL_GameControllerClose(SDL_GameController *gamecontroller);
+
+/**
+ * Return the sfSymbolsName for a given button on a game controller on Apple
+ * platforms.
+ *
+ * \param gamecontroller the controller to query
+ * \param button a button on the game controller
+ * \returns the sfSymbolsName or NULL if the name can't be found
+ *
+ * \since This function is available since SDL 2.0.18.
+ *
+ * \sa SDL_GameControllerGetAppleSFSymbolsNameForAxis
+ */
+extern DECLSPEC const char* SDLCALL SDL_GameControllerGetAppleSFSymbolsNameForButton(SDL_GameController *gamecontroller, SDL_GameControllerButton button);
+
+/**
+ * Return the sfSymbolsName for a given axis on a game controller on Apple
+ * platforms.
+ *
+ * \param gamecontroller the controller to query
+ * \param axis an axis on the game controller
+ * \returns the sfSymbolsName or NULL if the name can't be found
+ *
+ * \since This function is available since SDL 2.0.18.
+ *
+ * \sa SDL_GameControllerGetAppleSFSymbolsNameForButton
+ */
+extern DECLSPEC const char* SDLCALL SDL_GameControllerGetAppleSFSymbolsNameForAxis(SDL_GameController *gamecontroller, SDL_GameControllerAxis axis);
+
+
+/* Ends C function definitions when using C++ */
+#ifdef __cplusplus
+}
+#endif
+#include
+
+#endif /* SDL_gamecontroller_h_ */
+
+/* vi: set ts=4 sw=4 expandtab: */
diff --git a/bindings/sdl2wgpu/src/main/headers/SDL2/SDL_gesture.h b/bindings/sdl2wgpu/src/main/headers/SDL2/SDL_gesture.h
new file mode 100644
index 00000000..eee38475
--- /dev/null
+++ b/bindings/sdl2wgpu/src/main/headers/SDL2/SDL_gesture.h
@@ -0,0 +1,117 @@
+/*
+ Simple DirectMedia Layer
+ Copyright (C) 1997-2023 Sam Lantinga
+
+ This software is provided 'as-is', without any express or implied
+ warranty. In no event will the authors be held liable for any damages
+ arising from the use of this software.
+
+ Permission is granted to anyone to use this software for any purpose,
+ including commercial applications, and to alter it and redistribute it
+ freely, subject to the following restrictions:
+
+ 1. The origin of this software must not be misrepresented; you must not
+ claim that you wrote the original software. If you use this software
+ in a product, an acknowledgment in the product documentation would be
+ appreciated but is not required.
+ 2. Altered source versions must be plainly marked as such, and must not be
+ misrepresented as being the original software.
+ 3. This notice may not be removed or altered from any source distribution.
+*/
+
+/**
+ * \file SDL_gesture.h
+ *
+ * Include file for SDL gesture event handling.
+ */
+
+#ifndef SDL_gesture_h_
+#define SDL_gesture_h_
+
+#include
+#include
+#include
+
+#include
+
+
+#include
+/* Set up for C function definitions, even when using C++ */
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+typedef Sint64 SDL_GestureID;
+
+/* Function prototypes */
+
+/**
+ * Begin recording a gesture on a specified touch device or all touch devices.
+ *
+ * If the parameter `touchId` is -1 (i.e., all devices), this function will
+ * always return 1, regardless of whether there actually are any devices.
+ *
+ * \param touchId the touch device id, or -1 for all touch devices
+ * \returns 1 on success or 0 if the specified device could not be found.
+ *
+ * \since This function is available since SDL 2.0.0.
+ *
+ * \sa SDL_GetTouchDevice
+ */
+extern DECLSPEC int SDLCALL SDL_RecordGesture(SDL_TouchID touchId);
+
+
+/**
+ * Save all currently loaded Dollar Gesture templates.
+ *
+ * \param dst a SDL_RWops to save to
+ * \returns the number of saved templates on success or 0 on failure; call
+ * SDL_GetError() for more information.
+ *
+ * \since This function is available since SDL 2.0.0.
+ *
+ * \sa SDL_LoadDollarTemplates
+ * \sa SDL_SaveDollarTemplate
+ */
+extern DECLSPEC int SDLCALL SDL_SaveAllDollarTemplates(SDL_RWops *dst);
+
+/**
+ * Save a currently loaded Dollar Gesture template.
+ *
+ * \param gestureId a gesture id
+ * \param dst a SDL_RWops to save to
+ * \returns 1 on success or 0 on failure; call SDL_GetError() for more
+ * information.
+ *
+ * \since This function is available since SDL 2.0.0.
+ *
+ * \sa SDL_LoadDollarTemplates
+ * \sa SDL_SaveAllDollarTemplates
+ */
+extern DECLSPEC int SDLCALL SDL_SaveDollarTemplate(SDL_GestureID gestureId,SDL_RWops *dst);
+
+
+/**
+ * Load Dollar Gesture templates from a file.
+ *
+ * \param touchId a touch id
+ * \param src a SDL_RWops to load from
+ * \returns the number of loaded templates on success or a negative error code
+ * (or 0) on failure; call SDL_GetError() for more information.
+ *
+ * \since This function is available since SDL 2.0.0.
+ *
+ * \sa SDL_SaveAllDollarTemplates
+ * \sa SDL_SaveDollarTemplate
+ */
+extern DECLSPEC int SDLCALL SDL_LoadDollarTemplates(SDL_TouchID touchId, SDL_RWops *src);
+
+/* Ends C function definitions when using C++ */
+#ifdef __cplusplus
+}
+#endif
+#include
+
+#endif /* SDL_gesture_h_ */
+
+/* vi: set ts=4 sw=4 expandtab: */
diff --git a/bindings/sdl2wgpu/src/main/headers/SDL2/SDL_guid.h b/bindings/sdl2wgpu/src/main/headers/SDL2/SDL_guid.h
new file mode 100644
index 00000000..27c3dda7
--- /dev/null
+++ b/bindings/sdl2wgpu/src/main/headers/SDL2/SDL_guid.h
@@ -0,0 +1,100 @@
+/*
+ Simple DirectMedia Layer
+ Copyright (C) 1997-2023 Sam Lantinga
+
+ This software is provided 'as-is', without any express or implied
+ warranty. In no event will the authors be held liable for any damages
+ arising from the use of this software.
+
+ Permission is granted to anyone to use this software for any purpose,
+ including commercial applications, and to alter it and redistribute it
+ freely, subject to the following restrictions:
+
+ 1. The origin of this software must not be misrepresented; you must not
+ claim that you wrote the original software. If you use this software
+ in a product, an acknowledgment in the product documentation would be
+ appreciated but is not required.
+ 2. Altered source versions must be plainly marked as such, and must not be
+ misrepresented as being the original software.
+ 3. This notice may not be removed or altered from any source distribution.
+*/
+
+/**
+ * \file SDL_guid.h
+ *
+ * Include file for handling ::SDL_GUID values.
+ */
+
+#ifndef SDL_guid_h_
+#define SDL_guid_h_
+
+#include
+#include
+
+#include
+/* Set up for C function definitions, even when using C++ */
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * An SDL_GUID is a 128-bit identifier for an input device that
+ * identifies that device across runs of SDL programs on the same
+ * platform. If the device is detached and then re-attached to a
+ * different port, or if the base system is rebooted, the device
+ * should still report the same GUID.
+ *
+ * GUIDs are as precise as possible but are not guaranteed to
+ * distinguish physically distinct but equivalent devices. For
+ * example, two game controllers from the same vendor with the same
+ * product ID and revision may have the same GUID.
+ *
+ * GUIDs may be platform-dependent (i.e., the same device may report
+ * different GUIDs on different operating systems).
+ */
+typedef struct {
+ Uint8 data[16];
+} SDL_GUID;
+
+/* Function prototypes */
+
+/**
+ * Get an ASCII string representation for a given ::SDL_GUID.
+ *
+ * You should supply at least 33 bytes for pszGUID.
+ *
+ * \param guid the ::SDL_GUID you wish to convert to string
+ * \param pszGUID buffer in which to write the ASCII string
+ * \param cbGUID the size of pszGUID
+ *
+ * \since This function is available since SDL 2.24.0.
+ *
+ * \sa SDL_GUIDFromString
+ */
+extern DECLSPEC void SDLCALL SDL_GUIDToString(SDL_GUID guid, char *pszGUID, int cbGUID);
+
+/**
+ * Convert a GUID string into a ::SDL_GUID structure.
+ *
+ * Performs no error checking. If this function is given a string containing
+ * an invalid GUID, the function will silently succeed, but the GUID generated
+ * will not be useful.
+ *
+ * \param pchGUID string containing an ASCII representation of a GUID
+ * \returns a ::SDL_GUID structure.
+ *
+ * \since This function is available since SDL 2.24.0.
+ *
+ * \sa SDL_GUIDToString
+ */
+extern DECLSPEC SDL_GUID SDLCALL SDL_GUIDFromString(const char *pchGUID);
+
+/* Ends C function definitions when using C++ */
+#ifdef __cplusplus
+}
+#endif
+#include
+
+#endif /* SDL_guid_h_ */
+
+/* vi: set ts=4 sw=4 expandtab: */
diff --git a/bindings/sdl2wgpu/src/main/headers/SDL2/SDL_haptic.h b/bindings/sdl2wgpu/src/main/headers/SDL2/SDL_haptic.h
new file mode 100644
index 00000000..111d197a
--- /dev/null
+++ b/bindings/sdl2wgpu/src/main/headers/SDL2/SDL_haptic.h
@@ -0,0 +1,1341 @@
+/*
+ Simple DirectMedia Layer
+ Copyright (C) 1997-2023 Sam Lantinga
+
+ This software is provided 'as-is', without any express or implied
+ warranty. In no event will the authors be held liable for any damages
+ arising from the use of this software.
+
+ Permission is granted to anyone to use this software for any purpose,
+ including commercial applications, and to alter it and redistribute it
+ freely, subject to the following restrictions:
+
+ 1. The origin of this software must not be misrepresented; you must not
+ claim that you wrote the original software. If you use this software
+ in a product, an acknowledgment in the product documentation would be
+ appreciated but is not required.
+ 2. Altered source versions must be plainly marked as such, and must not be
+ misrepresented as being the original software.
+ 3. This notice may not be removed or altered from any source distribution.
+*/
+
+/**
+ * \file SDL_haptic.h
+ *
+ * \brief The SDL haptic subsystem allows you to control haptic (force feedback)
+ * devices.
+ *
+ * The basic usage is as follows:
+ * - Initialize the subsystem (::SDL_INIT_HAPTIC).
+ * - Open a haptic device.
+ * - SDL_HapticOpen() to open from index.
+ * - SDL_HapticOpenFromJoystick() to open from an existing joystick.
+ * - Create an effect (::SDL_HapticEffect).
+ * - Upload the effect with SDL_HapticNewEffect().
+ * - Run the effect with SDL_HapticRunEffect().
+ * - (optional) Free the effect with SDL_HapticDestroyEffect().
+ * - Close the haptic device with SDL_HapticClose().
+ *
+ * \par Simple rumble example:
+ * \code
+ * SDL_Haptic *haptic;
+ *
+ * // Open the device
+ * haptic = SDL_HapticOpen( 0 );
+ * if (haptic == NULL)
+ * return -1;
+ *
+ * // Initialize simple rumble
+ * if (SDL_HapticRumbleInit( haptic ) != 0)
+ * return -1;
+ *
+ * // Play effect at 50% strength for 2 seconds
+ * if (SDL_HapticRumblePlay( haptic, 0.5, 2000 ) != 0)
+ * return -1;
+ * SDL_Delay( 2000 );
+ *
+ * // Clean up
+ * SDL_HapticClose( haptic );
+ * \endcode
+ *
+ * \par Complete example:
+ * \code
+ * int test_haptic( SDL_Joystick * joystick ) {
+ * SDL_Haptic *haptic;
+ * SDL_HapticEffect effect;
+ * int effect_id;
+ *
+ * // Open the device
+ * haptic = SDL_HapticOpenFromJoystick( joystick );
+ * if (haptic == NULL) return -1; // Most likely joystick isn't haptic
+ *
+ * // See if it can do sine waves
+ * if ((SDL_HapticQuery(haptic) & SDL_HAPTIC_SINE)==0) {
+ * SDL_HapticClose(haptic); // No sine effect
+ * return -1;
+ * }
+ *
+ * // Create the effect
+ * SDL_memset( &effect, 0, sizeof(SDL_HapticEffect) ); // 0 is safe default
+ * effect.type = SDL_HAPTIC_SINE;
+ * effect.periodic.direction.type = SDL_HAPTIC_POLAR; // Polar coordinates
+ * effect.periodic.direction.dir[0] = 18000; // Force comes from south
+ * effect.periodic.period = 1000; // 1000 ms
+ * effect.periodic.magnitude = 20000; // 20000/32767 strength
+ * effect.periodic.length = 5000; // 5 seconds long
+ * effect.periodic.attack_length = 1000; // Takes 1 second to get max strength
+ * effect.periodic.fade_length = 1000; // Takes 1 second to fade away
+ *
+ * // Upload the effect
+ * effect_id = SDL_HapticNewEffect( haptic, &effect );
+ *
+ * // Test the effect
+ * SDL_HapticRunEffect( haptic, effect_id, 1 );
+ * SDL_Delay( 5000); // Wait for the effect to finish
+ *
+ * // We destroy the effect, although closing the device also does this
+ * SDL_HapticDestroyEffect( haptic, effect_id );
+ *
+ * // Close the device
+ * SDL_HapticClose(haptic);
+ *
+ * return 0; // Success
+ * }
+ * \endcode
+ */
+
+#ifndef SDL_haptic_h_
+#define SDL_haptic_h_
+
+#include
+#include
+#include
+
+#include
+/* Set up for C function definitions, even when using C++ */
+#ifdef __cplusplus
+extern "C" {
+#endif /* __cplusplus */
+
+/* FIXME: For SDL 2.1, adjust all the magnitude variables to be Uint16 (0xFFFF).
+ *
+ * At the moment the magnitude variables are mixed between signed/unsigned, and
+ * it is also not made clear that ALL of those variables expect a max of 0x7FFF.
+ *
+ * Some platforms may have higher precision than that (Linux FF, Windows XInput)
+ * so we should fix the inconsistency in favor of higher possible precision,
+ * adjusting for platforms that use different scales.
+ * -flibit
+ */
+
+/**
+ * \typedef SDL_Haptic
+ *
+ * \brief The haptic structure used to identify an SDL haptic.
+ *
+ * \sa SDL_HapticOpen
+ * \sa SDL_HapticOpenFromJoystick
+ * \sa SDL_HapticClose
+ */
+struct _SDL_Haptic;
+typedef struct _SDL_Haptic SDL_Haptic;
+
+
+/**
+ * \name Haptic features
+ *
+ * Different haptic features a device can have.
+ */
+/* @{ */
+
+/**
+ * \name Haptic effects
+ */
+/* @{ */
+
+/**
+ * \brief Constant effect supported.
+ *
+ * Constant haptic effect.
+ *
+ * \sa SDL_HapticCondition
+ */
+#define SDL_HAPTIC_CONSTANT (1u<<0)
+
+/**
+ * \brief Sine wave effect supported.
+ *
+ * Periodic haptic effect that simulates sine waves.
+ *
+ * \sa SDL_HapticPeriodic
+ */
+#define SDL_HAPTIC_SINE (1u<<1)
+
+/**
+ * \brief Left/Right effect supported.
+ *
+ * Haptic effect for direct control over high/low frequency motors.
+ *
+ * \sa SDL_HapticLeftRight
+ * \warning this value was SDL_HAPTIC_SQUARE right before 2.0.0 shipped. Sorry,
+ * we ran out of bits, and this is important for XInput devices.
+ */
+#define SDL_HAPTIC_LEFTRIGHT (1u<<2)
+
+/* !!! FIXME: put this back when we have more bits in 2.1 */
+/* #define SDL_HAPTIC_SQUARE (1<<2) */
+
+/**
+ * \brief Triangle wave effect supported.
+ *
+ * Periodic haptic effect that simulates triangular waves.
+ *
+ * \sa SDL_HapticPeriodic
+ */
+#define SDL_HAPTIC_TRIANGLE (1u<<3)
+
+/**
+ * \brief Sawtoothup wave effect supported.
+ *
+ * Periodic haptic effect that simulates saw tooth up waves.
+ *
+ * \sa SDL_HapticPeriodic
+ */
+#define SDL_HAPTIC_SAWTOOTHUP (1u<<4)
+
+/**
+ * \brief Sawtoothdown wave effect supported.
+ *
+ * Periodic haptic effect that simulates saw tooth down waves.
+ *
+ * \sa SDL_HapticPeriodic
+ */
+#define SDL_HAPTIC_SAWTOOTHDOWN (1u<<5)
+
+/**
+ * \brief Ramp effect supported.
+ *
+ * Ramp haptic effect.
+ *
+ * \sa SDL_HapticRamp
+ */
+#define SDL_HAPTIC_RAMP (1u<<6)
+
+/**
+ * \brief Spring effect supported - uses axes position.
+ *
+ * Condition haptic effect that simulates a spring. Effect is based on the
+ * axes position.
+ *
+ * \sa SDL_HapticCondition
+ */
+#define SDL_HAPTIC_SPRING (1u<<7)
+
+/**
+ * \brief Damper effect supported - uses axes velocity.
+ *
+ * Condition haptic effect that simulates dampening. Effect is based on the
+ * axes velocity.
+ *
+ * \sa SDL_HapticCondition
+ */
+#define SDL_HAPTIC_DAMPER (1u<<8)
+
+/**
+ * \brief Inertia effect supported - uses axes acceleration.
+ *
+ * Condition haptic effect that simulates inertia. Effect is based on the axes
+ * acceleration.
+ *
+ * \sa SDL_HapticCondition
+ */
+#define SDL_HAPTIC_INERTIA (1u<<9)
+
+/**
+ * \brief Friction effect supported - uses axes movement.
+ *
+ * Condition haptic effect that simulates friction. Effect is based on the
+ * axes movement.
+ *
+ * \sa SDL_HapticCondition
+ */
+#define SDL_HAPTIC_FRICTION (1u<<10)
+
+/**
+ * \brief Custom effect is supported.
+ *
+ * User defined custom haptic effect.
+ */
+#define SDL_HAPTIC_CUSTOM (1u<<11)
+
+/* @} *//* Haptic effects */
+
+/* These last few are features the device has, not effects */
+
+/**
+ * \brief Device can set global gain.
+ *
+ * Device supports setting the global gain.
+ *
+ * \sa SDL_HapticSetGain
+ */
+#define SDL_HAPTIC_GAIN (1u<<12)
+
+/**
+ * \brief Device can set autocenter.
+ *
+ * Device supports setting autocenter.
+ *
+ * \sa SDL_HapticSetAutocenter
+ */
+#define SDL_HAPTIC_AUTOCENTER (1u<<13)
+
+/**
+ * \brief Device can be queried for effect status.
+ *
+ * Device supports querying effect status.
+ *
+ * \sa SDL_HapticGetEffectStatus
+ */
+#define SDL_HAPTIC_STATUS (1u<<14)
+
+/**
+ * \brief Device can be paused.
+ *
+ * Devices supports being paused.
+ *
+ * \sa SDL_HapticPause
+ * \sa SDL_HapticUnpause
+ */
+#define SDL_HAPTIC_PAUSE (1u<<15)
+
+
+/**
+ * \name Direction encodings
+ */
+/* @{ */
+
+/**
+ * \brief Uses polar coordinates for the direction.
+ *
+ * \sa SDL_HapticDirection
+ */
+#define SDL_HAPTIC_POLAR 0
+
+/**
+ * \brief Uses cartesian coordinates for the direction.
+ *
+ * \sa SDL_HapticDirection
+ */
+#define SDL_HAPTIC_CARTESIAN 1
+
+/**
+ * \brief Uses spherical coordinates for the direction.
+ *
+ * \sa SDL_HapticDirection
+ */
+#define SDL_HAPTIC_SPHERICAL 2
+
+/**
+ * \brief Use this value to play an effect on the steering wheel axis. This
+ * provides better compatibility across platforms and devices as SDL will guess
+ * the correct axis.
+ * \sa SDL_HapticDirection
+ */
+#define SDL_HAPTIC_STEERING_AXIS 3
+
+/* @} *//* Direction encodings */
+
+/* @} *//* Haptic features */
+
+/*
+ * Misc defines.
+ */
+
+/**
+ * \brief Used to play a device an infinite number of times.
+ *
+ * \sa SDL_HapticRunEffect
+ */
+#define SDL_HAPTIC_INFINITY 4294967295U
+
+
+/**
+ * \brief Structure that represents a haptic direction.
+ *
+ * This is the direction where the force comes from,
+ * instead of the direction in which the force is exerted.
+ *
+ * Directions can be specified by:
+ * - ::SDL_HAPTIC_POLAR : Specified by polar coordinates.
+ * - ::SDL_HAPTIC_CARTESIAN : Specified by cartesian coordinates.
+ * - ::SDL_HAPTIC_SPHERICAL : Specified by spherical coordinates.
+ *
+ * Cardinal directions of the haptic device are relative to the positioning
+ * of the device. North is considered to be away from the user.
+ *
+ * The following diagram represents the cardinal directions:
+ * \verbatim
+ .--.
+ |__| .-------.
+ |=.| |.-----.|
+ |--| || ||
+ | | |'-----'|
+ |__|~')_____('
+ [ COMPUTER ]
+
+
+ North (0,-1)
+ ^
+ |
+ |
+ (-1,0) West <----[ HAPTIC ]----> East (1,0)
+ |
+ |
+ v
+ South (0,1)
+
+
+ [ USER ]
+ \|||/
+ (o o)
+ ---ooO-(_)-Ooo---
+ \endverbatim
+ *
+ * If type is ::SDL_HAPTIC_POLAR, direction is encoded by hundredths of a
+ * degree starting north and turning clockwise. ::SDL_HAPTIC_POLAR only uses
+ * the first \c dir parameter. The cardinal directions would be:
+ * - North: 0 (0 degrees)
+ * - East: 9000 (90 degrees)
+ * - South: 18000 (180 degrees)
+ * - West: 27000 (270 degrees)
+ *
+ * If type is ::SDL_HAPTIC_CARTESIAN, direction is encoded by three positions
+ * (X axis, Y axis and Z axis (with 3 axes)). ::SDL_HAPTIC_CARTESIAN uses
+ * the first three \c dir parameters. The cardinal directions would be:
+ * - North: 0,-1, 0
+ * - East: 1, 0, 0
+ * - South: 0, 1, 0
+ * - West: -1, 0, 0
+ *
+ * The Z axis represents the height of the effect if supported, otherwise
+ * it's unused. In cartesian encoding (1, 2) would be the same as (2, 4), you
+ * can use any multiple you want, only the direction matters.
+ *
+ * If type is ::SDL_HAPTIC_SPHERICAL, direction is encoded by two rotations.
+ * The first two \c dir parameters are used. The \c dir parameters are as
+ * follows (all values are in hundredths of degrees):
+ * - Degrees from (1, 0) rotated towards (0, 1).
+ * - Degrees towards (0, 0, 1) (device needs at least 3 axes).
+ *
+ *
+ * Example of force coming from the south with all encodings (force coming
+ * from the south means the user will have to pull the stick to counteract):
+ * \code
+ * SDL_HapticDirection direction;
+ *
+ * // Cartesian directions
+ * direction.type = SDL_HAPTIC_CARTESIAN; // Using cartesian direction encoding.
+ * direction.dir[0] = 0; // X position
+ * direction.dir[1] = 1; // Y position
+ * // Assuming the device has 2 axes, we don't need to specify third parameter.
+ *
+ * // Polar directions
+ * direction.type = SDL_HAPTIC_POLAR; // We'll be using polar direction encoding.
+ * direction.dir[0] = 18000; // Polar only uses first parameter
+ *
+ * // Spherical coordinates
+ * direction.type = SDL_HAPTIC_SPHERICAL; // Spherical encoding
+ * direction.dir[0] = 9000; // Since we only have two axes we don't need more parameters.
+ * \endcode
+ *
+ * \sa SDL_HAPTIC_POLAR
+ * \sa SDL_HAPTIC_CARTESIAN
+ * \sa SDL_HAPTIC_SPHERICAL
+ * \sa SDL_HAPTIC_STEERING_AXIS
+ * \sa SDL_HapticEffect
+ * \sa SDL_HapticNumAxes
+ */
+typedef struct SDL_HapticDirection
+{
+ Uint8 type; /**< The type of encoding. */
+ Sint32 dir[3]; /**< The encoded direction. */
+} SDL_HapticDirection;
+
+
+/**
+ * \brief A structure containing a template for a Constant effect.
+ *
+ * This struct is exclusively for the ::SDL_HAPTIC_CONSTANT effect.
+ *
+ * A constant effect applies a constant force in the specified direction
+ * to the joystick.
+ *
+ * \sa SDL_HAPTIC_CONSTANT
+ * \sa SDL_HapticEffect
+ */
+typedef struct SDL_HapticConstant
+{
+ /* Header */
+ Uint16 type; /**< ::SDL_HAPTIC_CONSTANT */
+ SDL_HapticDirection direction; /**< Direction of the effect. */
+
+ /* Replay */
+ Uint32 length; /**< Duration of the effect. */
+ Uint16 delay; /**< Delay before starting the effect. */
+
+ /* Trigger */
+ Uint16 button; /**< Button that triggers the effect. */
+ Uint16 interval; /**< How soon it can be triggered again after button. */
+
+ /* Constant */
+ Sint16 level; /**< Strength of the constant effect. */
+
+ /* Envelope */
+ Uint16 attack_length; /**< Duration of the attack. */
+ Uint16 attack_level; /**< Level at the start of the attack. */
+ Uint16 fade_length; /**< Duration of the fade. */
+ Uint16 fade_level; /**< Level at the end of the fade. */
+} SDL_HapticConstant;
+
+/**
+ * \brief A structure containing a template for a Periodic effect.
+ *
+ * The struct handles the following effects:
+ * - ::SDL_HAPTIC_SINE
+ * - ::SDL_HAPTIC_LEFTRIGHT
+ * - ::SDL_HAPTIC_TRIANGLE
+ * - ::SDL_HAPTIC_SAWTOOTHUP
+ * - ::SDL_HAPTIC_SAWTOOTHDOWN
+ *
+ * A periodic effect consists in a wave-shaped effect that repeats itself
+ * over time. The type determines the shape of the wave and the parameters
+ * determine the dimensions of the wave.
+ *
+ * Phase is given by hundredth of a degree meaning that giving the phase a value
+ * of 9000 will displace it 25% of its period. Here are sample values:
+ * - 0: No phase displacement.
+ * - 9000: Displaced 25% of its period.
+ * - 18000: Displaced 50% of its period.
+ * - 27000: Displaced 75% of its period.
+ * - 36000: Displaced 100% of its period, same as 0, but 0 is preferred.
+ *
+ * Examples:
+ * \verbatim
+ SDL_HAPTIC_SINE
+ __ __ __ __
+ / \ / \ / \ /
+ / \__/ \__/ \__/
+
+ SDL_HAPTIC_SQUARE
+ __ __ __ __ __
+ | | | | | | | | | |
+ | |__| |__| |__| |__| |
+
+ SDL_HAPTIC_TRIANGLE
+ /\ /\ /\ /\ /\
+ / \ / \ / \ / \ /
+ / \/ \/ \/ \/
+
+ SDL_HAPTIC_SAWTOOTHUP
+ /| /| /| /| /| /| /|
+ / | / | / | / | / | / | / |
+ / |/ |/ |/ |/ |/ |/ |
+
+ SDL_HAPTIC_SAWTOOTHDOWN
+ \ |\ |\ |\ |\ |\ |\ |
+ \ | \ | \ | \ | \ | \ | \ |
+ \| \| \| \| \| \| \|
+ \endverbatim
+ *
+ * \sa SDL_HAPTIC_SINE
+ * \sa SDL_HAPTIC_LEFTRIGHT
+ * \sa SDL_HAPTIC_TRIANGLE
+ * \sa SDL_HAPTIC_SAWTOOTHUP
+ * \sa SDL_HAPTIC_SAWTOOTHDOWN
+ * \sa SDL_HapticEffect
+ */
+typedef struct SDL_HapticPeriodic
+{
+ /* Header */
+ Uint16 type; /**< ::SDL_HAPTIC_SINE, ::SDL_HAPTIC_LEFTRIGHT,
+ ::SDL_HAPTIC_TRIANGLE, ::SDL_HAPTIC_SAWTOOTHUP or
+ ::SDL_HAPTIC_SAWTOOTHDOWN */
+ SDL_HapticDirection direction; /**< Direction of the effect. */
+
+ /* Replay */
+ Uint32 length; /**< Duration of the effect. */
+ Uint16 delay; /**< Delay before starting the effect. */
+
+ /* Trigger */
+ Uint16 button; /**< Button that triggers the effect. */
+ Uint16 interval; /**< How soon it can be triggered again after button. */
+
+ /* Periodic */
+ Uint16 period; /**< Period of the wave. */
+ Sint16 magnitude; /**< Peak value; if negative, equivalent to 180 degrees extra phase shift. */
+ Sint16 offset; /**< Mean value of the wave. */
+ Uint16 phase; /**< Positive phase shift given by hundredth of a degree. */
+
+ /* Envelope */
+ Uint16 attack_length; /**< Duration of the attack. */
+ Uint16 attack_level; /**< Level at the start of the attack. */
+ Uint16 fade_length; /**< Duration of the fade. */
+ Uint16 fade_level; /**< Level at the end of the fade. */
+} SDL_HapticPeriodic;
+
+/**
+ * \brief A structure containing a template for a Condition effect.
+ *
+ * The struct handles the following effects:
+ * - ::SDL_HAPTIC_SPRING: Effect based on axes position.
+ * - ::SDL_HAPTIC_DAMPER: Effect based on axes velocity.
+ * - ::SDL_HAPTIC_INERTIA: Effect based on axes acceleration.
+ * - ::SDL_HAPTIC_FRICTION: Effect based on axes movement.
+ *
+ * Direction is handled by condition internals instead of a direction member.
+ * The condition effect specific members have three parameters. The first
+ * refers to the X axis, the second refers to the Y axis and the third
+ * refers to the Z axis. The right terms refer to the positive side of the
+ * axis and the left terms refer to the negative side of the axis. Please
+ * refer to the ::SDL_HapticDirection diagram for which side is positive and
+ * which is negative.
+ *
+ * \sa SDL_HapticDirection
+ * \sa SDL_HAPTIC_SPRING
+ * \sa SDL_HAPTIC_DAMPER
+ * \sa SDL_HAPTIC_INERTIA
+ * \sa SDL_HAPTIC_FRICTION
+ * \sa SDL_HapticEffect
+ */
+typedef struct SDL_HapticCondition
+{
+ /* Header */
+ Uint16 type; /**< ::SDL_HAPTIC_SPRING, ::SDL_HAPTIC_DAMPER,
+ ::SDL_HAPTIC_INERTIA or ::SDL_HAPTIC_FRICTION */
+ SDL_HapticDirection direction; /**< Direction of the effect - Not used ATM. */
+
+ /* Replay */
+ Uint32 length; /**< Duration of the effect. */
+ Uint16 delay; /**< Delay before starting the effect. */
+
+ /* Trigger */
+ Uint16 button; /**< Button that triggers the effect. */
+ Uint16 interval; /**< How soon it can be triggered again after button. */
+
+ /* Condition */
+ Uint16 right_sat[3]; /**< Level when joystick is to the positive side; max 0xFFFF. */
+ Uint16 left_sat[3]; /**< Level when joystick is to the negative side; max 0xFFFF. */
+ Sint16 right_coeff[3]; /**< How fast to increase the force towards the positive side. */
+ Sint16 left_coeff[3]; /**< How fast to increase the force towards the negative side. */
+ Uint16 deadband[3]; /**< Size of the dead zone; max 0xFFFF: whole axis-range when 0-centered. */
+ Sint16 center[3]; /**< Position of the dead zone. */
+} SDL_HapticCondition;
+
+/**
+ * \brief A structure containing a template for a Ramp effect.
+ *
+ * This struct is exclusively for the ::SDL_HAPTIC_RAMP effect.
+ *
+ * The ramp effect starts at start strength and ends at end strength.
+ * It augments in linear fashion. If you use attack and fade with a ramp
+ * the effects get added to the ramp effect making the effect become
+ * quadratic instead of linear.
+ *
+ * \sa SDL_HAPTIC_RAMP
+ * \sa SDL_HapticEffect
+ */
+typedef struct SDL_HapticRamp
+{
+ /* Header */
+ Uint16 type; /**< ::SDL_HAPTIC_RAMP */
+ SDL_HapticDirection direction; /**< Direction of the effect. */
+
+ /* Replay */
+ Uint32 length; /**< Duration of the effect. */
+ Uint16 delay; /**< Delay before starting the effect. */
+
+ /* Trigger */
+ Uint16 button; /**< Button that triggers the effect. */
+ Uint16 interval; /**< How soon it can be triggered again after button. */
+
+ /* Ramp */
+ Sint16 start; /**< Beginning strength level. */
+ Sint16 end; /**< Ending strength level. */
+
+ /* Envelope */
+ Uint16 attack_length; /**< Duration of the attack. */
+ Uint16 attack_level; /**< Level at the start of the attack. */
+ Uint16 fade_length; /**< Duration of the fade. */
+ Uint16 fade_level; /**< Level at the end of the fade. */
+} SDL_HapticRamp;
+
+/**
+ * \brief A structure containing a template for a Left/Right effect.
+ *
+ * This struct is exclusively for the ::SDL_HAPTIC_LEFTRIGHT effect.
+ *
+ * The Left/Right effect is used to explicitly control the large and small
+ * motors, commonly found in modern game controllers. The small (right) motor
+ * is high frequency, and the large (left) motor is low frequency.
+ *
+ * \sa SDL_HAPTIC_LEFTRIGHT
+ * \sa SDL_HapticEffect
+ */
+typedef struct SDL_HapticLeftRight
+{
+ /* Header */
+ Uint16 type; /**< ::SDL_HAPTIC_LEFTRIGHT */
+
+ /* Replay */
+ Uint32 length; /**< Duration of the effect in milliseconds. */
+
+ /* Rumble */
+ Uint16 large_magnitude; /**< Control of the large controller motor. */
+ Uint16 small_magnitude; /**< Control of the small controller motor. */
+} SDL_HapticLeftRight;
+
+/**
+ * \brief A structure containing a template for the ::SDL_HAPTIC_CUSTOM effect.
+ *
+ * This struct is exclusively for the ::SDL_HAPTIC_CUSTOM effect.
+ *
+ * A custom force feedback effect is much like a periodic effect, where the
+ * application can define its exact shape. You will have to allocate the
+ * data yourself. Data should consist of channels * samples Uint16 samples.
+ *
+ * If channels is one, the effect is rotated using the defined direction.
+ * Otherwise it uses the samples in data for the different axes.
+ *
+ * \sa SDL_HAPTIC_CUSTOM
+ * \sa SDL_HapticEffect
+ */
+typedef struct SDL_HapticCustom
+{
+ /* Header */
+ Uint16 type; /**< ::SDL_HAPTIC_CUSTOM */
+ SDL_HapticDirection direction; /**< Direction of the effect. */
+
+ /* Replay */
+ Uint32 length; /**< Duration of the effect. */
+ Uint16 delay; /**< Delay before starting the effect. */
+
+ /* Trigger */
+ Uint16 button; /**< Button that triggers the effect. */
+ Uint16 interval; /**< How soon it can be triggered again after button. */
+
+ /* Custom */
+ Uint8 channels; /**< Axes to use, minimum of one. */
+ Uint16 period; /**< Sample periods. */
+ Uint16 samples; /**< Amount of samples. */
+ Uint16 *data; /**< Should contain channels*samples items. */
+
+ /* Envelope */
+ Uint16 attack_length; /**< Duration of the attack. */
+ Uint16 attack_level; /**< Level at the start of the attack. */
+ Uint16 fade_length; /**< Duration of the fade. */
+ Uint16 fade_level; /**< Level at the end of the fade. */
+} SDL_HapticCustom;
+
+/**
+ * \brief The generic template for any haptic effect.
+ *
+ * All values max at 32767 (0x7FFF). Signed values also can be negative.
+ * Time values unless specified otherwise are in milliseconds.
+ *
+ * You can also pass ::SDL_HAPTIC_INFINITY to length instead of a 0-32767
+ * value. Neither delay, interval, attack_length nor fade_length support
+ * ::SDL_HAPTIC_INFINITY. Fade will also not be used since effect never ends.
+ *
+ * Additionally, the ::SDL_HAPTIC_RAMP effect does not support a duration of
+ * ::SDL_HAPTIC_INFINITY.
+ *
+ * Button triggers may not be supported on all devices, it is advised to not
+ * use them if possible. Buttons start at index 1 instead of index 0 like
+ * the joystick.
+ *
+ * If both attack_length and fade_level are 0, the envelope is not used,
+ * otherwise both values are used.
+ *
+ * Common parts:
+ * \code
+ * // Replay - All effects have this
+ * Uint32 length; // Duration of effect (ms).
+ * Uint16 delay; // Delay before starting effect.
+ *
+ * // Trigger - All effects have this
+ * Uint16 button; // Button that triggers effect.
+ * Uint16 interval; // How soon before effect can be triggered again.
+ *
+ * // Envelope - All effects except condition effects have this
+ * Uint16 attack_length; // Duration of the attack (ms).
+ * Uint16 attack_level; // Level at the start of the attack.
+ * Uint16 fade_length; // Duration of the fade out (ms).
+ * Uint16 fade_level; // Level at the end of the fade.
+ * \endcode
+ *
+ *
+ * Here we have an example of a constant effect evolution in time:
+ * \verbatim
+ Strength
+ ^
+ |
+ | effect level --> _________________
+ | / \
+ | / \
+ | / \
+ | / \
+ | attack_level --> | \
+ | | | <--- fade_level
+ |
+ +--------------------------------------------------> Time
+ [--] [---]
+ attack_length fade_length
+
+ [------------------][-----------------------]
+ delay length
+ \endverbatim
+ *
+ * Note either the attack_level or the fade_level may be above the actual
+ * effect level.
+ *
+ * \sa SDL_HapticConstant
+ * \sa SDL_HapticPeriodic
+ * \sa SDL_HapticCondition
+ * \sa SDL_HapticRamp
+ * \sa SDL_HapticLeftRight
+ * \sa SDL_HapticCustom
+ */
+typedef union SDL_HapticEffect
+{
+ /* Common for all force feedback effects */
+ Uint16 type; /**< Effect type. */
+ SDL_HapticConstant constant; /**< Constant effect. */
+ SDL_HapticPeriodic periodic; /**< Periodic effect. */
+ SDL_HapticCondition condition; /**< Condition effect. */
+ SDL_HapticRamp ramp; /**< Ramp effect. */
+ SDL_HapticLeftRight leftright; /**< Left/Right effect. */
+ SDL_HapticCustom custom; /**< Custom effect. */
+} SDL_HapticEffect;
+
+
+/* Function prototypes */
+
+/**
+ * Count the number of haptic devices attached to the system.
+ *
+ * \returns the number of haptic devices detected on the system or a negative
+ * error code on failure; call SDL_GetError() for more information.
+ *
+ * \since This function is available since SDL 2.0.0.
+ *
+ * \sa SDL_HapticName
+ */
+extern DECLSPEC int SDLCALL SDL_NumHaptics(void);
+
+/**
+ * Get the implementation dependent name of a haptic device.
+ *
+ * This can be called before any joysticks are opened. If no name can be
+ * found, this function returns NULL.
+ *
+ * \param device_index index of the device to query.
+ * \returns the name of the device or NULL on failure; call SDL_GetError() for
+ * more information.
+ *
+ * \since This function is available since SDL 2.0.0.
+ *
+ * \sa SDL_NumHaptics
+ */
+extern DECLSPEC const char *SDLCALL SDL_HapticName(int device_index);
+
+/**
+ * Open a haptic device for use.
+ *
+ * The index passed as an argument refers to the N'th haptic device on this
+ * system.
+ *
+ * When opening a haptic device, its gain will be set to maximum and
+ * autocenter will be disabled. To modify these values use SDL_HapticSetGain()
+ * and SDL_HapticSetAutocenter().
+ *
+ * \param device_index index of the device to open
+ * \returns the device identifier or NULL on failure; call SDL_GetError() for
+ * more information.
+ *
+ * \since This function is available since SDL 2.0.0.
+ *
+ * \sa SDL_HapticClose
+ * \sa SDL_HapticIndex
+ * \sa SDL_HapticOpenFromJoystick
+ * \sa SDL_HapticOpenFromMouse
+ * \sa SDL_HapticPause
+ * \sa SDL_HapticSetAutocenter
+ * \sa SDL_HapticSetGain
+ * \sa SDL_HapticStopAll
+ */
+extern DECLSPEC SDL_Haptic *SDLCALL SDL_HapticOpen(int device_index);
+
+/**
+ * Check if the haptic device at the designated index has been opened.
+ *
+ * \param device_index the index of the device to query
+ * \returns 1 if it has been opened, 0 if it hasn't or on failure; call
+ * SDL_GetError() for more information.
+ *
+ * \since This function is available since SDL 2.0.0.
+ *
+ * \sa SDL_HapticIndex
+ * \sa SDL_HapticOpen
+ */
+extern DECLSPEC int SDLCALL SDL_HapticOpened(int device_index);
+
+/**
+ * Get the index of a haptic device.
+ *
+ * \param haptic the SDL_Haptic device to query
+ * \returns the index of the specified haptic device or a negative error code
+ * on failure; call SDL_GetError() for more information.
+ *
+ * \since This function is available since SDL 2.0.0.
+ *
+ * \sa SDL_HapticOpen
+ * \sa SDL_HapticOpened
+ */
+extern DECLSPEC int SDLCALL SDL_HapticIndex(SDL_Haptic * haptic);
+
+/**
+ * Query whether or not the current mouse has haptic capabilities.
+ *
+ * \returns SDL_TRUE if the mouse is haptic or SDL_FALSE if it isn't.
+ *
+ * \since This function is available since SDL 2.0.0.
+ *
+ * \sa SDL_HapticOpenFromMouse
+ */
+extern DECLSPEC int SDLCALL SDL_MouseIsHaptic(void);
+
+/**
+ * Try to open a haptic device from the current mouse.
+ *
+ * \returns the haptic device identifier or NULL on failure; call
+ * SDL_GetError() for more information.
+ *
+ * \since This function is available since SDL 2.0.0.
+ *
+ * \sa SDL_HapticOpen
+ * \sa SDL_MouseIsHaptic
+ */
+extern DECLSPEC SDL_Haptic *SDLCALL SDL_HapticOpenFromMouse(void);
+
+/**
+ * Query if a joystick has haptic features.
+ *
+ * \param joystick the SDL_Joystick to test for haptic capabilities
+ * \returns SDL_TRUE if the joystick is haptic, SDL_FALSE if it isn't, or a
+ * negative error code on failure; call SDL_GetError() for more
+ * information.
+ *
+ * \since This function is available since SDL 2.0.0.
+ *
+ * \sa SDL_HapticOpenFromJoystick
+ */
+extern DECLSPEC int SDLCALL SDL_JoystickIsHaptic(SDL_Joystick * joystick);
+
+/**
+ * Open a haptic device for use from a joystick device.
+ *
+ * You must still close the haptic device separately. It will not be closed
+ * with the joystick.
+ *
+ * When opened from a joystick you should first close the haptic device before
+ * closing the joystick device. If not, on some implementations the haptic
+ * device will also get unallocated and you'll be unable to use force feedback
+ * on that device.
+ *
+ * \param joystick the SDL_Joystick to create a haptic device from
+ * \returns a valid haptic device identifier on success or NULL on failure;
+ * call SDL_GetError() for more information.
+ *
+ * \since This function is available since SDL 2.0.0.
+ *
+ * \sa SDL_HapticClose
+ * \sa SDL_HapticOpen
+ * \sa SDL_JoystickIsHaptic
+ */
+extern DECLSPEC SDL_Haptic *SDLCALL SDL_HapticOpenFromJoystick(SDL_Joystick *
+ joystick);
+
+/**
+ * Close a haptic device previously opened with SDL_HapticOpen().
+ *
+ * \param haptic the SDL_Haptic device to close
+ *
+ * \since This function is available since SDL 2.0.0.
+ *
+ * \sa SDL_HapticOpen
+ */
+extern DECLSPEC void SDLCALL SDL_HapticClose(SDL_Haptic * haptic);
+
+/**
+ * Get the number of effects a haptic device can store.
+ *
+ * On some platforms this isn't fully supported, and therefore is an
+ * approximation. Always check to see if your created effect was actually
+ * created and do not rely solely on SDL_HapticNumEffects().
+ *
+ * \param haptic the SDL_Haptic device to query
+ * \returns the number of effects the haptic device can store or a negative
+ * error code on failure; call SDL_GetError() for more information.
+ *
+ * \since This function is available since SDL 2.0.0.
+ *
+ * \sa SDL_HapticNumEffectsPlaying
+ * \sa SDL_HapticQuery
+ */
+extern DECLSPEC int SDLCALL SDL_HapticNumEffects(SDL_Haptic * haptic);
+
+/**
+ * Get the number of effects a haptic device can play at the same time.
+ *
+ * This is not supported on all platforms, but will always return a value.
+ *
+ * \param haptic the SDL_Haptic device to query maximum playing effects
+ * \returns the number of effects the haptic device can play at the same time
+ * or a negative error code on failure; call SDL_GetError() for more
+ * information.
+ *
+ * \since This function is available since SDL 2.0.0.
+ *
+ * \sa SDL_HapticNumEffects
+ * \sa SDL_HapticQuery
+ */
+extern DECLSPEC int SDLCALL SDL_HapticNumEffectsPlaying(SDL_Haptic * haptic);
+
+/**
+ * Get the haptic device's supported features in bitwise manner.
+ *
+ * \param haptic the SDL_Haptic device to query
+ * \returns a list of supported haptic features in bitwise manner (OR'd), or 0
+ * on failure; call SDL_GetError() for more information.
+ *
+ * \since This function is available since SDL 2.0.0.
+ *
+ * \sa SDL_HapticEffectSupported
+ * \sa SDL_HapticNumEffects
+ */
+extern DECLSPEC unsigned int SDLCALL SDL_HapticQuery(SDL_Haptic * haptic);
+
+
+/**
+ * Get the number of haptic axes the device has.
+ *
+ * The number of haptic axes might be useful if working with the
+ * SDL_HapticDirection effect.
+ *
+ * \param haptic the SDL_Haptic device to query
+ * \returns the number of axes on success or a negative error code on failure;
+ * call SDL_GetError() for more information.
+ *
+ * \since This function is available since SDL 2.0.0.
+ */
+extern DECLSPEC int SDLCALL SDL_HapticNumAxes(SDL_Haptic * haptic);
+
+/**
+ * Check to see if an effect is supported by a haptic device.
+ *
+ * \param haptic the SDL_Haptic device to query
+ * \param effect the desired effect to query
+ * \returns SDL_TRUE if effect is supported, SDL_FALSE if it isn't, or a
+ * negative error code on failure; call SDL_GetError() for more
+ * information.
+ *
+ * \since This function is available since SDL 2.0.0.
+ *
+ * \sa SDL_HapticNewEffect
+ * \sa SDL_HapticQuery
+ */
+extern DECLSPEC int SDLCALL SDL_HapticEffectSupported(SDL_Haptic * haptic,
+ SDL_HapticEffect *
+ effect);
+
+/**
+ * Create a new haptic effect on a specified device.
+ *
+ * \param haptic an SDL_Haptic device to create the effect on
+ * \param effect an SDL_HapticEffect structure containing the properties of
+ * the effect to create
+ * \returns the ID of the effect on success or a negative error code on
+ * failure; call SDL_GetError() for more information.
+ *
+ * \since This function is available since SDL 2.0.0.
+ *
+ * \sa SDL_HapticDestroyEffect
+ * \sa SDL_HapticRunEffect
+ * \sa SDL_HapticUpdateEffect
+ */
+extern DECLSPEC int SDLCALL SDL_HapticNewEffect(SDL_Haptic * haptic,
+ SDL_HapticEffect * effect);
+
+/**
+ * Update the properties of an effect.
+ *
+ * Can be used dynamically, although behavior when dynamically changing
+ * direction may be strange. Specifically the effect may re-upload itself and
+ * start playing from the start. You also cannot change the type either when
+ * running SDL_HapticUpdateEffect().
+ *
+ * \param haptic the SDL_Haptic device that has the effect
+ * \param effect the identifier of the effect to update
+ * \param data an SDL_HapticEffect structure containing the new effect
+ * properties to use
+ * \returns 0 on success or a negative error code on failure; call
+ * SDL_GetError() for more information.
+ *
+ * \since This function is available since SDL 2.0.0.
+ *
+ * \sa SDL_HapticDestroyEffect
+ * \sa SDL_HapticNewEffect
+ * \sa SDL_HapticRunEffect
+ */
+extern DECLSPEC int SDLCALL SDL_HapticUpdateEffect(SDL_Haptic * haptic,
+ int effect,
+ SDL_HapticEffect * data);
+
+/**
+ * Run the haptic effect on its associated haptic device.
+ *
+ * To repeat the effect over and over indefinitely, set `iterations` to
+ * `SDL_HAPTIC_INFINITY`. (Repeats the envelope - attack and fade.) To make
+ * one instance of the effect last indefinitely (so the effect does not fade),
+ * set the effect's `length` in its structure/union to `SDL_HAPTIC_INFINITY`
+ * instead.
+ *
+ * \param haptic the SDL_Haptic device to run the effect on
+ * \param effect the ID of the haptic effect to run
+ * \param iterations the number of iterations to run the effect; use
+ * `SDL_HAPTIC_INFINITY` to repeat forever
+ * \returns 0 on success or a negative error code on failure; call
+ * SDL_GetError() for more information.
+ *
+ * \since This function is available since SDL 2.0.0.
+ *
+ * \sa SDL_HapticDestroyEffect
+ * \sa SDL_HapticGetEffectStatus
+ * \sa SDL_HapticStopEffect
+ */
+extern DECLSPEC int SDLCALL SDL_HapticRunEffect(SDL_Haptic * haptic,
+ int effect,
+ Uint32 iterations);
+
+/**
+ * Stop the haptic effect on its associated haptic device.
+ *
+ * *
+ *
+ * \param haptic the SDL_Haptic device to stop the effect on
+ * \param effect the ID of the haptic effect to stop
+ * \returns 0 on success or a negative error code on failure; call
+ * SDL_GetError() for more information.
+ *
+ * \since This function is available since SDL 2.0.0.
+ *
+ * \sa SDL_HapticDestroyEffect
+ * \sa SDL_HapticRunEffect
+ */
+extern DECLSPEC int SDLCALL SDL_HapticStopEffect(SDL_Haptic * haptic,
+ int effect);
+
+/**
+ * Destroy a haptic effect on the device.
+ *
+ * This will stop the effect if it's running. Effects are automatically
+ * destroyed when the device is closed.
+ *
+ * \param haptic the SDL_Haptic device to destroy the effect on
+ * \param effect the ID of the haptic effect to destroy
+ *
+ * \since This function is available since SDL 2.0.0.
+ *
+ * \sa SDL_HapticNewEffect
+ */
+extern DECLSPEC void SDLCALL SDL_HapticDestroyEffect(SDL_Haptic * haptic,
+ int effect);
+
+/**
+ * Get the status of the current effect on the specified haptic device.
+ *
+ * Device must support the SDL_HAPTIC_STATUS feature.
+ *
+ * \param haptic the SDL_Haptic device to query for the effect status on
+ * \param effect the ID of the haptic effect to query its status
+ * \returns 0 if it isn't playing, 1 if it is playing, or a negative error
+ * code on failure; call SDL_GetError() for more information.
+ *
+ * \since This function is available since SDL 2.0.0.
+ *
+ * \sa SDL_HapticRunEffect
+ * \sa SDL_HapticStopEffect
+ */
+extern DECLSPEC int SDLCALL SDL_HapticGetEffectStatus(SDL_Haptic * haptic,
+ int effect);
+
+/**
+ * Set the global gain of the specified haptic device.
+ *
+ * Device must support the SDL_HAPTIC_GAIN feature.
+ *
+ * The user may specify the maximum gain by setting the environment variable
+ * `SDL_HAPTIC_GAIN_MAX` which should be between 0 and 100. All calls to
+ * SDL_HapticSetGain() will scale linearly using `SDL_HAPTIC_GAIN_MAX` as the
+ * maximum.
+ *
+ * \param haptic the SDL_Haptic device to set the gain on
+ * \param gain value to set the gain to, should be between 0 and 100 (0 - 100)
+ * \returns 0 on success or a negative error code on failure; call
+ * SDL_GetError() for more information.
+ *
+ * \since This function is available since SDL 2.0.0.
+ *
+ * \sa SDL_HapticQuery
+ */
+extern DECLSPEC int SDLCALL SDL_HapticSetGain(SDL_Haptic * haptic, int gain);
+
+/**
+ * Set the global autocenter of the device.
+ *
+ * Autocenter should be between 0 and 100. Setting it to 0 will disable
+ * autocentering.
+ *
+ * Device must support the SDL_HAPTIC_AUTOCENTER feature.
+ *
+ * \param haptic the SDL_Haptic device to set autocentering on
+ * \param autocenter value to set autocenter to (0-100)
+ * \returns 0 on success or a negative error code on failure; call
+ * SDL_GetError() for more information.
+ *
+ * \since This function is available since SDL 2.0.0.
+ *
+ * \sa SDL_HapticQuery
+ */
+extern DECLSPEC int SDLCALL SDL_HapticSetAutocenter(SDL_Haptic * haptic,
+ int autocenter);
+
+/**
+ * Pause a haptic device.
+ *
+ * Device must support the `SDL_HAPTIC_PAUSE` feature. Call
+ * SDL_HapticUnpause() to resume playback.
+ *
+ * Do not modify the effects nor add new ones while the device is paused. That
+ * can cause all sorts of weird errors.
+ *
+ * \param haptic the SDL_Haptic device to pause
+ * \returns 0 on success or a negative error code on failure; call
+ * SDL_GetError() for more information.
+ *
+ * \since This function is available since SDL 2.0.0.
+ *
+ * \sa SDL_HapticUnpause
+ */
+extern DECLSPEC int SDLCALL SDL_HapticPause(SDL_Haptic * haptic);
+
+/**
+ * Unpause a haptic device.
+ *
+ * Call to unpause after SDL_HapticPause().
+ *
+ * \param haptic the SDL_Haptic device to unpause
+ * \returns 0 on success or a negative error code on failure; call
+ * SDL_GetError() for more information.
+ *
+ * \since This function is available since SDL 2.0.0.
+ *
+ * \sa SDL_HapticPause
+ */
+extern DECLSPEC int SDLCALL SDL_HapticUnpause(SDL_Haptic * haptic);
+
+/**
+ * Stop all the currently playing effects on a haptic device.
+ *
+ * \param haptic the SDL_Haptic device to stop
+ * \returns 0 on success or a negative error code on failure; call
+ * SDL_GetError() for more information.
+ *
+ * \since This function is available since SDL 2.0.0.
+ */
+extern DECLSPEC int SDLCALL SDL_HapticStopAll(SDL_Haptic * haptic);
+
+/**
+ * Check whether rumble is supported on a haptic device.
+ *
+ * \param haptic haptic device to check for rumble support
+ * \returns SDL_TRUE if effect is supported, SDL_FALSE if it isn't, or a
+ * negative error code on failure; call SDL_GetError() for more
+ * information.
+ *
+ * \since This function is available since SDL 2.0.0.
+ *
+ * \sa SDL_HapticRumbleInit
+ * \sa SDL_HapticRumblePlay
+ * \sa SDL_HapticRumbleStop
+ */
+extern DECLSPEC int SDLCALL SDL_HapticRumbleSupported(SDL_Haptic * haptic);
+
+/**
+ * Initialize a haptic device for simple rumble playback.
+ *
+ * \param haptic the haptic device to initialize for simple rumble playback
+ * \returns 0 on success or a negative error code on failure; call
+ * SDL_GetError() for more information.
+ *
+ * \since This function is available since SDL 2.0.0.
+ *
+ * \sa SDL_HapticOpen
+ * \sa SDL_HapticRumblePlay
+ * \sa SDL_HapticRumbleStop
+ * \sa SDL_HapticRumbleSupported
+ */
+extern DECLSPEC int SDLCALL SDL_HapticRumbleInit(SDL_Haptic * haptic);
+
+/**
+ * Run a simple rumble effect on a haptic device.
+ *
+ * \param haptic the haptic device to play the rumble effect on
+ * \param strength strength of the rumble to play as a 0-1 float value
+ * \param length length of the rumble to play in milliseconds
+ * \returns 0 on success or a negative error code on failure; call
+ * SDL_GetError() for more information.
+ *
+ * \since This function is available since SDL 2.0.0.
+ *
+ * \sa SDL_HapticRumbleInit
+ * \sa SDL_HapticRumbleStop
+ * \sa SDL_HapticRumbleSupported
+ */
+extern DECLSPEC int SDLCALL SDL_HapticRumblePlay(SDL_Haptic * haptic, float strength, Uint32 length );
+
+/**
+ * Stop the simple rumble on a haptic device.
+ *
+ * \param haptic the haptic device to stop the rumble effect on
+ * \returns 0 on success or a negative error code on failure; call
+ * SDL_GetError() for more information.
+ *
+ * \since This function is available since SDL 2.0.0.
+ *
+ * \sa SDL_HapticRumbleInit
+ * \sa SDL_HapticRumblePlay
+ * \sa SDL_HapticRumbleSupported
+ */
+extern DECLSPEC int SDLCALL SDL_HapticRumbleStop(SDL_Haptic * haptic);
+
+/* Ends C function definitions when using C++ */
+#ifdef __cplusplus
+}
+#endif
+#include
+
+#endif /* SDL_haptic_h_ */
+
+/* vi: set ts=4 sw=4 expandtab: */
diff --git a/bindings/sdl2wgpu/src/main/headers/SDL2/SDL_hidapi.h b/bindings/sdl2wgpu/src/main/headers/SDL2/SDL_hidapi.h
new file mode 100644
index 00000000..62cc3014
--- /dev/null
+++ b/bindings/sdl2wgpu/src/main/headers/SDL2/SDL_hidapi.h
@@ -0,0 +1,451 @@
+/*
+ Simple DirectMedia Layer
+ Copyright (C) 1997-2023 Sam Lantinga
+
+ This software is provided 'as-is', without any express or implied
+ warranty. In no event will the authors be held liable for any damages
+ arising from the use of this software.
+
+ Permission is granted to anyone to use this software for any purpose,
+ including commercial applications, and to alter it and redistribute it
+ freely, subject to the following restrictions:
+
+ 1. The origin of this software must not be misrepresented; you must not
+ claim that you wrote the original software. If you use this software
+ in a product, an acknowledgment in the product documentation would be
+ appreciated but is not required.
+ 2. Altered source versions must be plainly marked as such, and must not be
+ misrepresented as being the original software.
+ 3. This notice may not be removed or altered from any source distribution.
+*/
+
+/**
+ * \file SDL_hidapi.h
+ *
+ * Header file for SDL HIDAPI functions.
+ *
+ * This is an adaptation of the original HIDAPI interface by Alan Ott,
+ * and includes source code licensed under the following BSD license:
+ *
+ Copyright (c) 2010, Alan Ott, Signal 11 Software
+ All rights reserved.
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions are met:
+
+ * Redistributions of source code must retain the above copyright notice,
+ this list of conditions and the following disclaimer.
+ * Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+ * Neither the name of Signal 11 Software nor the names of its
+ contributors may be used to endorse or promote products derived from
+ this software without specific prior written permission.
+
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
+ LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+ *
+ * If you would like a version of SDL without this code, you can build SDL
+ * with SDL_HIDAPI_DISABLED defined to 1. You might want to do this for example
+ * on iOS or tvOS to avoid a dependency on the CoreBluetooth framework.
+ */
+
+#ifndef SDL_hidapi_h_
+#define SDL_hidapi_h_
+
+#include
+
+#include
+/* Set up for C function definitions, even when using C++ */
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * \brief A handle representing an open HID device
+ */
+struct SDL_hid_device_;
+typedef struct SDL_hid_device_ SDL_hid_device; /**< opaque hidapi structure */
+
+/** hidapi info structure */
+/**
+ * \brief Information about a connected HID device
+ */
+typedef struct SDL_hid_device_info
+{
+ /** Platform-specific device path */
+ char *path;
+ /** Device Vendor ID */
+ unsigned short vendor_id;
+ /** Device Product ID */
+ unsigned short product_id;
+ /** Serial Number */
+ wchar_t *serial_number;
+ /** Device Release Number in binary-coded decimal,
+ also known as Device Version Number */
+ unsigned short release_number;
+ /** Manufacturer String */
+ wchar_t *manufacturer_string;
+ /** Product string */
+ wchar_t *product_string;
+ /** Usage Page for this Device/Interface
+ (Windows/Mac only). */
+ unsigned short usage_page;
+ /** Usage for this Device/Interface
+ (Windows/Mac only).*/
+ unsigned short usage;
+ /** The USB interface which this logical device
+ represents.
+
+ * Valid on both Linux implementations in all cases.
+ * Valid on the Windows implementation only if the device
+ contains more than one interface. */
+ int interface_number;
+
+ /** Additional information about the USB interface.
+ Valid on libusb and Android implementations. */
+ int interface_class;
+ int interface_subclass;
+ int interface_protocol;
+
+ /** Pointer to the next device */
+ struct SDL_hid_device_info *next;
+} SDL_hid_device_info;
+
+
+/**
+ * Initialize the HIDAPI library.
+ *
+ * This function initializes the HIDAPI library. Calling it is not strictly
+ * necessary, as it will be called automatically by SDL_hid_enumerate() and
+ * any of the SDL_hid_open_*() functions if it is needed. This function should
+ * be called at the beginning of execution however, if there is a chance of
+ * HIDAPI handles being opened by different threads simultaneously.
+ *
+ * Each call to this function should have a matching call to SDL_hid_exit()
+ *
+ * \returns 0 on success and -1 on error.
+ *
+ * \since This function is available since SDL 2.0.18.
+ *
+ * \sa SDL_hid_exit
+ */
+extern DECLSPEC int SDLCALL SDL_hid_init(void);
+
+/**
+ * Finalize the HIDAPI library.
+ *
+ * This function frees all of the static data associated with HIDAPI. It
+ * should be called at the end of execution to avoid memory leaks.
+ *
+ * \returns 0 on success and -1 on error.
+ *
+ * \since This function is available since SDL 2.0.18.
+ *
+ * \sa SDL_hid_init
+ */
+extern DECLSPEC int SDLCALL SDL_hid_exit(void);
+
+/**
+ * Check to see if devices may have been added or removed.
+ *
+ * Enumerating the HID devices is an expensive operation, so you can call this
+ * to see if there have been any system device changes since the last call to
+ * this function. A change in the counter returned doesn't necessarily mean
+ * that anything has changed, but you can call SDL_hid_enumerate() to get an
+ * updated device list.
+ *
+ * Calling this function for the first time may cause a thread or other system
+ * resource to be allocated to track device change notifications.
+ *
+ * \returns a change counter that is incremented with each potential device
+ * change, or 0 if device change detection isn't available.
+ *
+ * \since This function is available since SDL 2.0.18.
+ *
+ * \sa SDL_hid_enumerate
+ */
+extern DECLSPEC Uint32 SDLCALL SDL_hid_device_change_count(void);
+
+/**
+ * Enumerate the HID Devices.
+ *
+ * This function returns a linked list of all the HID devices attached to the
+ * system which match vendor_id and product_id. If `vendor_id` is set to 0
+ * then any vendor matches. If `product_id` is set to 0 then any product
+ * matches. If `vendor_id` and `product_id` are both set to 0, then all HID
+ * devices will be returned.
+ *
+ * \param vendor_id The Vendor ID (VID) of the types of device to open.
+ * \param product_id The Product ID (PID) of the types of device to open.
+ * \returns a pointer to a linked list of type SDL_hid_device_info, containing
+ * information about the HID devices attached to the system, or NULL
+ * in the case of failure. Free this linked list by calling
+ * SDL_hid_free_enumeration().
+ *
+ * \since This function is available since SDL 2.0.18.
+ *
+ * \sa SDL_hid_device_change_count
+ */
+extern DECLSPEC SDL_hid_device_info * SDLCALL SDL_hid_enumerate(unsigned short vendor_id, unsigned short product_id);
+
+/**
+ * Free an enumeration Linked List
+ *
+ * This function frees a linked list created by SDL_hid_enumerate().
+ *
+ * \param devs Pointer to a list of struct_device returned from
+ * SDL_hid_enumerate().
+ *
+ * \since This function is available since SDL 2.0.18.
+ */
+extern DECLSPEC void SDLCALL SDL_hid_free_enumeration(SDL_hid_device_info *devs);
+
+/**
+ * Open a HID device using a Vendor ID (VID), Product ID (PID) and optionally
+ * a serial number.
+ *
+ * If `serial_number` is NULL, the first device with the specified VID and PID
+ * is opened.
+ *
+ * \param vendor_id The Vendor ID (VID) of the device to open.
+ * \param product_id The Product ID (PID) of the device to open.
+ * \param serial_number The Serial Number of the device to open (Optionally
+ * NULL).
+ * \returns a pointer to a SDL_hid_device object on success or NULL on
+ * failure.
+ *
+ * \since This function is available since SDL 2.0.18.
+ */
+extern DECLSPEC SDL_hid_device * SDLCALL SDL_hid_open(unsigned short vendor_id, unsigned short product_id, const wchar_t *serial_number);
+
+/**
+ * Open a HID device by its path name.
+ *
+ * The path name be determined by calling SDL_hid_enumerate(), or a
+ * platform-specific path name can be used (eg: /dev/hidraw0 on Linux).
+ *
+ * \param path The path name of the device to open
+ * \returns a pointer to a SDL_hid_device object on success or NULL on
+ * failure.
+ *
+ * \since This function is available since SDL 2.0.18.
+ */
+extern DECLSPEC SDL_hid_device * SDLCALL SDL_hid_open_path(const char *path, int bExclusive /* = false */);
+
+/**
+ * Write an Output report to a HID device.
+ *
+ * The first byte of `data` must contain the Report ID. For devices which only
+ * support a single report, this must be set to 0x0. The remaining bytes
+ * contain the report data. Since the Report ID is mandatory, calls to
+ * SDL_hid_write() will always contain one more byte than the report contains.
+ * For example, if a hid report is 16 bytes long, 17 bytes must be passed to
+ * SDL_hid_write(), the Report ID (or 0x0, for devices with a single report),
+ * followed by the report data (16 bytes). In this example, the length passed
+ * in would be 17.
+ *
+ * SDL_hid_write() will send the data on the first OUT endpoint, if one
+ * exists. If it does not, it will send the data through the Control Endpoint
+ * (Endpoint 0).
+ *
+ * \param dev A device handle returned from SDL_hid_open().
+ * \param data The data to send, including the report number as the first
+ * byte.
+ * \param length The length in bytes of the data to send.
+ * \returns the actual number of bytes written and -1 on error.
+ *
+ * \since This function is available since SDL 2.0.18.
+ */
+extern DECLSPEC int SDLCALL SDL_hid_write(SDL_hid_device *dev, const unsigned char *data, size_t length);
+
+/**
+ * Read an Input report from a HID device with timeout.
+ *
+ * Input reports are returned to the host through the INTERRUPT IN endpoint.
+ * The first byte will contain the Report number if the device uses numbered
+ * reports.
+ *
+ * \param dev A device handle returned from SDL_hid_open().
+ * \param data A buffer to put the read data into.
+ * \param length The number of bytes to read. For devices with multiple
+ * reports, make sure to read an extra byte for the report
+ * number.
+ * \param milliseconds timeout in milliseconds or -1 for blocking wait.
+ * \returns the actual number of bytes read and -1 on error. If no packet was
+ * available to be read within the timeout period, this function
+ * returns 0.
+ *
+ * \since This function is available since SDL 2.0.18.
+ */
+extern DECLSPEC int SDLCALL SDL_hid_read_timeout(SDL_hid_device *dev, unsigned char *data, size_t length, int milliseconds);
+
+/**
+ * Read an Input report from a HID device.
+ *
+ * Input reports are returned to the host through the INTERRUPT IN endpoint.
+ * The first byte will contain the Report number if the device uses numbered
+ * reports.
+ *
+ * \param dev A device handle returned from SDL_hid_open().
+ * \param data A buffer to put the read data into.
+ * \param length The number of bytes to read. For devices with multiple
+ * reports, make sure to read an extra byte for the report
+ * number.
+ * \returns the actual number of bytes read and -1 on error. If no packet was
+ * available to be read and the handle is in non-blocking mode, this
+ * function returns 0.
+ *
+ * \since This function is available since SDL 2.0.18.
+ */
+extern DECLSPEC int SDLCALL SDL_hid_read(SDL_hid_device *dev, unsigned char *data, size_t length);
+
+/**
+ * Set the device handle to be non-blocking.
+ *
+ * In non-blocking mode calls to SDL_hid_read() will return immediately with a
+ * value of 0 if there is no data to be read. In blocking mode, SDL_hid_read()
+ * will wait (block) until there is data to read before returning.
+ *
+ * Nonblocking can be turned on and off at any time.
+ *
+ * \param dev A device handle returned from SDL_hid_open().
+ * \param nonblock enable or not the nonblocking reads - 1 to enable
+ * nonblocking - 0 to disable nonblocking.
+ * \returns 0 on success and -1 on error.
+ *
+ * \since This function is available since SDL 2.0.18.
+ */
+extern DECLSPEC int SDLCALL SDL_hid_set_nonblocking(SDL_hid_device *dev, int nonblock);
+
+/**
+ * Send a Feature report to the device.
+ *
+ * Feature reports are sent over the Control endpoint as a Set_Report
+ * transfer. The first byte of `data` must contain the Report ID. For devices
+ * which only support a single report, this must be set to 0x0. The remaining
+ * bytes contain the report data. Since the Report ID is mandatory, calls to
+ * SDL_hid_send_feature_report() will always contain one more byte than the
+ * report contains. For example, if a hid report is 16 bytes long, 17 bytes
+ * must be passed to SDL_hid_send_feature_report(): the Report ID (or 0x0, for
+ * devices which do not use numbered reports), followed by the report data (16
+ * bytes). In this example, the length passed in would be 17.
+ *
+ * \param dev A device handle returned from SDL_hid_open().
+ * \param data The data to send, including the report number as the first
+ * byte.
+ * \param length The length in bytes of the data to send, including the report
+ * number.
+ * \returns the actual number of bytes written and -1 on error.
+ *
+ * \since This function is available since SDL 2.0.18.
+ */
+extern DECLSPEC int SDLCALL SDL_hid_send_feature_report(SDL_hid_device *dev, const unsigned char *data, size_t length);
+
+/**
+ * Get a feature report from a HID device.
+ *
+ * Set the first byte of `data` to the Report ID of the report to be read.
+ * Make sure to allow space for this extra byte in `data`. Upon return, the
+ * first byte will still contain the Report ID, and the report data will start
+ * in data[1].
+ *
+ * \param dev A device handle returned from SDL_hid_open().
+ * \param data A buffer to put the read data into, including the Report ID.
+ * Set the first byte of `data` to the Report ID of the report to
+ * be read, or set it to zero if your device does not use numbered
+ * reports.
+ * \param length The number of bytes to read, including an extra byte for the
+ * report ID. The buffer can be longer than the actual report.
+ * \returns the number of bytes read plus one for the report ID (which is
+ * still in the first byte), or -1 on error.
+ *
+ * \since This function is available since SDL 2.0.18.
+ */
+extern DECLSPEC int SDLCALL SDL_hid_get_feature_report(SDL_hid_device *dev, unsigned char *data, size_t length);
+
+/**
+ * Close a HID device.
+ *
+ * \param dev A device handle returned from SDL_hid_open().
+ *
+ * \since This function is available since SDL 2.0.18.
+ */
+extern DECLSPEC void SDLCALL SDL_hid_close(SDL_hid_device *dev);
+
+/**
+ * Get The Manufacturer String from a HID device.
+ *
+ * \param dev A device handle returned from SDL_hid_open().
+ * \param string A wide string buffer to put the data into.
+ * \param maxlen The length of the buffer in multiples of wchar_t.
+ * \returns 0 on success and -1 on error.
+ *
+ * \since This function is available since SDL 2.0.18.
+ */
+extern DECLSPEC int SDLCALL SDL_hid_get_manufacturer_string(SDL_hid_device *dev, wchar_t *string, size_t maxlen);
+
+/**
+ * Get The Product String from a HID device.
+ *
+ * \param dev A device handle returned from SDL_hid_open().
+ * \param string A wide string buffer to put the data into.
+ * \param maxlen The length of the buffer in multiples of wchar_t.
+ * \returns 0 on success and -1 on error.
+ *
+ * \since This function is available since SDL 2.0.18.
+ */
+extern DECLSPEC int SDLCALL SDL_hid_get_product_string(SDL_hid_device *dev, wchar_t *string, size_t maxlen);
+
+/**
+ * Get The Serial Number String from a HID device.
+ *
+ * \param dev A device handle returned from SDL_hid_open().
+ * \param string A wide string buffer to put the data into.
+ * \param maxlen The length of the buffer in multiples of wchar_t.
+ * \returns 0 on success and -1 on error.
+ *
+ * \since This function is available since SDL 2.0.18.
+ */
+extern DECLSPEC int SDLCALL SDL_hid_get_serial_number_string(SDL_hid_device *dev, wchar_t *string, size_t maxlen);
+
+/**
+ * Get a string from a HID device, based on its string index.
+ *
+ * \param dev A device handle returned from SDL_hid_open().
+ * \param string_index The index of the string to get.
+ * \param string A wide string buffer to put the data into.
+ * \param maxlen The length of the buffer in multiples of wchar_t.
+ * \returns 0 on success and -1 on error.
+ *
+ * \since This function is available since SDL 2.0.18.
+ */
+extern DECLSPEC int SDLCALL SDL_hid_get_indexed_string(SDL_hid_device *dev, int string_index, wchar_t *string, size_t maxlen);
+
+/**
+ * Start or stop a BLE scan on iOS and tvOS to pair Steam Controllers
+ *
+ * \param active SDL_TRUE to start the scan, SDL_FALSE to stop the scan
+ *
+ * \since This function is available since SDL 2.0.18.
+ */
+extern DECLSPEC void SDLCALL SDL_hid_ble_scan(SDL_bool active);
+
+/* Ends C function definitions when using C++ */
+#ifdef __cplusplus
+}
+#endif
+#include
+
+#endif /* SDL_hidapi_h_ */
+
+/* vi: set sts=4 ts=4 sw=4 expandtab: */
diff --git a/bindings/sdl2wgpu/src/main/headers/SDL2/SDL_hints.h b/bindings/sdl2wgpu/src/main/headers/SDL2/SDL_hints.h
new file mode 100644
index 00000000..3faa7652
--- /dev/null
+++ b/bindings/sdl2wgpu/src/main/headers/SDL2/SDL_hints.h
@@ -0,0 +1,2613 @@
+/*
+ Simple DirectMedia Layer
+ Copyright (C) 1997-2023 Sam Lantinga
+
+ This software is provided 'as-is', without any express or implied
+ warranty. In no event will the authors be held liable for any damages
+ arising from the use of this software.
+
+ Permission is granted to anyone to use this software for any purpose,
+ including commercial applications, and to alter it and redistribute it
+ freely, subject to the following restrictions:
+
+ 1. The origin of this software must not be misrepresented; you must not
+ claim that you wrote the original software. If you use this software
+ in a product, an acknowledgment in the product documentation would be
+ appreciated but is not required.
+ 2. Altered source versions must be plainly marked as such, and must not be
+ misrepresented as being the original software.
+ 3. This notice may not be removed or altered from any source distribution.
+*/
+
+/**
+ * \file SDL_hints.h
+ *
+ * Official documentation for SDL configuration variables
+ *
+ * This file contains functions to set and get configuration hints,
+ * as well as listing each of them alphabetically.
+ *
+ * The convention for naming hints is SDL_HINT_X, where "SDL_X" is
+ * the environment variable that can be used to override the default.
+ *
+ * In general these hints are just that - they may or may not be
+ * supported or applicable on any given platform, but they provide
+ * a way for an application or user to give the library a hint as
+ * to how they would like the library to work.
+ */
+
+#ifndef SDL_hints_h_
+#define SDL_hints_h_
+
+#include
+
+#include
+/* Set up for C function definitions, even when using C++ */
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * \brief A variable controlling whether the Android / iOS built-in
+ * accelerometer should be listed as a joystick device.
+ *
+ * This variable can be set to the following values:
+ * "0" - The accelerometer is not listed as a joystick
+ * "1" - The accelerometer is available as a 3 axis joystick (the default).
+ */
+#define SDL_HINT_ACCELEROMETER_AS_JOYSTICK "SDL_ACCELEROMETER_AS_JOYSTICK"
+
+/**
+ * \brief Specify the behavior of Alt+Tab while the keyboard is grabbed.
+ *
+ * By default, SDL emulates Alt+Tab functionality while the keyboard is grabbed
+ * and your window is full-screen. This prevents the user from getting stuck in
+ * your application if you've enabled keyboard grab.
+ *
+ * The variable can be set to the following values:
+ * "0" - SDL will not handle Alt+Tab. Your application is responsible
+ for handling Alt+Tab while the keyboard is grabbed.
+ * "1" - SDL will minimize your window when Alt+Tab is pressed (default)
+*/
+#define SDL_HINT_ALLOW_ALT_TAB_WHILE_GRABBED "SDL_ALLOW_ALT_TAB_WHILE_GRABBED"
+
+/**
+ * \brief If set to "0" then never set the top most bit on a SDL Window, even if the video mode expects it.
+ * This is a debugging aid for developers and not expected to be used by end users. The default is "1"
+ *
+ * This variable can be set to the following values:
+ * "0" - don't allow topmost
+ * "1" - allow topmost
+ */
+#define SDL_HINT_ALLOW_TOPMOST "SDL_ALLOW_TOPMOST"
+
+/**
+ * \brief Android APK expansion main file version. Should be a string number like "1", "2" etc.
+ *
+ * Must be set together with SDL_HINT_ANDROID_APK_EXPANSION_PATCH_FILE_VERSION.
+ *
+ * If both hints were set then SDL_RWFromFile() will look into expansion files
+ * after a given relative path was not found in the internal storage and assets.
+ *
+ * By default this hint is not set and the APK expansion files are not searched.
+ */
+#define SDL_HINT_ANDROID_APK_EXPANSION_MAIN_FILE_VERSION "SDL_ANDROID_APK_EXPANSION_MAIN_FILE_VERSION"
+
+/**
+ * \brief Android APK expansion patch file version. Should be a string number like "1", "2" etc.
+ *
+ * Must be set together with SDL_HINT_ANDROID_APK_EXPANSION_MAIN_FILE_VERSION.
+ *
+ * If both hints were set then SDL_RWFromFile() will look into expansion files
+ * after a given relative path was not found in the internal storage and assets.
+ *
+ * By default this hint is not set and the APK expansion files are not searched.
+ */
+#define SDL_HINT_ANDROID_APK_EXPANSION_PATCH_FILE_VERSION "SDL_ANDROID_APK_EXPANSION_PATCH_FILE_VERSION"
+
+/**
+ * \brief A variable to control whether the event loop will block itself when the app is paused.
+ *
+ * The variable can be set to the following values:
+ * "0" - Non blocking.
+ * "1" - Blocking. (default)
+ *
+ * The value should be set before SDL is initialized.
+ */
+#define SDL_HINT_ANDROID_BLOCK_ON_PAUSE "SDL_ANDROID_BLOCK_ON_PAUSE"
+
+/**
+ * \brief A variable to control whether SDL will pause audio in background
+ * (Requires SDL_ANDROID_BLOCK_ON_PAUSE as "Non blocking")
+ *
+ * The variable can be set to the following values:
+ * "0" - Non paused.
+ * "1" - Paused. (default)
+ *
+ * The value should be set before SDL is initialized.
+ */
+#define SDL_HINT_ANDROID_BLOCK_ON_PAUSE_PAUSEAUDIO "SDL_ANDROID_BLOCK_ON_PAUSE_PAUSEAUDIO"
+
+/**
+ * \brief A variable to control whether we trap the Android back button to handle it manually.
+ * This is necessary for the right mouse button to work on some Android devices, or
+ * to be able to trap the back button for use in your code reliably. If set to true,
+ * the back button will show up as an SDL_KEYDOWN / SDL_KEYUP pair with a keycode of
+ * SDL_SCANCODE_AC_BACK.
+ *
+ * The variable can be set to the following values:
+ * "0" - Back button will be handled as usual for system. (default)
+ * "1" - Back button will be trapped, allowing you to handle the key press
+ * manually. (This will also let right mouse click work on systems
+ * where the right mouse button functions as back.)
+ *
+ * The value of this hint is used at runtime, so it can be changed at any time.
+ */
+#define SDL_HINT_ANDROID_TRAP_BACK_BUTTON "SDL_ANDROID_TRAP_BACK_BUTTON"
+
+/**
+ * \brief Specify an application name.
+ *
+ * This hint lets you specify the application name sent to the OS when
+ * required. For example, this will often appear in volume control applets for
+ * audio streams, and in lists of applications which are inhibiting the
+ * screensaver. You should use a string that describes your program ("My Game
+ * 2: The Revenge")
+ *
+ * Setting this to "" or leaving it unset will have SDL use a reasonable
+ * default: probably the application's name or "SDL Application" if SDL
+ * doesn't have any better information.
+ *
+ * Note that, for audio streams, this can be overridden with
+ * SDL_HINT_AUDIO_DEVICE_APP_NAME.
+ *
+ * On targets where this is not supported, this hint does nothing.
+ */
+#define SDL_HINT_APP_NAME "SDL_APP_NAME"
+
+/**
+ * \brief A variable controlling whether controllers used with the Apple TV
+ * generate UI events.
+ *
+ * When UI events are generated by controller input, the app will be
+ * backgrounded when the Apple TV remote's menu button is pressed, and when the
+ * pause or B buttons on gamepads are pressed.
+ *
+ * More information about properly making use of controllers for the Apple TV
+ * can be found here:
+ * https://developer.apple.com/tvos/human-interface-guidelines/remote-and-controllers/
+ *
+ * This variable can be set to the following values:
+ * "0" - Controller input does not generate UI events (the default).
+ * "1" - Controller input generates UI events.
+ */
+#define SDL_HINT_APPLE_TV_CONTROLLER_UI_EVENTS "SDL_APPLE_TV_CONTROLLER_UI_EVENTS"
+
+/**
+ * \brief A variable controlling whether the Apple TV remote's joystick axes
+ * will automatically match the rotation of the remote.
+ *
+ * This variable can be set to the following values:
+ * "0" - Remote orientation does not affect joystick axes (the default).
+ * "1" - Joystick axes are based on the orientation of the remote.
+ */
+#define SDL_HINT_APPLE_TV_REMOTE_ALLOW_ROTATION "SDL_APPLE_TV_REMOTE_ALLOW_ROTATION"
+
+/**
+ * \brief A variable controlling the audio category on iOS and Mac OS X
+ *
+ * This variable can be set to the following values:
+ *
+ * "ambient" - Use the AVAudioSessionCategoryAmbient audio category, will be muted by the phone mute switch (default)
+ * "playback" - Use the AVAudioSessionCategoryPlayback category
+ *
+ * For more information, see Apple's documentation:
+ * https://developer.apple.com/library/content/documentation/Audio/Conceptual/AudioSessionProgrammingGuide/AudioSessionCategoriesandModes/AudioSessionCategoriesandModes.html
+ */
+#define SDL_HINT_AUDIO_CATEGORY "SDL_AUDIO_CATEGORY"
+
+/**
+ * \brief Specify an application name for an audio device.
+ *
+ * Some audio backends (such as PulseAudio) allow you to describe your audio
+ * stream. Among other things, this description might show up in a system
+ * control panel that lets the user adjust the volume on specific audio
+ * streams instead of using one giant master volume slider.
+ *
+ * This hints lets you transmit that information to the OS. The contents of
+ * this hint are used while opening an audio device. You should use a string
+ * that describes your program ("My Game 2: The Revenge")
+ *
+ * Setting this to "" or leaving it unset will have SDL use a reasonable
+ * default: this will be the name set with SDL_HINT_APP_NAME, if that hint is
+ * set. Otherwise, it'll probably the application's name or "SDL Application"
+ * if SDL doesn't have any better information.
+ *
+ * On targets where this is not supported, this hint does nothing.
+ */
+#define SDL_HINT_AUDIO_DEVICE_APP_NAME "SDL_AUDIO_DEVICE_APP_NAME"
+
+/**
+ * \brief Specify an application name for an audio device.
+ *
+ * Some audio backends (such as PulseAudio) allow you to describe your audio
+ * stream. Among other things, this description might show up in a system
+ * control panel that lets the user adjust the volume on specific audio
+ * streams instead of using one giant master volume slider.
+ *
+ * This hints lets you transmit that information to the OS. The contents of
+ * this hint are used while opening an audio device. You should use a string
+ * that describes your what your program is playing ("audio stream" is
+ * probably sufficient in many cases, but this could be useful for something
+ * like "team chat" if you have a headset playing VoIP audio separately).
+ *
+ * Setting this to "" or leaving it unset will have SDL use a reasonable
+ * default: "audio stream" or something similar.
+ *
+ * On targets where this is not supported, this hint does nothing.
+ */
+#define SDL_HINT_AUDIO_DEVICE_STREAM_NAME "SDL_AUDIO_DEVICE_STREAM_NAME"
+
+/**
+ * \brief Specify an application role for an audio device.
+ *
+ * Some audio backends (such as Pipewire) allow you to describe the role of
+ * your audio stream. Among other things, this description might show up in
+ * a system control panel or software for displaying and manipulating media
+ * playback/capture graphs.
+ *
+ * This hints lets you transmit that information to the OS. The contents of
+ * this hint are used while opening an audio device. You should use a string
+ * that describes your what your program is playing (Game, Music, Movie,
+ * etc...).
+ *
+ * Setting this to "" or leaving it unset will have SDL use a reasonable
+ * default: "Game" or something similar.
+ *
+ * On targets where this is not supported, this hint does nothing.
+ */
+#define SDL_HINT_AUDIO_DEVICE_STREAM_ROLE "SDL_AUDIO_DEVICE_STREAM_ROLE"
+
+/**
+ * \brief A variable controlling speed/quality tradeoff of audio resampling.
+ *
+ * If available, SDL can use libsamplerate ( http://www.mega-nerd.com/SRC/ )
+ * to handle audio resampling. There are different resampling modes available
+ * that produce different levels of quality, using more CPU.
+ *
+ * If this hint isn't specified to a valid setting, or libsamplerate isn't
+ * available, SDL will use the default, internal resampling algorithm.
+ *
+ * As of SDL 2.26, SDL_ConvertAudio() respects this hint when libsamplerate is available.
+ *
+ * This hint is currently only checked at audio subsystem initialization.
+ *
+ * This variable can be set to the following values:
+ *
+ * "0" or "default" - Use SDL's internal resampling (Default when not set - low quality, fast)
+ * "1" or "fast" - Use fast, slightly higher quality resampling, if available
+ * "2" or "medium" - Use medium quality resampling, if available
+ * "3" or "best" - Use high quality resampling, if available
+ */
+#define SDL_HINT_AUDIO_RESAMPLING_MODE "SDL_AUDIO_RESAMPLING_MODE"
+
+/**
+ * \brief A variable controlling whether SDL updates joystick state when getting input events
+ *
+ * This variable can be set to the following values:
+ *
+ * "0" - You'll call SDL_JoystickUpdate() manually
+ * "1" - SDL will automatically call SDL_JoystickUpdate() (default)
+ *
+ * This hint can be toggled on and off at runtime.
+ */
+#define SDL_HINT_AUTO_UPDATE_JOYSTICKS "SDL_AUTO_UPDATE_JOYSTICKS"
+
+/**
+ * \brief A variable controlling whether SDL updates sensor state when getting input events
+ *
+ * This variable can be set to the following values:
+ *
+ * "0" - You'll call SDL_SensorUpdate() manually
+ * "1" - SDL will automatically call SDL_SensorUpdate() (default)
+ *
+ * This hint can be toggled on and off at runtime.
+ */
+#define SDL_HINT_AUTO_UPDATE_SENSORS "SDL_AUTO_UPDATE_SENSORS"
+
+/**
+ * \brief Prevent SDL from using version 4 of the bitmap header when saving BMPs.
+ *
+ * The bitmap header version 4 is required for proper alpha channel support and
+ * SDL will use it when required. Should this not be desired, this hint can
+ * force the use of the 40 byte header version which is supported everywhere.
+ *
+ * The variable can be set to the following values:
+ * "0" - Surfaces with a colorkey or an alpha channel are saved to a
+ * 32-bit BMP file with an alpha mask. SDL will use the bitmap
+ * header version 4 and set the alpha mask accordingly.
+ * "1" - Surfaces with a colorkey or an alpha channel are saved to a
+ * 32-bit BMP file without an alpha mask. The alpha channel data
+ * will be in the file, but applications are going to ignore it.
+ *
+ * The default value is "0".
+ */
+#define SDL_HINT_BMP_SAVE_LEGACY_FORMAT "SDL_BMP_SAVE_LEGACY_FORMAT"
+
+/**
+ * \brief Override for SDL_GetDisplayUsableBounds()
+ *
+ * If set, this hint will override the expected results for
+ * SDL_GetDisplayUsableBounds() for display index 0. Generally you don't want
+ * to do this, but this allows an embedded system to request that some of the
+ * screen be reserved for other uses when paired with a well-behaved
+ * application.
+ *
+ * The contents of this hint must be 4 comma-separated integers, the first
+ * is the bounds x, then y, width and height, in that order.
+ */
+#define SDL_HINT_DISPLAY_USABLE_BOUNDS "SDL_DISPLAY_USABLE_BOUNDS"
+
+/**
+ * \brief Disable giving back control to the browser automatically
+ * when running with asyncify
+ *
+ * With -s ASYNCIFY, SDL2 calls emscripten_sleep during operations
+ * such as refreshing the screen or polling events.
+ *
+ * This hint only applies to the emscripten platform
+ *
+ * The variable can be set to the following values:
+ * "0" - Disable emscripten_sleep calls (if you give back browser control manually or use asyncify for other purposes)
+ * "1" - Enable emscripten_sleep calls (the default)
+ */
+#define SDL_HINT_EMSCRIPTEN_ASYNCIFY "SDL_EMSCRIPTEN_ASYNCIFY"
+
+/**
+ * \brief override the binding element for keyboard inputs for Emscripten builds
+ *
+ * This hint only applies to the emscripten platform
+ *
+ * The variable can be one of
+ * "#window" - The javascript window object (this is the default)
+ * "#document" - The javascript document object
+ * "#screen" - the javascript window.screen object
+ * "#canvas" - the WebGL canvas element
+ * any other string without a leading # sign applies to the element on the page with that ID.
+ */
+#define SDL_HINT_EMSCRIPTEN_KEYBOARD_ELEMENT "SDL_EMSCRIPTEN_KEYBOARD_ELEMENT"
+
+/**
+ * \brief A variable that controls whether the on-screen keyboard should be shown when text input is active
+ *
+ * The variable can be set to the following values:
+ * "0" - Do not show the on-screen keyboard
+ * "1" - Show the on-screen keyboard
+ *
+ * The default value is "1". This hint must be set before text input is activated.
+ */
+#define SDL_HINT_ENABLE_SCREEN_KEYBOARD "SDL_ENABLE_SCREEN_KEYBOARD"
+
+/**
+ * \brief A variable that controls whether Steam Controllers should be exposed using the SDL joystick and game controller APIs
+ *
+ * The variable can be set to the following values:
+ * "0" - Do not scan for Steam Controllers
+ * "1" - Scan for Steam Controllers (the default)
+ *
+ * The default value is "1". This hint must be set before initializing the joystick subsystem.
+ */
+#define SDL_HINT_ENABLE_STEAM_CONTROLLERS "SDL_ENABLE_STEAM_CONTROLLERS"
+
+/**
+ * \brief A variable controlling verbosity of the logging of SDL events pushed onto the internal queue.
+ *
+ * This variable can be set to the following values, from least to most verbose:
+ *
+ * "0" - Don't log any events (default)
+ * "1" - Log most events (other than the really spammy ones).
+ * "2" - Include mouse and finger motion events.
+ * "3" - Include SDL_SysWMEvent events.
+ *
+ * This is generally meant to be used to debug SDL itself, but can be useful
+ * for application developers that need better visibility into what is going
+ * on in the event queue. Logged events are sent through SDL_Log(), which
+ * means by default they appear on stdout on most platforms or maybe
+ * OutputDebugString() on Windows, and can be funneled by the app with
+ * SDL_LogSetOutputFunction(), etc.
+ *
+ * This hint can be toggled on and off at runtime, if you only need to log
+ * events for a small subset of program execution.
+ */
+#define SDL_HINT_EVENT_LOGGING "SDL_EVENT_LOGGING"
+
+/**
+ * \brief A variable controlling whether raising the window should be done more forcefully
+ *
+ * This variable can be set to the following values:
+ * "0" - No forcing (the default)
+ * "1" - Extra level of forcing
+ *
+ * At present, this is only an issue under MS Windows, which makes it nearly impossible to
+ * programmatically move a window to the foreground, for "security" reasons. See
+ * http://stackoverflow.com/a/34414846 for a discussion.
+ */
+#define SDL_HINT_FORCE_RAISEWINDOW "SDL_HINT_FORCE_RAISEWINDOW"
+
+/**
+ * \brief A variable controlling how 3D acceleration is used to accelerate the SDL screen surface.
+ *
+ * SDL can try to accelerate the SDL screen surface by using streaming
+ * textures with a 3D rendering engine. This variable controls whether and
+ * how this is done.
+ *
+ * This variable can be set to the following values:
+ * "0" - Disable 3D acceleration
+ * "1" - Enable 3D acceleration, using the default renderer.
+ * "X" - Enable 3D acceleration, using X where X is one of the valid rendering drivers. (e.g. "direct3d", "opengl", etc.)
+ *
+ * By default SDL tries to make a best guess for each platform whether
+ * to use acceleration or not.
+ */
+#define SDL_HINT_FRAMEBUFFER_ACCELERATION "SDL_FRAMEBUFFER_ACCELERATION"
+
+/**
+ * \brief A variable that lets you manually hint extra gamecontroller db entries.
+ *
+ * The variable should be newline delimited rows of gamecontroller config data, see SDL_gamecontroller.h
+ *
+ * This hint must be set before calling SDL_Init(SDL_INIT_GAMECONTROLLER)
+ * You can update mappings after the system is initialized with SDL_GameControllerMappingForGUID() and SDL_GameControllerAddMapping()
+ */
+#define SDL_HINT_GAMECONTROLLERCONFIG "SDL_GAMECONTROLLERCONFIG"
+
+/**
+ * \brief A variable that lets you provide a file with extra gamecontroller db entries.
+ *
+ * The file should contain lines of gamecontroller config data, see SDL_gamecontroller.h
+ *
+ * This hint must be set before calling SDL_Init(SDL_INIT_GAMECONTROLLER)
+ * You can update mappings after the system is initialized with SDL_GameControllerMappingForGUID() and SDL_GameControllerAddMapping()
+ */
+#define SDL_HINT_GAMECONTROLLERCONFIG_FILE "SDL_GAMECONTROLLERCONFIG_FILE"
+
+/**
+ * \brief A variable that overrides the automatic controller type detection
+ *
+ * The variable should be comma separated entries, in the form: VID/PID=type
+ *
+ * The VID and PID should be hexadecimal with exactly 4 digits, e.g. 0x00fd
+ *
+ * The type should be one of:
+ * Xbox360
+ * XboxOne
+ * PS3
+ * PS4
+ * PS5
+ * SwitchPro
+ *
+ * This hint affects what driver is used, and must be set before calling SDL_Init(SDL_INIT_GAMECONTROLLER)
+ */
+#define SDL_HINT_GAMECONTROLLERTYPE "SDL_GAMECONTROLLERTYPE"
+
+/**
+ * \brief A variable containing a list of devices to skip when scanning for game controllers.
+ *
+ * The format of the string is a comma separated list of USB VID/PID pairs
+ * in hexadecimal form, e.g.
+ *
+ * 0xAAAA/0xBBBB,0xCCCC/0xDDDD
+ *
+ * The variable can also take the form of @file, in which case the named
+ * file will be loaded and interpreted as the value of the variable.
+ */
+#define SDL_HINT_GAMECONTROLLER_IGNORE_DEVICES "SDL_GAMECONTROLLER_IGNORE_DEVICES"
+
+/**
+ * \brief If set, all devices will be skipped when scanning for game controllers except for the ones listed in this variable.
+ *
+ * The format of the string is a comma separated list of USB VID/PID pairs
+ * in hexadecimal form, e.g.
+ *
+ * 0xAAAA/0xBBBB,0xCCCC/0xDDDD
+ *
+ * The variable can also take the form of @file, in which case the named
+ * file will be loaded and interpreted as the value of the variable.
+ */
+#define SDL_HINT_GAMECONTROLLER_IGNORE_DEVICES_EXCEPT "SDL_GAMECONTROLLER_IGNORE_DEVICES_EXCEPT"
+
+/**
+ * \brief If set, game controller face buttons report their values according to their labels instead of their positional layout.
+ *
+ * For example, on Nintendo Switch controllers, normally you'd get:
+ *
+ * (Y)
+ * (X) (B)
+ * (A)
+ *
+ * but if this hint is set, you'll get:
+ *
+ * (X)
+ * (Y) (A)
+ * (B)
+ *
+ * The variable can be set to the following values:
+ * "0" - Report the face buttons by position, as though they were on an Xbox controller.
+ * "1" - Report the face buttons by label instead of position
+ *
+ * The default value is "1". This hint may be set at any time.
+ */
+#define SDL_HINT_GAMECONTROLLER_USE_BUTTON_LABELS "SDL_GAMECONTROLLER_USE_BUTTON_LABELS"
+
+/**
+ * \brief A variable controlling whether grabbing input grabs the keyboard
+ *
+ * This variable can be set to the following values:
+ * "0" - Grab will affect only the mouse
+ * "1" - Grab will affect mouse and keyboard
+ *
+ * By default SDL will not grab the keyboard so system shortcuts still work.
+ */
+#define SDL_HINT_GRAB_KEYBOARD "SDL_GRAB_KEYBOARD"
+
+/**
+ * \brief A variable containing a list of devices to ignore in SDL_hid_enumerate()
+ *
+ * For example, to ignore the Shanwan DS3 controller and any Valve controller, you might
+ * have the string "0x2563/0x0523,0x28de/0x0000"
+ */
+#define SDL_HINT_HIDAPI_IGNORE_DEVICES "SDL_HIDAPI_IGNORE_DEVICES"
+
+/**
+ * \brief A variable controlling whether the idle timer is disabled on iOS.
+ *
+ * When an iOS app does not receive touches for some time, the screen is
+ * dimmed automatically. For games where the accelerometer is the only input
+ * this is problematic. This functionality can be disabled by setting this
+ * hint.
+ *
+ * As of SDL 2.0.4, SDL_EnableScreenSaver() and SDL_DisableScreenSaver()
+ * accomplish the same thing on iOS. They should be preferred over this hint.
+ *
+ * This variable can be set to the following values:
+ * "0" - Enable idle timer
+ * "1" - Disable idle timer
+ */
+#define SDL_HINT_IDLE_TIMER_DISABLED "SDL_IOS_IDLE_TIMER_DISABLED"
+
+/**
+ * \brief A variable to control whether certain IMEs should handle text editing internally instead of sending SDL_TEXTEDITING events.
+ *
+ * The variable can be set to the following values:
+ * "0" - SDL_TEXTEDITING events are sent, and it is the application's
+ * responsibility to render the text from these events and
+ * differentiate it somehow from committed text. (default)
+ * "1" - If supported by the IME then SDL_TEXTEDITING events are not sent,
+ * and text that is being composed will be rendered in its own UI.
+ */
+#define SDL_HINT_IME_INTERNAL_EDITING "SDL_IME_INTERNAL_EDITING"
+
+/**
+ * \brief A variable to control whether certain IMEs should show native UI components (such as the Candidate List) instead of suppressing them.
+ *
+ * The variable can be set to the following values:
+ * "0" - Native UI components are not display. (default)
+ * "1" - Native UI components are displayed.
+ */
+#define SDL_HINT_IME_SHOW_UI "SDL_IME_SHOW_UI"
+
+/**
+ * \brief A variable to control if extended IME text support is enabled.
+ * If enabled then SDL_TextEditingExtEvent will be issued if the text would be truncated otherwise.
+ * Additionally SDL_TextInputEvent will be dispatched multiple times so that it is not truncated.
+ *
+ * The variable can be set to the following values:
+ * "0" - Legacy behavior. Text can be truncated, no heap allocations. (default)
+ * "1" - Modern behavior.
+ */
+#define SDL_HINT_IME_SUPPORT_EXTENDED_TEXT "SDL_IME_SUPPORT_EXTENDED_TEXT"
+
+/**
+ * \brief A variable controlling whether the home indicator bar on iPhone X
+ * should be hidden.
+ *
+ * This variable can be set to the following values:
+ * "0" - The indicator bar is not hidden (default for windowed applications)
+ * "1" - The indicator bar is hidden and is shown when the screen is touched (useful for movie playback applications)
+ * "2" - The indicator bar is dim and the first swipe makes it visible and the second swipe performs the "home" action (default for fullscreen applications)
+ */
+#define SDL_HINT_IOS_HIDE_HOME_INDICATOR "SDL_IOS_HIDE_HOME_INDICATOR"
+
+/**
+ * \brief A variable that lets you enable joystick (and gamecontroller) events even when your app is in the background.
+ *
+ * The variable can be set to the following values:
+ * "0" - Disable joystick & gamecontroller input events when the
+ * application is in the background.
+ * "1" - Enable joystick & gamecontroller input events when the
+ * application is in the background.
+ *
+ * The default value is "0". This hint may be set at any time.
+ */
+#define SDL_HINT_JOYSTICK_ALLOW_BACKGROUND_EVENTS "SDL_JOYSTICK_ALLOW_BACKGROUND_EVENTS"
+
+/**
+ * \brief A variable controlling whether the HIDAPI joystick drivers should be used.
+ *
+ * This variable can be set to the following values:
+ * "0" - HIDAPI drivers are not used
+ * "1" - HIDAPI drivers are used (the default)
+ *
+ * This variable is the default for all drivers, but can be overridden by the hints for specific drivers below.
+ */
+#define SDL_HINT_JOYSTICK_HIDAPI "SDL_JOYSTICK_HIDAPI"
+
+/**
+ * \brief A variable controlling whether the HIDAPI driver for Nintendo GameCube controllers should be used.
+ *
+ * This variable can be set to the following values:
+ * "0" - HIDAPI driver is not used
+ * "1" - HIDAPI driver is used
+ *
+ * The default is the value of SDL_HINT_JOYSTICK_HIDAPI
+ */
+#define SDL_HINT_JOYSTICK_HIDAPI_GAMECUBE "SDL_JOYSTICK_HIDAPI_GAMECUBE"
+
+/**
+ * \brief A variable controlling whether "low_frequency_rumble" and "high_frequency_rumble" is used to implement
+ * the GameCube controller's 3 rumble modes, Stop(0), Rumble(1), and StopHard(2)
+ * this is useful for applications that need full compatibility for things like ADSR envelopes.
+ * Stop is implemented by setting "low_frequency_rumble" to "0" and "high_frequency_rumble" ">0"
+ * Rumble is both at any arbitrary value,
+ * StopHard is implemented by setting both "low_frequency_rumble" and "high_frequency_rumble" to "0"
+ *
+ * This variable can be set to the following values:
+ * "0" - Normal rumble behavior is behavior is used (default)
+ * "1" - Proper GameCube controller rumble behavior is used
+ *
+ */
+#define SDL_HINT_JOYSTICK_GAMECUBE_RUMBLE_BRAKE "SDL_JOYSTICK_GAMECUBE_RUMBLE_BRAKE"
+
+/**
+ * \brief A variable controlling whether the HIDAPI driver for Nintendo Switch Joy-Cons should be used.
+ *
+ * This variable can be set to the following values:
+ * "0" - HIDAPI driver is not used
+ * "1" - HIDAPI driver is used
+ *
+ * The default is the value of SDL_HINT_JOYSTICK_HIDAPI
+ */
+#define SDL_HINT_JOYSTICK_HIDAPI_JOY_CONS "SDL_JOYSTICK_HIDAPI_JOY_CONS"
+
+/**
+ * \brief A variable controlling whether Nintendo Switch Joy-Con controllers will be combined into a single Pro-like controller when using the HIDAPI driver
+ *
+ * This variable can be set to the following values:
+ * "0" - Left and right Joy-Con controllers will not be combined and each will be a mini-gamepad
+ * "1" - Left and right Joy-Con controllers will be combined into a single controller (the default)
+ */
+#define SDL_HINT_JOYSTICK_HIDAPI_COMBINE_JOY_CONS "SDL_JOYSTICK_HIDAPI_COMBINE_JOY_CONS"
+
+/**
+ * \brief A variable controlling whether Nintendo Switch Joy-Con controllers will be in vertical mode when using the HIDAPI driver
+ *
+ * This variable can be set to the following values:
+ * "0" - Left and right Joy-Con controllers will not be in vertical mode (the default)
+ * "1" - Left and right Joy-Con controllers will be in vertical mode
+ *
+ * This hint must be set before calling SDL_Init(SDL_INIT_GAMECONTROLLER)
+ */
+#define SDL_HINT_JOYSTICK_HIDAPI_VERTICAL_JOY_CONS "SDL_JOYSTICK_HIDAPI_VERTICAL_JOY_CONS"
+
+/**
+ * \brief A variable controlling whether the HIDAPI driver for Amazon Luna controllers connected via Bluetooth should be used.
+ *
+ * This variable can be set to the following values:
+ * "0" - HIDAPI driver is not used
+ * "1" - HIDAPI driver is used
+ *
+ * The default is the value of SDL_HINT_JOYSTICK_HIDAPI
+ */
+#define SDL_HINT_JOYSTICK_HIDAPI_LUNA "SDL_JOYSTICK_HIDAPI_LUNA"
+
+/**
+ * \brief A variable controlling whether the HIDAPI driver for Nintendo Online classic controllers should be used.
+ *
+ * This variable can be set to the following values:
+ * "0" - HIDAPI driver is not used
+ * "1" - HIDAPI driver is used
+ *
+ * The default is the value of SDL_HINT_JOYSTICK_HIDAPI
+ */
+#define SDL_HINT_JOYSTICK_HIDAPI_NINTENDO_CLASSIC "SDL_JOYSTICK_HIDAPI_NINTENDO_CLASSIC"
+
+/**
+ * \brief A variable controlling whether the HIDAPI driver for NVIDIA SHIELD controllers should be used.
+ *
+ * This variable can be set to the following values:
+ * "0" - HIDAPI driver is not used
+ * "1" - HIDAPI driver is used
+ *
+ * The default is the value of SDL_HINT_JOYSTICK_HIDAPI
+ */
+#define SDL_HINT_JOYSTICK_HIDAPI_SHIELD "SDL_JOYSTICK_HIDAPI_SHIELD"
+
+/**
+ * \brief A variable controlling whether the HIDAPI driver for PS3 controllers should be used.
+ *
+ * This variable can be set to the following values:
+ * "0" - HIDAPI driver is not used
+ * "1" - HIDAPI driver is used
+ *
+ * The default is the value of SDL_HINT_JOYSTICK_HIDAPI on macOS, and "0" on other platforms.
+ *
+ * It is not possible to use this driver on Windows, due to limitations in the default drivers
+ * installed. See https://github.com/ViGEm/DsHidMini for an alternative driver on Windows.
+ */
+#define SDL_HINT_JOYSTICK_HIDAPI_PS3 "SDL_JOYSTICK_HIDAPI_PS3"
+
+/**
+ * \brief A variable controlling whether the HIDAPI driver for PS4 controllers should be used.
+ *
+ * This variable can be set to the following values:
+ * "0" - HIDAPI driver is not used
+ * "1" - HIDAPI driver is used
+ *
+ * The default is the value of SDL_HINT_JOYSTICK_HIDAPI
+ */
+#define SDL_HINT_JOYSTICK_HIDAPI_PS4 "SDL_JOYSTICK_HIDAPI_PS4"
+
+/**
+ * \brief A variable controlling whether extended input reports should be used for PS4 controllers when using the HIDAPI driver.
+ *
+ * This variable can be set to the following values:
+ * "0" - extended reports are not enabled (the default)
+ * "1" - extended reports
+ *
+ * Extended input reports allow rumble on Bluetooth PS4 controllers, but
+ * break DirectInput handling for applications that don't use SDL.
+ *
+ * Once extended reports are enabled, they can not be disabled without
+ * power cycling the controller.
+ *
+ * For compatibility with applications written for versions of SDL prior
+ * to the introduction of PS5 controller support, this value will also
+ * control the state of extended reports on PS5 controllers when the
+ * SDL_HINT_JOYSTICK_HIDAPI_PS5_RUMBLE hint is not explicitly set.
+ */
+#define SDL_HINT_JOYSTICK_HIDAPI_PS4_RUMBLE "SDL_JOYSTICK_HIDAPI_PS4_RUMBLE"
+
+/**
+ * \brief A variable controlling whether the HIDAPI driver for PS5 controllers should be used.
+ *
+ * This variable can be set to the following values:
+ * "0" - HIDAPI driver is not used
+ * "1" - HIDAPI driver is used
+ *
+ * The default is the value of SDL_HINT_JOYSTICK_HIDAPI
+ */
+#define SDL_HINT_JOYSTICK_HIDAPI_PS5 "SDL_JOYSTICK_HIDAPI_PS5"
+
+/**
+ * \brief A variable controlling whether the player LEDs should be lit to indicate which player is associated with a PS5 controller.
+ *
+ * This variable can be set to the following values:
+ * "0" - player LEDs are not enabled
+ * "1" - player LEDs are enabled (the default)
+ */
+#define SDL_HINT_JOYSTICK_HIDAPI_PS5_PLAYER_LED "SDL_JOYSTICK_HIDAPI_PS5_PLAYER_LED"
+
+/**
+ * \brief A variable controlling whether extended input reports should be used for PS5 controllers when using the HIDAPI driver.
+ *
+ * This variable can be set to the following values:
+ * "0" - extended reports are not enabled (the default)
+ * "1" - extended reports
+ *
+ * Extended input reports allow rumble on Bluetooth PS5 controllers, but
+ * break DirectInput handling for applications that don't use SDL.
+ *
+ * Once extended reports are enabled, they can not be disabled without
+ * power cycling the controller.
+ *
+ * For compatibility with applications written for versions of SDL prior
+ * to the introduction of PS5 controller support, this value defaults to
+ * the value of SDL_HINT_JOYSTICK_HIDAPI_PS4_RUMBLE.
+ */
+#define SDL_HINT_JOYSTICK_HIDAPI_PS5_RUMBLE "SDL_JOYSTICK_HIDAPI_PS5_RUMBLE"
+
+/**
+ * \brief A variable controlling whether the HIDAPI driver for Google Stadia controllers should be used.
+ *
+ * This variable can be set to the following values:
+ * "0" - HIDAPI driver is not used
+ * "1" - HIDAPI driver is used
+ *
+ * The default is the value of SDL_HINT_JOYSTICK_HIDAPI
+ */
+#define SDL_HINT_JOYSTICK_HIDAPI_STADIA "SDL_JOYSTICK_HIDAPI_STADIA"
+
+/**
+ * \brief A variable controlling whether the HIDAPI driver for Bluetooth Steam Controllers should be used.
+ *
+ * This variable can be set to the following values:
+ * "0" - HIDAPI driver is not used
+ * "1" - HIDAPI driver is used for Steam Controllers, which requires Bluetooth access
+ * and may prompt the user for permission on iOS and Android.
+ *
+ * The default is "0"
+ */
+#define SDL_HINT_JOYSTICK_HIDAPI_STEAM "SDL_JOYSTICK_HIDAPI_STEAM"
+
+/**
+ * \brief A variable controlling whether the HIDAPI driver for Nintendo Switch controllers should be used.
+ *
+ * This variable can be set to the following values:
+ * "0" - HIDAPI driver is not used
+ * "1" - HIDAPI driver is used
+ *
+ * The default is the value of SDL_HINT_JOYSTICK_HIDAPI
+ */
+#define SDL_HINT_JOYSTICK_HIDAPI_SWITCH "SDL_JOYSTICK_HIDAPI_SWITCH"
+
+/**
+ * \brief A variable controlling whether the Home button LED should be turned on when a Nintendo Switch Pro controller is opened
+ *
+ * This variable can be set to the following values:
+ * "0" - home button LED is turned off
+ * "1" - home button LED is turned on
+ *
+ * By default the Home button LED state is not changed. This hint can also be set to a floating point value between 0.0 and 1.0 which controls the brightness of the Home button LED.
+ */
+#define SDL_HINT_JOYSTICK_HIDAPI_SWITCH_HOME_LED "SDL_JOYSTICK_HIDAPI_SWITCH_HOME_LED"
+
+/**
+ * \brief A variable controlling whether the Home button LED should be turned on when a Nintendo Switch Joy-Con controller is opened
+ *
+ * This variable can be set to the following values:
+ * "0" - home button LED is turned off
+ * "1" - home button LED is turned on
+ *
+ * By default the Home button LED state is not changed. This hint can also be set to a floating point value between 0.0 and 1.0 which controls the brightness of the Home button LED.
+ */
+#define SDL_HINT_JOYSTICK_HIDAPI_JOYCON_HOME_LED "SDL_JOYSTICK_HIDAPI_JOYCON_HOME_LED"
+
+/**
+ * \brief A variable controlling whether the player LEDs should be lit to indicate which player is associated with a Nintendo Switch controller.
+ *
+ * This variable can be set to the following values:
+ * "0" - player LEDs are not enabled
+ * "1" - player LEDs are enabled (the default)
+ */
+#define SDL_HINT_JOYSTICK_HIDAPI_SWITCH_PLAYER_LED "SDL_JOYSTICK_HIDAPI_SWITCH_PLAYER_LED"
+
+/**
+ * \brief A variable controlling whether the HIDAPI driver for Nintendo Wii and Wii U controllers should be used.
+ *
+ * This variable can be set to the following values:
+ * "0" - HIDAPI driver is not used
+ * "1" - HIDAPI driver is used
+ *
+ * This driver doesn't work with the dolphinbar, so the default is SDL_FALSE for now.
+ */
+#define SDL_HINT_JOYSTICK_HIDAPI_WII "SDL_JOYSTICK_HIDAPI_WII"
+
+/**
+ * \brief A variable controlling whether the player LEDs should be lit to indicate which player is associated with a Wii controller.
+ *
+ * This variable can be set to the following values:
+ * "0" - player LEDs are not enabled
+ * "1" - player LEDs are enabled (the default)
+ */
+#define SDL_HINT_JOYSTICK_HIDAPI_WII_PLAYER_LED "SDL_JOYSTICK_HIDAPI_WII_PLAYER_LED"
+
+/**
+ * \brief A variable controlling whether the HIDAPI driver for XBox controllers should be used.
+ *
+ * This variable can be set to the following values:
+ * "0" - HIDAPI driver is not used
+ * "1" - HIDAPI driver is used
+ *
+ * The default is "0" on Windows, otherwise the value of SDL_HINT_JOYSTICK_HIDAPI
+ */
+#define SDL_HINT_JOYSTICK_HIDAPI_XBOX "SDL_JOYSTICK_HIDAPI_XBOX"
+
+/**
+ * \brief A variable controlling whether the HIDAPI driver for XBox 360 controllers should be used.
+ *
+ * This variable can be set to the following values:
+ * "0" - HIDAPI driver is not used
+ * "1" - HIDAPI driver is used
+ *
+ * The default is the value of SDL_HINT_JOYSTICK_HIDAPI_XBOX
+ */
+#define SDL_HINT_JOYSTICK_HIDAPI_XBOX_360 "SDL_JOYSTICK_HIDAPI_XBOX_360"
+
+/**
+ * \brief A variable controlling whether the player LEDs should be lit to indicate which player is associated with an Xbox 360 controller.
+ *
+ * This variable can be set to the following values:
+ * "0" - player LEDs are not enabled
+ * "1" - player LEDs are enabled (the default)
+ */
+#define SDL_HINT_JOYSTICK_HIDAPI_XBOX_360_PLAYER_LED "SDL_JOYSTICK_HIDAPI_XBOX_360_PLAYER_LED"
+
+/**
+ * \brief A variable controlling whether the HIDAPI driver for XBox 360 wireless controllers should be used.
+ *
+ * This variable can be set to the following values:
+ * "0" - HIDAPI driver is not used
+ * "1" - HIDAPI driver is used
+ *
+ * The default is the value of SDL_HINT_JOYSTICK_HIDAPI_XBOX_360
+ */
+#define SDL_HINT_JOYSTICK_HIDAPI_XBOX_360_WIRELESS "SDL_JOYSTICK_HIDAPI_XBOX_360_WIRELESS"
+
+/**
+ * \brief A variable controlling whether the HIDAPI driver for XBox One controllers should be used.
+ *
+ * This variable can be set to the following values:
+ * "0" - HIDAPI driver is not used
+ * "1" - HIDAPI driver is used
+ *
+ * The default is the value of SDL_HINT_JOYSTICK_HIDAPI_XBOX
+ */
+#define SDL_HINT_JOYSTICK_HIDAPI_XBOX_ONE "SDL_JOYSTICK_HIDAPI_XBOX_ONE"
+
+/**
+ * \brief A variable controlling whether the Home button LED should be turned on when an Xbox One controller is opened
+ *
+ * This variable can be set to the following values:
+ * "0" - home button LED is turned off
+ * "1" - home button LED is turned on
+ *
+ * By default the Home button LED state is not changed. This hint can also be set to a floating point value between 0.0 and 1.0 which controls the brightness of the Home button LED. The default brightness is 0.4.
+ */
+#define SDL_HINT_JOYSTICK_HIDAPI_XBOX_ONE_HOME_LED "SDL_JOYSTICK_HIDAPI_XBOX_ONE_HOME_LED"
+
+/**
+ * \brief A variable controlling whether the RAWINPUT joystick drivers should be used for better handling XInput-capable devices.
+ *
+ * This variable can be set to the following values:
+ * "0" - RAWINPUT drivers are not used
+ * "1" - RAWINPUT drivers are used (the default)
+ */
+#define SDL_HINT_JOYSTICK_RAWINPUT "SDL_JOYSTICK_RAWINPUT"
+
+/**
+ * \brief A variable controlling whether the RAWINPUT driver should pull correlated data from XInput.
+ *
+ * This variable can be set to the following values:
+ * "0" - RAWINPUT driver will only use data from raw input APIs
+ * "1" - RAWINPUT driver will also pull data from XInput, providing
+ * better trigger axes, guide button presses, and rumble support
+ * for Xbox controllers
+ *
+ * The default is "1". This hint applies to any joysticks opened after setting the hint.
+ */
+#define SDL_HINT_JOYSTICK_RAWINPUT_CORRELATE_XINPUT "SDL_JOYSTICK_RAWINPUT_CORRELATE_XINPUT"
+
+/**
+ * \brief A variable controlling whether the ROG Chakram mice should show up as joysticks
+ *
+ * This variable can be set to the following values:
+ * "0" - ROG Chakram mice do not show up as joysticks (the default)
+ * "1" - ROG Chakram mice show up as joysticks
+ */
+#define SDL_HINT_JOYSTICK_ROG_CHAKRAM "SDL_JOYSTICK_ROG_CHAKRAM"
+
+/**
+ * \brief A variable controlling whether a separate thread should be used
+ * for handling joystick detection and raw input messages on Windows
+ *
+ * This variable can be set to the following values:
+ * "0" - A separate thread is not used (the default)
+ * "1" - A separate thread is used for handling raw input messages
+ *
+ */
+#define SDL_HINT_JOYSTICK_THREAD "SDL_JOYSTICK_THREAD"
+
+/**
+ * \brief A variable controlling whether Windows.Gaming.Input should be used for controller handling.
+ *
+ * This variable can be set to the following values:
+ * "0" - WGI is not used
+ * "1" - WGI is used (the default)
+ */
+#define SDL_HINT_JOYSTICK_WGI "SDL_JOYSTICK_WGI"
+
+/**
+ * \brief Determines whether SDL enforces that DRM master is required in order
+ * to initialize the KMSDRM video backend.
+ *
+ * The DRM subsystem has a concept of a "DRM master" which is a DRM client that
+ * has the ability to set planes, set cursor, etc. When SDL is DRM master, it
+ * can draw to the screen using the SDL rendering APIs. Without DRM master, SDL
+ * is still able to process input and query attributes of attached displays,
+ * but it cannot change display state or draw to the screen directly.
+ *
+ * In some cases, it can be useful to have the KMSDRM backend even if it cannot
+ * be used for rendering. An app may want to use SDL for input processing while
+ * using another rendering API (such as an MMAL overlay on Raspberry Pi) or
+ * using its own code to render to DRM overlays that SDL doesn't support.
+ *
+ * This hint must be set before initializing the video subsystem.
+ *
+ * This variable can be set to the following values:
+ * "0" - SDL will allow usage of the KMSDRM backend without DRM master
+ * "1" - SDL Will require DRM master to use the KMSDRM backend (default)
+ */
+#define SDL_HINT_KMSDRM_REQUIRE_DRM_MASTER "SDL_KMSDRM_REQUIRE_DRM_MASTER"
+
+/**
+ * \brief A comma separated list of devices to open as joysticks
+ *
+ * This variable is currently only used by the Linux joystick driver.
+ */
+#define SDL_HINT_JOYSTICK_DEVICE "SDL_JOYSTICK_DEVICE"
+
+/**
+ * \brief A variable controlling whether joysticks on Linux will always treat 'hat' axis inputs (ABS_HAT0X - ABS_HAT3Y) as 8-way digital hats without checking whether they may be analog.
+ *
+ * This variable can be set to the following values:
+ * "0" - Only map hat axis inputs to digital hat outputs if the input axes appear to actually be digital (the default)
+ * "1" - Always handle the input axes numbered ABS_HAT0X to ABS_HAT3Y as digital hats
+ */
+#define SDL_HINT_LINUX_DIGITAL_HATS "SDL_LINUX_DIGITAL_HATS"
+
+/**
+ * \brief A variable controlling whether digital hats on Linux will apply deadzones to their underlying input axes or use unfiltered values.
+ *
+ * This variable can be set to the following values:
+ * "0" - Return digital hat values based on unfiltered input axis values
+ * "1" - Return digital hat values with deadzones on the input axes taken into account (the default)
+ */
+#define SDL_HINT_LINUX_HAT_DEADZONES "SDL_LINUX_HAT_DEADZONES"
+
+/**
+ * \brief A variable controlling whether to use the classic /dev/input/js* joystick interface or the newer /dev/input/event* joystick interface on Linux
+ *
+ * This variable can be set to the following values:
+ * "0" - Use /dev/input/event*
+ * "1" - Use /dev/input/js*
+ *
+ * By default the /dev/input/event* interfaces are used
+ */
+#define SDL_HINT_LINUX_JOYSTICK_CLASSIC "SDL_LINUX_JOYSTICK_CLASSIC"
+
+/**
+ * \brief A variable controlling whether joysticks on Linux adhere to their HID-defined deadzones or return unfiltered values.
+ *
+ * This variable can be set to the following values:
+ * "0" - Return unfiltered joystick axis values (the default)
+ * "1" - Return axis values with deadzones taken into account
+ */
+#define SDL_HINT_LINUX_JOYSTICK_DEADZONES "SDL_LINUX_JOYSTICK_DEADZONES"
+
+/**
+* \brief When set don't force the SDL app to become a foreground process
+*
+* This hint only applies to Mac OS X.
+*
+*/
+#define SDL_HINT_MAC_BACKGROUND_APP "SDL_MAC_BACKGROUND_APP"
+
+/**
+ * \brief A variable that determines whether ctrl+click should generate a right-click event on Mac
+ *
+ * If present, holding ctrl while left clicking will generate a right click
+ * event when on Mac.
+ */
+#define SDL_HINT_MAC_CTRL_CLICK_EMULATE_RIGHT_CLICK "SDL_MAC_CTRL_CLICK_EMULATE_RIGHT_CLICK"
+
+/**
+ * \brief A variable controlling whether dispatching OpenGL context updates should block the dispatching thread until the main thread finishes processing
+ *
+ * This variable can be set to the following values:
+ * "0" - Dispatching OpenGL context updates will block the dispatching thread until the main thread finishes processing (default).
+ * "1" - Dispatching OpenGL context updates will allow the dispatching thread to continue execution.
+ *
+ * Generally you want the default, but if you have OpenGL code in a background thread on a Mac, and the main thread
+ * hangs because it's waiting for that background thread, but that background thread is also hanging because it's
+ * waiting for the main thread to do an update, this might fix your issue.
+ *
+ * This hint only applies to macOS.
+ *
+ * This hint is available since SDL 2.24.0.
+ *
+ */
+#define SDL_HINT_MAC_OPENGL_ASYNC_DISPATCH "SDL_MAC_OPENGL_ASYNC_DISPATCH"
+
+/**
+ * \brief A variable setting the double click radius, in pixels.
+ */
+#define SDL_HINT_MOUSE_DOUBLE_CLICK_RADIUS "SDL_MOUSE_DOUBLE_CLICK_RADIUS"
+
+/**
+ * \brief A variable setting the double click time, in milliseconds.
+ */
+#define SDL_HINT_MOUSE_DOUBLE_CLICK_TIME "SDL_MOUSE_DOUBLE_CLICK_TIME"
+
+/**
+ * \brief Allow mouse click events when clicking to focus an SDL window
+ *
+ * This variable can be set to the following values:
+ * "0" - Ignore mouse clicks that activate a window
+ * "1" - Generate events for mouse clicks that activate a window
+ *
+ * By default SDL will ignore mouse clicks that activate a window
+ */
+#define SDL_HINT_MOUSE_FOCUS_CLICKTHROUGH "SDL_MOUSE_FOCUS_CLICKTHROUGH"
+
+/**
+ * \brief A variable setting the speed scale for mouse motion, in floating point, when the mouse is not in relative mode
+ */
+#define SDL_HINT_MOUSE_NORMAL_SPEED_SCALE "SDL_MOUSE_NORMAL_SPEED_SCALE"
+
+/**
+ * \brief A variable controlling whether relative mouse mode constrains the mouse to the center of the window
+ *
+ * This variable can be set to the following values:
+ * "0" - Relative mouse mode constrains the mouse to the window
+ * "1" - Relative mouse mode constrains the mouse to the center of the window
+ *
+ * Constraining to the center of the window works better for FPS games and when the
+ * application is running over RDP. Constraining to the whole window works better
+ * for 2D games and increases the chance that the mouse will be in the correct
+ * position when using high DPI mice.
+ *
+ * By default SDL will constrain the mouse to the center of the window
+ */
+#define SDL_HINT_MOUSE_RELATIVE_MODE_CENTER "SDL_MOUSE_RELATIVE_MODE_CENTER"
+
+/**
+ * \brief A variable controlling whether relative mouse mode is implemented using mouse warping
+ *
+ * This variable can be set to the following values:
+ * "0" - Relative mouse mode uses raw input
+ * "1" - Relative mouse mode uses mouse warping
+ *
+ * By default SDL will use raw input for relative mouse mode
+ */
+#define SDL_HINT_MOUSE_RELATIVE_MODE_WARP "SDL_MOUSE_RELATIVE_MODE_WARP"
+
+/**
+ * \brief A variable controlling whether relative mouse motion is affected by renderer scaling
+ *
+ * This variable can be set to the following values:
+ * "0" - Relative motion is unaffected by DPI or renderer's logical size
+ * "1" - Relative motion is scaled according to DPI scaling and logical size
+ *
+ * By default relative mouse deltas are affected by DPI and renderer scaling
+ */
+#define SDL_HINT_MOUSE_RELATIVE_SCALING "SDL_MOUSE_RELATIVE_SCALING"
+
+/**
+ * \brief A variable setting the scale for mouse motion, in floating point, when the mouse is in relative mode
+ */
+#define SDL_HINT_MOUSE_RELATIVE_SPEED_SCALE "SDL_MOUSE_RELATIVE_SPEED_SCALE"
+
+/**
+ * \brief A variable controlling whether the system mouse acceleration curve is used for relative mouse motion.
+ *
+ * This variable can be set to the following values:
+ * "0" - Relative mouse motion will be unscaled (the default)
+ * "1" - Relative mouse motion will be scaled using the system mouse acceleration curve.
+ *
+ * If SDL_HINT_MOUSE_RELATIVE_SPEED_SCALE is set, that will override the system speed scale.
+ */
+#define SDL_HINT_MOUSE_RELATIVE_SYSTEM_SCALE "SDL_MOUSE_RELATIVE_SYSTEM_SCALE"
+
+/**
+ * \brief A variable controlling whether a motion event should be generated for mouse warping in relative mode.
+ *
+ * This variable can be set to the following values:
+ * "0" - Warping the mouse will not generate a motion event in relative mode
+ * "1" - Warping the mouse will generate a motion event in relative mode
+ *
+ * By default warping the mouse will not generate motion events in relative mode. This avoids the application having to filter out large relative motion due to warping.
+ */
+#define SDL_HINT_MOUSE_RELATIVE_WARP_MOTION "SDL_MOUSE_RELATIVE_WARP_MOTION"
+
+/**
+ * \brief A variable controlling whether mouse events should generate synthetic touch events
+ *
+ * This variable can be set to the following values:
+ * "0" - Mouse events will not generate touch events (default for desktop platforms)
+ * "1" - Mouse events will generate touch events (default for mobile platforms, such as Android and iOS)
+ */
+#define SDL_HINT_MOUSE_TOUCH_EVENTS "SDL_MOUSE_TOUCH_EVENTS"
+
+/**
+ * \brief A variable controlling whether the mouse is captured while mouse buttons are pressed
+ *
+ * This variable can be set to the following values:
+ * "0" - The mouse is not captured while mouse buttons are pressed
+ * "1" - The mouse is captured while mouse buttons are pressed
+ *
+ * By default the mouse is captured while mouse buttons are pressed so if the mouse is dragged
+ * outside the window, the application continues to receive mouse events until the button is
+ * released.
+ */
+#define SDL_HINT_MOUSE_AUTO_CAPTURE "SDL_MOUSE_AUTO_CAPTURE"
+
+/**
+ * \brief Tell SDL not to catch the SIGINT or SIGTERM signals.
+ *
+ * This hint only applies to Unix-like platforms, and should set before
+ * any calls to SDL_Init()
+ *
+ * The variable can be set to the following values:
+ * "0" - SDL will install a SIGINT and SIGTERM handler, and when it
+ * catches a signal, convert it into an SDL_QUIT event.
+ * "1" - SDL will not install a signal handler at all.
+ */
+#define SDL_HINT_NO_SIGNAL_HANDLERS "SDL_NO_SIGNAL_HANDLERS"
+
+/**
+ * \brief A variable controlling what driver to use for OpenGL ES contexts.
+ *
+ * On some platforms, currently Windows and X11, OpenGL drivers may support
+ * creating contexts with an OpenGL ES profile. By default SDL uses these
+ * profiles, when available, otherwise it attempts to load an OpenGL ES
+ * library, e.g. that provided by the ANGLE project. This variable controls
+ * whether SDL follows this default behaviour or will always load an
+ * OpenGL ES library.
+ *
+ * Circumstances where this is useful include
+ * - Testing an app with a particular OpenGL ES implementation, e.g ANGLE,
+ * or emulator, e.g. those from ARM, Imagination or Qualcomm.
+ * - Resolving OpenGL ES function addresses at link time by linking with
+ * the OpenGL ES library instead of querying them at run time with
+ * SDL_GL_GetProcAddress().
+ *
+ * Caution: for an application to work with the default behaviour across
+ * different OpenGL drivers it must query the OpenGL ES function
+ * addresses at run time using SDL_GL_GetProcAddress().
+ *
+ * This variable is ignored on most platforms because OpenGL ES is native
+ * or not supported.
+ *
+ * This variable can be set to the following values:
+ * "0" - Use ES profile of OpenGL, if available. (Default when not set.)
+ * "1" - Load OpenGL ES library using the default library names.
+ *
+ */
+#define SDL_HINT_OPENGL_ES_DRIVER "SDL_OPENGL_ES_DRIVER"
+
+/**
+ * \brief A variable controlling which orientations are allowed on iOS/Android.
+ *
+ * In some circumstances it is necessary to be able to explicitly control
+ * which UI orientations are allowed.
+ *
+ * This variable is a space delimited list of the following values:
+ * "LandscapeLeft", "LandscapeRight", "Portrait" "PortraitUpsideDown"
+ */
+#define SDL_HINT_ORIENTATIONS "SDL_IOS_ORIENTATIONS"
+
+/**
+ * \brief A variable controlling the use of a sentinel event when polling the event queue
+ *
+ * This variable can be set to the following values:
+ * "0" - Disable poll sentinels
+ * "1" - Enable poll sentinels
+ *
+ * When polling for events, SDL_PumpEvents is used to gather new events from devices.
+ * If a device keeps producing new events between calls to SDL_PumpEvents, a poll loop will
+ * become stuck until the new events stop.
+ * This is most noticeable when moving a high frequency mouse.
+ *
+ * By default, poll sentinels are enabled.
+ */
+#define SDL_HINT_POLL_SENTINEL "SDL_POLL_SENTINEL"
+
+/**
+ * \brief Override for SDL_GetPreferredLocales()
+ *
+ * If set, this will be favored over anything the OS might report for the
+ * user's preferred locales. Changing this hint at runtime will not generate
+ * a SDL_LOCALECHANGED event (but if you can change the hint, you can push
+ * your own event, if you want).
+ *
+ * The format of this hint is a comma-separated list of language and locale,
+ * combined with an underscore, as is a common format: "en_GB". Locale is
+ * optional: "en". So you might have a list like this: "en_GB,jp,es_PT"
+ */
+#define SDL_HINT_PREFERRED_LOCALES "SDL_PREFERRED_LOCALES"
+
+/**
+ * \brief A variable describing the content orientation on QtWayland-based platforms.
+ *
+ * On QtWayland platforms, windows are rotated client-side to allow for custom
+ * transitions. In order to correctly position overlays (e.g. volume bar) and
+ * gestures (e.g. events view, close/minimize gestures), the system needs to
+ * know in which orientation the application is currently drawing its contents.
+ *
+ * This does not cause the window to be rotated or resized, the application
+ * needs to take care of drawing the content in the right orientation (the
+ * framebuffer is always in portrait mode).
+ *
+ * This variable can be one of the following values:
+ * "primary" (default), "portrait", "landscape", "inverted-portrait", "inverted-landscape"
+ *
+ * Since SDL 2.0.22 this variable accepts a comma-separated list of values above.
+ */
+#define SDL_HINT_QTWAYLAND_CONTENT_ORIENTATION "SDL_QTWAYLAND_CONTENT_ORIENTATION"
+
+/**
+ * \brief Flags to set on QtWayland windows to integrate with the native window manager.
+ *
+ * On QtWayland platforms, this hint controls the flags to set on the windows.
+ * For example, on Sailfish OS "OverridesSystemGestures" disables swipe gestures.
+ *
+ * This variable is a space-separated list of the following values (empty = no flags):
+ * "OverridesSystemGestures", "StaysOnTop", "BypassWindowManager"
+ */
+#define SDL_HINT_QTWAYLAND_WINDOW_FLAGS "SDL_QTWAYLAND_WINDOW_FLAGS"
+
+/**
+ * \brief A variable controlling whether the 2D render API is compatible or efficient.
+ *
+ * This variable can be set to the following values:
+ *
+ * "0" - Don't use batching to make rendering more efficient.
+ * "1" - Use batching, but might cause problems if app makes its own direct OpenGL calls.
+ *
+ * Up to SDL 2.0.9, the render API would draw immediately when requested. Now
+ * it batches up draw requests and sends them all to the GPU only when forced
+ * to (during SDL_RenderPresent, when changing render targets, by updating a
+ * texture that the batch needs, etc). This is significantly more efficient,
+ * but it can cause problems for apps that expect to render on top of the
+ * render API's output. As such, SDL will disable batching if a specific
+ * render backend is requested (since this might indicate that the app is
+ * planning to use the underlying graphics API directly). This hint can
+ * be used to explicitly request batching in this instance. It is a contract
+ * that you will either never use the underlying graphics API directly, or
+ * if you do, you will call SDL_RenderFlush() before you do so any current
+ * batch goes to the GPU before your work begins. Not following this contract
+ * will result in undefined behavior.
+ */
+#define SDL_HINT_RENDER_BATCHING "SDL_RENDER_BATCHING"
+
+/**
+ * \brief A variable controlling how the 2D render API renders lines
+ *
+ * This variable can be set to the following values:
+ * "0" - Use the default line drawing method (Bresenham's line algorithm as of SDL 2.0.20)
+ * "1" - Use the driver point API using Bresenham's line algorithm (correct, draws many points)
+ * "2" - Use the driver line API (occasionally misses line endpoints based on hardware driver quirks, was the default before 2.0.20)
+ * "3" - Use the driver geometry API (correct, draws thicker diagonal lines)
+ *
+ * This variable should be set when the renderer is created.
+ */
+#define SDL_HINT_RENDER_LINE_METHOD "SDL_RENDER_LINE_METHOD"
+
+/**
+ * \brief A variable controlling whether to enable Direct3D 11+'s Debug Layer.
+ *
+ * This variable does not have any effect on the Direct3D 9 based renderer.
+ *
+ * This variable can be set to the following values:
+ * "0" - Disable Debug Layer use
+ * "1" - Enable Debug Layer use
+ *
+ * By default, SDL does not use Direct3D Debug Layer.
+ */
+#define SDL_HINT_RENDER_DIRECT3D11_DEBUG "SDL_RENDER_DIRECT3D11_DEBUG"
+
+/**
+ * \brief A variable controlling whether the Direct3D device is initialized for thread-safe operations.
+ *
+ * This variable can be set to the following values:
+ * "0" - Thread-safety is not enabled (faster)
+ * "1" - Thread-safety is enabled
+ *
+ * By default the Direct3D device is created with thread-safety disabled.
+ */
+#define SDL_HINT_RENDER_DIRECT3D_THREADSAFE "SDL_RENDER_DIRECT3D_THREADSAFE"
+
+/**
+ * \brief A variable specifying which render driver to use.
+ *
+ * If the application doesn't pick a specific renderer to use, this variable
+ * specifies the name of the preferred renderer. If the preferred renderer
+ * can't be initialized, the normal default renderer is used.
+ *
+ * This variable is case insensitive and can be set to the following values:
+ * "direct3d"
+ * "direct3d11"
+ * "direct3d12"
+ * "opengl"
+ * "opengles2"
+ * "opengles"
+ * "metal"
+ * "software"
+ *
+ * The default varies by platform, but it's the first one in the list that
+ * is available on the current platform.
+ */
+#define SDL_HINT_RENDER_DRIVER "SDL_RENDER_DRIVER"
+
+/**
+ * \brief A variable controlling the scaling policy for SDL_RenderSetLogicalSize.
+ *
+ * This variable can be set to the following values:
+ * "0" or "letterbox" - Uses letterbox/sidebars to fit the entire rendering on screen
+ * "1" or "overscan" - Will zoom the rendering so it fills the entire screen, allowing edges to be drawn offscreen
+ *
+ * By default letterbox is used
+ */
+#define SDL_HINT_RENDER_LOGICAL_SIZE_MODE "SDL_RENDER_LOGICAL_SIZE_MODE"
+
+/**
+ * \brief A variable controlling whether the OpenGL render driver uses shaders if they are available.
+ *
+ * This variable can be set to the following values:
+ * "0" - Disable shaders
+ * "1" - Enable shaders
+ *
+ * By default shaders are used if OpenGL supports them.
+ */
+#define SDL_HINT_RENDER_OPENGL_SHADERS "SDL_RENDER_OPENGL_SHADERS"
+
+/**
+ * \brief A variable controlling the scaling quality
+ *
+ * This variable can be set to the following values:
+ * "0" or "nearest" - Nearest pixel sampling
+ * "1" or "linear" - Linear filtering (supported by OpenGL and Direct3D)
+ * "2" or "best" - Currently this is the same as "linear"
+ *
+ * By default nearest pixel sampling is used
+ */
+#define SDL_HINT_RENDER_SCALE_QUALITY "SDL_RENDER_SCALE_QUALITY"
+
+/**
+ * \brief A variable controlling whether updates to the SDL screen surface should be synchronized with the vertical refresh, to avoid tearing.
+ *
+ * This variable can be set to the following values:
+ * "0" - Disable vsync
+ * "1" - Enable vsync
+ *
+ * By default SDL does not sync screen surface updates with vertical refresh.
+ */
+#define SDL_HINT_RENDER_VSYNC "SDL_RENDER_VSYNC"
+
+/**
+ * \brief A variable controlling if VSYNC is automatically disable if doesn't reach the enough FPS
+ *
+ * This variable can be set to the following values:
+ * "0" - It will be using VSYNC as defined in the main flag. Default
+ * "1" - If VSYNC was previously enabled, then it will disable VSYNC if doesn't reach enough speed
+ *
+ * By default SDL does not enable the automatic VSYNC
+ */
+#define SDL_HINT_PS2_DYNAMIC_VSYNC "SDL_PS2_DYNAMIC_VSYNC"
+
+/**
+ * \brief A variable to control whether the return key on the soft keyboard
+ * should hide the soft keyboard on Android and iOS.
+ *
+ * The variable can be set to the following values:
+ * "0" - The return key will be handled as a key event. This is the behaviour of SDL <= 2.0.3. (default)
+ * "1" - The return key will hide the keyboard.
+ *
+ * The value of this hint is used at runtime, so it can be changed at any time.
+ */
+#define SDL_HINT_RETURN_KEY_HIDES_IME "SDL_RETURN_KEY_HIDES_IME"
+
+/**
+ * \brief Tell SDL which Dispmanx layer to use on a Raspberry PI
+ *
+ * Also known as Z-order. The variable can take a negative or positive value.
+ * The default is 10000.
+ */
+#define SDL_HINT_RPI_VIDEO_LAYER "SDL_RPI_VIDEO_LAYER"
+
+/**
+ * \brief Specify an "activity name" for screensaver inhibition.
+ *
+ * Some platforms, notably Linux desktops, list the applications which are
+ * inhibiting the screensaver or other power-saving features.
+ *
+ * This hint lets you specify the "activity name" sent to the OS when
+ * SDL_DisableScreenSaver() is used (or the screensaver is automatically
+ * disabled). The contents of this hint are used when the screensaver is
+ * disabled. You should use a string that describes what your program is doing
+ * (and, therefore, why the screensaver is disabled). For example, "Playing a
+ * game" or "Watching a video".
+ *
+ * Setting this to "" or leaving it unset will have SDL use a reasonable
+ * default: "Playing a game" or something similar.
+ *
+ * On targets where this is not supported, this hint does nothing.
+ */
+#define SDL_HINT_SCREENSAVER_INHIBIT_ACTIVITY_NAME "SDL_SCREENSAVER_INHIBIT_ACTIVITY_NAME"
+
+/**
+ * \brief Specifies whether SDL_THREAD_PRIORITY_TIME_CRITICAL should be treated as realtime.
+ *
+ * On some platforms, like Linux, a realtime priority thread may be subject to restrictions
+ * that require special handling by the application. This hint exists to let SDL know that
+ * the app is prepared to handle said restrictions.
+ *
+ * On Linux, SDL will apply the following configuration to any thread that becomes realtime:
+ * * The SCHED_RESET_ON_FORK bit will be set on the scheduling policy,
+ * * An RLIMIT_RTTIME budget will be configured to the rtkit specified limit.
+ * * Exceeding this limit will result in the kernel sending SIGKILL to the app,
+ * * Refer to the man pages for more information.
+ *
+ * This variable can be set to the following values:
+ * "0" - default platform specific behaviour
+ * "1" - Force SDL_THREAD_PRIORITY_TIME_CRITICAL to a realtime scheduling policy
+ */
+#define SDL_HINT_THREAD_FORCE_REALTIME_TIME_CRITICAL "SDL_THREAD_FORCE_REALTIME_TIME_CRITICAL"
+
+/**
+* \brief A string specifying additional information to use with SDL_SetThreadPriority.
+*
+* By default SDL_SetThreadPriority will make appropriate system changes in order to
+* apply a thread priority. For example on systems using pthreads the scheduler policy
+* is changed automatically to a policy that works well with a given priority.
+* Code which has specific requirements can override SDL's default behavior with this hint.
+*
+* pthread hint values are "current", "other", "fifo" and "rr".
+* Currently no other platform hint values are defined but may be in the future.
+*
+* \note On Linux, the kernel may send SIGKILL to realtime tasks which exceed the distro
+* configured execution budget for rtkit. This budget can be queried through RLIMIT_RTTIME
+* after calling SDL_SetThreadPriority().
+*/
+#define SDL_HINT_THREAD_PRIORITY_POLICY "SDL_THREAD_PRIORITY_POLICY"
+
+/**
+* \brief A string specifying SDL's threads stack size in bytes or "0" for the backend's default size
+*
+* Use this hint in case you need to set SDL's threads stack size to other than the default.
+* This is specially useful if you build SDL against a non glibc libc library (such as musl) which
+* provides a relatively small default thread stack size (a few kilobytes versus the default 8MB glibc uses).
+* Support for this hint is currently available only in the pthread, Windows, and PSP backend.
+*
+* Instead of this hint, in 2.0.9 and later, you can use
+* SDL_CreateThreadWithStackSize(). This hint only works with the classic
+* SDL_CreateThread().
+*/
+#define SDL_HINT_THREAD_STACK_SIZE "SDL_THREAD_STACK_SIZE"
+
+/**
+ * \brief A variable that controls the timer resolution, in milliseconds.
+ *
+ * The higher resolution the timer, the more frequently the CPU services
+ * timer interrupts, and the more precise delays are, but this takes up
+ * power and CPU time. This hint is only used on Windows.
+ *
+ * See this blog post for more information:
+ * http://randomascii.wordpress.com/2013/07/08/windows-timer-resolution-megawatts-wasted/
+ *
+ * If this variable is set to "0", the system timer resolution is not set.
+ *
+ * The default value is "1". This hint may be set at any time.
+ */
+#define SDL_HINT_TIMER_RESOLUTION "SDL_TIMER_RESOLUTION"
+
+/**
+ * \brief A variable controlling whether touch events should generate synthetic mouse events
+ *
+ * This variable can be set to the following values:
+ * "0" - Touch events will not generate mouse events
+ * "1" - Touch events will generate mouse events
+ *
+ * By default SDL will generate mouse events for touch events
+ */
+#define SDL_HINT_TOUCH_MOUSE_EVENTS "SDL_TOUCH_MOUSE_EVENTS"
+
+/**
+ * \brief A variable controlling which touchpad should generate synthetic mouse events
+ *
+ * This variable can be set to the following values:
+ * "0" - Only front touchpad should generate mouse events. Default
+ * "1" - Only back touchpad should generate mouse events.
+ * "2" - Both touchpads should generate mouse events.
+ *
+ * By default SDL will generate mouse events for all touch devices
+ */
+#define SDL_HINT_VITA_TOUCH_MOUSE_DEVICE "SDL_HINT_VITA_TOUCH_MOUSE_DEVICE"
+
+/**
+ * \brief A variable controlling whether the Android / tvOS remotes
+ * should be listed as joystick devices, instead of sending keyboard events.
+ *
+ * This variable can be set to the following values:
+ * "0" - Remotes send enter/escape/arrow key events
+ * "1" - Remotes are available as 2 axis, 2 button joysticks (the default).
+ */
+#define SDL_HINT_TV_REMOTE_AS_JOYSTICK "SDL_TV_REMOTE_AS_JOYSTICK"
+
+/**
+ * \brief A variable controlling whether the screensaver is enabled.
+ *
+ * This variable can be set to the following values:
+ * "0" - Disable screensaver
+ * "1" - Enable screensaver
+ *
+ * By default SDL will disable the screensaver.
+ */
+#define SDL_HINT_VIDEO_ALLOW_SCREENSAVER "SDL_VIDEO_ALLOW_SCREENSAVER"
+
+/**
+ * \brief Tell the video driver that we only want a double buffer.
+ *
+ * By default, most lowlevel 2D APIs will use a triple buffer scheme that
+ * wastes no CPU time on waiting for vsync after issuing a flip, but
+ * introduces a frame of latency. On the other hand, using a double buffer
+ * scheme instead is recommended for cases where low latency is an important
+ * factor because we save a whole frame of latency.
+ * We do so by waiting for vsync immediately after issuing a flip, usually just
+ * after eglSwapBuffers call in the backend's *_SwapWindow function.
+ *
+ * Since it's driver-specific, it's only supported where possible and
+ * implemented. Currently supported the following drivers:
+ *
+ * - KMSDRM (kmsdrm)
+ * - Raspberry Pi (raspberrypi)
+ */
+#define SDL_HINT_VIDEO_DOUBLE_BUFFER "SDL_VIDEO_DOUBLE_BUFFER"
+
+/**
+ * \brief A variable controlling whether the EGL window is allowed to be
+ * composited as transparent, rather than opaque.
+ *
+ * Most window systems will always render windows opaque, even if the surface
+ * format has an alpha channel. This is not always true, however, so by default
+ * SDL will try to enforce opaque composition. To override this behavior, you
+ * can set this hint to "1".
+ */
+#define SDL_HINT_VIDEO_EGL_ALLOW_TRANSPARENCY "SDL_VIDEO_EGL_ALLOW_TRANSPARENCY"
+
+/**
+ * \brief A variable controlling whether the graphics context is externally managed.
+ *
+ * This variable can be set to the following values:
+ * "0" - SDL will manage graphics contexts that are attached to windows.
+ * "1" - Disable graphics context management on windows.
+ *
+ * By default SDL will manage OpenGL contexts in certain situations. For example, on Android the
+ * context will be automatically saved and restored when pausing the application. Additionally, some
+ * platforms will assume usage of OpenGL if Vulkan isn't used. Setting this to "1" will prevent this
+ * behavior, which is desireable when the application manages the graphics context, such as
+ * an externally managed OpenGL context or attaching a Vulkan surface to the window.
+ */
+#define SDL_HINT_VIDEO_EXTERNAL_CONTEXT "SDL_VIDEO_EXTERNAL_CONTEXT"
+
+/**
+ * \brief If set to 1, then do not allow high-DPI windows. ("Retina" on Mac and iOS)
+ */
+#define SDL_HINT_VIDEO_HIGHDPI_DISABLED "SDL_VIDEO_HIGHDPI_DISABLED"
+
+/**
+ * \brief A variable that dictates policy for fullscreen Spaces on Mac OS X.
+ *
+ * This hint only applies to Mac OS X.
+ *
+ * The variable can be set to the following values:
+ * "0" - Disable Spaces support (FULLSCREEN_DESKTOP won't use them and
+ * SDL_WINDOW_RESIZABLE windows won't offer the "fullscreen"
+ * button on their titlebars).
+ * "1" - Enable Spaces support (FULLSCREEN_DESKTOP will use them and
+ * SDL_WINDOW_RESIZABLE windows will offer the "fullscreen"
+ * button on their titlebars).
+ *
+ * The default value is "1". This hint must be set before any windows are created.
+ */
+#define SDL_HINT_VIDEO_MAC_FULLSCREEN_SPACES "SDL_VIDEO_MAC_FULLSCREEN_SPACES"
+
+/**
+ * \brief Minimize your SDL_Window if it loses key focus when in fullscreen mode. Defaults to false.
+ * \warning Before SDL 2.0.14, this defaulted to true! In 2.0.14, we're
+ * seeing if "true" causes more problems than it solves in modern times.
+ *
+ */
+#define SDL_HINT_VIDEO_MINIMIZE_ON_FOCUS_LOSS "SDL_VIDEO_MINIMIZE_ON_FOCUS_LOSS"
+
+/**
+ * \brief A variable controlling whether the libdecor Wayland backend is allowed to be used.
+ *
+ * This variable can be set to the following values:
+ * "0" - libdecor use is disabled.
+ * "1" - libdecor use is enabled (default).
+ *
+ * libdecor is used over xdg-shell when xdg-decoration protocol is unavailable.
+ */
+#define SDL_HINT_VIDEO_WAYLAND_ALLOW_LIBDECOR "SDL_VIDEO_WAYLAND_ALLOW_LIBDECOR"
+
+/**
+ * \brief A variable controlling whether the libdecor Wayland backend is preferred over native decrations.
+ *
+ * When this hint is set, libdecor will be used to provide window decorations, even if xdg-decoration is
+ * available. (Note that, by default, libdecor will use xdg-decoration itself if available).
+ *
+ * This variable can be set to the following values:
+ * "0" - libdecor is enabled only if server-side decorations are unavailable.
+ * "1" - libdecor is always enabled if available.
+ *
+ * libdecor is used over xdg-shell when xdg-decoration protocol is unavailable.
+ */
+#define SDL_HINT_VIDEO_WAYLAND_PREFER_LIBDECOR "SDL_VIDEO_WAYLAND_PREFER_LIBDECOR"
+
+/**
+ * \brief A variable controlling whether video mode emulation is enabled under Wayland.
+ *
+ * When this hint is set, a standard set of emulated CVT video modes will be exposed for use by the application.
+ * If it is disabled, the only modes exposed will be the logical desktop size and, in the case of a scaled
+ * desktop, the native display resolution.
+ *
+ * This variable can be set to the following values:
+ * "0" - Video mode emulation is disabled.
+ * "1" - Video mode emulation is enabled.
+ *
+ * By default video mode emulation is enabled.
+ */
+#define SDL_HINT_VIDEO_WAYLAND_MODE_EMULATION "SDL_VIDEO_WAYLAND_MODE_EMULATION"
+
+/**
+ * \brief Enable or disable mouse pointer warp emulation, needed by some older games.
+ *
+ * When this hint is set, any SDL will emulate mouse warps using relative mouse mode.
+ * This is required for some older games (such as Source engine games), which warp the
+ * mouse to the centre of the screen rather than using relative mouse motion. Note that
+ * relative mouse mode may have different mouse acceleration behaviour than pointer warps.
+ *
+ * This variable can be set to the following values:
+ * "0" - All mouse warps fail, as mouse warping is not available under wayland.
+ * "1" - Some mouse warps will be emulated by forcing relative mouse mode.
+ *
+ * If not set, this is automatically enabled unless an application uses relative mouse
+ * mode directly.
+ */
+#define SDL_HINT_VIDEO_WAYLAND_EMULATE_MOUSE_WARP "SDL_VIDEO_WAYLAND_EMULATE_MOUSE_WARP"
+
+/**
+* \brief A variable that is the address of another SDL_Window* (as a hex string formatted with "%p").
+*
+* If this hint is set before SDL_CreateWindowFrom() and the SDL_Window* it is set to has
+* SDL_WINDOW_OPENGL set (and running on WGL only, currently), then two things will occur on the newly
+* created SDL_Window:
+*
+* 1. Its pixel format will be set to the same pixel format as this SDL_Window. This is
+* needed for example when sharing an OpenGL context across multiple windows.
+*
+* 2. The flag SDL_WINDOW_OPENGL will be set on the new window so it can be used for
+* OpenGL rendering.
+*
+* This variable can be set to the following values:
+* The address (as a string "%p") of the SDL_Window* that new windows created with SDL_CreateWindowFrom() should
+* share a pixel format with.
+*/
+#define SDL_HINT_VIDEO_WINDOW_SHARE_PIXEL_FORMAT "SDL_VIDEO_WINDOW_SHARE_PIXEL_FORMAT"
+
+/**
+ * \brief When calling SDL_CreateWindowFrom(), make the window compatible with OpenGL.
+ *
+ * This variable can be set to the following values:
+ * "0" - Don't add any graphics flags to the SDL_WindowFlags
+ * "1" - Add SDL_WINDOW_OPENGL to the SDL_WindowFlags
+ *
+ * By default SDL will not make the foreign window compatible with OpenGL.
+ */
+#define SDL_HINT_VIDEO_FOREIGN_WINDOW_OPENGL "SDL_VIDEO_FOREIGN_WINDOW_OPENGL"
+
+/**
+ * \brief When calling SDL_CreateWindowFrom(), make the window compatible with Vulkan.
+ *
+ * This variable can be set to the following values:
+ * "0" - Don't add any graphics flags to the SDL_WindowFlags
+ * "1" - Add SDL_WINDOW_VULKAN to the SDL_WindowFlags
+ *
+ * By default SDL will not make the foreign window compatible with Vulkan.
+ */
+#define SDL_HINT_VIDEO_FOREIGN_WINDOW_VULKAN "SDL_VIDEO_FOREIGN_WINDOW_VULKAN"
+
+/**
+* \brief A variable specifying which shader compiler to preload when using the Chrome ANGLE binaries
+*
+* SDL has EGL and OpenGL ES2 support on Windows via the ANGLE project. It
+* can use two different sets of binaries, those compiled by the user from source
+* or those provided by the Chrome browser. In the later case, these binaries require
+* that SDL loads a DLL providing the shader compiler.
+*
+* This variable can be set to the following values:
+* "d3dcompiler_46.dll" - default, best for Vista or later.
+* "d3dcompiler_43.dll" - for XP support.
+* "none" - do not load any library, useful if you compiled ANGLE from source and included the compiler in your binaries.
+*
+*/
+#define SDL_HINT_VIDEO_WIN_D3DCOMPILER "SDL_VIDEO_WIN_D3DCOMPILER"
+
+/**
+ * \brief A variable controlling whether X11 should use GLX or EGL by default
+ *
+ * This variable can be set to the following values:
+ * "0" - Use GLX
+ * "1" - Use EGL
+ *
+ * By default SDL will use GLX when both are present.
+ */
+#define SDL_HINT_VIDEO_X11_FORCE_EGL "SDL_VIDEO_X11_FORCE_EGL"
+
+/**
+ * \brief A variable controlling whether the X11 _NET_WM_BYPASS_COMPOSITOR hint should be used.
+ *
+ * This variable can be set to the following values:
+ * "0" - Disable _NET_WM_BYPASS_COMPOSITOR
+ * "1" - Enable _NET_WM_BYPASS_COMPOSITOR
+ *
+ * By default SDL will use _NET_WM_BYPASS_COMPOSITOR
+ *
+ */
+#define SDL_HINT_VIDEO_X11_NET_WM_BYPASS_COMPOSITOR "SDL_VIDEO_X11_NET_WM_BYPASS_COMPOSITOR"
+
+/**
+ * \brief A variable controlling whether the X11 _NET_WM_PING protocol should be supported.
+ *
+ * This variable can be set to the following values:
+ * "0" - Disable _NET_WM_PING
+ * "1" - Enable _NET_WM_PING
+ *
+ * By default SDL will use _NET_WM_PING, but for applications that know they
+ * will not always be able to respond to ping requests in a timely manner they can
+ * turn it off to avoid the window manager thinking the app is hung.
+ * The hint is checked in CreateWindow.
+ */
+#define SDL_HINT_VIDEO_X11_NET_WM_PING "SDL_VIDEO_X11_NET_WM_PING"
+
+/**
+ * \brief A variable forcing the visual ID chosen for new X11 windows
+ *
+ */
+#define SDL_HINT_VIDEO_X11_WINDOW_VISUALID "SDL_VIDEO_X11_WINDOW_VISUALID"
+
+/**
+ * \brief A no-longer-used variable controlling whether the X11 Xinerama extension should be used.
+ *
+ * Before SDL 2.0.24, this would let apps and users disable Xinerama support on X11.
+ * Now SDL never uses Xinerama, and does not check for this hint at all.
+ * The preprocessor define is left here for source compatibility.
+ */
+#define SDL_HINT_VIDEO_X11_XINERAMA "SDL_VIDEO_X11_XINERAMA"
+
+/**
+ * \brief A variable controlling whether the X11 XRandR extension should be used.
+ *
+ * This variable can be set to the following values:
+ * "0" - Disable XRandR
+ * "1" - Enable XRandR
+ *
+ * By default SDL will use XRandR.
+ */
+#define SDL_HINT_VIDEO_X11_XRANDR "SDL_VIDEO_X11_XRANDR"
+
+/**
+ * \brief A no-longer-used variable controlling whether the X11 VidMode extension should be used.
+ *
+ * Before SDL 2.0.24, this would let apps and users disable XVidMode support on X11.
+ * Now SDL never uses XVidMode, and does not check for this hint at all.
+ * The preprocessor define is left here for source compatibility.
+ */
+#define SDL_HINT_VIDEO_X11_XVIDMODE "SDL_VIDEO_X11_XVIDMODE"
+
+/**
+ * \brief Controls how the fact chunk affects the loading of a WAVE file.
+ *
+ * The fact chunk stores information about the number of samples of a WAVE
+ * file. The Standards Update from Microsoft notes that this value can be used
+ * to 'determine the length of the data in seconds'. This is especially useful
+ * for compressed formats (for which this is a mandatory chunk) if they produce
+ * multiple sample frames per block and truncating the block is not allowed.
+ * The fact chunk can exactly specify how many sample frames there should be
+ * in this case.
+ *
+ * Unfortunately, most application seem to ignore the fact chunk and so SDL
+ * ignores it by default as well.
+ *
+ * This variable can be set to the following values:
+ *
+ * "truncate" - Use the number of samples to truncate the wave data if
+ * the fact chunk is present and valid
+ * "strict" - Like "truncate", but raise an error if the fact chunk
+ * is invalid, not present for non-PCM formats, or if the
+ * data chunk doesn't have that many samples
+ * "ignorezero" - Like "truncate", but ignore fact chunk if the number of
+ * samples is zero
+ * "ignore" - Ignore fact chunk entirely (default)
+ */
+#define SDL_HINT_WAVE_FACT_CHUNK "SDL_WAVE_FACT_CHUNK"
+
+/**
+ * \brief Controls how the size of the RIFF chunk affects the loading of a WAVE file.
+ *
+ * The size of the RIFF chunk (which includes all the sub-chunks of the WAVE
+ * file) is not always reliable. In case the size is wrong, it's possible to
+ * just ignore it and step through the chunks until a fixed limit is reached.
+ *
+ * Note that files that have trailing data unrelated to the WAVE file or
+ * corrupt files may slow down the loading process without a reliable boundary.
+ * By default, SDL stops after 10000 chunks to prevent wasting time. Use the
+ * environment variable SDL_WAVE_CHUNK_LIMIT to adjust this value.
+ *
+ * This variable can be set to the following values:
+ *
+ * "force" - Always use the RIFF chunk size as a boundary for the chunk search
+ * "ignorezero" - Like "force", but a zero size searches up to 4 GiB (default)
+ * "ignore" - Ignore the RIFF chunk size and always search up to 4 GiB
+ * "maximum" - Search for chunks until the end of file (not recommended)
+ */
+#define SDL_HINT_WAVE_RIFF_CHUNK_SIZE "SDL_WAVE_RIFF_CHUNK_SIZE"
+
+/**
+ * \brief Controls how a truncated WAVE file is handled.
+ *
+ * A WAVE file is considered truncated if any of the chunks are incomplete or
+ * the data chunk size is not a multiple of the block size. By default, SDL
+ * decodes until the first incomplete block, as most applications seem to do.
+ *
+ * This variable can be set to the following values:
+ *
+ * "verystrict" - Raise an error if the file is truncated
+ * "strict" - Like "verystrict", but the size of the RIFF chunk is ignored
+ * "dropframe" - Decode until the first incomplete sample frame
+ * "dropblock" - Decode until the first incomplete block (default)
+ */
+#define SDL_HINT_WAVE_TRUNCATION "SDL_WAVE_TRUNCATION"
+
+/**
+ * \brief Tell SDL not to name threads on Windows with the 0x406D1388 Exception.
+ * The 0x406D1388 Exception is a trick used to inform Visual Studio of a
+ * thread's name, but it tends to cause problems with other debuggers,
+ * and the .NET runtime. Note that SDL 2.0.6 and later will still use
+ * the (safer) SetThreadDescription API, introduced in the Windows 10
+ * Creators Update, if available.
+ *
+ * The variable can be set to the following values:
+ * "0" - SDL will raise the 0x406D1388 Exception to name threads.
+ * This is the default behavior of SDL <= 2.0.4.
+ * "1" - SDL will not raise this exception, and threads will be unnamed. (default)
+ * This is necessary with .NET languages or debuggers that aren't Visual Studio.
+ */
+#define SDL_HINT_WINDOWS_DISABLE_THREAD_NAMING "SDL_WINDOWS_DISABLE_THREAD_NAMING"
+
+/**
+ * \brief Controls whether menus can be opened with their keyboard shortcut (Alt+mnemonic).
+ *
+ * If the mnemonics are enabled, then menus can be opened by pressing the Alt
+ * key and the corresponding mnemonic (for example, Alt+F opens the File menu).
+ * However, in case an invalid mnemonic is pressed, Windows makes an audible
+ * beep to convey that nothing happened. This is true even if the window has
+ * no menu at all!
+ *
+ * Because most SDL applications don't have menus, and some want to use the Alt
+ * key for other purposes, SDL disables mnemonics (and the beeping) by default.
+ *
+ * Note: This also affects keyboard events: with mnemonics enabled, when a
+ * menu is opened from the keyboard, you will not receive a KEYUP event for
+ * the mnemonic key, and *might* not receive one for Alt.
+ *
+ * This variable can be set to the following values:
+ * "0" - Alt+mnemonic does nothing, no beeping. (default)
+ * "1" - Alt+mnemonic opens menus, invalid mnemonics produce a beep.
+ */
+#define SDL_HINT_WINDOWS_ENABLE_MENU_MNEMONICS "SDL_WINDOWS_ENABLE_MENU_MNEMONICS"
+
+/**
+ * \brief A variable controlling whether the windows message loop is processed by SDL
+ *
+ * This variable can be set to the following values:
+ * "0" - The window message loop is not run
+ * "1" - The window message loop is processed in SDL_PumpEvents()
+ *
+ * By default SDL will process the windows message loop
+ */
+#define SDL_HINT_WINDOWS_ENABLE_MESSAGELOOP "SDL_WINDOWS_ENABLE_MESSAGELOOP"
+
+/**
+ * \brief Force SDL to use Critical Sections for mutexes on Windows.
+ * On Windows 7 and newer, Slim Reader/Writer Locks are available.
+ * They offer better performance, allocate no kernel ressources and
+ * use less memory. SDL will fall back to Critical Sections on older
+ * OS versions or if forced to by this hint.
+ *
+ * This variable can be set to the following values:
+ * "0" - Use SRW Locks when available. If not, fall back to Critical Sections. (default)
+ * "1" - Force the use of Critical Sections in all cases.
+ *
+ */
+#define SDL_HINT_WINDOWS_FORCE_MUTEX_CRITICAL_SECTIONS "SDL_WINDOWS_FORCE_MUTEX_CRITICAL_SECTIONS"
+
+/**
+ * \brief Force SDL to use Kernel Semaphores on Windows.
+ * Kernel Semaphores are inter-process and require a context
+ * switch on every interaction. On Windows 8 and newer, the
+ * WaitOnAddress API is available. Using that and atomics to
+ * implement semaphores increases performance.
+ * SDL will fall back to Kernel Objects on older OS versions
+ * or if forced to by this hint.
+ *
+ * This variable can be set to the following values:
+ * "0" - Use Atomics and WaitOnAddress API when available. If not, fall back to Kernel Objects. (default)
+ * "1" - Force the use of Kernel Objects in all cases.
+ *
+ */
+#define SDL_HINT_WINDOWS_FORCE_SEMAPHORE_KERNEL "SDL_WINDOWS_FORCE_SEMAPHORE_KERNEL"
+
+/**
+ * \brief A variable to specify custom icon resource id from RC file on Windows platform
+ */
+#define SDL_HINT_WINDOWS_INTRESOURCE_ICON "SDL_WINDOWS_INTRESOURCE_ICON"
+#define SDL_HINT_WINDOWS_INTRESOURCE_ICON_SMALL "SDL_WINDOWS_INTRESOURCE_ICON_SMALL"
+
+/**
+ * \brief Tell SDL not to generate window-close events for Alt+F4 on Windows.
+ *
+ * The variable can be set to the following values:
+ * "0" - SDL will generate a window-close event when it sees Alt+F4.
+ * "1" - SDL will only do normal key handling for Alt+F4.
+ */
+#define SDL_HINT_WINDOWS_NO_CLOSE_ON_ALT_F4 "SDL_WINDOWS_NO_CLOSE_ON_ALT_F4"
+
+/**
+ * \brief Use the D3D9Ex API introduced in Windows Vista, instead of normal D3D9.
+ * Direct3D 9Ex contains changes to state management that can eliminate device
+ * loss errors during scenarios like Alt+Tab or UAC prompts. D3D9Ex may require
+ * some changes to your application to cope with the new behavior, so this
+ * is disabled by default.
+ *
+ * This hint must be set before initializing the video subsystem.
+ *
+ * For more information on Direct3D 9Ex, see:
+ * - https://docs.microsoft.com/en-us/windows/win32/direct3darticles/graphics-apis-in-windows-vista#direct3d-9ex
+ * - https://docs.microsoft.com/en-us/windows/win32/direct3darticles/direct3d-9ex-improvements
+ *
+ * This variable can be set to the following values:
+ * "0" - Use the original Direct3D 9 API (default)
+ * "1" - Use the Direct3D 9Ex API on Vista and later (and fall back if D3D9Ex is unavailable)
+ *
+ */
+#define SDL_HINT_WINDOWS_USE_D3D9EX "SDL_WINDOWS_USE_D3D9EX"
+
+/**
+ * \brief Controls whether SDL will declare the process to be DPI aware.
+ *
+ * This hint must be set before initializing the video subsystem.
+ *
+ * The main purpose of declaring DPI awareness is to disable OS bitmap scaling of SDL windows on monitors with
+ * a DPI scale factor.
+ *
+ * This hint is equivalent to requesting DPI awareness via external means (e.g. calling SetProcessDpiAwarenessContext)
+ * and does not cause SDL to use a virtualized coordinate system, so it will generally give you 1 SDL coordinate = 1 pixel
+ * even on high-DPI displays.
+ *
+ * For more information, see:
+ * https://docs.microsoft.com/en-us/windows/win32/hidpi/high-dpi-desktop-application-development-on-windows
+ *
+ * This variable can be set to the following values:
+ * "" - Do not change the DPI awareness (default).
+ * "unaware" - Declare the process as DPI unaware. (Windows 8.1 and later).
+ * "system" - Request system DPI awareness. (Vista and later).
+ * "permonitor" - Request per-monitor DPI awareness. (Windows 8.1 and later).
+ * "permonitorv2" - Request per-monitor V2 DPI awareness. (Windows 10, version 1607 and later).
+ * The most visible difference from "permonitor" is that window title bar will be scaled
+ * to the visually correct size when dragging between monitors with different scale factors.
+ * This is the preferred DPI awareness level.
+ *
+ * If the requested DPI awareness is not available on the currently running OS, SDL will try to request the best
+ * available match.
+ */
+#define SDL_HINT_WINDOWS_DPI_AWARENESS "SDL_WINDOWS_DPI_AWARENESS"
+
+/**
+ * \brief Uses DPI-scaled points as the SDL coordinate system on Windows.
+ *
+ * This changes the SDL coordinate system units to be DPI-scaled points, rather than pixels everywhere.
+ * This means windows will be appropriately sized, even when created on high-DPI displays with scaling.
+ *
+ * e.g. requesting a 640x480 window from SDL, on a display with 125% scaling in Windows display settings,
+ * will create a window with an 800x600 client area (in pixels).
+ *
+ * Setting this to "1" implicitly requests process DPI awareness (setting SDL_WINDOWS_DPI_AWARENESS is unnecessary),
+ * and forces SDL_WINDOW_ALLOW_HIGHDPI on all windows.
+ *
+ * This variable can be set to the following values:
+ * "0" - SDL coordinates equal Windows coordinates. No automatic window resizing when dragging
+ * between monitors with different scale factors (unless this is performed by
+ * Windows itself, which is the case when the process is DPI unaware).
+ * "1" - SDL coordinates are in DPI-scaled points. Automatically resize windows as needed on
+ * displays with non-100% scale factors.
+ */
+#define SDL_HINT_WINDOWS_DPI_SCALING "SDL_WINDOWS_DPI_SCALING"
+
+/**
+ * \brief A variable controlling whether the window frame and title bar are interactive when the cursor is hidden
+ *
+ * This variable can be set to the following values:
+ * "0" - The window frame is not interactive when the cursor is hidden (no move, resize, etc)
+ * "1" - The window frame is interactive when the cursor is hidden
+ *
+ * By default SDL will allow interaction with the window frame when the cursor is hidden
+ */
+#define SDL_HINT_WINDOW_FRAME_USABLE_WHILE_CURSOR_HIDDEN "SDL_WINDOW_FRAME_USABLE_WHILE_CURSOR_HIDDEN"
+
+/**
+* \brief A variable controlling whether the window is activated when the SDL_ShowWindow function is called
+*
+* This variable can be set to the following values:
+* "0" - The window is activated when the SDL_ShowWindow function is called
+* "1" - The window is not activated when the SDL_ShowWindow function is called
+*
+* By default SDL will activate the window when the SDL_ShowWindow function is called
+*/
+#define SDL_HINT_WINDOW_NO_ACTIVATION_WHEN_SHOWN "SDL_WINDOW_NO_ACTIVATION_WHEN_SHOWN"
+
+/** \brief Allows back-button-press events on Windows Phone to be marked as handled
+ *
+ * Windows Phone devices typically feature a Back button. When pressed,
+ * the OS will emit back-button-press events, which apps are expected to
+ * handle in an appropriate manner. If apps do not explicitly mark these
+ * events as 'Handled', then the OS will invoke its default behavior for
+ * unhandled back-button-press events, which on Windows Phone 8 and 8.1 is to
+ * terminate the app (and attempt to switch to the previous app, or to the
+ * device's home screen).
+ *
+ * Setting the SDL_HINT_WINRT_HANDLE_BACK_BUTTON hint to "1" will cause SDL
+ * to mark back-button-press events as Handled, if and when one is sent to
+ * the app.
+ *
+ * Internally, Windows Phone sends back button events as parameters to
+ * special back-button-press callback functions. Apps that need to respond
+ * to back-button-press events are expected to register one or more
+ * callback functions for such, shortly after being launched (during the
+ * app's initialization phase). After the back button is pressed, the OS
+ * will invoke these callbacks. If the app's callback(s) do not explicitly
+ * mark the event as handled by the time they return, or if the app never
+ * registers one of these callback, the OS will consider the event
+ * un-handled, and it will apply its default back button behavior (terminate
+ * the app).
+ *
+ * SDL registers its own back-button-press callback with the Windows Phone
+ * OS. This callback will emit a pair of SDL key-press events (SDL_KEYDOWN
+ * and SDL_KEYUP), each with a scancode of SDL_SCANCODE_AC_BACK, after which
+ * it will check the contents of the hint, SDL_HINT_WINRT_HANDLE_BACK_BUTTON.
+ * If the hint's value is set to "1", the back button event's Handled
+ * property will get set to 'true'. If the hint's value is set to something
+ * else, or if it is unset, SDL will leave the event's Handled property
+ * alone. (By default, the OS sets this property to 'false', to note.)
+ *
+ * SDL apps can either set SDL_HINT_WINRT_HANDLE_BACK_BUTTON well before a
+ * back button is pressed, or can set it in direct-response to a back button
+ * being pressed.
+ *
+ * In order to get notified when a back button is pressed, SDL apps should
+ * register a callback function with SDL_AddEventWatch(), and have it listen
+ * for SDL_KEYDOWN events that have a scancode of SDL_SCANCODE_AC_BACK.
+ * (Alternatively, SDL_KEYUP events can be listened-for. Listening for
+ * either event type is suitable.) Any value of SDL_HINT_WINRT_HANDLE_BACK_BUTTON
+ * set by such a callback, will be applied to the OS' current
+ * back-button-press event.
+ *
+ * More details on back button behavior in Windows Phone apps can be found
+ * at the following page, on Microsoft's developer site:
+ * http://msdn.microsoft.com/en-us/library/windowsphone/develop/jj247550(v=vs.105).aspx
+ */
+#define SDL_HINT_WINRT_HANDLE_BACK_BUTTON "SDL_WINRT_HANDLE_BACK_BUTTON"
+
+/** \brief Label text for a WinRT app's privacy policy link
+ *
+ * Network-enabled WinRT apps must include a privacy policy. On Windows 8, 8.1, and RT,
+ * Microsoft mandates that this policy be available via the Windows Settings charm.
+ * SDL provides code to add a link there, with its label text being set via the
+ * optional hint, SDL_HINT_WINRT_PRIVACY_POLICY_LABEL.
+ *
+ * Please note that a privacy policy's contents are not set via this hint. A separate
+ * hint, SDL_HINT_WINRT_PRIVACY_POLICY_URL, is used to link to the actual text of the
+ * policy.
+ *
+ * The contents of this hint should be encoded as a UTF8 string.
+ *
+ * The default value is "Privacy Policy". This hint should only be set during app
+ * initialization, preferably before any calls to SDL_Init().
+ *
+ * For additional information on linking to a privacy policy, see the documentation for
+ * SDL_HINT_WINRT_PRIVACY_POLICY_URL.
+ */
+#define SDL_HINT_WINRT_PRIVACY_POLICY_LABEL "SDL_WINRT_PRIVACY_POLICY_LABEL"
+
+/**
+ * \brief A URL to a WinRT app's privacy policy
+ *
+ * All network-enabled WinRT apps must make a privacy policy available to its
+ * users. On Windows 8, 8.1, and RT, Microsoft mandates that this policy be
+ * be available in the Windows Settings charm, as accessed from within the app.
+ * SDL provides code to add a URL-based link there, which can point to the app's
+ * privacy policy.
+ *
+ * To setup a URL to an app's privacy policy, set SDL_HINT_WINRT_PRIVACY_POLICY_URL
+ * before calling any SDL_Init() functions. The contents of the hint should
+ * be a valid URL. For example, "http://www.example.com".
+ *
+ * The default value is "", which will prevent SDL from adding a privacy policy
+ * link to the Settings charm. This hint should only be set during app init.
+ *
+ * The label text of an app's "Privacy Policy" link may be customized via another
+ * hint, SDL_HINT_WINRT_PRIVACY_POLICY_LABEL.
+ *
+ * Please note that on Windows Phone, Microsoft does not provide standard UI
+ * for displaying a privacy policy link, and as such, SDL_HINT_WINRT_PRIVACY_POLICY_URL
+ * will not get used on that platform. Network-enabled phone apps should display
+ * their privacy policy through some other, in-app means.
+ */
+#define SDL_HINT_WINRT_PRIVACY_POLICY_URL "SDL_WINRT_PRIVACY_POLICY_URL"
+
+/**
+ * \brief Mark X11 windows as override-redirect.
+ *
+ * If set, this _might_ increase framerate at the expense of the desktop
+ * not working as expected. Override-redirect windows aren't noticed by the
+ * window manager at all.
+ *
+ * You should probably only use this for fullscreen windows, and you probably
+ * shouldn't even use it for that. But it's here if you want to try!
+ */
+#define SDL_HINT_X11_FORCE_OVERRIDE_REDIRECT "SDL_X11_FORCE_OVERRIDE_REDIRECT"
+
+/**
+ * \brief A variable that lets you disable the detection and use of Xinput gamepad devices
+ *
+ * The variable can be set to the following values:
+ * "0" - Disable XInput detection (only uses direct input)
+ * "1" - Enable XInput detection (the default)
+ */
+#define SDL_HINT_XINPUT_ENABLED "SDL_XINPUT_ENABLED"
+
+ /**
+ * \brief A variable that lets you disable the detection and use of DirectInput gamepad devices
+ *
+ * The variable can be set to the following values:
+ * "0" - Disable DirectInput detection (only uses XInput)
+ * "1" - Enable DirectInput detection (the default)
+ */
+#define SDL_HINT_DIRECTINPUT_ENABLED "SDL_DIRECTINPUT_ENABLED"
+
+/**
+ * \brief A variable that causes SDL to use the old axis and button mapping for XInput devices.
+ *
+ * This hint is for backwards compatibility only and will be removed in SDL 2.1
+ *
+ * The default value is "0". This hint must be set before SDL_Init()
+ */
+#define SDL_HINT_XINPUT_USE_OLD_JOYSTICK_MAPPING "SDL_XINPUT_USE_OLD_JOYSTICK_MAPPING"
+
+/**
+ * \brief A variable that causes SDL to not ignore audio "monitors"
+ *
+ * This is currently only used for PulseAudio and ignored elsewhere.
+ *
+ * By default, SDL ignores audio devices that aren't associated with physical
+ * hardware. Changing this hint to "1" will expose anything SDL sees that
+ * appears to be an audio source or sink. This will add "devices" to the list
+ * that the user probably doesn't want or need, but it can be useful in
+ * scenarios where you want to hook up SDL to some sort of virtual device,
+ * etc.
+ *
+ * The default value is "0". This hint must be set before SDL_Init().
+ *
+ * This hint is available since SDL 2.0.16. Before then, virtual devices are
+ * always ignored.
+ */
+#define SDL_HINT_AUDIO_INCLUDE_MONITORS "SDL_AUDIO_INCLUDE_MONITORS"
+
+/**
+ * \brief A variable that forces X11 windows to create as a custom type.
+ *
+ * This is currently only used for X11 and ignored elsewhere.
+ *
+ * During SDL_CreateWindow, SDL uses the _NET_WM_WINDOW_TYPE X11 property
+ * to report to the window manager the type of window it wants to create.
+ * This might be set to various things if SDL_WINDOW_TOOLTIP or
+ * SDL_WINDOW_POPUP_MENU, etc, were specified. For "normal" windows that
+ * haven't set a specific type, this hint can be used to specify a custom
+ * type. For example, a dock window might set this to
+ * "_NET_WM_WINDOW_TYPE_DOCK".
+ *
+ * If not set or set to "", this hint is ignored. This hint must be set
+ * before the SDL_CreateWindow() call that it is intended to affect.
+ *
+ * This hint is available since SDL 2.0.22.
+ */
+#define SDL_HINT_X11_WINDOW_TYPE "SDL_X11_WINDOW_TYPE"
+
+/**
+ * \brief A variable that decides whether to send SDL_QUIT when closing the final window.
+ *
+ * By default, SDL sends an SDL_QUIT event when there is only one window
+ * and it receives an SDL_WINDOWEVENT_CLOSE event, under the assumption most
+ * apps would also take the loss of this window as a signal to terminate the
+ * program.
+ *
+ * However, it's not unreasonable in some cases to have the program continue
+ * to live on, perhaps to create new windows later.
+ *
+ * Changing this hint to "0" will cause SDL to not send an SDL_QUIT event
+ * when the final window is requesting to close. Note that in this case,
+ * there are still other legitimate reasons one might get an SDL_QUIT
+ * event: choosing "Quit" from the macOS menu bar, sending a SIGINT (ctrl-c)
+ * on Unix, etc.
+ *
+ * The default value is "1". This hint can be changed at any time.
+ *
+ * This hint is available since SDL 2.0.22. Before then, you always get
+ * an SDL_QUIT event when closing the final window.
+ */
+#define SDL_HINT_QUIT_ON_LAST_WINDOW_CLOSE "SDL_QUIT_ON_LAST_WINDOW_CLOSE"
+
+
+/**
+ * \brief A variable that decides what video backend to use.
+ *
+ * By default, SDL will try all available video backends in a reasonable
+ * order until it finds one that can work, but this hint allows the app
+ * or user to force a specific target, such as "x11" if, say, you are
+ * on Wayland but want to try talking to the X server instead.
+ *
+ * This functionality has existed since SDL 2.0.0 (indeed, before that)
+ * but before 2.0.22 this was an environment variable only. In 2.0.22,
+ * it was upgraded to a full SDL hint, so you can set the environment
+ * variable as usual or programatically set the hint with SDL_SetHint,
+ * which won't propagate to child processes.
+ *
+ * The default value is unset, in which case SDL will try to figure out
+ * the best video backend on your behalf. This hint needs to be set
+ * before SDL_Init() is called to be useful.
+ *
+ * This hint is available since SDL 2.0.22. Before then, you could set
+ * the environment variable to get the same effect.
+ */
+#define SDL_HINT_VIDEODRIVER "SDL_VIDEODRIVER"
+
+/**
+ * \brief A variable that decides what audio backend to use.
+ *
+ * By default, SDL will try all available audio backends in a reasonable
+ * order until it finds one that can work, but this hint allows the app
+ * or user to force a specific target, such as "alsa" if, say, you are
+ * on PulseAudio but want to try talking to the lower level instead.
+ *
+ * This functionality has existed since SDL 2.0.0 (indeed, before that)
+ * but before 2.0.22 this was an environment variable only. In 2.0.22,
+ * it was upgraded to a full SDL hint, so you can set the environment
+ * variable as usual or programatically set the hint with SDL_SetHint,
+ * which won't propagate to child processes.
+ *
+ * The default value is unset, in which case SDL will try to figure out
+ * the best audio backend on your behalf. This hint needs to be set
+ * before SDL_Init() is called to be useful.
+ *
+ * This hint is available since SDL 2.0.22. Before then, you could set
+ * the environment variable to get the same effect.
+ */
+#define SDL_HINT_AUDIODRIVER "SDL_AUDIODRIVER"
+
+/**
+ * \brief A variable that decides what KMSDRM device to use.
+ *
+ * Internally, SDL might open something like "/dev/dri/cardNN" to
+ * access KMSDRM functionality, where "NN" is a device index number.
+ *
+ * SDL makes a guess at the best index to use (usually zero), but the
+ * app or user can set this hint to a number between 0 and 99 to
+ * force selection.
+ *
+ * This hint is available since SDL 2.24.0.
+ */
+#define SDL_HINT_KMSDRM_DEVICE_INDEX "SDL_KMSDRM_DEVICE_INDEX"
+
+
+/**
+ * \brief A variable that treats trackpads as touch devices.
+ *
+ * On macOS (and possibly other platforms in the future), SDL will report
+ * touches on a trackpad as mouse input, which is generally what users
+ * expect from this device; however, these are often actually full
+ * multitouch-capable touch devices, so it might be preferable to some apps
+ * to treat them as such.
+ *
+ * Setting this hint to true will make the trackpad input report as a
+ * multitouch device instead of a mouse. The default is false.
+ *
+ * Note that most platforms don't support this hint. As of 2.24.0, it
+ * only supports MacBooks' trackpads on macOS. Others may follow later.
+ *
+ * This hint is checked during SDL_Init and can not be changed after.
+ *
+ * This hint is available since SDL 2.24.0.
+ */
+#define SDL_HINT_TRACKPAD_IS_TOUCH_ONLY "SDL_TRACKPAD_IS_TOUCH_ONLY"
+
+
+/**
+ * \brief An enumeration of hint priorities
+ */
+typedef enum
+{
+ SDL_HINT_DEFAULT,
+ SDL_HINT_NORMAL,
+ SDL_HINT_OVERRIDE
+} SDL_HintPriority;
+
+
+/**
+ * Set a hint with a specific priority.
+ *
+ * The priority controls the behavior when setting a hint that already has a
+ * value. Hints will replace existing hints of their priority and lower.
+ * Environment variables are considered to have override priority.
+ *
+ * \param name the hint to set
+ * \param value the value of the hint variable
+ * \param priority the SDL_HintPriority level for the hint
+ * \returns SDL_TRUE if the hint was set, SDL_FALSE otherwise.
+ *
+ * \since This function is available since SDL 2.0.0.
+ *
+ * \sa SDL_GetHint
+ * \sa SDL_SetHint
+ */
+extern DECLSPEC SDL_bool SDLCALL SDL_SetHintWithPriority(const char *name,
+ const char *value,
+ SDL_HintPriority priority);
+
+/**
+ * Set a hint with normal priority.
+ *
+ * Hints will not be set if there is an existing override hint or environment
+ * variable that takes precedence. You can use SDL_SetHintWithPriority() to
+ * set the hint with override priority instead.
+ *
+ * \param name the hint to set
+ * \param value the value of the hint variable
+ * \returns SDL_TRUE if the hint was set, SDL_FALSE otherwise.
+ *
+ * \since This function is available since SDL 2.0.0.
+ *
+ * \sa SDL_GetHint
+ * \sa SDL_SetHintWithPriority
+ */
+extern DECLSPEC SDL_bool SDLCALL SDL_SetHint(const char *name,
+ const char *value);
+
+/**
+ * Reset a hint to the default value.
+ *
+ * This will reset a hint to the value of the environment variable, or NULL if
+ * the environment isn't set. Callbacks will be called normally with this
+ * change.
+ *
+ * \param name the hint to set
+ * \returns SDL_TRUE if the hint was set, SDL_FALSE otherwise.
+ *
+ * \since This function is available since SDL 2.24.0.
+ *
+ * \sa SDL_GetHint
+ * \sa SDL_SetHint
+ */
+extern DECLSPEC SDL_bool SDLCALL SDL_ResetHint(const char *name);
+
+/**
+ * Reset all hints to the default values.
+ *
+ * This will reset all hints to the value of the associated environment
+ * variable, or NULL if the environment isn't set. Callbacks will be called
+ * normally with this change.
+ *
+ * \since This function is available since SDL 2.26.0.
+ *
+ * \sa SDL_GetHint
+ * \sa SDL_SetHint
+ * \sa SDL_ResetHint
+ */
+extern DECLSPEC void SDLCALL SDL_ResetHints(void);
+
+/**
+ * Get the value of a hint.
+ *
+ * \param name the hint to query
+ * \returns the string value of a hint or NULL if the hint isn't set.
+ *
+ * \since This function is available since SDL 2.0.0.
+ *
+ * \sa SDL_SetHint
+ * \sa SDL_SetHintWithPriority
+ */
+extern DECLSPEC const char * SDLCALL SDL_GetHint(const char *name);
+
+/**
+ * Get the boolean value of a hint variable.
+ *
+ * \param name the name of the hint to get the boolean value from
+ * \param default_value the value to return if the hint does not exist
+ * \returns the boolean value of a hint or the provided default value if the
+ * hint does not exist.
+ *
+ * \since This function is available since SDL 2.0.5.
+ *
+ * \sa SDL_GetHint
+ * \sa SDL_SetHint
+ */
+extern DECLSPEC SDL_bool SDLCALL SDL_GetHintBoolean(const char *name, SDL_bool default_value);
+
+/**
+ * Type definition of the hint callback function.
+ *
+ * \param userdata what was passed as `userdata` to SDL_AddHintCallback()
+ * \param name what was passed as `name` to SDL_AddHintCallback()
+ * \param oldValue the previous hint value
+ * \param newValue the new value hint is to be set to
+ */
+typedef void (SDLCALL *SDL_HintCallback)(void *userdata, const char *name, const char *oldValue, const char *newValue);
+
+/**
+ * Add a function to watch a particular hint.
+ *
+ * \param name the hint to watch
+ * \param callback An SDL_HintCallback function that will be called when the
+ * hint value changes
+ * \param userdata a pointer to pass to the callback function
+ *
+ * \since This function is available since SDL 2.0.0.
+ *
+ * \sa SDL_DelHintCallback
+ */
+extern DECLSPEC void SDLCALL SDL_AddHintCallback(const char *name,
+ SDL_HintCallback callback,
+ void *userdata);
+
+/**
+ * Remove a function watching a particular hint.
+ *
+ * \param name the hint being watched
+ * \param callback An SDL_HintCallback function that will be called when the
+ * hint value changes
+ * \param userdata a pointer being passed to the callback function
+ *
+ * \since This function is available since SDL 2.0.0.
+ *
+ * \sa SDL_AddHintCallback
+ */
+extern DECLSPEC void SDLCALL SDL_DelHintCallback(const char *name,
+ SDL_HintCallback callback,
+ void *userdata);
+
+/**
+ * Clear all hints.
+ *
+ * This function is automatically called during SDL_Quit(), and deletes all
+ * callbacks without calling them and frees all memory associated with hints.
+ * If you're calling this from application code you probably want to call
+ * SDL_ResetHints() instead.
+ *
+ * This function will be removed from the API the next time we rev the ABI.
+ *
+ * \since This function is available since SDL 2.0.0.
+ *
+ * \sa SDL_ResetHints
+ */
+extern DECLSPEC void SDLCALL SDL_ClearHints(void);
+
+
+/* Ends C function definitions when using C++ */
+#ifdef __cplusplus
+}
+#endif
+#include
+
+#endif /* SDL_hints_h_ */
+
+/* vi: set ts=4 sw=4 expandtab: */
diff --git a/bindings/sdl2wgpu/src/main/headers/SDL2/SDL_joystick.h b/bindings/sdl2wgpu/src/main/headers/SDL2/SDL_joystick.h
new file mode 100644
index 00000000..8c05fdb8
--- /dev/null
+++ b/bindings/sdl2wgpu/src/main/headers/SDL2/SDL_joystick.h
@@ -0,0 +1,1069 @@
+/*
+ Simple DirectMedia Layer
+ Copyright (C) 1997-2023 Sam Lantinga
+
+ This software is provided 'as-is', without any express or implied
+ warranty. In no event will the authors be held liable for any damages
+ arising from the use of this software.
+
+ Permission is granted to anyone to use this software for any purpose,
+ including commercial applications, and to alter it and redistribute it
+ freely, subject to the following restrictions:
+
+ 1. The origin of this software must not be misrepresented; you must not
+ claim that you wrote the original software. If you use this software
+ in a product, an acknowledgment in the product documentation would be
+ appreciated but is not required.
+ 2. Altered source versions must be plainly marked as such, and must not be
+ misrepresented as being the original software.
+ 3. This notice may not be removed or altered from any source distribution.
+*/
+
+/**
+ * \file SDL_joystick.h
+ *
+ * Include file for SDL joystick event handling
+ *
+ * The term "device_index" identifies currently plugged in joystick devices between 0 and SDL_NumJoysticks(), with the exact joystick
+ * behind a device_index changing as joysticks are plugged and unplugged.
+ *
+ * The term "instance_id" is the current instantiation of a joystick device in the system, if the joystick is removed and then re-inserted
+ * then it will get a new instance_id, instance_id's are monotonically increasing identifiers of a joystick plugged in.
+ *
+ * The term "player_index" is the number assigned to a player on a specific
+ * controller. For XInput controllers this returns the XInput user index.
+ * Many joysticks will not be able to supply this information.
+ *
+ * The term JoystickGUID is a stable 128-bit identifier for a joystick device that does not change over time, it identifies class of
+ * the device (a X360 wired controller for example). This identifier is platform dependent.
+ */
+
+#ifndef SDL_joystick_h_
+#define SDL_joystick_h_
+
+#include
+#include
+#include
+#include
+
+#include
+/* Set up for C function definitions, even when using C++ */
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * \file SDL_joystick.h
+ *
+ * In order to use these functions, SDL_Init() must have been called
+ * with the ::SDL_INIT_JOYSTICK flag. This causes SDL to scan the system
+ * for joysticks, and load appropriate drivers.
+ *
+ * If you would like to receive joystick updates while the application
+ * is in the background, you should set the following hint before calling
+ * SDL_Init(): SDL_HINT_JOYSTICK_ALLOW_BACKGROUND_EVENTS
+ */
+
+/**
+ * The joystick structure used to identify an SDL joystick
+ */
+#ifdef SDL_THREAD_SAFETY_ANALYSIS
+extern SDL_mutex *SDL_joystick_lock;
+#endif
+struct _SDL_Joystick;
+typedef struct _SDL_Joystick SDL_Joystick;
+
+/* A structure that encodes the stable unique id for a joystick device */
+typedef SDL_GUID SDL_JoystickGUID;
+
+/**
+ * This is a unique ID for a joystick for the time it is connected to the system,
+ * and is never reused for the lifetime of the application. If the joystick is
+ * disconnected and reconnected, it will get a new ID.
+ *
+ * The ID value starts at 0 and increments from there. The value -1 is an invalid ID.
+ */
+typedef Sint32 SDL_JoystickID;
+
+typedef enum
+{
+ SDL_JOYSTICK_TYPE_UNKNOWN,
+ SDL_JOYSTICK_TYPE_GAMECONTROLLER,
+ SDL_JOYSTICK_TYPE_WHEEL,
+ SDL_JOYSTICK_TYPE_ARCADE_STICK,
+ SDL_JOYSTICK_TYPE_FLIGHT_STICK,
+ SDL_JOYSTICK_TYPE_DANCE_PAD,
+ SDL_JOYSTICK_TYPE_GUITAR,
+ SDL_JOYSTICK_TYPE_DRUM_KIT,
+ SDL_JOYSTICK_TYPE_ARCADE_PAD,
+ SDL_JOYSTICK_TYPE_THROTTLE
+} SDL_JoystickType;
+
+typedef enum
+{
+ SDL_JOYSTICK_POWER_UNKNOWN = -1,
+ SDL_JOYSTICK_POWER_EMPTY, /* <= 5% */
+ SDL_JOYSTICK_POWER_LOW, /* <= 20% */
+ SDL_JOYSTICK_POWER_MEDIUM, /* <= 70% */
+ SDL_JOYSTICK_POWER_FULL, /* <= 100% */
+ SDL_JOYSTICK_POWER_WIRED,
+ SDL_JOYSTICK_POWER_MAX
+} SDL_JoystickPowerLevel;
+
+/* Set max recognized G-force from accelerometer
+ See src/joystick/uikit/SDL_sysjoystick.m for notes on why this is needed
+ */
+#define SDL_IPHONE_MAX_GFORCE 5.0
+
+
+/* Function prototypes */
+
+/**
+ * Locking for multi-threaded access to the joystick API
+ *
+ * If you are using the joystick API or handling events from multiple threads
+ * you should use these locking functions to protect access to the joysticks.
+ *
+ * In particular, you are guaranteed that the joystick list won't change, so
+ * the API functions that take a joystick index will be valid, and joystick
+ * and game controller events will not be delivered.
+ *
+ * As of SDL 2.26.0, you can take the joystick lock around reinitializing the
+ * joystick subsystem, to prevent other threads from seeing joysticks in an
+ * uninitialized state. However, all open joysticks will be closed and SDL
+ * functions called with them will fail.
+ *
+ * \since This function is available since SDL 2.0.7.
+ */
+extern DECLSPEC void SDLCALL SDL_LockJoysticks(void) SDL_ACQUIRE(SDL_joystick_lock);
+
+
+/**
+ * Unlocking for multi-threaded access to the joystick API
+ *
+ * If you are using the joystick API or handling events from multiple threads
+ * you should use these locking functions to protect access to the joysticks.
+ *
+ * In particular, you are guaranteed that the joystick list won't change, so
+ * the API functions that take a joystick index will be valid, and joystick
+ * and game controller events will not be delivered.
+ *
+ * \since This function is available since SDL 2.0.7.
+ */
+extern DECLSPEC void SDLCALL SDL_UnlockJoysticks(void) SDL_RELEASE(SDL_joystick_lock);
+
+/**
+ * Count the number of joysticks attached to the system.
+ *
+ * \returns the number of attached joysticks on success or a negative error
+ * code on failure; call SDL_GetError() for more information.
+ *
+ * \since This function is available since SDL 2.0.0.
+ *
+ * \sa SDL_JoystickName
+ * \sa SDL_JoystickPath
+ * \sa SDL_JoystickOpen
+ */
+extern DECLSPEC int SDLCALL SDL_NumJoysticks(void);
+
+/**
+ * Get the implementation dependent name of a joystick.
+ *
+ * This can be called before any joysticks are opened.
+ *
+ * \param device_index the index of the joystick to query (the N'th joystick
+ * on the system)
+ * \returns the name of the selected joystick. If no name can be found, this
+ * function returns NULL; call SDL_GetError() for more information.
+ *
+ * \since This function is available since SDL 2.0.0.
+ *
+ * \sa SDL_JoystickName
+ * \sa SDL_JoystickOpen
+ */
+extern DECLSPEC const char *SDLCALL SDL_JoystickNameForIndex(int device_index);
+
+/**
+ * Get the implementation dependent path of a joystick.
+ *
+ * This can be called before any joysticks are opened.
+ *
+ * \param device_index the index of the joystick to query (the N'th joystick
+ * on the system)
+ * \returns the path of the selected joystick. If no path can be found, this
+ * function returns NULL; call SDL_GetError() for more information.
+ *
+ * \since This function is available since SDL 2.24.0.
+ *
+ * \sa SDL_JoystickPath
+ * \sa SDL_JoystickOpen
+ */
+extern DECLSPEC const char *SDLCALL SDL_JoystickPathForIndex(int device_index);
+
+/**
+ * Get the player index of a joystick, or -1 if it's not available This can be
+ * called before any joysticks are opened.
+ *
+ * \since This function is available since SDL 2.0.9.
+ */
+extern DECLSPEC int SDLCALL SDL_JoystickGetDevicePlayerIndex(int device_index);
+
+/**
+ * Get the implementation-dependent GUID for the joystick at a given device
+ * index.
+ *
+ * This function can be called before any joysticks are opened.
+ *
+ * \param device_index the index of the joystick to query (the N'th joystick
+ * on the system
+ * \returns the GUID of the selected joystick. If called on an invalid index,
+ * this function returns a zero GUID
+ *
+ * \since This function is available since SDL 2.0.0.
+ *
+ * \sa SDL_JoystickGetGUID
+ * \sa SDL_JoystickGetGUIDString
+ */
+extern DECLSPEC SDL_JoystickGUID SDLCALL SDL_JoystickGetDeviceGUID(int device_index);
+
+/**
+ * Get the USB vendor ID of a joystick, if available.
+ *
+ * This can be called before any joysticks are opened. If the vendor ID isn't
+ * available this function returns 0.
+ *
+ * \param device_index the index of the joystick to query (the N'th joystick
+ * on the system
+ * \returns the USB vendor ID of the selected joystick. If called on an
+ * invalid index, this function returns zero
+ *
+ * \since This function is available since SDL 2.0.6.
+ */
+extern DECLSPEC Uint16 SDLCALL SDL_JoystickGetDeviceVendor(int device_index);
+
+/**
+ * Get the USB product ID of a joystick, if available.
+ *
+ * This can be called before any joysticks are opened. If the product ID isn't
+ * available this function returns 0.
+ *
+ * \param device_index the index of the joystick to query (the N'th joystick
+ * on the system
+ * \returns the USB product ID of the selected joystick. If called on an
+ * invalid index, this function returns zero
+ *
+ * \since This function is available since SDL 2.0.6.
+ */
+extern DECLSPEC Uint16 SDLCALL SDL_JoystickGetDeviceProduct(int device_index);
+
+/**
+ * Get the product version of a joystick, if available.
+ *
+ * This can be called before any joysticks are opened. If the product version
+ * isn't available this function returns 0.
+ *
+ * \param device_index the index of the joystick to query (the N'th joystick
+ * on the system
+ * \returns the product version of the selected joystick. If called on an
+ * invalid index, this function returns zero
+ *
+ * \since This function is available since SDL 2.0.6.
+ */
+extern DECLSPEC Uint16 SDLCALL SDL_JoystickGetDeviceProductVersion(int device_index);
+
+/**
+ * Get the type of a joystick, if available.
+ *
+ * This can be called before any joysticks are opened.
+ *
+ * \param device_index the index of the joystick to query (the N'th joystick
+ * on the system
+ * \returns the SDL_JoystickType of the selected joystick. If called on an
+ * invalid index, this function returns `SDL_JOYSTICK_TYPE_UNKNOWN`
+ *
+ * \since This function is available since SDL 2.0.6.
+ */
+extern DECLSPEC SDL_JoystickType SDLCALL SDL_JoystickGetDeviceType(int device_index);
+
+/**
+ * Get the instance ID of a joystick.
+ *
+ * This can be called before any joysticks are opened.
+ *
+ * \param device_index the index of the joystick to query (the N'th joystick
+ * on the system
+ * \returns the instance id of the selected joystick. If called on an invalid
+ * index, this function returns -1.
+ *
+ * \since This function is available since SDL 2.0.6.
+ */
+extern DECLSPEC SDL_JoystickID SDLCALL SDL_JoystickGetDeviceInstanceID(int device_index);
+
+/**
+ * Open a joystick for use.
+ *
+ * The `device_index` argument refers to the N'th joystick presently
+ * recognized by SDL on the system. It is **NOT** the same as the instance ID
+ * used to identify the joystick in future events. See
+ * SDL_JoystickInstanceID() for more details about instance IDs.
+ *
+ * The joystick subsystem must be initialized before a joystick can be opened
+ * for use.
+ *
+ * \param device_index the index of the joystick to query
+ * \returns a joystick identifier or NULL if an error occurred; call
+ * SDL_GetError() for more information.
+ *
+ * \since This function is available since SDL 2.0.0.
+ *
+ * \sa SDL_JoystickClose
+ * \sa SDL_JoystickInstanceID
+ */
+extern DECLSPEC SDL_Joystick *SDLCALL SDL_JoystickOpen(int device_index);
+
+/**
+ * Get the SDL_Joystick associated with an instance id.
+ *
+ * \param instance_id the instance id to get the SDL_Joystick for
+ * \returns an SDL_Joystick on success or NULL on failure; call SDL_GetError()
+ * for more information.
+ *
+ * \since This function is available since SDL 2.0.4.
+ */
+extern DECLSPEC SDL_Joystick *SDLCALL SDL_JoystickFromInstanceID(SDL_JoystickID instance_id);
+
+/**
+ * Get the SDL_Joystick associated with a player index.
+ *
+ * \param player_index the player index to get the SDL_Joystick for
+ * \returns an SDL_Joystick on success or NULL on failure; call SDL_GetError()
+ * for more information.
+ *
+ * \since This function is available since SDL 2.0.12.
+ */
+extern DECLSPEC SDL_Joystick *SDLCALL SDL_JoystickFromPlayerIndex(int player_index);
+
+/**
+ * Attach a new virtual joystick.
+ *
+ * \returns the joystick's device index, or -1 if an error occurred.
+ *
+ * \since This function is available since SDL 2.0.14.
+ */
+extern DECLSPEC int SDLCALL SDL_JoystickAttachVirtual(SDL_JoystickType type,
+ int naxes,
+ int nbuttons,
+ int nhats);
+
+/**
+ * The structure that defines an extended virtual joystick description
+ *
+ * The caller must zero the structure and then initialize the version with `SDL_VIRTUAL_JOYSTICK_DESC_VERSION` before passing it to SDL_JoystickAttachVirtualEx()
+ * All other elements of this structure are optional and can be left 0.
+ *
+ * \sa SDL_JoystickAttachVirtualEx
+ */
+typedef struct SDL_VirtualJoystickDesc
+{
+ Uint16 version; /**< `SDL_VIRTUAL_JOYSTICK_DESC_VERSION` */
+ Uint16 type; /**< `SDL_JoystickType` */
+ Uint16 naxes; /**< the number of axes on this joystick */
+ Uint16 nbuttons; /**< the number of buttons on this joystick */
+ Uint16 nhats; /**< the number of hats on this joystick */
+ Uint16 vendor_id; /**< the USB vendor ID of this joystick */
+ Uint16 product_id; /**< the USB product ID of this joystick */
+ Uint16 padding; /**< unused */
+ Uint32 button_mask; /**< A mask of which buttons are valid for this controller
+ e.g. (1 << SDL_CONTROLLER_BUTTON_A) */
+ Uint32 axis_mask; /**< A mask of which axes are valid for this controller
+ e.g. (1 << SDL_CONTROLLER_AXIS_LEFTX) */
+ const char *name; /**< the name of the joystick */
+
+ void *userdata; /**< User data pointer passed to callbacks */
+ void (SDLCALL *Update)(void *userdata); /**< Called when the joystick state should be updated */
+ void (SDLCALL *SetPlayerIndex)(void *userdata, int player_index); /**< Called when the player index is set */
+ int (SDLCALL *Rumble)(void *userdata, Uint16 low_frequency_rumble, Uint16 high_frequency_rumble); /**< Implements SDL_JoystickRumble() */
+ int (SDLCALL *RumbleTriggers)(void *userdata, Uint16 left_rumble, Uint16 right_rumble); /**< Implements SDL_JoystickRumbleTriggers() */
+ int (SDLCALL *SetLED)(void *userdata, Uint8 red, Uint8 green, Uint8 blue); /**< Implements SDL_JoystickSetLED() */
+ int (SDLCALL *SendEffect)(void *userdata, const void *data, int size); /**< Implements SDL_JoystickSendEffect() */
+
+} SDL_VirtualJoystickDesc;
+
+/**
+ * \brief The current version of the SDL_VirtualJoystickDesc structure
+ */
+#define SDL_VIRTUAL_JOYSTICK_DESC_VERSION 1
+
+/**
+ * Attach a new virtual joystick with extended properties.
+ *
+ * \returns the joystick's device index, or -1 if an error occurred.
+ *
+ * \since This function is available since SDL 2.24.0.
+ */
+extern DECLSPEC int SDLCALL SDL_JoystickAttachVirtualEx(const SDL_VirtualJoystickDesc *desc);
+
+/**
+ * Detach a virtual joystick.
+ *
+ * \param device_index a value previously returned from
+ * SDL_JoystickAttachVirtual()
+ * \returns 0 on success, or -1 if an error occurred.
+ *
+ * \since This function is available since SDL 2.0.14.
+ */
+extern DECLSPEC int SDLCALL SDL_JoystickDetachVirtual(int device_index);
+
+/**
+ * Query whether or not the joystick at a given device index is virtual.
+ *
+ * \param device_index a joystick device index.
+ * \returns SDL_TRUE if the joystick is virtual, SDL_FALSE otherwise.
+ *
+ * \since This function is available since SDL 2.0.14.
+ */
+extern DECLSPEC SDL_bool SDLCALL SDL_JoystickIsVirtual(int device_index);
+
+/**
+ * Set values on an opened, virtual-joystick's axis.
+ *
+ * Please note that values set here will not be applied until the next call to
+ * SDL_JoystickUpdate, which can either be called directly, or can be called
+ * indirectly through various other SDL APIs, including, but not limited to
+ * the following: SDL_PollEvent, SDL_PumpEvents, SDL_WaitEventTimeout,
+ * SDL_WaitEvent.
+ *
+ * Note that when sending trigger axes, you should scale the value to the full
+ * range of Sint16. For example, a trigger at rest would have the value of
+ * `SDL_JOYSTICK_AXIS_MIN`.
+ *
+ * \param joystick the virtual joystick on which to set state.
+ * \param axis the specific axis on the virtual joystick to set.
+ * \param value the new value for the specified axis.
+ * \returns 0 on success, -1 on error.
+ *
+ * \since This function is available since SDL 2.0.14.
+ */
+extern DECLSPEC int SDLCALL SDL_JoystickSetVirtualAxis(SDL_Joystick *joystick, int axis, Sint16 value);
+
+/**
+ * Set values on an opened, virtual-joystick's button.
+ *
+ * Please note that values set here will not be applied until the next call to
+ * SDL_JoystickUpdate, which can either be called directly, or can be called
+ * indirectly through various other SDL APIs, including, but not limited to
+ * the following: SDL_PollEvent, SDL_PumpEvents, SDL_WaitEventTimeout,
+ * SDL_WaitEvent.
+ *
+ * \param joystick the virtual joystick on which to set state.
+ * \param button the specific button on the virtual joystick to set.
+ * \param value the new value for the specified button.
+ * \returns 0 on success, -1 on error.
+ *
+ * \since This function is available since SDL 2.0.14.
+ */
+extern DECLSPEC int SDLCALL SDL_JoystickSetVirtualButton(SDL_Joystick *joystick, int button, Uint8 value);
+
+/**
+ * Set values on an opened, virtual-joystick's hat.
+ *
+ * Please note that values set here will not be applied until the next call to
+ * SDL_JoystickUpdate, which can either be called directly, or can be called
+ * indirectly through various other SDL APIs, including, but not limited to
+ * the following: SDL_PollEvent, SDL_PumpEvents, SDL_WaitEventTimeout,
+ * SDL_WaitEvent.
+ *
+ * \param joystick the virtual joystick on which to set state.
+ * \param hat the specific hat on the virtual joystick to set.
+ * \param value the new value for the specified hat.
+ * \returns 0 on success, -1 on error.
+ *
+ * \since This function is available since SDL 2.0.14.
+ */
+extern DECLSPEC int SDLCALL SDL_JoystickSetVirtualHat(SDL_Joystick *joystick, int hat, Uint8 value);
+
+/**
+ * Get the implementation dependent name of a joystick.
+ *
+ * \param joystick the SDL_Joystick obtained from SDL_JoystickOpen()
+ * \returns the name of the selected joystick. If no name can be found, this
+ * function returns NULL; call SDL_GetError() for more information.
+ *
+ * \since This function is available since SDL 2.0.0.
+ *
+ * \sa SDL_JoystickNameForIndex
+ * \sa SDL_JoystickOpen
+ */
+extern DECLSPEC const char *SDLCALL SDL_JoystickName(SDL_Joystick *joystick);
+
+/**
+ * Get the implementation dependent path of a joystick.
+ *
+ * \param joystick the SDL_Joystick obtained from SDL_JoystickOpen()
+ * \returns the path of the selected joystick. If no path can be found, this
+ * function returns NULL; call SDL_GetError() for more information.
+ *
+ * \since This function is available since SDL 2.24.0.
+ *
+ * \sa SDL_JoystickPathForIndex
+ */
+extern DECLSPEC const char *SDLCALL SDL_JoystickPath(SDL_Joystick *joystick);
+
+/**
+ * Get the player index of an opened joystick.
+ *
+ * For XInput controllers this returns the XInput user index. Many joysticks
+ * will not be able to supply this information.
+ *
+ * \param joystick the SDL_Joystick obtained from SDL_JoystickOpen()
+ * \returns the player index, or -1 if it's not available.
+ *
+ * \since This function is available since SDL 2.0.9.
+ */
+extern DECLSPEC int SDLCALL SDL_JoystickGetPlayerIndex(SDL_Joystick *joystick);
+
+/**
+ * Set the player index of an opened joystick.
+ *
+ * \param joystick the SDL_Joystick obtained from SDL_JoystickOpen()
+ * \param player_index Player index to assign to this joystick, or -1 to clear
+ * the player index and turn off player LEDs.
+ *
+ * \since This function is available since SDL 2.0.12.
+ */
+extern DECLSPEC void SDLCALL SDL_JoystickSetPlayerIndex(SDL_Joystick *joystick, int player_index);
+
+/**
+ * Get the implementation-dependent GUID for the joystick.
+ *
+ * This function requires an open joystick.
+ *
+ * \param joystick the SDL_Joystick obtained from SDL_JoystickOpen()
+ * \returns the GUID of the given joystick. If called on an invalid index,
+ * this function returns a zero GUID; call SDL_GetError() for more
+ * information.
+ *
+ * \since This function is available since SDL 2.0.0.
+ *
+ * \sa SDL_JoystickGetDeviceGUID
+ * \sa SDL_JoystickGetGUIDString
+ */
+extern DECLSPEC SDL_JoystickGUID SDLCALL SDL_JoystickGetGUID(SDL_Joystick *joystick);
+
+/**
+ * Get the USB vendor ID of an opened joystick, if available.
+ *
+ * If the vendor ID isn't available this function returns 0.
+ *
+ * \param joystick the SDL_Joystick obtained from SDL_JoystickOpen()
+ * \returns the USB vendor ID of the selected joystick, or 0 if unavailable.
+ *
+ * \since This function is available since SDL 2.0.6.
+ */
+extern DECLSPEC Uint16 SDLCALL SDL_JoystickGetVendor(SDL_Joystick *joystick);
+
+/**
+ * Get the USB product ID of an opened joystick, if available.
+ *
+ * If the product ID isn't available this function returns 0.
+ *
+ * \param joystick the SDL_Joystick obtained from SDL_JoystickOpen()
+ * \returns the USB product ID of the selected joystick, or 0 if unavailable.
+ *
+ * \since This function is available since SDL 2.0.6.
+ */
+extern DECLSPEC Uint16 SDLCALL SDL_JoystickGetProduct(SDL_Joystick *joystick);
+
+/**
+ * Get the product version of an opened joystick, if available.
+ *
+ * If the product version isn't available this function returns 0.
+ *
+ * \param joystick the SDL_Joystick obtained from SDL_JoystickOpen()
+ * \returns the product version of the selected joystick, or 0 if unavailable.
+ *
+ * \since This function is available since SDL 2.0.6.
+ */
+extern DECLSPEC Uint16 SDLCALL SDL_JoystickGetProductVersion(SDL_Joystick *joystick);
+
+/**
+ * Get the firmware version of an opened joystick, if available.
+ *
+ * If the firmware version isn't available this function returns 0.
+ *
+ * \param joystick the SDL_Joystick obtained from SDL_JoystickOpen()
+ * \returns the firmware version of the selected joystick, or 0 if
+ * unavailable.
+ *
+ * \since This function is available since SDL 2.24.0.
+ */
+extern DECLSPEC Uint16 SDLCALL SDL_JoystickGetFirmwareVersion(SDL_Joystick *joystick);
+
+/**
+ * Get the serial number of an opened joystick, if available.
+ *
+ * Returns the serial number of the joystick, or NULL if it is not available.
+ *
+ * \param joystick the SDL_Joystick obtained from SDL_JoystickOpen()
+ * \returns the serial number of the selected joystick, or NULL if
+ * unavailable.
+ *
+ * \since This function is available since SDL 2.0.14.
+ */
+extern DECLSPEC const char * SDLCALL SDL_JoystickGetSerial(SDL_Joystick *joystick);
+
+/**
+ * Get the type of an opened joystick.
+ *
+ * \param joystick the SDL_Joystick obtained from SDL_JoystickOpen()
+ * \returns the SDL_JoystickType of the selected joystick.
+ *
+ * \since This function is available since SDL 2.0.6.
+ */
+extern DECLSPEC SDL_JoystickType SDLCALL SDL_JoystickGetType(SDL_Joystick *joystick);
+
+/**
+ * Get an ASCII string representation for a given SDL_JoystickGUID.
+ *
+ * You should supply at least 33 bytes for pszGUID.
+ *
+ * \param guid the SDL_JoystickGUID you wish to convert to string
+ * \param pszGUID buffer in which to write the ASCII string
+ * \param cbGUID the size of pszGUID
+ *
+ * \since This function is available since SDL 2.0.0.
+ *
+ * \sa SDL_JoystickGetDeviceGUID
+ * \sa SDL_JoystickGetGUID
+ * \sa SDL_JoystickGetGUIDFromString
+ */
+extern DECLSPEC void SDLCALL SDL_JoystickGetGUIDString(SDL_JoystickGUID guid, char *pszGUID, int cbGUID);
+
+/**
+ * Convert a GUID string into a SDL_JoystickGUID structure.
+ *
+ * Performs no error checking. If this function is given a string containing
+ * an invalid GUID, the function will silently succeed, but the GUID generated
+ * will not be useful.
+ *
+ * \param pchGUID string containing an ASCII representation of a GUID
+ * \returns a SDL_JoystickGUID structure.
+ *
+ * \since This function is available since SDL 2.0.0.
+ *
+ * \sa SDL_JoystickGetGUIDString
+ */
+extern DECLSPEC SDL_JoystickGUID SDLCALL SDL_JoystickGetGUIDFromString(const char *pchGUID);
+
+/**
+ * Get the device information encoded in a SDL_JoystickGUID structure
+ *
+ * \param guid the SDL_JoystickGUID you wish to get info about
+ * \param vendor A pointer filled in with the device VID, or 0 if not
+ * available
+ * \param product A pointer filled in with the device PID, or 0 if not
+ * available
+ * \param version A pointer filled in with the device version, or 0 if not
+ * available
+ * \param crc16 A pointer filled in with a CRC used to distinguish different
+ * products with the same VID/PID, or 0 if not available
+ *
+ * \since This function is available since SDL 2.26.0.
+ *
+ * \sa SDL_JoystickGetDeviceGUID
+ */
+extern DECLSPEC void SDLCALL SDL_GetJoystickGUIDInfo(SDL_JoystickGUID guid, Uint16 *vendor, Uint16 *product, Uint16 *version, Uint16 *crc16);
+
+/**
+ * Get the status of a specified joystick.
+ *
+ * \param joystick the joystick to query
+ * \returns SDL_TRUE if the joystick has been opened, SDL_FALSE if it has not;
+ * call SDL_GetError() for more information.
+ *
+ * \since This function is available since SDL 2.0.0.
+ *
+ * \sa SDL_JoystickClose
+ * \sa SDL_JoystickOpen
+ */
+extern DECLSPEC SDL_bool SDLCALL SDL_JoystickGetAttached(SDL_Joystick *joystick);
+
+/**
+ * Get the instance ID of an opened joystick.
+ *
+ * \param joystick an SDL_Joystick structure containing joystick information
+ * \returns the instance ID of the specified joystick on success or a negative
+ * error code on failure; call SDL_GetError() for more information.
+ *
+ * \since This function is available since SDL 2.0.0.
+ *
+ * \sa SDL_JoystickOpen
+ */
+extern DECLSPEC SDL_JoystickID SDLCALL SDL_JoystickInstanceID(SDL_Joystick *joystick);
+
+/**
+ * Get the number of general axis controls on a joystick.
+ *
+ * Often, the directional pad on a game controller will either look like 4
+ * separate buttons or a POV hat, and not axes, but all of this is up to the
+ * device and platform.
+ *
+ * \param joystick an SDL_Joystick structure containing joystick information
+ * \returns the number of axis controls/number of axes on success or a
+ * negative error code on failure; call SDL_GetError() for more
+ * information.
+ *
+ * \since This function is available since SDL 2.0.0.
+ *
+ * \sa SDL_JoystickGetAxis
+ * \sa SDL_JoystickOpen
+ */
+extern DECLSPEC int SDLCALL SDL_JoystickNumAxes(SDL_Joystick *joystick);
+
+/**
+ * Get the number of trackballs on a joystick.
+ *
+ * Joystick trackballs have only relative motion events associated with them
+ * and their state cannot be polled.
+ *
+ * Most joysticks do not have trackballs.
+ *
+ * \param joystick an SDL_Joystick structure containing joystick information
+ * \returns the number of trackballs on success or a negative error code on
+ * failure; call SDL_GetError() for more information.
+ *
+ * \since This function is available since SDL 2.0.0.
+ *
+ * \sa SDL_JoystickGetBall
+ */
+extern DECLSPEC int SDLCALL SDL_JoystickNumBalls(SDL_Joystick *joystick);
+
+/**
+ * Get the number of POV hats on a joystick.
+ *
+ * \param joystick an SDL_Joystick structure containing joystick information
+ * \returns the number of POV hats on success or a negative error code on
+ * failure; call SDL_GetError() for more information.
+ *
+ * \since This function is available since SDL 2.0.0.
+ *
+ * \sa SDL_JoystickGetHat
+ * \sa SDL_JoystickOpen
+ */
+extern DECLSPEC int SDLCALL SDL_JoystickNumHats(SDL_Joystick *joystick);
+
+/**
+ * Get the number of buttons on a joystick.
+ *
+ * \param joystick an SDL_Joystick structure containing joystick information
+ * \returns the number of buttons on success or a negative error code on
+ * failure; call SDL_GetError() for more information.
+ *
+ * \since This function is available since SDL 2.0.0.
+ *
+ * \sa SDL_JoystickGetButton
+ * \sa SDL_JoystickOpen
+ */
+extern DECLSPEC int SDLCALL SDL_JoystickNumButtons(SDL_Joystick *joystick);
+
+/**
+ * Update the current state of the open joysticks.
+ *
+ * This is called automatically by the event loop if any joystick events are
+ * enabled.
+ *
+ * \since This function is available since SDL 2.0.0.
+ *
+ * \sa SDL_JoystickEventState
+ */
+extern DECLSPEC void SDLCALL SDL_JoystickUpdate(void);
+
+/**
+ * Enable/disable joystick event polling.
+ *
+ * If joystick events are disabled, you must call SDL_JoystickUpdate()
+ * yourself and manually check the state of the joystick when you want
+ * joystick information.
+ *
+ * It is recommended that you leave joystick event handling enabled.
+ *
+ * **WARNING**: Calling this function may delete all events currently in SDL's
+ * event queue.
+ *
+ * \param state can be one of `SDL_QUERY`, `SDL_IGNORE`, or `SDL_ENABLE`
+ * \returns 1 if enabled, 0 if disabled, or a negative error code on failure;
+ * call SDL_GetError() for more information.
+ *
+ * If `state` is `SDL_QUERY` then the current state is returned,
+ * otherwise the new processing state is returned.
+ *
+ * \since This function is available since SDL 2.0.0.
+ *
+ * \sa SDL_GameControllerEventState
+ */
+extern DECLSPEC int SDLCALL SDL_JoystickEventState(int state);
+
+#define SDL_JOYSTICK_AXIS_MAX 32767
+#define SDL_JOYSTICK_AXIS_MIN -32768
+
+/**
+ * Get the current state of an axis control on a joystick.
+ *
+ * SDL makes no promises about what part of the joystick any given axis refers
+ * to. Your game should have some sort of configuration UI to let users
+ * specify what each axis should be bound to. Alternately, SDL's higher-level
+ * Game Controller API makes a great effort to apply order to this lower-level
+ * interface, so you know that a specific axis is the "left thumb stick," etc.
+ *
+ * The value returned by SDL_JoystickGetAxis() is a signed integer (-32768 to
+ * 32767) representing the current position of the axis. It may be necessary
+ * to impose certain tolerances on these values to account for jitter.
+ *
+ * \param joystick an SDL_Joystick structure containing joystick information
+ * \param axis the axis to query; the axis indices start at index 0
+ * \returns a 16-bit signed integer representing the current position of the
+ * axis or 0 on failure; call SDL_GetError() for more information.
+ *
+ * \since This function is available since SDL 2.0.0.
+ *
+ * \sa SDL_JoystickNumAxes
+ */
+extern DECLSPEC Sint16 SDLCALL SDL_JoystickGetAxis(SDL_Joystick *joystick,
+ int axis);
+
+/**
+ * Get the initial state of an axis control on a joystick.
+ *
+ * The state is a value ranging from -32768 to 32767.
+ *
+ * The axis indices start at index 0.
+ *
+ * \param joystick an SDL_Joystick structure containing joystick information
+ * \param axis the axis to query; the axis indices start at index 0
+ * \param state Upon return, the initial value is supplied here.
+ * \return SDL_TRUE if this axis has any initial value, or SDL_FALSE if not.
+ *
+ * \since This function is available since SDL 2.0.6.
+ */
+extern DECLSPEC SDL_bool SDLCALL SDL_JoystickGetAxisInitialState(SDL_Joystick *joystick,
+ int axis, Sint16 *state);
+
+/**
+ * \name Hat positions
+ */
+/* @{ */
+#define SDL_HAT_CENTERED 0x00
+#define SDL_HAT_UP 0x01
+#define SDL_HAT_RIGHT 0x02
+#define SDL_HAT_DOWN 0x04
+#define SDL_HAT_LEFT 0x08
+#define SDL_HAT_RIGHTUP (SDL_HAT_RIGHT|SDL_HAT_UP)
+#define SDL_HAT_RIGHTDOWN (SDL_HAT_RIGHT|SDL_HAT_DOWN)
+#define SDL_HAT_LEFTUP (SDL_HAT_LEFT|SDL_HAT_UP)
+#define SDL_HAT_LEFTDOWN (SDL_HAT_LEFT|SDL_HAT_DOWN)
+/* @} */
+
+/**
+ * Get the current state of a POV hat on a joystick.
+ *
+ * The returned value will be one of the following positions:
+ *
+ * - `SDL_HAT_CENTERED`
+ * - `SDL_HAT_UP`
+ * - `SDL_HAT_RIGHT`
+ * - `SDL_HAT_DOWN`
+ * - `SDL_HAT_LEFT`
+ * - `SDL_HAT_RIGHTUP`
+ * - `SDL_HAT_RIGHTDOWN`
+ * - `SDL_HAT_LEFTUP`
+ * - `SDL_HAT_LEFTDOWN`
+ *
+ * \param joystick an SDL_Joystick structure containing joystick information
+ * \param hat the hat index to get the state from; indices start at index 0
+ * \returns the current hat position.
+ *
+ * \since This function is available since SDL 2.0.0.
+ *
+ * \sa SDL_JoystickNumHats
+ */
+extern DECLSPEC Uint8 SDLCALL SDL_JoystickGetHat(SDL_Joystick *joystick,
+ int hat);
+
+/**
+ * Get the ball axis change since the last poll.
+ *
+ * Trackballs can only return relative motion since the last call to
+ * SDL_JoystickGetBall(), these motion deltas are placed into `dx` and `dy`.
+ *
+ * Most joysticks do not have trackballs.
+ *
+ * \param joystick the SDL_Joystick to query
+ * \param ball the ball index to query; ball indices start at index 0
+ * \param dx stores the difference in the x axis position since the last poll
+ * \param dy stores the difference in the y axis position since the last poll
+ * \returns 0 on success or a negative error code on failure; call
+ * SDL_GetError() for more information.
+ *
+ * \since This function is available since SDL 2.0.0.
+ *
+ * \sa SDL_JoystickNumBalls
+ */
+extern DECLSPEC int SDLCALL SDL_JoystickGetBall(SDL_Joystick *joystick,
+ int ball, int *dx, int *dy);
+
+/**
+ * Get the current state of a button on a joystick.
+ *
+ * \param joystick an SDL_Joystick structure containing joystick information
+ * \param button the button index to get the state from; indices start at
+ * index 0
+ * \returns 1 if the specified button is pressed, 0 otherwise.
+ *
+ * \since This function is available since SDL 2.0.0.
+ *
+ * \sa SDL_JoystickNumButtons
+ */
+extern DECLSPEC Uint8 SDLCALL SDL_JoystickGetButton(SDL_Joystick *joystick,
+ int button);
+
+/**
+ * Start a rumble effect.
+ *
+ * Each call to this function cancels any previous rumble effect, and calling
+ * it with 0 intensity stops any rumbling.
+ *
+ * \param joystick The joystick to vibrate
+ * \param low_frequency_rumble The intensity of the low frequency (left)
+ * rumble motor, from 0 to 0xFFFF
+ * \param high_frequency_rumble The intensity of the high frequency (right)
+ * rumble motor, from 0 to 0xFFFF
+ * \param duration_ms The duration of the rumble effect, in milliseconds
+ * \returns 0, or -1 if rumble isn't supported on this joystick
+ *
+ * \since This function is available since SDL 2.0.9.
+ *
+ * \sa SDL_JoystickHasRumble
+ */
+extern DECLSPEC int SDLCALL SDL_JoystickRumble(SDL_Joystick *joystick, Uint16 low_frequency_rumble, Uint16 high_frequency_rumble, Uint32 duration_ms);
+
+/**
+ * Start a rumble effect in the joystick's triggers
+ *
+ * Each call to this function cancels any previous trigger rumble effect, and
+ * calling it with 0 intensity stops any rumbling.
+ *
+ * Note that this is rumbling of the _triggers_ and not the game controller as
+ * a whole. This is currently only supported on Xbox One controllers. If you
+ * want the (more common) whole-controller rumble, use SDL_JoystickRumble()
+ * instead.
+ *
+ * \param joystick The joystick to vibrate
+ * \param left_rumble The intensity of the left trigger rumble motor, from 0
+ * to 0xFFFF
+ * \param right_rumble The intensity of the right trigger rumble motor, from 0
+ * to 0xFFFF
+ * \param duration_ms The duration of the rumble effect, in milliseconds
+ * \returns 0, or -1 if trigger rumble isn't supported on this joystick
+ *
+ * \since This function is available since SDL 2.0.14.
+ *
+ * \sa SDL_JoystickHasRumbleTriggers
+ */
+extern DECLSPEC int SDLCALL SDL_JoystickRumbleTriggers(SDL_Joystick *joystick, Uint16 left_rumble, Uint16 right_rumble, Uint32 duration_ms);
+
+/**
+ * Query whether a joystick has an LED.
+ *
+ * An example of a joystick LED is the light on the back of a PlayStation 4's
+ * DualShock 4 controller.
+ *
+ * \param joystick The joystick to query
+ * \return SDL_TRUE if the joystick has a modifiable LED, SDL_FALSE otherwise.
+ *
+ * \since This function is available since SDL 2.0.14.
+ */
+extern DECLSPEC SDL_bool SDLCALL SDL_JoystickHasLED(SDL_Joystick *joystick);
+
+/**
+ * Query whether a joystick has rumble support.
+ *
+ * \param joystick The joystick to query
+ * \return SDL_TRUE if the joystick has rumble, SDL_FALSE otherwise.
+ *
+ * \since This function is available since SDL 2.0.18.
+ *
+ * \sa SDL_JoystickRumble
+ */
+extern DECLSPEC SDL_bool SDLCALL SDL_JoystickHasRumble(SDL_Joystick *joystick);
+
+/**
+ * Query whether a joystick has rumble support on triggers.
+ *
+ * \param joystick The joystick to query
+ * \return SDL_TRUE if the joystick has trigger rumble, SDL_FALSE otherwise.
+ *
+ * \since This function is available since SDL 2.0.18.
+ *
+ * \sa SDL_JoystickRumbleTriggers
+ */
+extern DECLSPEC SDL_bool SDLCALL SDL_JoystickHasRumbleTriggers(SDL_Joystick *joystick);
+
+/**
+ * Update a joystick's LED color.
+ *
+ * An example of a joystick LED is the light on the back of a PlayStation 4's
+ * DualShock 4 controller.
+ *
+ * \param joystick The joystick to update
+ * \param red The intensity of the red LED
+ * \param green The intensity of the green LED
+ * \param blue The intensity of the blue LED
+ * \returns 0 on success, -1 if this joystick does not have a modifiable LED
+ *
+ * \since This function is available since SDL 2.0.14.
+ */
+extern DECLSPEC int SDLCALL SDL_JoystickSetLED(SDL_Joystick *joystick, Uint8 red, Uint8 green, Uint8 blue);
+
+/**
+ * Send a joystick specific effect packet
+ *
+ * \param joystick The joystick to affect
+ * \param data The data to send to the joystick
+ * \param size The size of the data to send to the joystick
+ * \returns 0, or -1 if this joystick or driver doesn't support effect packets
+ *
+ * \since This function is available since SDL 2.0.16.
+ */
+extern DECLSPEC int SDLCALL SDL_JoystickSendEffect(SDL_Joystick *joystick, const void *data, int size);
+
+/**
+ * Close a joystick previously opened with SDL_JoystickOpen().
+ *
+ * \param joystick The joystick device to close
+ *
+ * \since This function is available since SDL 2.0.0.
+ *
+ * \sa SDL_JoystickOpen
+ */
+extern DECLSPEC void SDLCALL SDL_JoystickClose(SDL_Joystick *joystick);
+
+/**
+ * Get the battery level of a joystick as SDL_JoystickPowerLevel.
+ *
+ * \param joystick the SDL_Joystick to query
+ * \returns the current battery level as SDL_JoystickPowerLevel on success or
+ * `SDL_JOYSTICK_POWER_UNKNOWN` if it is unknown
+ *
+ * \since This function is available since SDL 2.0.4.
+ */
+extern DECLSPEC SDL_JoystickPowerLevel SDLCALL SDL_JoystickCurrentPowerLevel(SDL_Joystick *joystick);
+
+/* Ends C function definitions when using C++ */
+#ifdef __cplusplus
+}
+#endif
+#include
+
+#endif /* SDL_joystick_h_ */
+
+/* vi: set ts=4 sw=4 expandtab: */
diff --git a/bindings/sdl2wgpu/src/main/headers/SDL2/SDL_keyboard.h b/bindings/sdl2wgpu/src/main/headers/SDL2/SDL_keyboard.h
new file mode 100644
index 00000000..039494ec
--- /dev/null
+++ b/bindings/sdl2wgpu/src/main/headers/SDL2/SDL_keyboard.h
@@ -0,0 +1,353 @@
+/*
+ Simple DirectMedia Layer
+ Copyright (C) 1997-2023 Sam Lantinga
+
+ This software is provided 'as-is', without any express or implied
+ warranty. In no event will the authors be held liable for any damages
+ arising from the use of this software.
+
+ Permission is granted to anyone to use this software for any purpose,
+ including commercial applications, and to alter it and redistribute it
+ freely, subject to the following restrictions:
+
+ 1. The origin of this software must not be misrepresented; you must not
+ claim that you wrote the original software. If you use this software
+ in a product, an acknowledgment in the product documentation would be
+ appreciated but is not required.
+ 2. Altered source versions must be plainly marked as such, and must not be
+ misrepresented as being the original software.
+ 3. This notice may not be removed or altered from any source distribution.
+*/
+
+/**
+ * \file SDL_keyboard.h
+ *
+ * Include file for SDL keyboard event handling
+ */
+
+#ifndef SDL_keyboard_h_
+#define SDL_keyboard_h_
+
+#include
+#include
+#include
+#include
+
+#include
+/* Set up for C function definitions, even when using C++ */
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * \brief The SDL keysym structure, used in key events.
+ *
+ * \note If you are looking for translated character input, see the ::SDL_TEXTINPUT event.
+ */
+typedef struct SDL_Keysym
+{
+ SDL_Scancode scancode; /**< SDL physical key code - see ::SDL_Scancode for details */
+ SDL_Keycode sym; /**< SDL virtual key code - see ::SDL_Keycode for details */
+ Uint16 mod; /**< current key modifiers */
+ Uint32 unused;
+} SDL_Keysym;
+
+/* Function prototypes */
+
+/**
+ * Query the window which currently has keyboard focus.
+ *
+ * \returns the window with keyboard focus.
+ *
+ * \since This function is available since SDL 2.0.0.
+ */
+extern DECLSPEC SDL_Window * SDLCALL SDL_GetKeyboardFocus(void);
+
+/**
+ * Get a snapshot of the current state of the keyboard.
+ *
+ * The pointer returned is a pointer to an internal SDL array. It will be
+ * valid for the whole lifetime of the application and should not be freed by
+ * the caller.
+ *
+ * A array element with a value of 1 means that the key is pressed and a value
+ * of 0 means that it is not. Indexes into this array are obtained by using
+ * SDL_Scancode values.
+ *
+ * Use SDL_PumpEvents() to update the state array.
+ *
+ * This function gives you the current state after all events have been
+ * processed, so if a key or button has been pressed and released before you
+ * process events, then the pressed state will never show up in the
+ * SDL_GetKeyboardState() calls.
+ *
+ * Note: This function doesn't take into account whether shift has been
+ * pressed or not.
+ *
+ * \param numkeys if non-NULL, receives the length of the returned array
+ * \returns a pointer to an array of key states.
+ *
+ * \since This function is available since SDL 2.0.0.
+ *
+ * \sa SDL_PumpEvents
+ * \sa SDL_ResetKeyboard
+ */
+extern DECLSPEC const Uint8 *SDLCALL SDL_GetKeyboardState(int *numkeys);
+
+/**
+ * Clear the state of the keyboard
+ *
+ * This function will generate key up events for all pressed keys.
+ *
+ * \since This function is available since SDL 2.24.0.
+ *
+ * \sa SDL_GetKeyboardState
+ */
+extern DECLSPEC void SDLCALL SDL_ResetKeyboard(void);
+
+/**
+ * Get the current key modifier state for the keyboard.
+ *
+ * \returns an OR'd combination of the modifier keys for the keyboard. See
+ * SDL_Keymod for details.
+ *
+ * \since This function is available since SDL 2.0.0.
+ *
+ * \sa SDL_GetKeyboardState
+ * \sa SDL_SetModState
+ */
+extern DECLSPEC SDL_Keymod SDLCALL SDL_GetModState(void);
+
+/**
+ * Set the current key modifier state for the keyboard.
+ *
+ * The inverse of SDL_GetModState(), SDL_SetModState() allows you to impose
+ * modifier key states on your application. Simply pass your desired modifier
+ * states into `modstate`. This value may be a bitwise, OR'd combination of
+ * SDL_Keymod values.
+ *
+ * This does not change the keyboard state, only the key modifier flags that
+ * SDL reports.
+ *
+ * \param modstate the desired SDL_Keymod for the keyboard
+ *
+ * \since This function is available since SDL 2.0.0.
+ *
+ * \sa SDL_GetModState
+ */
+extern DECLSPEC void SDLCALL SDL_SetModState(SDL_Keymod modstate);
+
+/**
+ * Get the key code corresponding to the given scancode according to the
+ * current keyboard layout.
+ *
+ * See SDL_Keycode for details.
+ *
+ * \param scancode the desired SDL_Scancode to query
+ * \returns the SDL_Keycode that corresponds to the given SDL_Scancode.
+ *
+ * \since This function is available since SDL 2.0.0.
+ *
+ * \sa SDL_GetKeyName
+ * \sa SDL_GetScancodeFromKey
+ */
+extern DECLSPEC SDL_Keycode SDLCALL SDL_GetKeyFromScancode(SDL_Scancode scancode);
+
+/**
+ * Get the scancode corresponding to the given key code according to the
+ * current keyboard layout.
+ *
+ * See SDL_Scancode for details.
+ *
+ * \param key the desired SDL_Keycode to query
+ * \returns the SDL_Scancode that corresponds to the given SDL_Keycode.
+ *
+ * \since This function is available since SDL 2.0.0.
+ *
+ * \sa SDL_GetKeyFromScancode
+ * \sa SDL_GetScancodeName
+ */
+extern DECLSPEC SDL_Scancode SDLCALL SDL_GetScancodeFromKey(SDL_Keycode key);
+
+/**
+ * Get a human-readable name for a scancode.
+ *
+ * See SDL_Scancode for details.
+ *
+ * **Warning**: The returned name is by design not stable across platforms,
+ * e.g. the name for `SDL_SCANCODE_LGUI` is "Left GUI" under Linux but "Left
+ * Windows" under Microsoft Windows, and some scancodes like
+ * `SDL_SCANCODE_NONUSBACKSLASH` don't have any name at all. There are even
+ * scancodes that share names, e.g. `SDL_SCANCODE_RETURN` and
+ * `SDL_SCANCODE_RETURN2` (both called "Return"). This function is therefore
+ * unsuitable for creating a stable cross-platform two-way mapping between
+ * strings and scancodes.
+ *
+ * \param scancode the desired SDL_Scancode to query
+ * \returns a pointer to the name for the scancode. If the scancode doesn't
+ * have a name this function returns an empty string ("").
+ *
+ * \since This function is available since SDL 2.0.0.
+ *
+ * \sa SDL_GetScancodeFromKey
+ * \sa SDL_GetScancodeFromName
+ */
+extern DECLSPEC const char *SDLCALL SDL_GetScancodeName(SDL_Scancode scancode);
+
+/**
+ * Get a scancode from a human-readable name.
+ *
+ * \param name the human-readable scancode name
+ * \returns the SDL_Scancode, or `SDL_SCANCODE_UNKNOWN` if the name wasn't
+ * recognized; call SDL_GetError() for more information.
+ *
+ * \since This function is available since SDL 2.0.0.
+ *
+ * \sa SDL_GetKeyFromName
+ * \sa SDL_GetScancodeFromKey
+ * \sa SDL_GetScancodeName
+ */
+extern DECLSPEC SDL_Scancode SDLCALL SDL_GetScancodeFromName(const char *name);
+
+/**
+ * Get a human-readable name for a key.
+ *
+ * See SDL_Scancode and SDL_Keycode for details.
+ *
+ * \param key the desired SDL_Keycode to query
+ * \returns a pointer to a UTF-8 string that stays valid at least until the
+ * next call to this function. If you need it around any longer, you
+ * must copy it. If the key doesn't have a name, this function
+ * returns an empty string ("").
+ *
+ * \since This function is available since SDL 2.0.0.
+ *
+ * \sa SDL_GetKeyFromName
+ * \sa SDL_GetKeyFromScancode
+ * \sa SDL_GetScancodeFromKey
+ */
+extern DECLSPEC const char *SDLCALL SDL_GetKeyName(SDL_Keycode key);
+
+/**
+ * Get a key code from a human-readable name.
+ *
+ * \param name the human-readable key name
+ * \returns key code, or `SDLK_UNKNOWN` if the name wasn't recognized; call
+ * SDL_GetError() for more information.
+ *
+ * \since This function is available since SDL 2.0.0.
+ *
+ * \sa SDL_GetKeyFromScancode
+ * \sa SDL_GetKeyName
+ * \sa SDL_GetScancodeFromName
+ */
+extern DECLSPEC SDL_Keycode SDLCALL SDL_GetKeyFromName(const char *name);
+
+/**
+ * Start accepting Unicode text input events.
+ *
+ * This function will start accepting Unicode text input events in the focused
+ * SDL window, and start emitting SDL_TextInputEvent (SDL_TEXTINPUT) and
+ * SDL_TextEditingEvent (SDL_TEXTEDITING) events. Please use this function in
+ * pair with SDL_StopTextInput().
+ *
+ * On some platforms using this function activates the screen keyboard.
+ *
+ * \since This function is available since SDL 2.0.0.
+ *
+ * \sa SDL_SetTextInputRect
+ * \sa SDL_StopTextInput
+ */
+extern DECLSPEC void SDLCALL SDL_StartTextInput(void);
+
+/**
+ * Check whether or not Unicode text input events are enabled.
+ *
+ * \returns SDL_TRUE if text input events are enabled else SDL_FALSE.
+ *
+ * \since This function is available since SDL 2.0.0.
+ *
+ * \sa SDL_StartTextInput
+ */
+extern DECLSPEC SDL_bool SDLCALL SDL_IsTextInputActive(void);
+
+/**
+ * Stop receiving any text input events.
+ *
+ * \since This function is available since SDL 2.0.0.
+ *
+ * \sa SDL_StartTextInput
+ */
+extern DECLSPEC void SDLCALL SDL_StopTextInput(void);
+
+/**
+ * Dismiss the composition window/IME without disabling the subsystem.
+ *
+ * \since This function is available since SDL 2.0.22.
+ *
+ * \sa SDL_StartTextInput
+ * \sa SDL_StopTextInput
+ */
+extern DECLSPEC void SDLCALL SDL_ClearComposition(void);
+
+/**
+ * Returns if an IME Composite or Candidate window is currently shown.
+ *
+ * \since This function is available since SDL 2.0.22.
+ */
+extern DECLSPEC SDL_bool SDLCALL SDL_IsTextInputShown(void);
+
+/**
+ * Set the rectangle used to type Unicode text inputs.
+ *
+ * To start text input in a given location, this function is intended to be
+ * called before SDL_StartTextInput, although some platforms support moving
+ * the rectangle even while text input (and a composition) is active.
+ *
+ * Note: If you want to use the system native IME window, try setting hint
+ * **SDL_HINT_IME_SHOW_UI** to **1**, otherwise this function won't give you
+ * any feedback.
+ *
+ * \param rect the SDL_Rect structure representing the rectangle to receive
+ * text (ignored if NULL)
+ *
+ * \since This function is available since SDL 2.0.0.
+ *
+ * \sa SDL_StartTextInput
+ */
+extern DECLSPEC void SDLCALL SDL_SetTextInputRect(const SDL_Rect *rect);
+
+/**
+ * Check whether the platform has screen keyboard support.
+ *
+ * \returns SDL_TRUE if the platform has some screen keyboard support or
+ * SDL_FALSE if not.
+ *
+ * \since This function is available since SDL 2.0.0.
+ *
+ * \sa SDL_StartTextInput
+ * \sa SDL_IsScreenKeyboardShown
+ */
+extern DECLSPEC SDL_bool SDLCALL SDL_HasScreenKeyboardSupport(void);
+
+/**
+ * Check whether the screen keyboard is shown for given window.
+ *
+ * \param window the window for which screen keyboard should be queried
+ * \returns SDL_TRUE if screen keyboard is shown or SDL_FALSE if not.
+ *
+ * \since This function is available since SDL 2.0.0.
+ *
+ * \sa SDL_HasScreenKeyboardSupport
+ */
+extern DECLSPEC SDL_bool SDLCALL SDL_IsScreenKeyboardShown(SDL_Window *window);
+
+/* Ends C function definitions when using C++ */
+#ifdef __cplusplus
+}
+#endif
+#include
+
+#endif /* SDL_keyboard_h_ */
+
+/* vi: set ts=4 sw=4 expandtab: */
diff --git a/bindings/sdl2wgpu/src/main/headers/SDL2/SDL_keycode.h b/bindings/sdl2wgpu/src/main/headers/SDL2/SDL_keycode.h
new file mode 100644
index 00000000..cc08478a
--- /dev/null
+++ b/bindings/sdl2wgpu/src/main/headers/SDL2/SDL_keycode.h
@@ -0,0 +1,358 @@
+/*
+ Simple DirectMedia Layer
+ Copyright (C) 1997-2023 Sam Lantinga
+
+ This software is provided 'as-is', without any express or implied
+ warranty. In no event will the authors be held liable for any damages
+ arising from the use of this software.
+
+ Permission is granted to anyone to use this software for any purpose,
+ including commercial applications, and to alter it and redistribute it
+ freely, subject to the following restrictions:
+
+ 1. The origin of this software must not be misrepresented; you must not
+ claim that you wrote the original software. If you use this software
+ in a product, an acknowledgment in the product documentation would be
+ appreciated but is not required.
+ 2. Altered source versions must be plainly marked as such, and must not be
+ misrepresented as being the original software.
+ 3. This notice may not be removed or altered from any source distribution.
+*/
+
+/**
+ * \file SDL_keycode.h
+ *
+ * Defines constants which identify keyboard keys and modifiers.
+ */
+
+#ifndef SDL_keycode_h_
+#define SDL_keycode_h_
+
+#include
+#include
+
+/**
+ * \brief The SDL virtual key representation.
+ *
+ * Values of this type are used to represent keyboard keys using the current
+ * layout of the keyboard. These values include Unicode values representing
+ * the unmodified character that would be generated by pressing the key, or
+ * an SDLK_* constant for those keys that do not generate characters.
+ *
+ * A special exception is the number keys at the top of the keyboard which
+ * map to SDLK_0...SDLK_9 on AZERTY layouts.
+ */
+typedef Sint32 SDL_Keycode;
+
+#define SDLK_SCANCODE_MASK (1<<30)
+#define SDL_SCANCODE_TO_KEYCODE(X) (X | SDLK_SCANCODE_MASK)
+
+typedef enum
+{
+ SDLK_UNKNOWN = 0,
+
+ SDLK_RETURN = '\r',
+ SDLK_ESCAPE = '\x1B',
+ SDLK_BACKSPACE = '\b',
+ SDLK_TAB = '\t',
+ SDLK_SPACE = ' ',
+ SDLK_EXCLAIM = '!',
+ SDLK_QUOTEDBL = '"',
+ SDLK_HASH = '#',
+ SDLK_PERCENT = '%',
+ SDLK_DOLLAR = '$',
+ SDLK_AMPERSAND = '&',
+ SDLK_QUOTE = '\'',
+ SDLK_LEFTPAREN = '(',
+ SDLK_RIGHTPAREN = ')',
+ SDLK_ASTERISK = '*',
+ SDLK_PLUS = '+',
+ SDLK_COMMA = ',',
+ SDLK_MINUS = '-',
+ SDLK_PERIOD = '.',
+ SDLK_SLASH = '/',
+ SDLK_0 = '0',
+ SDLK_1 = '1',
+ SDLK_2 = '2',
+ SDLK_3 = '3',
+ SDLK_4 = '4',
+ SDLK_5 = '5',
+ SDLK_6 = '6',
+ SDLK_7 = '7',
+ SDLK_8 = '8',
+ SDLK_9 = '9',
+ SDLK_COLON = ':',
+ SDLK_SEMICOLON = ';',
+ SDLK_LESS = '<',
+ SDLK_EQUALS = '=',
+ SDLK_GREATER = '>',
+ SDLK_QUESTION = '?',
+ SDLK_AT = '@',
+
+ /*
+ Skip uppercase letters
+ */
+
+ SDLK_LEFTBRACKET = '[',
+ SDLK_BACKSLASH = '\\',
+ SDLK_RIGHTBRACKET = ']',
+ SDLK_CARET = '^',
+ SDLK_UNDERSCORE = '_',
+ SDLK_BACKQUOTE = '`',
+ SDLK_a = 'a',
+ SDLK_b = 'b',
+ SDLK_c = 'c',
+ SDLK_d = 'd',
+ SDLK_e = 'e',
+ SDLK_f = 'f',
+ SDLK_g = 'g',
+ SDLK_h = 'h',
+ SDLK_i = 'i',
+ SDLK_j = 'j',
+ SDLK_k = 'k',
+ SDLK_l = 'l',
+ SDLK_m = 'm',
+ SDLK_n = 'n',
+ SDLK_o = 'o',
+ SDLK_p = 'p',
+ SDLK_q = 'q',
+ SDLK_r = 'r',
+ SDLK_s = 's',
+ SDLK_t = 't',
+ SDLK_u = 'u',
+ SDLK_v = 'v',
+ SDLK_w = 'w',
+ SDLK_x = 'x',
+ SDLK_y = 'y',
+ SDLK_z = 'z',
+
+ SDLK_CAPSLOCK = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_CAPSLOCK),
+
+ SDLK_F1 = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_F1),
+ SDLK_F2 = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_F2),
+ SDLK_F3 = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_F3),
+ SDLK_F4 = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_F4),
+ SDLK_F5 = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_F5),
+ SDLK_F6 = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_F6),
+ SDLK_F7 = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_F7),
+ SDLK_F8 = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_F8),
+ SDLK_F9 = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_F9),
+ SDLK_F10 = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_F10),
+ SDLK_F11 = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_F11),
+ SDLK_F12 = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_F12),
+
+ SDLK_PRINTSCREEN = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_PRINTSCREEN),
+ SDLK_SCROLLLOCK = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_SCROLLLOCK),
+ SDLK_PAUSE = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_PAUSE),
+ SDLK_INSERT = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_INSERT),
+ SDLK_HOME = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_HOME),
+ SDLK_PAGEUP = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_PAGEUP),
+ SDLK_DELETE = '\x7F',
+ SDLK_END = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_END),
+ SDLK_PAGEDOWN = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_PAGEDOWN),
+ SDLK_RIGHT = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_RIGHT),
+ SDLK_LEFT = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_LEFT),
+ SDLK_DOWN = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_DOWN),
+ SDLK_UP = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_UP),
+
+ SDLK_NUMLOCKCLEAR = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_NUMLOCKCLEAR),
+ SDLK_KP_DIVIDE = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_KP_DIVIDE),
+ SDLK_KP_MULTIPLY = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_KP_MULTIPLY),
+ SDLK_KP_MINUS = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_KP_MINUS),
+ SDLK_KP_PLUS = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_KP_PLUS),
+ SDLK_KP_ENTER = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_KP_ENTER),
+ SDLK_KP_1 = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_KP_1),
+ SDLK_KP_2 = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_KP_2),
+ SDLK_KP_3 = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_KP_3),
+ SDLK_KP_4 = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_KP_4),
+ SDLK_KP_5 = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_KP_5),
+ SDLK_KP_6 = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_KP_6),
+ SDLK_KP_7 = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_KP_7),
+ SDLK_KP_8 = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_KP_8),
+ SDLK_KP_9 = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_KP_9),
+ SDLK_KP_0 = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_KP_0),
+ SDLK_KP_PERIOD = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_KP_PERIOD),
+
+ SDLK_APPLICATION = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_APPLICATION),
+ SDLK_POWER = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_POWER),
+ SDLK_KP_EQUALS = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_KP_EQUALS),
+ SDLK_F13 = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_F13),
+ SDLK_F14 = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_F14),
+ SDLK_F15 = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_F15),
+ SDLK_F16 = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_F16),
+ SDLK_F17 = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_F17),
+ SDLK_F18 = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_F18),
+ SDLK_F19 = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_F19),
+ SDLK_F20 = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_F20),
+ SDLK_F21 = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_F21),
+ SDLK_F22 = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_F22),
+ SDLK_F23 = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_F23),
+ SDLK_F24 = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_F24),
+ SDLK_EXECUTE = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_EXECUTE),
+ SDLK_HELP = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_HELP),
+ SDLK_MENU = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_MENU),
+ SDLK_SELECT = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_SELECT),
+ SDLK_STOP = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_STOP),
+ SDLK_AGAIN = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_AGAIN),
+ SDLK_UNDO = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_UNDO),
+ SDLK_CUT = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_CUT),
+ SDLK_COPY = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_COPY),
+ SDLK_PASTE = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_PASTE),
+ SDLK_FIND = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_FIND),
+ SDLK_MUTE = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_MUTE),
+ SDLK_VOLUMEUP = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_VOLUMEUP),
+ SDLK_VOLUMEDOWN = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_VOLUMEDOWN),
+ SDLK_KP_COMMA = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_KP_COMMA),
+ SDLK_KP_EQUALSAS400 =
+ SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_KP_EQUALSAS400),
+
+ SDLK_ALTERASE = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_ALTERASE),
+ SDLK_SYSREQ = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_SYSREQ),
+ SDLK_CANCEL = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_CANCEL),
+ SDLK_CLEAR = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_CLEAR),
+ SDLK_PRIOR = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_PRIOR),
+ SDLK_RETURN2 = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_RETURN2),
+ SDLK_SEPARATOR = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_SEPARATOR),
+ SDLK_OUT = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_OUT),
+ SDLK_OPER = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_OPER),
+ SDLK_CLEARAGAIN = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_CLEARAGAIN),
+ SDLK_CRSEL = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_CRSEL),
+ SDLK_EXSEL = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_EXSEL),
+
+ SDLK_KP_00 = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_KP_00),
+ SDLK_KP_000 = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_KP_000),
+ SDLK_THOUSANDSSEPARATOR =
+ SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_THOUSANDSSEPARATOR),
+ SDLK_DECIMALSEPARATOR =
+ SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_DECIMALSEPARATOR),
+ SDLK_CURRENCYUNIT = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_CURRENCYUNIT),
+ SDLK_CURRENCYSUBUNIT =
+ SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_CURRENCYSUBUNIT),
+ SDLK_KP_LEFTPAREN = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_KP_LEFTPAREN),
+ SDLK_KP_RIGHTPAREN = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_KP_RIGHTPAREN),
+ SDLK_KP_LEFTBRACE = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_KP_LEFTBRACE),
+ SDLK_KP_RIGHTBRACE = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_KP_RIGHTBRACE),
+ SDLK_KP_TAB = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_KP_TAB),
+ SDLK_KP_BACKSPACE = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_KP_BACKSPACE),
+ SDLK_KP_A = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_KP_A),
+ SDLK_KP_B = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_KP_B),
+ SDLK_KP_C = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_KP_C),
+ SDLK_KP_D = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_KP_D),
+ SDLK_KP_E = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_KP_E),
+ SDLK_KP_F = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_KP_F),
+ SDLK_KP_XOR = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_KP_XOR),
+ SDLK_KP_POWER = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_KP_POWER),
+ SDLK_KP_PERCENT = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_KP_PERCENT),
+ SDLK_KP_LESS = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_KP_LESS),
+ SDLK_KP_GREATER = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_KP_GREATER),
+ SDLK_KP_AMPERSAND = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_KP_AMPERSAND),
+ SDLK_KP_DBLAMPERSAND =
+ SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_KP_DBLAMPERSAND),
+ SDLK_KP_VERTICALBAR =
+ SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_KP_VERTICALBAR),
+ SDLK_KP_DBLVERTICALBAR =
+ SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_KP_DBLVERTICALBAR),
+ SDLK_KP_COLON = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_KP_COLON),
+ SDLK_KP_HASH = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_KP_HASH),
+ SDLK_KP_SPACE = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_KP_SPACE),
+ SDLK_KP_AT = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_KP_AT),
+ SDLK_KP_EXCLAM = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_KP_EXCLAM),
+ SDLK_KP_MEMSTORE = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_KP_MEMSTORE),
+ SDLK_KP_MEMRECALL = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_KP_MEMRECALL),
+ SDLK_KP_MEMCLEAR = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_KP_MEMCLEAR),
+ SDLK_KP_MEMADD = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_KP_MEMADD),
+ SDLK_KP_MEMSUBTRACT =
+ SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_KP_MEMSUBTRACT),
+ SDLK_KP_MEMMULTIPLY =
+ SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_KP_MEMMULTIPLY),
+ SDLK_KP_MEMDIVIDE = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_KP_MEMDIVIDE),
+ SDLK_KP_PLUSMINUS = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_KP_PLUSMINUS),
+ SDLK_KP_CLEAR = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_KP_CLEAR),
+ SDLK_KP_CLEARENTRY = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_KP_CLEARENTRY),
+ SDLK_KP_BINARY = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_KP_BINARY),
+ SDLK_KP_OCTAL = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_KP_OCTAL),
+ SDLK_KP_DECIMAL = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_KP_DECIMAL),
+ SDLK_KP_HEXADECIMAL =
+ SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_KP_HEXADECIMAL),
+
+ SDLK_LCTRL = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_LCTRL),
+ SDLK_LSHIFT = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_LSHIFT),
+ SDLK_LALT = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_LALT),
+ SDLK_LGUI = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_LGUI),
+ SDLK_RCTRL = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_RCTRL),
+ SDLK_RSHIFT = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_RSHIFT),
+ SDLK_RALT = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_RALT),
+ SDLK_RGUI = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_RGUI),
+
+ SDLK_MODE = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_MODE),
+
+ SDLK_AUDIONEXT = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_AUDIONEXT),
+ SDLK_AUDIOPREV = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_AUDIOPREV),
+ SDLK_AUDIOSTOP = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_AUDIOSTOP),
+ SDLK_AUDIOPLAY = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_AUDIOPLAY),
+ SDLK_AUDIOMUTE = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_AUDIOMUTE),
+ SDLK_MEDIASELECT = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_MEDIASELECT),
+ SDLK_WWW = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_WWW),
+ SDLK_MAIL = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_MAIL),
+ SDLK_CALCULATOR = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_CALCULATOR),
+ SDLK_COMPUTER = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_COMPUTER),
+ SDLK_AC_SEARCH = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_AC_SEARCH),
+ SDLK_AC_HOME = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_AC_HOME),
+ SDLK_AC_BACK = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_AC_BACK),
+ SDLK_AC_FORWARD = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_AC_FORWARD),
+ SDLK_AC_STOP = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_AC_STOP),
+ SDLK_AC_REFRESH = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_AC_REFRESH),
+ SDLK_AC_BOOKMARKS = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_AC_BOOKMARKS),
+
+ SDLK_BRIGHTNESSDOWN =
+ SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_BRIGHTNESSDOWN),
+ SDLK_BRIGHTNESSUP = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_BRIGHTNESSUP),
+ SDLK_DISPLAYSWITCH = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_DISPLAYSWITCH),
+ SDLK_KBDILLUMTOGGLE =
+ SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_KBDILLUMTOGGLE),
+ SDLK_KBDILLUMDOWN = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_KBDILLUMDOWN),
+ SDLK_KBDILLUMUP = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_KBDILLUMUP),
+ SDLK_EJECT = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_EJECT),
+ SDLK_SLEEP = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_SLEEP),
+ SDLK_APP1 = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_APP1),
+ SDLK_APP2 = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_APP2),
+
+ SDLK_AUDIOREWIND = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_AUDIOREWIND),
+ SDLK_AUDIOFASTFORWARD = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_AUDIOFASTFORWARD),
+
+ SDLK_SOFTLEFT = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_SOFTLEFT),
+ SDLK_SOFTRIGHT = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_SOFTRIGHT),
+ SDLK_CALL = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_CALL),
+ SDLK_ENDCALL = SDL_SCANCODE_TO_KEYCODE(SDL_SCANCODE_ENDCALL)
+} SDL_KeyCode;
+
+/**
+ * \brief Enumeration of valid key mods (possibly OR'd together).
+ */
+typedef enum
+{
+ KMOD_NONE = 0x0000,
+ KMOD_LSHIFT = 0x0001,
+ KMOD_RSHIFT = 0x0002,
+ KMOD_LCTRL = 0x0040,
+ KMOD_RCTRL = 0x0080,
+ KMOD_LALT = 0x0100,
+ KMOD_RALT = 0x0200,
+ KMOD_LGUI = 0x0400,
+ KMOD_RGUI = 0x0800,
+ KMOD_NUM = 0x1000,
+ KMOD_CAPS = 0x2000,
+ KMOD_MODE = 0x4000,
+ KMOD_SCROLL = 0x8000,
+
+ KMOD_CTRL = KMOD_LCTRL | KMOD_RCTRL,
+ KMOD_SHIFT = KMOD_LSHIFT | KMOD_RSHIFT,
+ KMOD_ALT = KMOD_LALT | KMOD_RALT,
+ KMOD_GUI = KMOD_LGUI | KMOD_RGUI,
+
+ KMOD_RESERVED = KMOD_SCROLL /* This is for source-level compatibility with SDL 2.0.0. */
+} SDL_Keymod;
+
+#endif /* SDL_keycode_h_ */
+
+/* vi: set ts=4 sw=4 expandtab: */
diff --git a/bindings/sdl2wgpu/src/main/headers/SDL2/SDL_loadso.h b/bindings/sdl2wgpu/src/main/headers/SDL2/SDL_loadso.h
new file mode 100644
index 00000000..c2b4f0a2
--- /dev/null
+++ b/bindings/sdl2wgpu/src/main/headers/SDL2/SDL_loadso.h
@@ -0,0 +1,115 @@
+/*
+ Simple DirectMedia Layer
+ Copyright (C) 1997-2023 Sam Lantinga
+
+ This software is provided 'as-is', without any express or implied
+ warranty. In no event will the authors be held liable for any damages
+ arising from the use of this software.
+
+ Permission is granted to anyone to use this software for any purpose,
+ including commercial applications, and to alter it and redistribute it
+ freely, subject to the following restrictions:
+
+ 1. The origin of this software must not be misrepresented; you must not
+ claim that you wrote the original software. If you use this software
+ in a product, an acknowledgment in the product documentation would be
+ appreciated but is not required.
+ 2. Altered source versions must be plainly marked as such, and must not be
+ misrepresented as being the original software.
+ 3. This notice may not be removed or altered from any source distribution.
+*/
+
+/**
+ * \file SDL_loadso.h
+ *
+ * System dependent library loading routines
+ *
+ * Some things to keep in mind:
+ * \li These functions only work on C function names. Other languages may
+ * have name mangling and intrinsic language support that varies from
+ * compiler to compiler.
+ * \li Make sure you declare your function pointers with the same calling
+ * convention as the actual library function. Your code will crash
+ * mysteriously if you do not do this.
+ * \li Avoid namespace collisions. If you load a symbol from the library,
+ * it is not defined whether or not it goes into the global symbol
+ * namespace for the application. If it does and it conflicts with
+ * symbols in your code or other shared libraries, you will not get
+ * the results you expect. :)
+ */
+
+#ifndef SDL_loadso_h_
+#define SDL_loadso_h_
+
+#include
+#include
+
+#include
+/* Set up for C function definitions, even when using C++ */
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * Dynamically load a shared object.
+ *
+ * \param sofile a system-dependent name of the object file
+ * \returns an opaque pointer to the object handle or NULL if there was an
+ * error; call SDL_GetError() for more information.
+ *
+ * \since This function is available since SDL 2.0.0.
+ *
+ * \sa SDL_LoadFunction
+ * \sa SDL_UnloadObject
+ */
+extern DECLSPEC void *SDLCALL SDL_LoadObject(const char *sofile);
+
+/**
+ * Look up the address of the named function in a shared object.
+ *
+ * This function pointer is no longer valid after calling SDL_UnloadObject().
+ *
+ * This function can only look up C function names. Other languages may have
+ * name mangling and intrinsic language support that varies from compiler to
+ * compiler.
+ *
+ * Make sure you declare your function pointers with the same calling
+ * convention as the actual library function. Your code will crash
+ * mysteriously if you do not do this.
+ *
+ * If the requested function doesn't exist, NULL is returned.
+ *
+ * \param handle a valid shared object handle returned by SDL_LoadObject()
+ * \param name the name of the function to look up
+ * \returns a pointer to the function or NULL if there was an error; call
+ * SDL_GetError() for more information.
+ *
+ * \since This function is available since SDL 2.0.0.
+ *
+ * \sa SDL_LoadObject
+ * \sa SDL_UnloadObject
+ */
+extern DECLSPEC void *SDLCALL SDL_LoadFunction(void *handle,
+ const char *name);
+
+/**
+ * Unload a shared object from memory.
+ *
+ * \param handle a valid shared object handle returned by SDL_LoadObject()
+ *
+ * \since This function is available since SDL 2.0.0.
+ *
+ * \sa SDL_LoadFunction
+ * \sa SDL_LoadObject
+ */
+extern DECLSPEC void SDLCALL SDL_UnloadObject(void *handle);
+
+/* Ends C function definitions when using C++ */
+#ifdef __cplusplus
+}
+#endif
+#include
+
+#endif /* SDL_loadso_h_ */
+
+/* vi: set ts=4 sw=4 expandtab: */
diff --git a/bindings/sdl2wgpu/src/main/headers/SDL2/SDL_locale.h b/bindings/sdl2wgpu/src/main/headers/SDL2/SDL_locale.h
new file mode 100644
index 00000000..a0e5923d
--- /dev/null
+++ b/bindings/sdl2wgpu/src/main/headers/SDL2/SDL_locale.h
@@ -0,0 +1,103 @@
+/*
+ Simple DirectMedia Layer
+ Copyright (C) 1997-2023 Sam Lantinga
+
+ This software is provided 'as-is', without any express or implied
+ warranty. In no event will the authors be held liable for any damages
+ arising from the use of this software.
+
+ Permission is granted to anyone to use this software for any purpose,
+ including commercial applications, and to alter it and redistribute it
+ freely, subject to the following restrictions:
+
+ 1. The origin of this software must not be misrepresented; you must not
+ claim that you wrote the original software. If you use this software
+ in a product, an acknowledgment in the product documentation would be
+ appreciated but is not required.
+ 2. Altered source versions must be plainly marked as such, and must not be
+ misrepresented as being the original software.
+ 3. This notice may not be removed or altered from any source distribution.
+*/
+
+/**
+ * \file SDL_locale.h
+ *
+ * Include file for SDL locale services
+ */
+
+#ifndef _SDL_locale_h
+#define _SDL_locale_h
+
+#include
+#include
+
+#include
+/* Set up for C function definitions, even when using C++ */
+#ifdef __cplusplus
+/* *INDENT-OFF* */
+extern "C" {
+/* *INDENT-ON* */
+#endif
+
+
+typedef struct SDL_Locale
+{
+ const char *language; /**< A language name, like "en" for English. */
+ const char *country; /**< A country, like "US" for America. Can be NULL. */
+} SDL_Locale;
+
+/**
+ * Report the user's preferred locale.
+ *
+ * This returns an array of SDL_Locale structs, the final item zeroed out.
+ * When the caller is done with this array, it should call SDL_free() on the
+ * returned value; all the memory involved is allocated in a single block, so
+ * a single SDL_free() will suffice.
+ *
+ * Returned language strings are in the format xx, where 'xx' is an ISO-639
+ * language specifier (such as "en" for English, "de" for German, etc).
+ * Country strings are in the format YY, where "YY" is an ISO-3166 country
+ * code (such as "US" for the United States, "CA" for Canada, etc). Country
+ * might be NULL if there's no specific guidance on them (so you might get {
+ * "en", "US" } for American English, but { "en", NULL } means "English
+ * language, generically"). Language strings are never NULL, except to
+ * terminate the array.
+ *
+ * Please note that not all of these strings are 2 characters; some are three
+ * or more.
+ *
+ * The returned list of locales are in the order of the user's preference. For
+ * example, a German citizen that is fluent in US English and knows enough
+ * Japanese to navigate around Tokyo might have a list like: { "de", "en_US",
+ * "jp", NULL }. Someone from England might prefer British English (where
+ * "color" is spelled "colour", etc), but will settle for anything like it: {
+ * "en_GB", "en", NULL }.
+ *
+ * This function returns NULL on error, including when the platform does not
+ * supply this information at all.
+ *
+ * This might be a "slow" call that has to query the operating system. It's
+ * best to ask for this once and save the results. However, this list can
+ * change, usually because the user has changed a system preference outside of
+ * your program; SDL will send an SDL_LOCALECHANGED event in this case, if
+ * possible, and you can call this function again to get an updated copy of
+ * preferred locales.
+ *
+ * \return array of locales, terminated with a locale with a NULL language
+ * field. Will return NULL on error.
+ *
+ * \since This function is available since SDL 2.0.14.
+ */
+extern DECLSPEC SDL_Locale * SDLCALL SDL_GetPreferredLocales(void);
+
+/* Ends C function definitions when using C++ */
+#ifdef __cplusplus
+/* *INDENT-OFF* */
+}
+/* *INDENT-ON* */
+#endif
+#include
+
+#endif /* _SDL_locale_h */
+
+/* vi: set ts=4 sw=4 expandtab: */
diff --git a/bindings/sdl2wgpu/src/main/headers/SDL2/SDL_log.h b/bindings/sdl2wgpu/src/main/headers/SDL2/SDL_log.h
new file mode 100644
index 00000000..0afb9fe7
--- /dev/null
+++ b/bindings/sdl2wgpu/src/main/headers/SDL2/SDL_log.h
@@ -0,0 +1,404 @@
+/*
+ Simple DirectMedia Layer
+ Copyright (C) 1997-2023 Sam Lantinga
+
+ This software is provided 'as-is', without any express or implied
+ warranty. In no event will the authors be held liable for any damages
+ arising from the use of this software.
+
+ Permission is granted to anyone to use this software for any purpose,
+ including commercial applications, and to alter it and redistribute it
+ freely, subject to the following restrictions:
+
+ 1. The origin of this software must not be misrepresented; you must not
+ claim that you wrote the original software. If you use this software
+ in a product, an acknowledgment in the product documentation would be
+ appreciated but is not required.
+ 2. Altered source versions must be plainly marked as such, and must not be
+ misrepresented as being the original software.
+ 3. This notice may not be removed or altered from any source distribution.
+*/
+
+/**
+ * \file SDL_log.h
+ *
+ * Simple log messages with categories and priorities.
+ *
+ * By default logs are quiet, but if you're debugging SDL you might want:
+ *
+ * SDL_LogSetAllPriority(SDL_LOG_PRIORITY_WARN);
+ *
+ * Here's where the messages go on different platforms:
+ * Windows: debug output stream
+ * Android: log output
+ * Others: standard error output (stderr)
+ */
+
+#ifndef SDL_log_h_
+#define SDL_log_h_
+
+#include
+
+#include
+/* Set up for C function definitions, even when using C++ */
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+
+/**
+ * \brief The maximum size of a log message prior to SDL 2.0.24
+ *
+ * As of 2.0.24 there is no limit to the length of SDL log messages.
+ */
+#define SDL_MAX_LOG_MESSAGE 4096
+
+/**
+ * \brief The predefined log categories
+ *
+ * By default the application category is enabled at the INFO level,
+ * the assert category is enabled at the WARN level, test is enabled
+ * at the VERBOSE level and all other categories are enabled at the
+ * CRITICAL level.
+ */
+typedef enum
+{
+ SDL_LOG_CATEGORY_APPLICATION,
+ SDL_LOG_CATEGORY_ERROR,
+ SDL_LOG_CATEGORY_ASSERT,
+ SDL_LOG_CATEGORY_SYSTEM,
+ SDL_LOG_CATEGORY_AUDIO,
+ SDL_LOG_CATEGORY_VIDEO,
+ SDL_LOG_CATEGORY_RENDER,
+ SDL_LOG_CATEGORY_INPUT,
+ SDL_LOG_CATEGORY_TEST,
+
+ /* Reserved for future SDL library use */
+ SDL_LOG_CATEGORY_RESERVED1,
+ SDL_LOG_CATEGORY_RESERVED2,
+ SDL_LOG_CATEGORY_RESERVED3,
+ SDL_LOG_CATEGORY_RESERVED4,
+ SDL_LOG_CATEGORY_RESERVED5,
+ SDL_LOG_CATEGORY_RESERVED6,
+ SDL_LOG_CATEGORY_RESERVED7,
+ SDL_LOG_CATEGORY_RESERVED8,
+ SDL_LOG_CATEGORY_RESERVED9,
+ SDL_LOG_CATEGORY_RESERVED10,
+
+ /* Beyond this point is reserved for application use, e.g.
+ enum {
+ MYAPP_CATEGORY_AWESOME1 = SDL_LOG_CATEGORY_CUSTOM,
+ MYAPP_CATEGORY_AWESOME2,
+ MYAPP_CATEGORY_AWESOME3,
+ ...
+ };
+ */
+ SDL_LOG_CATEGORY_CUSTOM
+} SDL_LogCategory;
+
+/**
+ * \brief The predefined log priorities
+ */
+typedef enum
+{
+ SDL_LOG_PRIORITY_VERBOSE = 1,
+ SDL_LOG_PRIORITY_DEBUG,
+ SDL_LOG_PRIORITY_INFO,
+ SDL_LOG_PRIORITY_WARN,
+ SDL_LOG_PRIORITY_ERROR,
+ SDL_LOG_PRIORITY_CRITICAL,
+ SDL_NUM_LOG_PRIORITIES
+} SDL_LogPriority;
+
+
+/**
+ * Set the priority of all log categories.
+ *
+ * \param priority the SDL_LogPriority to assign
+ *
+ * \since This function is available since SDL 2.0.0.
+ *
+ * \sa SDL_LogSetPriority
+ */
+extern DECLSPEC void SDLCALL SDL_LogSetAllPriority(SDL_LogPriority priority);
+
+/**
+ * Set the priority of a particular log category.
+ *
+ * \param category the category to assign a priority to
+ * \param priority the SDL_LogPriority to assign
+ *
+ * \since This function is available since SDL 2.0.0.
+ *
+ * \sa SDL_LogGetPriority
+ * \sa SDL_LogSetAllPriority
+ */
+extern DECLSPEC void SDLCALL SDL_LogSetPriority(int category,
+ SDL_LogPriority priority);
+
+/**
+ * Get the priority of a particular log category.
+ *
+ * \param category the category to query
+ * \returns the SDL_LogPriority for the requested category
+ *
+ * \since This function is available since SDL 2.0.0.
+ *
+ * \sa SDL_LogSetPriority
+ */
+extern DECLSPEC SDL_LogPriority SDLCALL SDL_LogGetPriority(int category);
+
+/**
+ * Reset all priorities to default.
+ *
+ * This is called by SDL_Quit().
+ *
+ * \since This function is available since SDL 2.0.0.
+ *
+ * \sa SDL_LogSetAllPriority
+ * \sa SDL_LogSetPriority
+ */
+extern DECLSPEC void SDLCALL SDL_LogResetPriorities(void);
+
+/**
+ * Log a message with SDL_LOG_CATEGORY_APPLICATION and SDL_LOG_PRIORITY_INFO.
+ *
+ * = * \param fmt a printf() style message format string
+ *
+ * \param ... additional parameters matching % tokens in the `fmt` string, if
+ * any
+ *
+ * \since This function is available since SDL 2.0.0.
+ *
+ * \sa SDL_LogCritical
+ * \sa SDL_LogDebug
+ * \sa SDL_LogError
+ * \sa SDL_LogInfo
+ * \sa SDL_LogMessage
+ * \sa SDL_LogMessageV
+ * \sa SDL_LogVerbose
+ * \sa SDL_LogWarn
+ */
+extern DECLSPEC void SDLCALL SDL_Log(SDL_PRINTF_FORMAT_STRING const char *fmt, ...) SDL_PRINTF_VARARG_FUNC(1);
+
+/**
+ * Log a message with SDL_LOG_PRIORITY_VERBOSE.
+ *
+ * \param category the category of the message
+ * \param fmt a printf() style message format string
+ * \param ... additional parameters matching % tokens in the **fmt** string,
+ * if any
+ *
+ * \since This function is available since SDL 2.0.0.
+ *
+ * \sa SDL_Log
+ * \sa SDL_LogCritical
+ * \sa SDL_LogDebug
+ * \sa SDL_LogError
+ * \sa SDL_LogInfo
+ * \sa SDL_LogMessage
+ * \sa SDL_LogMessageV
+ * \sa SDL_LogWarn
+ */
+extern DECLSPEC void SDLCALL SDL_LogVerbose(int category, SDL_PRINTF_FORMAT_STRING const char *fmt, ...) SDL_PRINTF_VARARG_FUNC(2);
+
+/**
+ * Log a message with SDL_LOG_PRIORITY_DEBUG.
+ *
+ * \param category the category of the message
+ * \param fmt a printf() style message format string
+ * \param ... additional parameters matching % tokens in the **fmt** string,
+ * if any
+ *
+ * \since This function is available since SDL 2.0.0.
+ *
+ * \sa SDL_Log
+ * \sa SDL_LogCritical
+ * \sa SDL_LogError
+ * \sa SDL_LogInfo
+ * \sa SDL_LogMessage
+ * \sa SDL_LogMessageV
+ * \sa SDL_LogVerbose
+ * \sa SDL_LogWarn
+ */
+extern DECLSPEC void SDLCALL SDL_LogDebug(int category, SDL_PRINTF_FORMAT_STRING const char *fmt, ...) SDL_PRINTF_VARARG_FUNC(2);
+
+/**
+ * Log a message with SDL_LOG_PRIORITY_INFO.
+ *
+ * \param category the category of the message
+ * \param fmt a printf() style message format string
+ * \param ... additional parameters matching % tokens in the **fmt** string,
+ * if any
+ *
+ * \since This function is available since SDL 2.0.0.
+ *
+ * \sa SDL_Log
+ * \sa SDL_LogCritical
+ * \sa SDL_LogDebug
+ * \sa SDL_LogError
+ * \sa SDL_LogMessage
+ * \sa SDL_LogMessageV
+ * \sa SDL_LogVerbose
+ * \sa SDL_LogWarn
+ */
+extern DECLSPEC void SDLCALL SDL_LogInfo(int category, SDL_PRINTF_FORMAT_STRING const char *fmt, ...) SDL_PRINTF_VARARG_FUNC(2);
+
+/**
+ * Log a message with SDL_LOG_PRIORITY_WARN.
+ *
+ * \param category the category of the message
+ * \param fmt a printf() style message format string
+ * \param ... additional parameters matching % tokens in the **fmt** string,
+ * if any
+ *
+ * \since This function is available since SDL 2.0.0.
+ *
+ * \sa SDL_Log
+ * \sa SDL_LogCritical
+ * \sa SDL_LogDebug
+ * \sa SDL_LogError
+ * \sa SDL_LogInfo
+ * \sa SDL_LogMessage
+ * \sa SDL_LogMessageV
+ * \sa SDL_LogVerbose
+ */
+extern DECLSPEC void SDLCALL SDL_LogWarn(int category, SDL_PRINTF_FORMAT_STRING const char *fmt, ...) SDL_PRINTF_VARARG_FUNC(2);
+
+/**
+ * Log a message with SDL_LOG_PRIORITY_ERROR.
+ *
+ * \param category the category of the message
+ * \param fmt a printf() style message format string
+ * \param ... additional parameters matching % tokens in the **fmt** string,
+ * if any
+ *
+ * \since This function is available since SDL 2.0.0.
+ *
+ * \sa SDL_Log
+ * \sa SDL_LogCritical
+ * \sa SDL_LogDebug
+ * \sa SDL_LogInfo
+ * \sa SDL_LogMessage
+ * \sa SDL_LogMessageV
+ * \sa SDL_LogVerbose
+ * \sa SDL_LogWarn
+ */
+extern DECLSPEC void SDLCALL SDL_LogError(int category, SDL_PRINTF_FORMAT_STRING const char *fmt, ...) SDL_PRINTF_VARARG_FUNC(2);
+
+/**
+ * Log a message with SDL_LOG_PRIORITY_CRITICAL.
+ *
+ * \param category the category of the message
+ * \param fmt a printf() style message format string
+ * \param ... additional parameters matching % tokens in the **fmt** string,
+ * if any
+ *
+ * \since This function is available since SDL 2.0.0.
+ *
+ * \sa SDL_Log
+ * \sa SDL_LogDebug
+ * \sa SDL_LogError
+ * \sa SDL_LogInfo
+ * \sa SDL_LogMessage
+ * \sa SDL_LogMessageV
+ * \sa SDL_LogVerbose
+ * \sa SDL_LogWarn
+ */
+extern DECLSPEC void SDLCALL SDL_LogCritical(int category, SDL_PRINTF_FORMAT_STRING const char *fmt, ...) SDL_PRINTF_VARARG_FUNC(2);
+
+/**
+ * Log a message with the specified category and priority.
+ *
+ * \param category the category of the message
+ * \param priority the priority of the message
+ * \param fmt a printf() style message format string
+ * \param ... additional parameters matching % tokens in the **fmt** string,
+ * if any
+ *
+ * \since This function is available since SDL 2.0.0.
+ *
+ * \sa SDL_Log
+ * \sa SDL_LogCritical
+ * \sa SDL_LogDebug
+ * \sa SDL_LogError
+ * \sa SDL_LogInfo
+ * \sa SDL_LogMessageV
+ * \sa SDL_LogVerbose
+ * \sa SDL_LogWarn
+ */
+extern DECLSPEC void SDLCALL SDL_LogMessage(int category,
+ SDL_LogPriority priority,
+ SDL_PRINTF_FORMAT_STRING const char *fmt, ...) SDL_PRINTF_VARARG_FUNC(3);
+
+/**
+ * Log a message with the specified category and priority.
+ *
+ * \param category the category of the message
+ * \param priority the priority of the message
+ * \param fmt a printf() style message format string
+ * \param ap a variable argument list
+ *
+ * \since This function is available since SDL 2.0.0.
+ *
+ * \sa SDL_Log
+ * \sa SDL_LogCritical
+ * \sa SDL_LogDebug
+ * \sa SDL_LogError
+ * \sa SDL_LogInfo
+ * \sa SDL_LogMessage
+ * \sa SDL_LogVerbose
+ * \sa SDL_LogWarn
+ */
+extern DECLSPEC void SDLCALL SDL_LogMessageV(int category,
+ SDL_LogPriority priority,
+ const char *fmt, va_list ap);
+
+/**
+ * The prototype for the log output callback function.
+ *
+ * This function is called by SDL when there is new text to be logged.
+ *
+ * \param userdata what was passed as `userdata` to SDL_LogSetOutputFunction()
+ * \param category the category of the message
+ * \param priority the priority of the message
+ * \param message the message being output
+ */
+typedef void (SDLCALL *SDL_LogOutputFunction)(void *userdata, int category, SDL_LogPriority priority, const char *message);
+
+/**
+ * Get the current log output function.
+ *
+ * \param callback an SDL_LogOutputFunction filled in with the current log
+ * callback
+ * \param userdata a pointer filled in with the pointer that is passed to
+ * `callback`
+ *
+ * \since This function is available since SDL 2.0.0.
+ *
+ * \sa SDL_LogSetOutputFunction
+ */
+extern DECLSPEC void SDLCALL SDL_LogGetOutputFunction(SDL_LogOutputFunction *callback, void **userdata);
+
+/**
+ * Replace the default log output function with one of your own.
+ *
+ * \param callback an SDL_LogOutputFunction to call instead of the default
+ * \param userdata a pointer that is passed to `callback`
+ *
+ * \since This function is available since SDL 2.0.0.
+ *
+ * \sa SDL_LogGetOutputFunction
+ */
+extern DECLSPEC void SDLCALL SDL_LogSetOutputFunction(SDL_LogOutputFunction callback, void *userdata);
+
+
+/* Ends C function definitions when using C++ */
+#ifdef __cplusplus
+}
+#endif
+#include
+
+#endif /* SDL_log_h_ */
+
+/* vi: set ts=4 sw=4 expandtab: */
diff --git a/bindings/sdl2wgpu/src/main/headers/SDL2/SDL_main.h b/bindings/sdl2wgpu/src/main/headers/SDL2/SDL_main.h
new file mode 100644
index 00000000..8e938ca8
--- /dev/null
+++ b/bindings/sdl2wgpu/src/main/headers/SDL2/SDL_main.h
@@ -0,0 +1,282 @@
+/*
+ Simple DirectMedia Layer
+ Copyright (C) 1997-2023 Sam Lantinga
+
+ This software is provided 'as-is', without any express or implied
+ warranty. In no event will the authors be held liable for any damages
+ arising from the use of this software.
+
+ Permission is granted to anyone to use this software for any purpose,
+ including commercial applications, and to alter it and redistribute it
+ freely, subject to the following restrictions:
+
+ 1. The origin of this software must not be misrepresented; you must not
+ claim that you wrote the original software. If you use this software
+ in a product, an acknowledgment in the product documentation would be
+ appreciated but is not required.
+ 2. Altered source versions must be plainly marked as such, and must not be
+ misrepresented as being the original software.
+ 3. This notice may not be removed or altered from any source distribution.
+*/
+
+#ifndef SDL_main_h_
+#define SDL_main_h_
+
+#include
+
+/**
+ * \file SDL_main.h
+ *
+ * Redefine main() on some platforms so that it is called by SDL.
+ */
+
+#ifndef SDL_MAIN_HANDLED
+#if defined(__WIN32__)
+/* On Windows SDL provides WinMain(), which parses the command line and passes
+ the arguments to your main function.
+
+ If you provide your own WinMain(), you may define SDL_MAIN_HANDLED
+ */
+#define SDL_MAIN_AVAILABLE
+
+#elif defined(__WINRT__)
+/* On WinRT, SDL provides a main function that initializes CoreApplication,
+ creating an instance of IFrameworkView in the process.
+
+ Please note that #include'ing SDL_main.h is not enough to get a main()
+ function working. In non-XAML apps, the file,
+ src/main/winrt/SDL_WinRT_main_NonXAML.cpp, or a copy of it, must be compiled
+ into the app itself. In XAML apps, the function, SDL_WinRTRunApp must be
+ called, with a pointer to the Direct3D-hosted XAML control passed in.
+*/
+#define SDL_MAIN_NEEDED
+
+#elif defined(__GDK__)
+/* On GDK, SDL provides a main function that initializes the game runtime.
+
+ Please note that #include'ing SDL_main.h is not enough to get a main()
+ function working. You must either link against SDL2main or, if not possible,
+ call the SDL_GDKRunApp function from your entry point.
+*/
+#define SDL_MAIN_NEEDED
+
+#elif defined(__IPHONEOS__)
+/* On iOS SDL provides a main function that creates an application delegate
+ and starts the iOS application run loop.
+
+ If you link with SDL dynamically on iOS, the main function can't be in a
+ shared library, so you need to link with libSDLmain.a, which includes a
+ stub main function that calls into the shared library to start execution.
+
+ See src/video/uikit/SDL_uikitappdelegate.m for more details.
+ */
+#define SDL_MAIN_NEEDED
+
+#elif defined(__ANDROID__)
+/* On Android SDL provides a Java class in SDLActivity.java that is the
+ main activity entry point.
+
+ See docs/README-android.md for more details on extending that class.
+ */
+#define SDL_MAIN_NEEDED
+
+/* We need to export SDL_main so it can be launched from Java */
+#define SDLMAIN_DECLSPEC DECLSPEC
+
+#elif defined(__NACL__)
+/* On NACL we use ppapi_simple to set up the application helper code,
+ then wait for the first PSE_INSTANCE_DIDCHANGEVIEW event before
+ starting the user main function.
+ All user code is run in a separate thread by ppapi_simple, thus
+ allowing for blocking io to take place via nacl_io
+*/
+#define SDL_MAIN_NEEDED
+
+#elif defined(__PSP__)
+/* On PSP SDL provides a main function that sets the module info,
+ activates the GPU and starts the thread required to be able to exit
+ the software.
+
+ If you provide this yourself, you may define SDL_MAIN_HANDLED
+ */
+#define SDL_MAIN_AVAILABLE
+
+#elif defined(__PS2__)
+#define SDL_MAIN_AVAILABLE
+
+#define SDL_PS2_SKIP_IOP_RESET() \
+ void reset_IOP(); \
+ void reset_IOP() {}
+
+#elif defined(__3DS__)
+/*
+ On N3DS, SDL provides a main function that sets up the screens
+ and storage.
+
+ If you provide this yourself, you may define SDL_MAIN_HANDLED
+*/
+#define SDL_MAIN_AVAILABLE
+
+#endif
+#endif /* SDL_MAIN_HANDLED */
+
+#ifndef SDLMAIN_DECLSPEC
+#define SDLMAIN_DECLSPEC
+#endif
+
+/**
+ * \file SDL_main.h
+ *
+ * The application's main() function must be called with C linkage,
+ * and should be declared like this:
+ * \code
+ * #ifdef __cplusplus
+ * extern "C"
+ * #endif
+ * int main(int argc, char *argv[])
+ * {
+ * }
+ * \endcode
+ */
+
+#if defined(SDL_MAIN_NEEDED) || defined(SDL_MAIN_AVAILABLE)
+#define main SDL_main
+#endif
+
+#include
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * The prototype for the application's main() function
+ */
+typedef int (*SDL_main_func)(int argc, char *argv[]);
+extern SDLMAIN_DECLSPEC int SDL_main(int argc, char *argv[]);
+
+
+/**
+ * Circumvent failure of SDL_Init() when not using SDL_main() as an entry
+ * point.
+ *
+ * This function is defined in SDL_main.h, along with the preprocessor rule to
+ * redefine main() as SDL_main(). Thus to ensure that your main() function
+ * will not be changed it is necessary to define SDL_MAIN_HANDLED before
+ * including SDL.h.
+ *
+ * \since This function is available since SDL 2.0.0.
+ *
+ * \sa SDL_Init
+ */
+extern DECLSPEC void SDLCALL SDL_SetMainReady(void);
+
+#if defined(__WIN32__) || defined(__GDK__)
+
+/**
+ * Register a win32 window class for SDL's use.
+ *
+ * This can be called to set the application window class at startup. It is
+ * safe to call this multiple times, as long as every call is eventually
+ * paired with a call to SDL_UnregisterApp, but a second registration attempt
+ * while a previous registration is still active will be ignored, other than
+ * to increment a counter.
+ *
+ * Most applications do not need to, and should not, call this directly; SDL
+ * will call it when initializing the video subsystem.
+ *
+ * \param name the window class name, in UTF-8 encoding. If NULL, SDL
+ * currently uses "SDL_app" but this isn't guaranteed.
+ * \param style the value to use in WNDCLASSEX::style. If `name` is NULL, SDL
+ * currently uses `(CS_BYTEALIGNCLIENT | CS_OWNDC)` regardless of
+ * what is specified here.
+ * \param hInst the HINSTANCE to use in WNDCLASSEX::hInstance. If zero, SDL
+ * will use `GetModuleHandle(NULL)` instead.
+ * \returns 0 on success, -1 on error. SDL_GetError() may have details.
+ *
+ * \since This function is available since SDL 2.0.2.
+ */
+extern DECLSPEC int SDLCALL SDL_RegisterApp(const char *name, Uint32 style, void *hInst);
+
+/**
+ * Deregister the win32 window class from an SDL_RegisterApp call.
+ *
+ * This can be called to undo the effects of SDL_RegisterApp.
+ *
+ * Most applications do not need to, and should not, call this directly; SDL
+ * will call it when deinitializing the video subsystem.
+ *
+ * It is safe to call this multiple times, as long as every call is eventually
+ * paired with a prior call to SDL_RegisterApp. The window class will only be
+ * deregistered when the registration counter in SDL_RegisterApp decrements to
+ * zero through calls to this function.
+ *
+ * \since This function is available since SDL 2.0.2.
+ */
+extern DECLSPEC void SDLCALL SDL_UnregisterApp(void);
+
+#endif /* defined(__WIN32__) || defined(__GDK__) */
+
+
+#ifdef __WINRT__
+
+/**
+ * Initialize and launch an SDL/WinRT application.
+ *
+ * \param mainFunction the SDL app's C-style main(), an SDL_main_func
+ * \param reserved reserved for future use; should be NULL
+ * \returns 0 on success or -1 on failure; call SDL_GetError() to retrieve
+ * more information on the failure.
+ *
+ * \since This function is available since SDL 2.0.3.
+ */
+extern DECLSPEC int SDLCALL SDL_WinRTRunApp(SDL_main_func mainFunction, void * reserved);
+
+#endif /* __WINRT__ */
+
+#if defined(__IPHONEOS__)
+
+/**
+ * Initializes and launches an SDL application.
+ *
+ * \param argc The argc parameter from the application's main() function
+ * \param argv The argv parameter from the application's main() function
+ * \param mainFunction The SDL app's C-style main(), an SDL_main_func
+ * \return the return value from mainFunction
+ *
+ * \since This function is available since SDL 2.0.10.
+ */
+extern DECLSPEC int SDLCALL SDL_UIKitRunApp(int argc, char *argv[], SDL_main_func mainFunction);
+
+#endif /* __IPHONEOS__ */
+
+#ifdef __GDK__
+
+/**
+ * Initialize and launch an SDL GDK application.
+ *
+ * \param mainFunction the SDL app's C-style main(), an SDL_main_func
+ * \param reserved reserved for future use; should be NULL
+ * \returns 0 on success or -1 on failure; call SDL_GetError() to retrieve
+ * more information on the failure.
+ *
+ * \since This function is available since SDL 2.24.0.
+ */
+extern DECLSPEC int SDLCALL SDL_GDKRunApp(SDL_main_func mainFunction, void *reserved);
+
+/**
+ * Callback from the application to let the suspend continue.
+ *
+ * \since This function is available since SDL 2.28.0.
+ */
+extern DECLSPEC void SDLCALL SDL_GDKSuspendComplete(void);
+
+#endif /* __GDK__ */
+
+#ifdef __cplusplus
+}
+#endif
+#include
+
+#endif /* SDL_main_h_ */
+
+/* vi: set ts=4 sw=4 expandtab: */
diff --git a/bindings/sdl2wgpu/src/main/headers/SDL2/SDL_messagebox.h b/bindings/sdl2wgpu/src/main/headers/SDL2/SDL_messagebox.h
new file mode 100644
index 00000000..3edafdbc
--- /dev/null
+++ b/bindings/sdl2wgpu/src/main/headers/SDL2/SDL_messagebox.h
@@ -0,0 +1,193 @@
+/*
+ Simple DirectMedia Layer
+ Copyright (C) 1997-2023 Sam Lantinga
+
+ This software is provided 'as-is', without any express or implied
+ warranty. In no event will the authors be held liable for any damages
+ arising from the use of this software.
+
+ Permission is granted to anyone to use this software for any purpose,
+ including commercial applications, and to alter it and redistribute it
+ freely, subject to the following restrictions:
+
+ 1. The origin of this software must not be misrepresented; you must not
+ claim that you wrote the original software. If you use this software
+ in a product, an acknowledgment in the product documentation would be
+ appreciated but is not required.
+ 2. Altered source versions must be plainly marked as such, and must not be
+ misrepresented as being the original software.
+ 3. This notice may not be removed or altered from any source distribution.
+*/
+
+#ifndef SDL_messagebox_h_
+#define SDL_messagebox_h_
+
+#include
+#include /* For SDL_Window */
+
+#include | | | |